diff --git a/deployments/mainnet/SushiswapMasterChefV1Adapter.json b/deployments/mainnet/SushiswapMasterChefV1Adapter.json new file mode 100644 index 000000000..4a5795c25 --- /dev/null +++ b/deployments/mainnet/SushiswapMasterChefV1Adapter.json @@ -0,0 +1,1052 @@ +{ + "address": "0x159ecFB357A407cb62Ef8cF2697a5A66198d9ca7", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxDepositAmount", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogMaxDepositAmount", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxDepositPoolPct", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogMaxDepositPoolPct", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "enum MaxExposure", + "name": "maxDepositProtocolMode", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogMaxDepositProtocolMode", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "maxDepositProtocolPct", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogMaxDepositProtocolPct", + "type": "event" + }, + { + "inputs": [], + "name": "AAVE_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "COMP_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DAI_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "ILV_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LDO_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "LINK_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANA_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SNX_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SUSHISWAP_ROUTER", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SUSHI_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "UNI_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "USDC_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBTC_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "XSUSHI_WETH", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "calculateAmountInLPToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "calculateRedeemableLPTokenAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "canStake", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + } + ], + "name": "getAddLiquidityCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + } + ], + "name": "getAllAmountInToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getClaimRewardTokenCode", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + } + ], + "name": "getDepositAllCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "getDepositSomeCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "_codes", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + } + ], + "name": "getHarvestAllCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_rewardTokenAmount", + "type": "uint256" + } + ], + "name": "getHarvestSomeCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getLiquidityPoolToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + } + ], + "name": "getLiquidityPoolTokenBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + } + ], + "name": "getPoolValue", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + } + ], + "name": "getRewardToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "getSomeAmountInToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + } + ], + "name": "getUnclaimedRewardTokenAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "getUnderlyingTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + } + ], + "name": "getWithdrawAllCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_redeemAmount", + "type": "uint256" + } + ], + "name": "getWithdrawSomeCodes", + "outputs": [ + { + "internalType": "bytes[]", + "name": "_codes", + "type": "bytes[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_vault", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_redeemAmount", + "type": "uint256" + } + ], + "name": "isRedeemableAmountSufficient", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxDepositAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "maxDepositPoolPct", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxDepositProtocolMode", + "outputs": [ + { + "internalType": "enum MaxExposure", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxDepositProtocolPct", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "registryContract", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_masterChef", + "type": "address" + }, + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxDepositAmount", + "type": "uint256" + } + ], + "name": "setMaxDepositAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_underlyingToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_maxDepositPoolPct", + "type": "uint256" + } + ], + "name": "setMaxDepositPoolPct", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "enum MaxExposure", + "name": "_mode", + "type": "uint8" + } + ], + "name": "setMaxDepositProtocolMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_maxDepositProtocolPct", + "type": "uint256" + } + ], + "name": "setMaxDepositProtocolPct", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + } + ], + "name": "setRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_underlyingTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "_pids", + "type": "uint256[]" + } + ], + "name": "setUnderlyingTokenToPid", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "underlyingTokenToPid", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x9d1f6710296e77402f0f209be2c3e70a506dd5df43b27f16eb0ac796e1f3de20", + "receipt": { + "to": null, + "from": "0xD26Ec7401C198ADAc340d3A4Cb8B52b845F3A542", + "contractAddress": "0x159ecFB357A407cb62Ef8cF2697a5A66198d9ca7", + "transactionIndex": 94, + "gasUsed": "2144186", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x84c6746f222330b4abc0b69e0f7375e9c0dba07b9e7d2f228fe6d1a7e8ff965d", + "transactionHash": "0x9d1f6710296e77402f0f209be2c3e70a506dd5df43b27f16eb0ac796e1f3de20", + "logs": [], + "blockNumber": 14975354, + "cumulativeGasUsed": "10918180", + "status": 1, + "byzantium": true + }, + "args": ["0x99fa011e33a8c6196869dec7bc407e896ba67fe3"], + "bytecode": "0x608060405234801561001057600080fd5b5060405161223a38038061223a83398101604081905261002f9161025e565b600080546001600160a01b0319166001600160a01b038316178082556127106001908155919060ff60a01b1916600160a01b830217905550506004602081905260017f692f6c1bea7ad41311f3decfbc930dbadfbcedbf7f698ca59515c625be85b6685560027f7caf90e268e2c12a138bf844a42e8757bcd8fcf71bebda5cbb0edb3c30ba4b4f557fc962c565abd2b2196fcb2e82b02ae64463f35e26c4c4bd6057539abc1380cab65560067f77332721bfcf5f9ec969c9b73d3fd2c893b56897008bc447fa18ae0dfc226f2c5560087fefd1f7b44462bbf1d41838fcbe5692ff6e0bd4d4f20aa574db517dc2596c43bc55600c7ffa41f22f94fa727879a23637f16dab243d1abee8d8e6496f98c315128aed36f45560127f6c438e12ad7b1aee99cd6636a76464b7c1c706ff0adc018575a40234fa307c405560137f42f530ddac2a72e5c67ef8424763406c89d16c88ae0a2d6bcb39b8f652c7efb05560157f12e18b540d3061d1d2ad299021efcc9204dd3b8764717cc18a78352e13cc4f485560257fbdd00bc0b8a20fe13b6080a0ec1a00845dc027e5dd28eb22f5970c6196c953e755606d7fa24dc8c7faf234c310ddcdc5890b6e7ad7fec8cbf43c01df134e03f0277d82655560f07f281313d65dd2d2908ab77aca8feb5bcef712777324af1bd7bf01ab8644cf2a4d55736a091a3406e0073c3cd6340122143009adac0eda60005260f47fc3dbf0b9aa6805cc3f7be32a8486eaedb80870b6cce44eace0733135c86a5e3d5561028c565b60006020828403121561026f578081fd5b81516001600160a01b0381168114610285578182fd5b9392505050565b611f9f8061029b6000396000f3fe608060405234801561001057600080fd5b506004361061028a5760003560e01c80637528e3ab1161015c578063c4e481e7116100ce578063e4aceee711610087578063e4aceee71461051b578063ee665bed14610455578063ef856be914610523578063efa3854e14610543578063f1aacbb71461054b578063f49307ca1461055e5761028a565b8063c4e481e7146104b4578063d463fcf6146104bc578063d74baaf8146104cf578063da699f96146104e2578063df935722146104f5578063e49d5ecc146105085761028a565b806385541e441161012057806385541e441461045557806390e61605146103de578063919b69d714610468578063a91ee0dc1461047b578063aab97a9e1461048e578063b3fe7f5a146104a15761028a565b80637528e3ab1461040c57806377078872146104145780637c47b3f4146104275780637df50ed81461043a57806381e139f31461044d5761028a565b80632af06b96116102005780634ad36e02116101b95780634ad36e02146103a55780634f83b52d146103b857806360925779146103cb57806364dd5f80146103de5780636d267d7c146103f15780636eecde39146104045761028a565b80632af06b961461033a5780632de778381461034f5780633600e32a1461036257806336d8bf931461036a57806337a9d7611461038a578063489b5295146103925761028a565b806317febb1b1161025257806317febb1b1461030a578063191c194b14610312578063194cbe7b1461031a57806323e84c1e14610322578063277754ed1461032a57806328c1f99b146103325761028a565b806301073cdf1461028f578063027a304d146102a45780630c34cabd146102cd5780630c9d8d5c146102e2578063116d602714610302575b600080fd5b6102a261029d3660046119a9565b610571565b005b6102b76102b236600461192c565b6106b3565b6040516102c49190611ed5565b60405180910390f35b6102d56106d0565b6040516102c49190611bf5565b6102f56102f0366004611892565b6106e8565b6040516102c49190611ce0565b6102d561077c565b6102d5610794565b6102b76107ac565b6102d56107b2565b6102d56107ca565b6102d56107e2565b6102d56107fa565b610342610809565b6040516102c49190611d4b565b6102b761035d36600461192c565b610819565b6102d56108a1565b61037d610378366004611822565b6108b9565b6040516102c49190611d40565b6102d56108bf565b6102f56103a0366004611892565b6108d7565b6102b76103b33660046118dc565b61095b565b6102b76103c6366004611822565b6109f5565b6102f56103d93660046118dc565b610a07565b6102b76103ec366004611892565b610ad1565b6102f56103ff36600461185a565b610b6a565b6102d5610b72565b6102d5610b8a565b6102d5610422366004611822565b610ba2565b6102a2610435366004611b47565b610c15565b6102f561044836600461185a565b610d33565b6102d5610e47565b6102b761046336600461193e565b61089b565b6102a261047636600461197e565b610e5f565b6102a2610489366004611822565b610f5c565b6102b761049c366004611822565b611060565b6102b76104af366004611892565b611072565b6102d5611103565b6102f56104ca3660046118dc565b61111b565b6102d56104dd36600461192c565b61122e565b6102a26104f0366004611b99565b611232565b6102f56105033660046118dc565b61131b565b61037d6105163660046118dc565b6114ea565b6102d5611503565b61053661053136600461192c565b61151b565b6040516102c49190611c93565b6102d5611535565b6102a261055936600461193e565b61154d565b6102f561056c366004611892565b61165a565b60008054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b1580156105bd57600080fd5b505afa1580156105d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f5919061183e565b6001600160a01b0316336001600160a01b03161461062e5760405162461bcd60e51b815260040161062590611d7f565b60405180910390fd5b815181518082146106515760405162461bcd60e51b815260040161062590611e2e565b60005b828110156106ac5783818151811061066857fe5b60200260200101516004600087848151811061068057fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055600101610654565b5050505050565b600360209081526000928352604080842090915290825290205481565b73a1d7b2d891e3a1f9ef4bbc5be20630c2feb1c47081565b60606107748484846106f986610ba2565b6001600160a01b03166370a08231896040518263ffffffff1660e01b81526004016107249190611bf5565b60206040518083038186803b15801561073c57600080fd5b505afa158015610750573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ca9190611bb1565b949350505050565b7331503dcb60119a812fee820bb7042752019f235581565b736a091a3406e0073c3cd6340122143009adac0eda81565b60015481565b73d75ea151a61d06868e31f8988d28dfe5e9df57b481565b73c3d03e4f041fd4cd388c549ee2a29a9e5075882f81565b73d9e1ce17f2641f24ae83637ab66a2cca9c378b9f81565b6000546001600160a01b031681565b600054600160a01b900460ff1681565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610848908690600401611bf5565b60206040518083038186803b15801561086057600080fd5b505afa158015610874573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190611bb1565b90505b92915050565b73795065dcc9f64b5614c407a6efdc400da6221fb081565b50600090565b73c558f600b34a5f69dd2f0d06cb8a88d829b7420a81565b6060610774848484866001600160a01b03166370a08231896040518263ffffffff1660e01b815260040161090b9190611bf5565b60206040518083038186803b15801561092357600080fd5b505afa158015610937573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105039190611bb1565b6001600160a01b0383811660009081526004602081905260408083205490516393f1a40b60e01b815292938616926393f1a40b9261099c92918a9101611ede565b604080518083038186803b1580156109b357600080fd5b505afa1580156109c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109eb9190611b66565b5195945050505050565b60026020526000908152604090205481565b606081156107745760408051600180825281830190925290816020015b6060815260200190600190039081610a245750506001600160a01b038516600090815260046020526040908190205490519192508491610a6991908590602401611ef5565b60408051601f19818403018152918152602080830180516001600160e01b0316630441a3e760e41b1790529051610aa293929101611c56565b60405160208183030381529060405281600081518110610abe57fe5b6020026020010181905250949350505050565b6001600160a01b0382811660009081526004602081905260408083205490516393f1a40b60e01b815292938516926393f1a40b92610b129291899101611ede565b604080518083038186803b158015610b2957600080fd5b505afa158015610b3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b619190611b66565b51949350505050565b606092915050565b7336e2fcccc59e5747ff63a03ea2e5c0c2c14911e781565b731bec4db6c3bc499f3dbf289f5499c30d541fec9781565b6000816001600160a01b0316630a0879036040518163ffffffff1660e01b815260040160206040518083038186803b158015610bdd57600080fd5b505afa158015610bf1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089b919061183e565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6157600080fd5b505afa158015610c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c99919061183e565b6001600160a01b0316336001600160a01b031614610cc95760405162461bcd60e51b815260040161062590611e9e565b6000805482919060ff60a01b1916600160a01b836001811115610ce857fe5b02179055506000543390600160a01b900460ff166001811115610d0757fe5b6040517f68e3b01155b193b02181f2c0ed491c934a74348d211ff023f8fc6ac5edf22aa090600090a350565b6000546040805163450b674360e11b815290516060926001600160a01b031691638a16ce86916004808301926020929190829003018186803b158015610d7857600080fd5b505afa158015610d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db0919061183e565b6001600160a01b031663f8e9dfc273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f85856040518463ffffffff1660e01b8152600401610df393929190611c33565b60006040518083038186803b158015610e0b57600080fd5b505afa158015610e1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108989190810190611a6c565b73397ff1542f962076d0bfe58ea045ffa2d347aca081565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b158015610eab57600080fd5b505afa158015610ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee3919061183e565b6001600160a01b0316336001600160a01b031614610f135760405162461bcd60e51b815260040161062590611e9e565b6001600160a01b03821660009081526002602052604080822083905551339183917fac58e29a41d996caca756d050dce90806b277f0c939337653638329247e16f4c9190a35050565b60008054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b158015610fa857600080fd5b505afa158015610fbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe0919061183e565b6001600160a01b0316336001600160a01b0316146110105760405162461bcd60e51b815260040161062590611d7f565b611022816001600160a01b031661166d565b61103e5760405162461bcd60e51b815260040161062590611e79565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60046020526000908152604090205481565b6001600160a01b03818116600090815260046020819052604080832054905163065509bb60e21b8152929386169263195426ec926110b39291899101611ede565b60206040518083038186803b1580156110cb57600080fd5b505afa1580156110df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107749190611bb1565b73c40d16476380e4037e6b1a2594caf6a6cc8da96781565b6000546040805163450b674360e11b815290516060926001600160a01b031691638a16ce86916004808301926020929190829003018186803b15801561116057600080fd5b505afa158015611174573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611198919061183e565b6001600160a01b031663218826cd866111b086610ba2565b87866040518563ffffffff1660e01b81526004016111d19493929190611c09565b60006040518083038186803b1580156111e957600080fd5b505afa1580156111fd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112259190810190611a6c565b95945050505050565b5090565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b15801561127e57600080fd5b505afa158015611292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b6919061183e565b6001600160a01b0316336001600160a01b0316146112e65760405162461bcd60e51b815260040161062590611e9e565b6001819055604051339082907f19c60b0612798cc65bd298cd47e17d9fd07e74e0d3baa6c0019411bb334d9bda90600090a350565b60608115610774576000611330848685611673565b60408051600380825260808201909252919250816020015b606081526020019060019003908161134857905050915084846000604051602401611374929190611c7a565b60408051601f19818403018152918152602080830180516001600160e01b031663095ea7b360e01b17905290516113ad93929101611c56565b604051602081830303815290604052826000815181106113c957fe5b60200260200101819052508484826040516024016113e8929190611c7a565b60408051601f19818403018152918152602080830180516001600160e01b031663095ea7b360e01b179052905161142193929101611c56565b6040516020818303038152906040528260018151811061143d57fe5b60200260200101819052508360046000876001600160a01b03166001600160a01b031681526020019081526020016000205482604051602401611481929190611ef5565b60408051601f19818403018152918152602080830180516001600160e01b0316631c57762b60e31b17905290516114ba93929101611c56565b604051602081830303815290604052826002815181106114d657fe5b602002602001018190525050949350505050565b6000816114f8868686610ad1565b101595945050505050565b73dafd66636e2561b0284edde37e42d192f2844d4081565b606060405162461bcd60e51b815260040161062590611d5f565b73ceff51756c56ceffca006cd410b03ffc46dd3a5881565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b15801561159957600080fd5b505afa1580156115ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d1919061183e565b6001600160a01b0316336001600160a01b0316146116015760405162461bcd60e51b815260040161062590611e9e565b6001600160a01b03838116600090815260036020908152604080832093861683529290528181208390559051339183917f197807a6a2633dd9bde6550aca985cfc69e655e9130930314c0e9da01a75cc549190a3505050565b60606107748484846103d9888888610ad1565b3b151590565b6000806001600054600160a01b900460ff16600181111561169057fe5b146116c0576001600160a01b038086166000908152600360209081526040808320938816835292905220546116ca565b6116ca85856116d9565b90508083116107745782611225565b6000806116e68484610819565b6001600160a01b03841660009081526002602052604081205491925081156117235761171e6127106117188585611748565b90611782565b61173e565b61173e6127106117186001548661174890919063ffffffff16565b9695505050505050565b6000826117575750600061089b565b8282028284828161176457fe5b04146108985760405162461bcd60e51b815260040161062590611ded565b60008082116117a35760405162461bcd60e51b815260040161062590611db6565b8183816117ac57fe5b049392505050565b600082601f8301126117c4578081fd5b81356117d76117d282611f2a565b611f03565b8181529150602080830190848101818402860182018710156117f857600080fd5b60005b84811015611817578135845292820192908201906001016117fb565b505050505092915050565b600060208284031215611833578081fd5b813561089881611f7a565b60006020828403121561184f578081fd5b815161089881611f7a565b6000806040838503121561186c578081fd5b823561187781611f7a565b9150602083013561188781611f7a565b809150509250929050565b6000806000606084860312156118a6578081fd5b83356118b181611f7a565b925060208401356118c181611f7a565b915060408401356118d181611f7a565b809150509250925092565b600080600080608085870312156118f1578081fd5b84356118fc81611f7a565b9350602085013561190c81611f7a565b9250604085013561191c81611f7a565b9396929550929360600135925050565b6000806040838503121561186c578182fd5b600080600060608486031215611952578283fd5b833561195d81611f7a565b9250602084013561196d81611f7a565b929592945050506040919091013590565b60008060408385031215611990578182fd5b823561199b81611f7a565b946020939093013593505050565b600080604083850312156119bb578182fd5b823567ffffffffffffffff808211156119d2578384fd5b818501915085601f8301126119e5578384fd5b81356119f36117d282611f2a565b80828252602080830192508086018a828387028901011115611a13578889fd5b8896505b84871015611a3e578035611a2a81611f7a565b845260019690960195928101928101611a17565b509096508701359350505080821115611a55578283fd5b50611a62858286016117b4565b9150509250929050565b60006020808385031215611a7e578182fd5b825167ffffffffffffffff80821115611a95578384fd5b8185019150601f8681840112611aa9578485fd5b8251611ab76117d282611f2a565b81815285810190858701885b84811015611b3757815188018c603f820112611add578a8bfd5b8981015188811115611aed578b8cfd5b611afe818901601f19168c01611f03565b81815260408f81848601011115611b13578d8efd5b611b22838e8401838701611f4a565b50865250509288019290880190600101611ac3565b50909a9950505050505050505050565b600060208284031215611b58578081fd5b813560028110610898578182fd5b600060408284031215611b77578081fd5b611b816040611f03565b82518152602083015160208201528091505092915050565b600060208284031215611baa578081fd5b5035919050565b600060208284031215611bc2578081fd5b5051919050565b60008151808452611be1816020860160208601611f4a565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b038316815260406020820181905260009061077490830184611bc9565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b81811015611cd45783516001600160a01b031683529284019291840191600101611caf565b50909695505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611d3357603f19888603018452611d21858351611bc9565b94509285019290850190600101611d05565b5092979650505050505050565b901515815260200190565b6020810160028310611d5957fe5b91905290565b60208082526006908201526521656d70747960d01b604082015260600190565b6020808252601a908201527f63616c6c6572206973206e6f7420746865206f70657261746f72000000000000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602b908201527f696e657175616c206c656e677468206f6620756e6465726c79696e67746f6b6560408201526a6e7320616e64207069647360a81b606082015260800190565b6020808252600b908201526a085a5cd0dbdb9d1c9858dd60aa1b604082015260600190565b6020808252601e908201527f63616c6c6572206973206e6f7420746865207269736b4f70657261746f720000604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715611f2257600080fd5b604052919050565b600067ffffffffffffffff821115611f40578081fd5b5060209081020190565b60005b83811015611f65578181015183820152602001611f4d565b83811115611f74576000848401525b50505050565b6001600160a01b0381168114611f8f57600080fd5b5056fea164736f6c634300060c000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061028a5760003560e01c80637528e3ab1161015c578063c4e481e7116100ce578063e4aceee711610087578063e4aceee71461051b578063ee665bed14610455578063ef856be914610523578063efa3854e14610543578063f1aacbb71461054b578063f49307ca1461055e5761028a565b8063c4e481e7146104b4578063d463fcf6146104bc578063d74baaf8146104cf578063da699f96146104e2578063df935722146104f5578063e49d5ecc146105085761028a565b806385541e441161012057806385541e441461045557806390e61605146103de578063919b69d714610468578063a91ee0dc1461047b578063aab97a9e1461048e578063b3fe7f5a146104a15761028a565b80637528e3ab1461040c57806377078872146104145780637c47b3f4146104275780637df50ed81461043a57806381e139f31461044d5761028a565b80632af06b96116102005780634ad36e02116101b95780634ad36e02146103a55780634f83b52d146103b857806360925779146103cb57806364dd5f80146103de5780636d267d7c146103f15780636eecde39146104045761028a565b80632af06b961461033a5780632de778381461034f5780633600e32a1461036257806336d8bf931461036a57806337a9d7611461038a578063489b5295146103925761028a565b806317febb1b1161025257806317febb1b1461030a578063191c194b14610312578063194cbe7b1461031a57806323e84c1e14610322578063277754ed1461032a57806328c1f99b146103325761028a565b806301073cdf1461028f578063027a304d146102a45780630c34cabd146102cd5780630c9d8d5c146102e2578063116d602714610302575b600080fd5b6102a261029d3660046119a9565b610571565b005b6102b76102b236600461192c565b6106b3565b6040516102c49190611ed5565b60405180910390f35b6102d56106d0565b6040516102c49190611bf5565b6102f56102f0366004611892565b6106e8565b6040516102c49190611ce0565b6102d561077c565b6102d5610794565b6102b76107ac565b6102d56107b2565b6102d56107ca565b6102d56107e2565b6102d56107fa565b610342610809565b6040516102c49190611d4b565b6102b761035d36600461192c565b610819565b6102d56108a1565b61037d610378366004611822565b6108b9565b6040516102c49190611d40565b6102d56108bf565b6102f56103a0366004611892565b6108d7565b6102b76103b33660046118dc565b61095b565b6102b76103c6366004611822565b6109f5565b6102f56103d93660046118dc565b610a07565b6102b76103ec366004611892565b610ad1565b6102f56103ff36600461185a565b610b6a565b6102d5610b72565b6102d5610b8a565b6102d5610422366004611822565b610ba2565b6102a2610435366004611b47565b610c15565b6102f561044836600461185a565b610d33565b6102d5610e47565b6102b761046336600461193e565b61089b565b6102a261047636600461197e565b610e5f565b6102a2610489366004611822565b610f5c565b6102b761049c366004611822565b611060565b6102b76104af366004611892565b611072565b6102d5611103565b6102f56104ca3660046118dc565b61111b565b6102d56104dd36600461192c565b61122e565b6102a26104f0366004611b99565b611232565b6102f56105033660046118dc565b61131b565b61037d6105163660046118dc565b6114ea565b6102d5611503565b61053661053136600461192c565b61151b565b6040516102c49190611c93565b6102d5611535565b6102a261055936600461193e565b61154d565b6102f561056c366004611892565b61165a565b60008054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b1580156105bd57600080fd5b505afa1580156105d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105f5919061183e565b6001600160a01b0316336001600160a01b03161461062e5760405162461bcd60e51b815260040161062590611d7f565b60405180910390fd5b815181518082146106515760405162461bcd60e51b815260040161062590611e2e565b60005b828110156106ac5783818151811061066857fe5b60200260200101516004600087848151811061068057fe5b6020908102919091018101516001600160a01b0316825281019190915260400160002055600101610654565b5050505050565b600360209081526000928352604080842090915290825290205481565b73a1d7b2d891e3a1f9ef4bbc5be20630c2feb1c47081565b60606107748484846106f986610ba2565b6001600160a01b03166370a08231896040518263ffffffff1660e01b81526004016107249190611bf5565b60206040518083038186803b15801561073c57600080fd5b505afa158015610750573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104ca9190611bb1565b949350505050565b7331503dcb60119a812fee820bb7042752019f235581565b736a091a3406e0073c3cd6340122143009adac0eda81565b60015481565b73d75ea151a61d06868e31f8988d28dfe5e9df57b481565b73c3d03e4f041fd4cd388c549ee2a29a9e5075882f81565b73d9e1ce17f2641f24ae83637ab66a2cca9c378b9f81565b6000546001600160a01b031681565b600054600160a01b900460ff1681565b6040516370a0823160e01b81526000906001600160a01b038316906370a0823190610848908690600401611bf5565b60206040518083038186803b15801561086057600080fd5b505afa158015610874573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108989190611bb1565b90505b92915050565b73795065dcc9f64b5614c407a6efdc400da6221fb081565b50600090565b73c558f600b34a5f69dd2f0d06cb8a88d829b7420a81565b6060610774848484866001600160a01b03166370a08231896040518263ffffffff1660e01b815260040161090b9190611bf5565b60206040518083038186803b15801561092357600080fd5b505afa158015610937573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105039190611bb1565b6001600160a01b0383811660009081526004602081905260408083205490516393f1a40b60e01b815292938616926393f1a40b9261099c92918a9101611ede565b604080518083038186803b1580156109b357600080fd5b505afa1580156109c7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109eb9190611b66565b5195945050505050565b60026020526000908152604090205481565b606081156107745760408051600180825281830190925290816020015b6060815260200190600190039081610a245750506001600160a01b038516600090815260046020526040908190205490519192508491610a6991908590602401611ef5565b60408051601f19818403018152918152602080830180516001600160e01b0316630441a3e760e41b1790529051610aa293929101611c56565b60405160208183030381529060405281600081518110610abe57fe5b6020026020010181905250949350505050565b6001600160a01b0382811660009081526004602081905260408083205490516393f1a40b60e01b815292938516926393f1a40b92610b129291899101611ede565b604080518083038186803b158015610b2957600080fd5b505afa158015610b3d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b619190611b66565b51949350505050565b606092915050565b7336e2fcccc59e5747ff63a03ea2e5c0c2c14911e781565b731bec4db6c3bc499f3dbf289f5499c30d541fec9781565b6000816001600160a01b0316630a0879036040518163ffffffff1660e01b815260040160206040518083038186803b158015610bdd57600080fd5b505afa158015610bf1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061089b919061183e565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b158015610c6157600080fd5b505afa158015610c75573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c99919061183e565b6001600160a01b0316336001600160a01b031614610cc95760405162461bcd60e51b815260040161062590611e9e565b6000805482919060ff60a01b1916600160a01b836001811115610ce857fe5b02179055506000543390600160a01b900460ff166001811115610d0757fe5b6040517f68e3b01155b193b02181f2c0ed491c934a74348d211ff023f8fc6ac5edf22aa090600090a350565b6000546040805163450b674360e11b815290516060926001600160a01b031691638a16ce86916004808301926020929190829003018186803b158015610d7857600080fd5b505afa158015610d8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db0919061183e565b6001600160a01b031663f8e9dfc273d9e1ce17f2641f24ae83637ab66a2cca9c378b9f85856040518463ffffffff1660e01b8152600401610df393929190611c33565b60006040518083038186803b158015610e0b57600080fd5b505afa158015610e1f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108989190810190611a6c565b73397ff1542f962076d0bfe58ea045ffa2d347aca081565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b158015610eab57600080fd5b505afa158015610ebf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee3919061183e565b6001600160a01b0316336001600160a01b031614610f135760405162461bcd60e51b815260040161062590611e9e565b6001600160a01b03821660009081526002602052604080822083905551339183917fac58e29a41d996caca756d050dce90806b277f0c939337653638329247e16f4c9190a35050565b60008054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b158015610fa857600080fd5b505afa158015610fbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fe0919061183e565b6001600160a01b0316336001600160a01b0316146110105760405162461bcd60e51b815260040161062590611d7f565b611022816001600160a01b031661166d565b61103e5760405162461bcd60e51b815260040161062590611e79565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b60046020526000908152604090205481565b6001600160a01b03818116600090815260046020819052604080832054905163065509bb60e21b8152929386169263195426ec926110b39291899101611ede565b60206040518083038186803b1580156110cb57600080fd5b505afa1580156110df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107749190611bb1565b73c40d16476380e4037e6b1a2594caf6a6cc8da96781565b6000546040805163450b674360e11b815290516060926001600160a01b031691638a16ce86916004808301926020929190829003018186803b15801561116057600080fd5b505afa158015611174573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611198919061183e565b6001600160a01b031663218826cd866111b086610ba2565b87866040518563ffffffff1660e01b81526004016111d19493929190611c09565b60006040518083038186803b1580156111e957600080fd5b505afa1580156111fd573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112259190810190611a6c565b95945050505050565b5090565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b15801561127e57600080fd5b505afa158015611292573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112b6919061183e565b6001600160a01b0316336001600160a01b0316146112e65760405162461bcd60e51b815260040161062590611e9e565b6001819055604051339082907f19c60b0612798cc65bd298cd47e17d9fd07e74e0d3baa6c0019411bb334d9bda90600090a350565b60608115610774576000611330848685611673565b60408051600380825260808201909252919250816020015b606081526020019060019003908161134857905050915084846000604051602401611374929190611c7a565b60408051601f19818403018152918152602080830180516001600160e01b031663095ea7b360e01b17905290516113ad93929101611c56565b604051602081830303815290604052826000815181106113c957fe5b60200260200101819052508484826040516024016113e8929190611c7a565b60408051601f19818403018152918152602080830180516001600160e01b031663095ea7b360e01b179052905161142193929101611c56565b6040516020818303038152906040528260018151811061143d57fe5b60200260200101819052508360046000876001600160a01b03166001600160a01b031681526020019081526020016000205482604051602401611481929190611ef5565b60408051601f19818403018152918152602080830180516001600160e01b0316631c57762b60e31b17905290516114ba93929101611c56565b604051602081830303815290604052826002815181106114d657fe5b602002602001018190525050949350505050565b6000816114f8868686610ad1565b101595945050505050565b73dafd66636e2561b0284edde37e42d192f2844d4081565b606060405162461bcd60e51b815260040161062590611d5f565b73ceff51756c56ceffca006cd410b03ffc46dd3a5881565b60008054906101000a90046001600160a01b03166001600160a01b0316637af0e5576040518163ffffffff1660e01b815260040160206040518083038186803b15801561159957600080fd5b505afa1580156115ad573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d1919061183e565b6001600160a01b0316336001600160a01b0316146116015760405162461bcd60e51b815260040161062590611e9e565b6001600160a01b03838116600090815260036020908152604080832093861683529290528181208390559051339183917f197807a6a2633dd9bde6550aca985cfc69e655e9130930314c0e9da01a75cc549190a3505050565b60606107748484846103d9888888610ad1565b3b151590565b6000806001600054600160a01b900460ff16600181111561169057fe5b146116c0576001600160a01b038086166000908152600360209081526040808320938816835292905220546116ca565b6116ca85856116d9565b90508083116107745782611225565b6000806116e68484610819565b6001600160a01b03841660009081526002602052604081205491925081156117235761171e6127106117188585611748565b90611782565b61173e565b61173e6127106117186001548661174890919063ffffffff16565b9695505050505050565b6000826117575750600061089b565b8282028284828161176457fe5b04146108985760405162461bcd60e51b815260040161062590611ded565b60008082116117a35760405162461bcd60e51b815260040161062590611db6565b8183816117ac57fe5b049392505050565b600082601f8301126117c4578081fd5b81356117d76117d282611f2a565b611f03565b8181529150602080830190848101818402860182018710156117f857600080fd5b60005b84811015611817578135845292820192908201906001016117fb565b505050505092915050565b600060208284031215611833578081fd5b813561089881611f7a565b60006020828403121561184f578081fd5b815161089881611f7a565b6000806040838503121561186c578081fd5b823561187781611f7a565b9150602083013561188781611f7a565b809150509250929050565b6000806000606084860312156118a6578081fd5b83356118b181611f7a565b925060208401356118c181611f7a565b915060408401356118d181611f7a565b809150509250925092565b600080600080608085870312156118f1578081fd5b84356118fc81611f7a565b9350602085013561190c81611f7a565b9250604085013561191c81611f7a565b9396929550929360600135925050565b6000806040838503121561186c578182fd5b600080600060608486031215611952578283fd5b833561195d81611f7a565b9250602084013561196d81611f7a565b929592945050506040919091013590565b60008060408385031215611990578182fd5b823561199b81611f7a565b946020939093013593505050565b600080604083850312156119bb578182fd5b823567ffffffffffffffff808211156119d2578384fd5b818501915085601f8301126119e5578384fd5b81356119f36117d282611f2a565b80828252602080830192508086018a828387028901011115611a13578889fd5b8896505b84871015611a3e578035611a2a81611f7a565b845260019690960195928101928101611a17565b509096508701359350505080821115611a55578283fd5b50611a62858286016117b4565b9150509250929050565b60006020808385031215611a7e578182fd5b825167ffffffffffffffff80821115611a95578384fd5b8185019150601f8681840112611aa9578485fd5b8251611ab76117d282611f2a565b81815285810190858701885b84811015611b3757815188018c603f820112611add578a8bfd5b8981015188811115611aed578b8cfd5b611afe818901601f19168c01611f03565b81815260408f81848601011115611b13578d8efd5b611b22838e8401838701611f4a565b50865250509288019290880190600101611ac3565b50909a9950505050505050505050565b600060208284031215611b58578081fd5b813560028110610898578182fd5b600060408284031215611b77578081fd5b611b816040611f03565b82518152602083015160208201528091505092915050565b600060208284031215611baa578081fd5b5035919050565b600060208284031215611bc2578081fd5b5051919050565b60008151808452611be1816020860160208601611f4a565b601f01601f19169290920160200192915050565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b038316815260406020820181905260009061077490830184611bc9565b6001600160a01b03929092168252602082015260400190565b6020808252825182820181905260009190848201906040850190845b81811015611cd45783516001600160a01b031683529284019291840191600101611caf565b50909695505050505050565b6000602080830181845280855180835260408601915060408482028701019250838701855b82811015611d3357603f19888603018452611d21858351611bc9565b94509285019290850190600101611d05565b5092979650505050505050565b901515815260200190565b6020810160028310611d5957fe5b91905290565b60208082526006908201526521656d70747960d01b604082015260600190565b6020808252601a908201527f63616c6c6572206973206e6f7420746865206f70657261746f72000000000000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602b908201527f696e657175616c206c656e677468206f6620756e6465726c79696e67746f6b6560408201526a6e7320616e64207069647360a81b606082015260800190565b6020808252600b908201526a085a5cd0dbdb9d1c9858dd60aa1b604082015260600190565b6020808252601e908201527f63616c6c6572206973206e6f7420746865207269736b4f70657261746f720000604082015260600190565b90815260200190565b9182526001600160a01b0316602082015260400190565b918252602082015260400190565b60405181810167ffffffffffffffff81118282101715611f2257600080fd5b604052919050565b600067ffffffffffffffff821115611f40578081fd5b5060209081020190565b60005b83811015611f65578181015183820152602001611f4d565b83811115611f74576000848401525b50505050565b6001600160a01b0381168114611f8f57600080fd5b5056fea164736f6c634300060c000a" +} diff --git a/deployments/mainnet/opAAVEaggr.json b/deployments/mainnet/opAAVEaggr.json new file mode 100644 index 000000000..cddcfd0e1 --- /dev/null +++ b/deployments/mainnet/opAAVEaggr.json @@ -0,0 +1,1472 @@ +{ + "address": "0xd610c0CcE9792321BfEd3c2f31dceA6784c84F19", + "abi": [ + { + "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": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "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": "", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bool", + "name": "emergencyShutdown", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogEmergencyShutdown", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "minimumDepositValueUT", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogMinimumDepositValueUT", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "totalValueLockedLimitUT", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogTotalValueLockedLimitUT", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bool", + "name": "unpaused", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogUnpause", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "userDepositCapUT", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogUserDepositCapUT", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "_codes", + "type": "bytes[]" + } + ], + "name": "adminCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "balanceUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "blockToBlockVaultValues", + "outputs": [ + { + "internalType": "uint256", + "name": "actualVaultValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockMinVaultValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockMaxVaultValue", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositUT", + "type": "uint256" + } + ], + "name": "calcDepositFeeUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userWithdrawUT", + "type": "uint256" + } + ], + "name": "calcWithdrawalFeeUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "_investStrategySteps", + "type": "tuple[]" + } + ], + "name": "computeInvestStrategyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getInvestStrategySteps", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "_investStrategySteps", + "type": "tuple[]" + } + ], + "name": "getLastStrategyStepBalanceLP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextBestInvestStrategy", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricePerFullShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_underlyingTokensHash", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_riskProfileCode", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "investStrategyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "investStrategySteps", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_diff", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_currentVaultValue", + "type": "uint256" + } + ], + "name": "isMaxVaultValueJumpAllowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumDepositValueUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "opTOKEN_REVISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pendingDeposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rebalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registryContract", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_active", + "type": "bool" + } + ], + "name": "setEmergencyShutdown", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumDepositValueUT", + "type": "uint256" + } + ], + "name": "setMinimumDepositValueUT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + } + ], + "name": "setRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_riskProfileCode", + "type": "uint256" + } + ], + "name": "setRiskProfileCode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_totalValueLockedLimitUT", + "type": "uint256" + } + ], + "name": "setTotalValueLockedLimitUT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_underlyingTokensHash", + "type": "bytes32" + } + ], + "name": "setUnderlyingTokensHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_unpaused", + "type": "bool" + } + ], + "name": "setUnpaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositCapUT", + "type": "uint256" + } + ], + "name": "setUserDepositCapUT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositCapUT", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumDepositValueUT", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_totalValueLockedLimitUT", + "type": "uint256" + } + ], + "name": "setValueControlParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_vaultConfiguration", + "type": "uint256" + } + ], + "name": "setVaultConfiguration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_whitelistedAccountsRoot", + "type": "bytes32" + } + ], + "name": "setWhitelistedAccountsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_whitelistedCodesRoot", + "type": "bytes32" + } + ], + "name": "setWhitelistedCodesRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalDeposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalValueLockedLimitUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingTokensHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "userDepositCapUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bool", + "name": "_addUserDepositUT", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_userDepositUTWithDeductions", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_deductions", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userDepositPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositUT", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userDepositVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_userWithdrawVT", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userWithdrawPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userWithdrawVT", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userWithdrawVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultDepositAllToStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultDepositPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultWithdrawPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistedAccountsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistedCodesRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "_admin", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } + ], + "transactionHash": "0x167a201ee9dfeefb38ac820508adc84ca4c19d929bfce67b180a4efde6f32c55", + "receipt": { + "to": null, + "from": "0xD26Ec7401C198ADAc340d3A4Cb8B52b845F3A542", + "contractAddress": "0xd610c0CcE9792321BfEd3c2f31dceA6784c84F19", + "transactionIndex": 125, + "gasUsed": "658649", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x64028a0df37b2b6bbdaf66e4a9e172ce16ba006563ae7f11c955533d134e820e", + "transactionHash": "0x167a201ee9dfeefb38ac820508adc84ca4c19d929bfce67b180a4efde6f32c55", + "logs": [], + "blockNumber": 14976022, + "cumulativeGasUsed": "13098252", + "status": 1, + "byzantium": true + }, + "args": [ + "0x9fe0eebe0b82bc629ba75aa6d69127602f53de86", + "0xF980ea5758f71F418909688b6448B41ACb5522E9", + "0x76e57d0300000000000000000000000099fa011e33a8c6196869dec7bc407e896ba67fe31bcbc96de2b4142404b9827f220545e3cee1f75a00560c3bdd29c9658103f7e200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a4161766520546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044141564500000000000000000000000000000000000000000000000000000000" + ], + "solcInputHash": "671d40d1898428f733662d50d9454e10", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"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\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"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\":\"\",\"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\"}],\"devdoc\":{\"details\":\"Extends from BaseAdminUpgradeabilityProxy with a constructor for initializing the implementation, admin, and init data.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"The address of the proxy admin.\"}},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Only the current admin can call this function.\",\"params\":{\"newAdmin\":\"Address to transfer proxy administration to.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the proxy administrator.\",\"_data\":\"Data to send as msg.data to the implementation to initialize the proxied contract. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\",\"_logic\":\"address of the initial implementation.\"}},\"implementation()\":{\"returns\":{\"_0\":\"The address of the implementation.\"}},\"upgradeTo(address)\":{\"details\":\"Upgrade the backing implementation of the proxy. Only the admin can call this function.\",\"params\":{\"newImplementation\":\"Address of the new implementation.\"}},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the backing implementation of the proxy and call a function on the new implementation. This is useful to initialize the proxied contract.\",\"params\":{\"data\":\"Data to send as msg.data in the low level call. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\",\"newImplementation\":\"Address of the new implementation.\"}}},\"title\":\"AdminUpgradeabilityProxy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":\"Contract constructor.\"},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/protocol/tokenization/VaultProxyV2.sol\":\"AdminUpgradeabilityProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\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 function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 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 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\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(address target, bytes memory data, string memory errorMessage) 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(address target, bytes memory data, uint256 value) 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(address target, bytes memory data, uint256 value, string memory errorMessage) 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 // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly\\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\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/protocol/tokenization/VaultProxyV2.sol\":{\"content\":\"// solhint-disable\\n// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @title Proxy\\n * @dev Implements delegation of calls to other contracts, with proper\\n * forwarding of return values and bubbling of failures.\\n * It defines a fallback function that delegates all calls to the address\\n * returned by the abstract _implementation() internal function.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Fallback function.\\n * Implemented entirely in `_fallback`.\\n */\\n fallback() external payable {\\n _fallback();\\n }\\n\\n /**\\n * @return The Address of the implementation.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * This is a low level function that doesn't return to its internal call site.\\n * It will return to the external caller whatever the implementation returns.\\n * @param implementation Address to delegate.\\n */\\n function _delegate(address implementation) internal {\\n //solium-disable-next-line\\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 Function that is run as the first thing in the fallback function.\\n * Can be redefined in derived contracts to add functionality.\\n * Redefinitions must call super._willFallback().\\n */\\n function _willFallback() internal virtual {}\\n\\n /**\\n * @dev fallback implementation.\\n * Extracted to enable manual triggering.\\n */\\n function _fallback() internal {\\n _willFallback();\\n _delegate(_implementation());\\n }\\n}\\n\\n/**\\n * @title BaseUpgradeabilityProxy\\n * @dev This contract implements a proxy that allows to change the\\n * implementation address to which it will delegate.\\n * Such a change is called an implementation upgrade.\\n */\\ncontract BaseUpgradeabilityProxy is Proxy {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n * @param implementation Address of the new implementation.\\n */\\n event Upgraded(address indexed implementation);\\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 Returns the current implementation.\\n * @return impl Address of the current implementation\\n */\\n function _implementation() internal view override returns (address impl) {\\n bytes32 slot = IMPLEMENTATION_SLOT;\\n //solium-disable-next-line\\n assembly {\\n impl := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Upgrades the proxy to a new implementation.\\n * @param newImplementation Address of the new implementation.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Sets the implementation address of the proxy.\\n * @param newImplementation Address of the new implementation.\\n */\\n function _setImplementation(address newImplementation) internal {\\n require(Address.isContract(newImplementation), \\\"Cannot set a proxy implementation to a non-contract address\\\");\\n\\n bytes32 slot = IMPLEMENTATION_SLOT;\\n\\n //solium-disable-next-line\\n assembly {\\n sstore(slot, newImplementation)\\n }\\n }\\n}\\n\\n/**\\n * @title UpgradeabilityProxy\\n * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing\\n * implementation and init data.\\n */\\ncontract UpgradeabilityProxy is BaseUpgradeabilityProxy {\\n /**\\n * @dev Contract constructor.\\n * @param _logic Address of the initial implementation.\\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\\n * It should include the signature and the parameters of the function to be called, as described in\\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\\n */\\n constructor(address _logic, bytes memory _data) public payable {\\n assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _setImplementation(_logic);\\n if (_data.length > 0) {\\n (bool success, ) = _logic.delegatecall(_data);\\n require(success);\\n }\\n }\\n}\\n\\n/**\\n * @title BaseAdminUpgradeabilityProxy\\n * @dev This contract combines an upgradeability proxy with an authorization\\n * mechanism for administrative tasks.\\n * All external functions in this contract must be guarded by the\\n * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity\\n * feature proposal that would enable this to be done automatically.\\n */\\ncontract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {\\n /**\\n * @dev Emitted when the administration has been transferred.\\n * @param previousAdmin Address of the previous admin.\\n * @param newAdmin Address of the new admin.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\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 Modifier to check whether the `msg.sender` is the admin.\\n * If it is, it will run the function. Otherwise, it will delegate the call\\n * to the implementation.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _admin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @return The address of the proxy admin.\\n */\\n function admin() external ifAdmin returns (address) {\\n return _admin();\\n }\\n\\n /**\\n * @return The address of the implementation.\\n */\\n function implementation() external ifAdmin returns (address) {\\n return _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n * Only the current admin can call this function.\\n * @param newAdmin Address to transfer proxy administration to.\\n */\\n function changeAdmin(address newAdmin) external ifAdmin {\\n require(newAdmin != address(0), \\\"Cannot change the admin of a proxy to the zero address\\\");\\n emit AdminChanged(_admin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the backing implementation of the proxy.\\n * Only the admin can call this function.\\n * @param newImplementation Address of the new implementation.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeTo(newImplementation);\\n }\\n\\n /**\\n * @dev Upgrade the backing implementation of the proxy and call a function\\n * on the new implementation.\\n * This is useful to initialize the proxied contract.\\n * @param newImplementation Address of the new implementation.\\n * @param data Data to send as msg.data in the low level call.\\n * It should include the signature and the parameters of the function to be called, as described in\\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeTo(newImplementation);\\n (bool success, ) = newImplementation.delegatecall(data);\\n require(success);\\n }\\n\\n /**\\n * @return adm The admin slot.\\n */\\n function _admin() internal view returns (address adm) {\\n bytes32 slot = ADMIN_SLOT;\\n //solium-disable-next-line\\n assembly {\\n adm := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Sets the address of the proxy admin.\\n * @param newAdmin Address of the new proxy admin.\\n */\\n function _setAdmin(address newAdmin) internal {\\n bytes32 slot = ADMIN_SLOT;\\n //solium-disable-next-line\\n assembly {\\n sstore(slot, newAdmin)\\n }\\n }\\n\\n /**\\n * @dev Only fall back when the sender is not the admin.\\n */\\n function _willFallback() internal virtual override {\\n require(msg.sender != _admin(), \\\"Cannot call fallback function from the proxy admin\\\");\\n super._willFallback();\\n }\\n}\\n\\n/**\\n * @title AdminUpgradeabilityProxy\\n * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for\\n * initializing the implementation, admin, and init data.\\n */\\ncontract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {\\n /**\\n * Contract constructor.\\n * @param _logic address of the initial implementation.\\n * @param _admin Address of the proxy administrator.\\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\\n * It should include the signature and the parameters of the function to be called, as described in\\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\\n */\\n constructor(\\n address _logic,\\n address _admin,\\n bytes memory _data\\n ) public payable UpgradeabilityProxy(_logic, _data) {\\n assert(ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _setAdmin(_admin);\\n }\\n\\n /**\\n * @dev Only fall back when the sender is not the admin.\\n */\\n function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) {\\n BaseAdminUpgradeabilityProxy._willFallback();\\n }\\n}\\n\",\"keccak256\":\"0x73bee0e9ca8a8ccd6b7f75816034c58f08a2d89ec8d9f3056ed08d1e37e26b36\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040526040516108a03803806108a08339818101604052606081101561002657600080fd5b8151602083015160408085018051915193959294830192918464010000000082111561005157600080fd5b90830190602082018581111561006657600080fd5b825164010000000081118282018810171561008057600080fd5b82525081516020918201929091019080838360005b838110156100ad578181015183820152602001610095565b50505050905090810190601f1680156100da5780820380516001836020036101000a031916815260200191505b50604052508491508290506100ee826101bf565b8051156101a6576000826001600160a01b0316826040518082805190602001908083835b602083106101315780518252601f199092019160209182019101610112565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50509050806101a457600080fd5b505b506101ae9050565b6101b782610231565b50505061025b565b6101d28161025560201b6103a31760201c565b61020d5760405162461bcd60e51b815260040180806020018281038252603b815260200180610865603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b3b151590565b6105fb8061026a6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101d4565b34801561011357600080fd5b5061011c610281565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b03166102be565b34801561017757600080fd5b5061011c610378565b6101886103a9565b6101986101936103b1565b6103d6565b565b6101a26103fa565b6001600160a01b0316336001600160a01b031614156101c9576101c48161041f565b6101d1565b6101d1610180565b50565b6101dc6103fa565b6001600160a01b0316336001600160a01b03161415610274576101fe8361041f565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d806000811461025b576040519150601f19603f3d011682016040523d82523d6000602084013e610260565b606091505b505090508061026e57600080fd5b5061027c565b61027c610180565b505050565b600061028b6103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103b1565b90506102bb565b6102bb610180565b90565b6102c66103fa565b6001600160a01b0316336001600160a01b031614156101c9576001600160a01b0381166103245760405162461bcd60e51b815260040180806020018281038252603681526020018061057e6036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61034d6103fa565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c48161045f565b60006103826103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103fa565b3b151590565b610198610483565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156103f5573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b610428816104e3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61048b6103fa565b6001600160a01b0316336001600160a01b031614156104db5760405162461bcd60e51b815260040180806020018281038252603281526020018061054c6032913960400191505060405180910390fd5b610198610198565b6104ec816103a3565b6105275760405162461bcd60e51b815260040180806020018281038252603b8152602001806105b4603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a164736f6c634300060c000a43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373", + "deployedBytecode": "0x60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101d4565b34801561011357600080fd5b5061011c610281565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b03166102be565b34801561017757600080fd5b5061011c610378565b6101886103a9565b6101986101936103b1565b6103d6565b565b6101a26103fa565b6001600160a01b0316336001600160a01b031614156101c9576101c48161041f565b6101d1565b6101d1610180565b50565b6101dc6103fa565b6001600160a01b0316336001600160a01b03161415610274576101fe8361041f565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d806000811461025b576040519150601f19603f3d011682016040523d82523d6000602084013e610260565b606091505b505090508061026e57600080fd5b5061027c565b61027c610180565b505050565b600061028b6103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103b1565b90506102bb565b6102bb610180565b90565b6102c66103fa565b6001600160a01b0316336001600160a01b031614156101c9576001600160a01b0381166103245760405162461bcd60e51b815260040180806020018281038252603681526020018061057e6036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61034d6103fa565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c48161045f565b60006103826103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103fa565b3b151590565b610198610483565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156103f5573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b610428816104e3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61048b6103fa565b6001600160a01b0316336001600160a01b031614156104db5760405162461bcd60e51b815260040180806020018281038252603281526020018061054c6032913960400191505060405180910390fd5b610198610198565b6104ec816103a3565b6105275760405162461bcd60e51b815260040180806020018281038252603b8152602001806105b4603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a164736f6c634300060c000a", + "execute": { + "methodName": "initialize", + "args": [ + "0x99fa011e33a8c6196869dec7bc407e896ba67fe3", + "0x1bcbc96de2b4142404b9827f220545e3cee1f75a00560c3bdd29c9658103f7e2", + "Aave Token", + "AAVE", + "2" + ] + }, + "implementation": "0x9fe0eebe0b82bc629ba75aa6d69127602f53de86", + "devdoc": { + "details": "Extends from BaseAdminUpgradeabilityProxy with a constructor for initializing the implementation, admin, and init data.", + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "The address of the proxy admin." + } + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Only the current admin can call this function.", + "params": { + "newAdmin": "Address to transfer proxy administration to." + } + }, + "constructor": { + "params": { + "_admin": "Address of the proxy administrator.", + "_data": "Data to send as msg.data to the implementation to initialize the proxied contract. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.", + "_logic": "address of the initial implementation." + } + }, + "implementation()": { + "returns": { + "_0": "The address of the implementation." + } + }, + "upgradeTo(address)": { + "details": "Upgrade the backing implementation of the proxy. Only the admin can call this function.", + "params": { + "newImplementation": "Address of the new implementation." + } + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the backing implementation of the proxy and call a function on the new implementation. This is useful to initialize the proxied contract.", + "params": { + "data": "Data to send as msg.data in the low level call. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.", + "newImplementation": "Address of the new implementation." + } + } + }, + "title": "AdminUpgradeabilityProxy", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "constructor": "Contract constructor." + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/mainnet/opAAVEaggr_Implementation.json b/deployments/mainnet/opAAVEaggr_Implementation.json new file mode 100644 index 000000000..79acb56d4 --- /dev/null +++ b/deployments/mainnet/opAAVEaggr_Implementation.json @@ -0,0 +1,1303 @@ +{ + "address": "0x9fe0eebe0b82bc629ba75aa6d69127602f53de86", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "string", + "name": "_riskProfileName", + "type": "string" + }, + { + "internalType": "string", + "name": "_riskProfileSymbol", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bool", + "name": "emergencyShutdown", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogEmergencyShutdown", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "minimumDepositValueUT", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogMinimumDepositValueUT", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "totalValueLockedLimitUT", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogTotalValueLockedLimitUT", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bool", + "name": "unpaused", + "type": "bool" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogUnpause", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "userDepositCapUT", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "LogUserDepositCapUT", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes[]", + "name": "_codes", + "type": "bytes[]" + } + ], + "name": "adminCall", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "balanceUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "blockToBlockVaultValues", + "outputs": [ + { + "internalType": "uint256", + "name": "actualVaultValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockMinVaultValue", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "blockMaxVaultValue", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositUT", + "type": "uint256" + } + ], + "name": "calcDepositFeeUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userWithdrawUT", + "type": "uint256" + } + ], + "name": "calcWithdrawalFeeUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "_investStrategySteps", + "type": "tuple[]" + } + ], + "name": "computeInvestStrategyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getInvestStrategySteps", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "_investStrategySteps", + "type": "tuple[]" + } + ], + "name": "getLastStrategyStepBalanceLP", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNextBestInvestStrategy", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "internalType": "struct DataTypes.StrategyStep[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricePerFullShare", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "_underlyingTokensHash", + "type": "bytes32" + }, + { + "internalType": "string", + "name": "_name", + "type": "string" + }, + { + "internalType": "string", + "name": "_symbol", + "type": "string" + }, + { + "internalType": "uint256", + "name": "_riskProfileCode", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "investStrategyHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "investStrategySteps", + "outputs": [ + { + "internalType": "address", + "name": "pool", + "type": "address" + }, + { + "internalType": "address", + "name": "outputToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "isBorrow", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_diff", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_currentVaultValue", + "type": "uint256" + } + ], + "name": "isMaxVaultValueJumpAllowed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minimumDepositValueUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "opTOKEN_REVISION", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pendingDeposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "queue", + "outputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rebalance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "registryContract", + "outputs": [ + { + "internalType": "contract IRegistry", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_active", + "type": "bool" + } + ], + "name": "setEmergencyShutdown", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_minimumDepositValueUT", + "type": "uint256" + } + ], + "name": "setMinimumDepositValueUT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_registry", + "type": "address" + } + ], + "name": "setRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_riskProfileCode", + "type": "uint256" + } + ], + "name": "setRiskProfileCode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_totalValueLockedLimitUT", + "type": "uint256" + } + ], + "name": "setTotalValueLockedLimitUT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_underlyingTokensHash", + "type": "bytes32" + } + ], + "name": "setUnderlyingTokensHash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_unpaused", + "type": "bool" + } + ], + "name": "setUnpaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositCapUT", + "type": "uint256" + } + ], + "name": "setUserDepositCapUT", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositCapUT", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minimumDepositValueUT", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_totalValueLockedLimitUT", + "type": "uint256" + } + ], + "name": "setValueControlParams", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_vaultConfiguration", + "type": "uint256" + } + ], + "name": "setVaultConfiguration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_whitelistedAccountsRoot", + "type": "bytes32" + } + ], + "name": "setWhitelistedAccountsRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_whitelistedCodesRoot", + "type": "bytes32" + } + ], + "name": "setWhitelistedCodesRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "totalDeposits", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalValueLockedLimitUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "underlyingTokensHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "userDepositCapUT", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "bool", + "name": "_addUserDepositUT", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "_userDepositUTWithDeductions", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_deductions", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userDepositPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userDepositUT", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userDepositVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_user", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_userWithdrawVT", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userWithdrawPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_userWithdrawVT", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "_accountsProof", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "_codesProof", + "type": "bytes32[]" + } + ], + "name": "userWithdrawVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultConfiguration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultDepositAllToStrategy", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultDepositPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaultWithdrawPermitted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + }, + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistedAccountsRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "whitelistedCodesRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x98330cafa7b8e91d075700c8d9c8d19e94fafb8796872b82dbffa5b45d6fe066", + "receipt": { + "to": null, + "from": "0xd26ec7401c198adac340d3a4cb8b52b845f3a542", + "contractAddress": "0x9fe0eebe0b82bc629ba75aa6d69127602f53de86", + "transactionIndex": "0x70", + "gasUsed": "0x536330", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x49693d3dc37f65467494fa0e56a5aa74cce4cc343cbf681892fcd42375e448d1", + "transactionHash": "0x98330cafa7b8e91d075700c8d9c8d19e94fafb8796872b82dbffa5b45d6fe066", + "logs": [], + "blockNumber": "0xe48410", + "cumulativeGasUsed": "0xc6245f", + "status": "0x1" + }, + "args": ["0x99fa011e33a8c6196869dec7bc407e896ba67fe3", "Aave Token", "AAVE", "Aggressive", "aggr"], + "bytecode": "0x6080604052600080553480156200001557600080fd5b50604051620063973803806200639783398101604081905262000038916200020f565b8484836040516020016200004e92919062000327565b604051602081830303815290604052848360405160200162000072929190620002e3565b60408051601f19818403018152919052815162000097906037906020850190620000f2565b508051620000ad906038906020840190620000f2565b5050603980546001600160a01b0390931661010002610100600160a81b031960ff19909416601217939093169290921790915550506001603a5550620003a992505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200013557805160ff191683800117855562000165565b8280016001018555821562000165579182015b828111156200016557825182559160200191906001019062000148565b506200017392915062000177565b5090565b5b8082111562000173576000815560010162000178565b600082601f8301126200019f578081fd5b81516001600160401b0380821115620001b6578283fd5b604051601f8301601f191681016020018281118282101715620001d7578485fd5b604052828152925082848301602001861015620001f357600080fd5b6200020683602083016020880162000376565b50505092915050565b600080600080600060a0868803121562000227578081fd5b85516001600160a01b03811681146200023e578182fd5b60208701519095506001600160401b03808211156200025b578283fd5b6200026989838a016200018e565b955060408801519150808211156200027f578283fd5b6200028d89838a016200018e565b94506060880151915080821115620002a3578283fd5b620002b189838a016200018e565b93506080880151915080821115620002c7578283fd5b50620002d6888289016200018e565b9150509295509295909350565b60006106f760f41b825283516200030281600285016020880162000376565b8351908301906200031b81600284016020880162000376565b01600201949350505050565b600062037b8160ed1b825283516200034781600385016020880162000376565b600160fd1b60039184019182015283516200036a81600484016020880162000376565b01600401949350505050565b60005b838110156200039357818101518382015260200162000379565b83811115620003a3576000848401525b50505050565b615fde80620003b96000396000f3fe608060405234801561001057600080fd5b506004361061038e5760003560e01c806387a53e7a116101de578063b1ff85221161010f578063d5802ec2116100ad578063dd62ed3e1161007c578063dd62ed3e1461071d578063ddf0b00914610730578063e940325614610751578063eb3349b9146107645761038e565b8063d5802ec2146106dc578063d952ca50146106ef578063da7058e414610702578063db7e5632146107155761038e565b8063c66da8e8116100e9578063c66da8e8146106a6578063c9dd6b24146106ae578063cf85f080146106b6578063d07c179b146106c95761038e565b8063b1ff852214610678578063b318b82d1461068b578063b8332c49146106935761038e565b8063a37085841161017c578063a91ee0dc11610156578063a91ee0dc14610642578063a9b497c814610655578063ae78b1b01461065d578063b00fce2a146106655761038e565b8063a370858414610614578063a457c2d71461061c578063a9059cbb1461062f5761038e565b80638c0e0357116101b85780638c0e0357146105e95780638d1efd78146105f157806395d89b4114610604578063a30b72711461060c5761038e565b806387a53e7a146105b0578063890ddde8146105c35780638aa2e4b4146105d65761038e565b80632e40939c116102c35780636889d6731161026157806376e57d031161023057806376e57d031461058557806377c7b8fc146105985780637c8eb82a146105a05780637d7c2a1c146105a85761038e565b80636889d6731461052a5780636db5eeb21461053d57806370a082311461055f57806371679bcb146105725761038e565b806337d62e541161029d57806337d62e54146104e957806339509351146104fc5780633c870dcf1461050f57806357a194ab146105175761038e565b80632e40939c146104b95780632e935aa7146104c1578063313ce567146104d45761038e565b806318160ddd116103305780632495a5991161030a5780632495a5991461048157806328c1f99b1461049657806329dc06581461049e5780632a4d7943146104a65761038e565b806318160ddd1461044457806323b872dd1461044c57806323bb5fac1461045f5761038e565b806306fdde031161036c57806306fdde03146103e757806307134773146103fc578063095ea7b31461041157806314c64402146104315761038e565b806301dcad0f1461039357806303f2e589146103bd5780630537df97146103d2575b600080fd5b6103a66103a13660046151b4565b610777565b6040516103b49291906159ed565b60405180910390f35b6103c561089e565b6040516103b491906157b4565b6103da6108a4565b6040516103b49190615988565b6103ef6109be565b6040516103b49190615a08565b61040f61040a36600461555e565b610a54565b005b61042461041f366004615189565b610b18565b6040516103b491906159e2565b61040f61043f366004615526565b610b36565b6103c5610cf0565b61042461045a36600461502e565b610cf6565b61047261046d3660046156d1565b610d7e565b6040516103b493929190615e61565b610489610dbd565b6040516103b491906158ac565b610489610dcc565b6103c5610de0565b61040f6104b43660046152c8565b610de6565b6103a6610ec3565b61040f6104cf3660046156f2565b610f14565b6104dc610fea565b6040516103b49190615e77565b61040f6104f7366004615526565b610ff3565b61042461050a366004615189565b6111a8565b61040f6111f6565b61040f61052536600461555e565b6112c9565b61040f61053836600461555e565b611388565b61055061054b36600461555e565b611447565b6040516103b493929190615927565b6103c561056d366004614f70565b61148a565b61040f61058036600461565b565b6114a9565b61040f610593366004615105565b6116a9565b6103c5611950565b6103a6611993565b61040f6119fc565b61040f6105be36600461555e565b611d00565b6103c56105d13660046153ca565b611dbb565b61040f6105e436600461555e565b611ee2565b6103c5611fa1565b6103c56105ff36600461555e565b611fa7565b6103ef611fef565b6103c5612050565b6103da612055565b61042461062a366004615189565b6120e2565b61042461063d366004615189565b61214a565b61040f610650366004614f70565b61215e565b6103c561226a565b6103c5612270565b6103a661067336600461506e565b612276565b6103c56106863660046153ca565b61242e565b6103c5612456565b6104246106a13660046156d1565b61245c565b6103c561248a565b6103c561250b565b61040f6106c436600461555e565b612511565b61040f6106d736600461555e565b6125cc565b6103c56106ea36600461555e565b612719565b61040f6106fd36600461555e565b612757565b61040f61071036600461565b565b612816565b6103c5612b21565b6103c561072b366004614ff6565b612b27565b61074361073e36600461555e565b612b52565b6040516103b492919061596f565b6103c561075f366004614f70565b612b87565b6103c5610772366004614f70565b612b99565b60006060604254600160fa1b166000141580156107a357506107a161079b87612bab565b85612bdb565b155b156107ca5750506040805180820190915260018152600760fb1b6020820152600090610895565b6001600160a01b03861632148015906107eb57506107e9868585612bea565b155b156108125750506040805180820190915260018152603960f81b6020820152600090610895565b604254600160f91b166108425750506040805180820190915260028152610c4d60f21b6020820152600090610895565b60008511801561085a57506108568661148a565b8511155b6108805750506040805180820190915260018152603160f81b6020820152600090610895565b50506040805160208101909152600081526001905b94509492505050565b60445481565b6060603960019054906101000a90046001600160a01b03166001600160a01b031663d71f05e66040518163ffffffff1660e01b815260040160206040518083038186803b1580156108f457600080fd5b505afa158015610908573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092c9190614f8c565b6001600160a01b031663a64e1e7b60f0604254901c60ff166047546040518363ffffffff1660e01b81526004016109649291906157f7565b60006040518083038186803b15801561097c57600080fd5b505afa158015610990573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109b89190810190615459565b90505b90565b60378054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a4a5780601f10610a1f57610100808354040283529160200191610a4a565b820191906000526020600020905b815481529060010190602001808311610a2d57829003601f168201915b5050505050905090565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610aa257600080fd5b505afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada9190614f8c565b6001600160a01b0316336001600160a01b031614610b135760405162461bcd60e51b8152600401610b0a90615a1b565b60405180910390fd5b604455565b6000610b2c610b25612c27565b8484612c2b565b5060015b92915050565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b8457600080fd5b505afa158015610b98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbc9190614f8c565b6001600160a01b0316336001600160a01b031614610bec5760405162461bcd60e51b8152600401610b0a90615a1b565b60428054600160ff60f81b031690558015610cb65760428054600160f81b179055603f5415610cb657610ca36048805480602002602001604051908101604052809291908181526020016000905b82821015610c9a576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101610c3a565b50505050612cdf565b6000603f819055610cb690604890614c38565b6042546040513391600160f81b161515907f3f14e04c219cb203de89f60db463113cc68cf16c00a46ef96a1fce6ca8abb5bb90600090a350565b60365490565b6000610d03848484612cf1565b610d7384610d0f612c27565b610d6e85604051806060016040528060288152602001615f85602891396001600160a01b038a16600090815260356020526040812090610d4d612c27565b6001600160a01b031681526020810191909152604001600020549190612e06565b612c2b565b5060015b9392505050565b603e6020528160005260406000208181548110610d9757fe5b600091825260209091206003909102018054600182015460029092015490935090915083565b6043546001600160a01b031681565b60395461010090046001600160a01b031681565b60455481565b603960019054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b158015610e3457600080fd5b505afa158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190614f8c565b6001600160a01b0316336001600160a01b031614610e9c5760405162461bcd60e51b8152600401610b0a90615b45565b610ec08160405180604001604052806002815260200161313560f01b815250612e32565b50565b60006060604254600160f91b1660001415610efb5750506040805180820190915260028152610c4d60f21b6020820152600090610f10565b50506040805160208101909152600081526001905b9091565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6257600080fd5b505afa158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a9190614f8c565b6001600160a01b0316336001600160a01b031614610fca5760405162461bcd60e51b8152600401610b0a90615bf4565b610fd383612e63565b610fdc82612e96565b610fe581612ecb565b505050565b60395460ff1690565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561104157600080fd5b505afa158015611055573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110799190614f8c565b6001600160a01b0316336001600160a01b0316146110a95760405162461bcd60e51b8152600401610b0a90615a1b565b604280546001607f60f91b031690558061116157603f541561115c5761114960488054806020026020016040519081016040528092919081815260200160009082821015610c9a576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101610c3a565b6000603f81905561115c90604890614c38565b61116e565b60428054600160f91b1790555b6042546040513391600160f91b161515907fbef546d8099130f7f80a42b7eb7f2aa81c1dd73f07fc569fe30338e102bba27390600090a350565b6000610b2c6111b5612c27565b84610d6e85603560006111c6612c27565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612f00565b60006060611202611993565b915091508181906112265760405162461bcd60e51b8152600401610b0a9190615a08565b50603f54156112c5576112c56048805480602002602001604051908101604052809291908181526020016000905b828210156112b4576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101611254565b505050506112c061248a565b612f25565b5050565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b15801561131757600080fd5b505afa15801561132b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134f9190614f8c565b6001600160a01b0316336001600160a01b03161461137f5760405162461bcd60e51b8152600401610b0a90615bf4565b610ec081612e63565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b1580156113d657600080fd5b505afa1580156113ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140e9190614f8c565b6001600160a01b0316336001600160a01b03161461143e5760405162461bcd60e51b8152600401610b0a90615bf4565b610ec081612e96565b6048818154811061145457fe5b6000918252602090912060029091020180546001909101546001600160a01b03918216925090811690600160a01b900460ff1683565b6001600160a01b0381166000908152603460205260409020545b919050565b6002603a5414156114cc5760405162461bcd60e51b8152600401610b0a90615df3565b6002603a55600060606114dd611993565b915091508181906115015760405162461bcd60e51b8152600401610b0a9190615a08565b50505061151461150f612fd2565b613099565b600061151e6132e9565b9050600061152a61248a565b604354909150611545906001600160a01b031633308a6132fe565b600061154f61248a565b9050600061155d8284613356565b9050600061156a82612719565b905060006115788383613356565b90506115fd33600083858e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508d8d8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061337e92505050565b336000908152603d60205260409020546116179082612f00565b336000908152603d6020526040902055811561164c5760425460435461164c916001600160a01b039091169060501c846133bf565b85158061165e575061165c610cf0565b155b156116725761166d33826133de565b611697565b611697336116928861168c611685610cf0565b869061349e565b906134d8565b6133de565b50506001603a55505050505050505050565b60006116b361350a565b60015490915060ff16806116ca57506116ca61350f565b806116d6575060005481115b6116f25760405162461bcd60e51b8152600401610b0a90615c35565b60015460ff16158015611711576001805460ff19168117905560008290555b6000855111604051806040016040528060018152602001600d60fa1b8152509061174e5760405162461bcd60e51b8152600401610b0a9190615a08565b506000845111604051806040016040528060018152602001600d60fa1b8152509061178c5760405162461bcd60e51b8152600401610b0a9190615a08565b5060398054610100600160a81b0319166101006001600160a01b038a16021790556117b5614c59565b603954604051639ec39e2f60e01b81526101009091046001600160a01b031690639ec39e2f906117e99087906004016157b4565b60006040518083038186803b15801561180157600080fd5b505afa158015611815573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261183d9190810190615576565b905061184d848260600151613515565b61185687613566565b611884868260800151604051602001611870929190615861565b604051602081830303815290604052613756565b6118b2858260a0015160405160200161189e929190615821565b604051602081830303815290604052613769565b6043546040805163313ce56760e01b81529051611935926001600160a01b03169163313ce567916004808301926020929190829003018186803b1580156118f857600080fd5b505afa15801561190c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611930919061571d565b61377c565b508015611947576001805460ff191690555b50505050505050565b600061195a610cf0565b1561198b5761198461196a610cf0565b61168c670de0b6b3a764000061197e6132e9565b9061349e565b90506109bb565b5060006109bb565b60006060604254600160f91b16600014156119cb5750506040805180820190915260028152610c4d60f21b6020820152600090610f10565b604254600160f81b1615610efb575050604080518082019091526002815261313360f01b6020820152600090610f10565b60006060611a08611993565b91509150818190611a2c5760405162461bcd60e51b8152600401610b0a9190615a08565b5060006060611a39610ec3565b91509150818190611a5d5760405162461bcd60e51b8152600401610b0a9190615a08565b50611a6e611a696108a4565b613792565b6000611afe6049805480602002602001604051908101604052809291908181526020016000905b82821015611af5576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101611a95565b50505050611dbb565b9050603f548114611c4657603f5415611b9557611b9560488054806020026020016040519081016040528092919081815260200160009082821015610c9a576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101610c3a565b611ba160486000614c38565b60005b604954811015611c3f57604860498281548110611bbd57fe5b6000918252602080832084546001818101875595855291909320600292830290930180549190920290920180546001600160a01b03199081166001600160a01b03948516178255918401805491850180549093169190931617808255915460ff600160a01b918290041615150260ff60a01b1990921691909117905501611ba4565b50603f8190555b6000611c5061248a565b603f5490915015801590611c645750600081115b15611cf857611cf86048805480602002602001604051908101604052809291908181526020016000905b82821015611cee576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101611c8e565b5050505082612f25565b505050505050565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d4e57600080fd5b505afa158015611d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d869190614f8c565b6001600160a01b0316336001600160a01b031614611db65760405162461bcd60e51b8152600401610b0a90615a1b565b604655565b805160009015611eda57606082516001600160401b0381118015611dde57600080fd5b50604051908082528060200260200182016040528015611e08578160200160208202803683370190505b50905060005b8351811015611ea657838181518110611e2357fe5b602002602001015160000151848281518110611e3b57fe5b602002602001015160200151858381518110611e5357fe5b602002602001015160400151604051602001611e7193929190615781565b60405160208183030381529060405280519060200120828281518110611e9357fe5b6020908102919091010152600101611e0e565b5060475481604051602001611ebc9291906157bd565b604051602081830303815290604052805190602001209150506114a4565b506000919050565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3057600080fd5b505afa158015611f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f689190614f8c565b6001600160a01b0316336001600160a01b031614611f985760405162461bcd60e51b8152600401610b0a90615bf4565b610ec081612ecb565b60405481565b6000610b30611fb4610fea565b60ff16600a0a6020604254901c61ffff1602611fe961271061168c6030604254901c61ffff168761349e90919063ffffffff16565b90612f00565b60388054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a4a5780601f10610a1f57610100808354040283529160200191610a4a565b600381565b60606048805480602002602001604051908101604052809291908181526020016000905b828210156120d9576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101612079565b50505050905090565b6000610b2c6120ef612c27565b84610d6e85604051806060016040528060258152602001615fad6025913960356000612119612c27565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612e06565b6000610b2c612157612c27565b8484612cf1565b603960019054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b1580156121ac57600080fd5b505afa1580156121c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e49190614f8c565b6001600160a01b0316336001600160a01b0316146122145760405162461bcd60e51b8152600401610b0a90615b45565b612226816001600160a01b031661382c565b6122425760405162461bcd60e51b8152600401610b0a90615d09565b603980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b603f5481565b60415481565b60006060604254600160fa1b1660001415801561229c575061229a61079b89612bab565b155b156122c35750506040805180820190915260018152600760fb1b6020820152600090612423565b6001600160a01b03881632148015906122e457506122e2888585612bea565b155b1561230b5750506040805180820190915260018152603960f81b6020820152600090612423565b604154861015612338575050604080518082019091526002815261031360f41b6020820152600090612423565b60006123426132e9565b90508715801561235c575060455461235a8288613356565b115b15612385575050604080518082019091526002815261313160f01b602082015260009150612423565b6045546123928289612f00565b11156123bc575050604080518082019091526002815261313160f01b602082015260009150612423565b604080546001600160a01b038b166000908152603d60205291909120546123e39089612f00565b111561240d575050604080518082019091526002815261189960f11b602082015260009150612423565b5050604080516020810190915260008152600191505b965096945050505050565b603954604354600091610b309184916001600160a01b03610100909104811691309116613832565b60465481565b60006040604254901c61ffff166124828361168c6127108761349e90919063ffffffff16565b109392505050565b6043546040516370a0823160e01b81526000916001600160a01b0316906370a08231906124bb9030906004016158ac565b60206040518083038186803b1580156124d357600080fd5b505afa1580156124e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b89190615643565b60475481565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561255f57600080fd5b505afa158015612573573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125979190614f8c565b6001600160a01b0316336001600160a01b0316146125c75760405162461bcd60e51b8152600401610b0a90615a1b565b604255565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561261a57600080fd5b505afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190614f8c565b6001600160a01b0316336001600160a01b0316146126825760405162461bcd60e51b8152600401610b0a90615a1b565b603954604051639ec39e2f60e01b8152610ec09183916101009091046001600160a01b031690639ec39e2f906126bc9084906004016157b4565b60006040518083038186803b1580156126d457600080fd5b505afa1580156126e8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127109190810190615576565b60600151613515565b6000610b30612726610fea565b60ff16600a0a60425461ffff1602611fe961271061168c6010604254901c61ffff168761349e90919063ffffffff16565b603960019054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190614f8c565b6001600160a01b0316336001600160a01b03161461280d5760405162461bcd60e51b8152600401610b0a90615b45565b610ec081613566565b6002603a5414156128395760405162461bcd60e51b8152600401610b0a90615df3565b6002603a556000606061284a610ec3565b9150915081819061286e5760405162461bcd60e51b8152600401610b0a9190615a08565b50505061287c61150f612fd2565b6128eb338686868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250613a8b92505050565b600061290a6128f8610cf0565b61168c6129036132e9565b899061349e565b90506129163387613abf565b600061292061248a565b905081811015612abf5760006129368383613356565b60395460435460488054604080516020808402820181019092528281529596506000956129f0956001600160a01b03610100909104811695169388939192909190889084015b828210156129dc576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff16151591830191909152908352909201910161297c565b50505050613b95909392919063ffffffff16565b9050612a816048805480602002602001604051908101604052809291908181526020016000905b82821015612a77576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101612a17565b5050505082613d0d565b6000612a8b61248a565b90506000612a998286613356565b905083811015612aba57612ab7612ab08583613356565b8790613356565b95505b505050505b6000612aca83611fa7565b90508015612af157604254604354612af1916001600160a01b039091169060501c836133bf565b612b1233612aff8584613356565b6043546001600160a01b031691906133bf565b50506001603a55505050505050565b60425481565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b603b8181548110612b5f57fe5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b603d6020526000908152604090205481565b603c6020526000908152604090205481565b600081604051602001612bbe9190615764565b604051602081830303815290604052805190602001209050919050565b6000610d778260445485613d9a565b6000612bfe612bf885612bab565b84612bdb565b8015612c1f5750612c1f612c19612c1486613e37565b613e3b565b83613e4e565b949350505050565b3390565b6001600160a01b038316612c515760405162461bcd60e51b8152600401610b0a90615d2e565b6001600160a01b038216612c775760405162461bcd60e51b8152600401610b0a90615a95565b6001600160a01b0380841660008181526035602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612cd29085906157b4565b60405180910390a3505050565b610ec081612cec8361242e565b613d0d565b6001600160a01b038316612d175760405162461bcd60e51b8152600401610b0a90615cc4565b6001600160a01b038216612d3d5760405162461bcd60e51b8152600401610b0a90615a52565b612d48838383613e5d565b612d8581604051806060016040528060268152602001615f5f602691396001600160a01b0386166000908152603460205260409020549190612e06565b6001600160a01b038085166000908152603460205260408082209390935590841681522054612db49082612f00565b6001600160a01b0380841660008181526034602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612cd29085906157b4565b60008184841115612e2a5760405162461bcd60e51b8152600401610b0a9190615a08565b505050900390565b60005b8251811015610fe557612e5b838281518110612e4d57fe5b602002602001015183613ea0565b600101612e35565b604081815551339082907f70c87424f133fbd8c8e63b0dc9c2d2702db0a79d7d4139b25a5035f250b9f73890600090a350565b6041819055604051339082907f7af95a1df120276e178a852832ba64d58429b2b5986955c772448d80c08ef39290600090a350565b6045819055604051339082907fae4cf6e16f407af30e4a8e158871dd4eb7d4ad22f2438ccc43c5855fcd6ebbee90600090a350565b600082820183811015610d775760405162461bcd60e51b8152600401610b0a90615ad7565b603954600090612f4490849061010090046001600160a01b0316613f3c565b905060005b81811015612fcc576040805160c0810182526039546001600160a01b03610100909104811682523060208301526043541691810191909152606081018490526080810182905260a08101839052612fc490612fa590869061406e565b604051806040016040528060018152602001601960f91b815250612e32565b600101612f49565b50505050565b603f54600090612fe35760006109b8565b60395460435460488054604080516020808402820181019092528281526109b8956001600160a01b036101009091048116953095911693919290919060009084015b82821015613085576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101613025565b50505050614455909392919063ffffffff16565b436000908152603e6020526040902054801561329357436000818152603e6020818152604080842081516060810190925287825294909352908152825490820190839060001986019081106130ea57fe5b906000526020600020906003020160010154851061313857436000908152603e602052604090208054600019860190811061312157fe5b90600052602060002090600302016001015461313a565b845b8152602001603e6000438152602001908152602001600020600185038154811061316057fe5b90600052602060002090600302016002015485116131ae57436000908152603e602052604090208054600019860190811061319757fe5b9060005260206000209060030201600201546131b0565b845b90528154600181810184556000938452602080852084516003909402019283558084015191830191909155604092830151600290920191909155438352603e9052902080546132549161324e918490811061320757fe5b906000526020600020906003020160010154603e6000438152602001908152602001600020848154811061323757fe5b90600052602060002090600302016002015461476b565b8361245c565b60405180604001604052806002815260200161189b60f11b8152509061328d5760405162461bcd60e51b8152600401610b0a9190615a08565b506112c5565b436000908152603e60209081526040808320815160608101835286815280840187815292810187815282546001818101855593875294909520905160039094020192835590519082015590516002909101555050565b60006109b86132f661248a565b611fe9612fd2565b612fcc846323b872dd60e01b85858560405160240161331f9392919061594b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261478d565b6000828211156133785760405162461bcd60e51b8152600401610b0a90615b0e565b50900390565b60006060613390888888888888612276565b915091508181906133b45760405162461bcd60e51b8152600401610b0a9190615a08565b505050505050505050565b610fe58363a9059cbb60e01b848460405160240161331f92919061596f565b6001600160a01b0382166134045760405162461bcd60e51b8152600401610b0a90615e2a565b61341060008383613e5d565b60365461341d9082612f00565b6036556001600160a01b0382166000908152603460205260409020546134439082612f00565b6001600160a01b0383166000818152603460205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906134929085906157b4565b60405180910390a35050565b6000826134ad57506000610b30565b828202828482816134ba57fe5b0414610d775760405162461bcd60e51b8152600401610b0a90615bb3565b60008082116134f95760405162461bcd60e51b8152600401610b0a90615b7c565b81838161350257fe5b049392505050565b600390565b303b1590565b6040805180820190915260018152603560f81b60208201528161354b5760405162461bcd60e51b8152600401610b0a9190615a08565b5060425460ff60f01b191660f083901b176042819055505050565b603954604051638346525f60e01b815260609161010090046001600160a01b031690638346525f9061359c9085906004016157b4565b60006040518083038186803b1580156135b457600080fd5b505afa1580156135c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135f09190810190615230565b9050805160011460405180604001604052806002815260200161313760f01b815250906136305760405162461bcd60e51b8152600401610b0a9190615a08565b50603960019054906101000a90046001600160a01b03166001600160a01b0316632d5ad3d58260008151811061366257fe5b60200260200101516040518263ffffffff1660e01b815260040161368691906158ac565b60206040518083038186803b15801561369e57600080fd5b505afa1580156136b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d69190615542565b60405180604001604052806002815260200161313960f01b8152509061370f5760405162461bcd60e51b8152600401610b0a9190615a08565b50816047819055508060008151811061372457fe5b6020026020010151604360006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b80516112c5906037906020840190614c91565b80516112c5906038906020840190614c91565b6039805460ff191660ff92909216919091179055565b61379e60496000614c38565b60005b81518110156112c55760498282815181106137b857fe5b602090810291909101810151825460018082018555600094855293839020825160029092020180546001600160a01b03199081166001600160a01b039384161782559383015190850180546040909401519390941691161760ff60a01b1916600160a01b91151591909102179055016137a1565b3b151590565b83516000908186600019830183811061384757fe5b60200260200101516000015190506000866001600160a01b031663923bb7ff836040518263ffffffff1660e01b815260040161388391906158ac565b60206040518083038186803b15801561389b57600080fd5b505afa1580156138af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d39190614f8c565b905060018311156138fc578760028403815181106138ed57fe5b60200260200101516020015194505b6040516336d8bf9360e01b81526001600160a01b038216906336d8bf93906139289085906004016158ac565b60206040518083038186803b15801561394057600080fd5b505afa158015613954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139789190615542565b613a01576040516390e6160560e01b81526001600160a01b038216906390e61605906139ac908990899087906004016158da565b60206040518083038186803b1580156139c457600080fd5b505afa1580156139d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139fc9190615643565b613a7f565b60405163afd908d960e01b81526001600160a01b0382169063afd908d990613a2f90899086906004016158c0565b60206040518083038186803b158015613a4757600080fd5b505afa158015613a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a7f9190615643565b98975050505050505050565b60006060613a9b86868686610777565b915091508181906119475760405162461bcd60e51b8152600401610b0a9190615a08565b6001600160a01b038216613ae55760405162461bcd60e51b8152600401610b0a90615c83565b613af182600083613e5d565b613b2e81604051806060016040528060228152602001615f3d602291396001600160a01b0385166000908152603460205260409020549190612e06565b6001600160a01b038316600090815260346020526040902055603654613b549082613356565b6036556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906134929085906157b4565b8351600090815b81811015613d03576000878281518110613bb257fe5b60200260200101516000015190506000876001600160a01b031663923bb7ff836040518263ffffffff1660e01b8152600401613bee91906158ac565b60206040518083038186803b158015613c0657600080fd5b505afa158015613c1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c3e9190614f8c565b9050868315613c6557896001850381518110613c5657fe5b60200260200101516020015190505b6001600160a01b0382166385541e4482858715613c825789613c84565b8a5b6040518463ffffffff1660e01b8152600401613ca29392919061594b565b60206040518083038186803b158015613cba57600080fd5b505afa158015613cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf29190615643565b95505060019092019150613b9c9050565b5050949350505050565b815160005b81811015612fcc576040805160c0810182526039546001600160a01b036101009091048116825230602083015260435416918101919091526060810184905281830360001901608082015260a08101839052613d9290613d7390869061481c565b604051806040016040528060018152602001603360f81b815250612e32565b600101613d12565b600081815b8551811015613e2c576000868281518110613db657fe5b60200260200101519050808311613df7578281604051602001613dda9291906157f7565b604051602081830303815290604052805190602001209250613e23565b8083604051602001613e0a9291906157f7565b6040516020818303038152906040528051906020012092505b50600101613d9f565b509092149392505050565b3f90565b600081604051602001612bbe91906157b4565b6000610d778260465485613d9a565b604080518082019091526002815261062760f31b60208201526001600160a01b038316301415612fcc5760405162461bcd60e51b8152600401610b0a9190615a08565b6000606083806020019051810190613eb89190614fa8565b915091506000826001600160a01b031682604051613ed69190615805565b6000604051808303816000865af19150503d8060008114613f13576040519150601f19603f3d011682016040523d82523d6000602084013e613f18565b606091505b50509050808490611cf85760405162461bcd60e51b8152600401610b0a9190615a08565b815160009081846000198301838110613f5157fe5b6020026020010151600001519050836001600160a01b031663923bb7ff826040518263ffffffff1660e01b8152600401613f8b91906158ac565b60206040518083038186803b158015613fa357600080fd5b505afa158015613fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fdb9190614f8c565b6001600160a01b03166336d8bf93826040518263ffffffff1660e01b815260040161400691906158ac565b60206040518083038186803b15801561401e57600080fd5b505afa158015614032573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140569190615542565b1561406657506001019050610b30565b509392505050565b80516040820151606083810151855160808601519294939281141561426c576000876001886080015103815181106140a257fe5b60200260200101516000015190506000856001600160a01b031663923bb7ff836040518263ffffffff1660e01b81526004016140de91906158ac565b60206040518083038186803b1580156140f657600080fd5b505afa15801561410a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061412e9190614f8c565b90508860018960800151038151811061414357fe5b602002602001015160200151945087604001516001600160a01b03166370a0823189602001516040518263ffffffff1660e01b815260040161418591906158ac565b60206040518083038186803b15801561419d57600080fd5b505afa1580156141b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d59190615643565b9350806001600160a01b03166374df3b2f89602001518a60400151856040518463ffffffff1660e01b815260040161420f939291906158da565b60006040518083038186803b15801561422757600080fd5b505afa15801561423b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526142639190810190615350565b9650505061444b565b60008787608001518151811061427e57fe5b60200260200101516000015190506000856001600160a01b031663923bb7ff836040518263ffffffff1660e01b81526004016142ba91906158ac565b60206040518083038186803b1580156142d257600080fd5b505afa1580156142e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061430a9190614f8c565b905087608001516000146143bc578860018960800151038151811061432b57fe5b6020026020010151602001519450846001600160a01b03166370a0823189602001516040518263ffffffff1660e01b815260040161436991906158ac565b60206040518083038186803b15801561438157600080fd5b505afa158015614395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143b99190615643565b93505b6020880151604051636fc9ab9160e11b81526001600160a01b0383169163df935722916143f29190899087908a906004016158fd565b60006040518083038186803b15801561440a57600080fd5b505afa15801561441e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526144469190810190615350565b965050505b5050505092915050565b835160009081805b828110156147605760008160018503039050600089828151811061447d57fe5b60200260200101516000015190506000896001600160a01b031663923bb7ff836040518263ffffffff1660e01b81526004016144b991906158ac565b60206040518083038186803b1580156144d157600080fd5b505afa1580156144e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145099190614f8c565b9050878315614530578b600185038151811061452157fe5b60200260200101516020015190505b600187038414156146ca576040516336d8bf9360e01b81526001600160a01b038316906336d8bf93906145679086906004016158ac565b60206040518083038186803b15801561457f57600080fd5b505afa158015614593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b79190615542565b1561464357604051632627a09960e01b81526001600160a01b03831690632627a099906145ec908d90859088906004016158da565b60206040518083038186803b15801561460457600080fd5b505afa158015614618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463c9190615643565b97506146c5565b60405162c9babf60e71b81526001600160a01b038316906364dd5f8090614672908d90859088906004016158da565b60206040518083038186803b15801561468a57600080fd5b505afa15801561469e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146c29190615643565b97505b61474d565b60405163ee665bed60e01b81526001600160a01b0383169063ee665bed906146fa90849087908b9060040161594b565b60206040518083038186803b15801561471257600080fd5b505afa158015614726573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061474a9190615643565b97505b50869450506001909201915061445d9050565b505050949350505050565b60008183116147835761477e8284613356565b610d77565b610d778383613356565b60606147e2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b559092919063ffffffff16565b805190915015610fe557808060200190518101906148009190615542565b610fe55760405162461bcd60e51b8152600401610b0a90615da9565b606060008383608001518151811061483057fe5b602090810291909101015151835160405163923bb7ff60e01b8152919250906000906001600160a01b0383169063923bb7ff906148719086906004016158ac565b60206040518083038186803b15801561488957600080fd5b505afa15801561489d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148c19190614f8c565b6040860151606087015160808801519293509091156148fc57876001886080015103815181106148ed57fe5b60200260200101516020015191505b60018760a00151038760800151146149ac578787608001518151811061491e57fe5b6020026020010151602001516001600160a01b03166370a0823188602001516040518263ffffffff1660e01b815260040161495991906158ac565b60206040518083038186803b15801561497157600080fd5b505afa158015614985573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149a99190615643565b90505b60018760a00151038760800151148015614a3d57506040516336d8bf9360e01b81526001600160a01b038416906336d8bf93906149ed9088906004016158ac565b60206040518083038186803b158015614a0557600080fd5b505afa158015614a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a3d9190615542565b614acb576020870151604051636092577960e01b81526001600160a01b03851691636092577991614a77919086908a9087906004016158fd565b60006040518083038186803b158015614a8f57600080fd5b505afa158015614aa3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139fc9190810190615350565b6020870151604051631496678160e11b81526001600160a01b0385169163292ccf0291614b01919086908a9087906004016158fd565b60006040518083038186803b158015614b1957600080fd5b505afa158015614b2d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a7f9190810190615350565b6060612c1f848460008585614b698561382c565b614b855760405162461bcd60e51b8152600401610b0a90615d72565b60006060866001600160a01b03168587604051614ba29190615805565b60006040518083038185875af1925050503d8060008114614bdf576040519150601f19603f3d011682016040523d82523d6000602084013e614be4565b606091505b5091509150614bf4828286614bff565b979650505050505050565b60608315614c0e575081610d77565b825115614c1e5782518084602001fd5b8160405162461bcd60e51b8152600401610b0a9190615a08565b5080546000825560020290600052602060002090810190610ec09190614d0f565b6040805160c08101825260008082526020820152908101614c78614d40565b8152600060208201526060604082018190529081015290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614cd257805160ff1916838001178555614cff565b82800160010185558215614cff579182015b82811115614cff578251825591602001919060010190614ce4565b50614d0b929150614d57565b5090565b5b80821115614d0b5780546001600160a01b03191681556001810180546001600160a81b0319169055600201614d10565b604080518082019091526000808252602082015290565b5b80821115614d0b5760008155600101614d58565b60008083601f840112614d7d578182fd5b5081356001600160401b03811115614d93578182fd5b6020830191508360208083028501011115614dad57600080fd5b9250929050565b600082601f830112614dc4578081fd5b8135614dd7614dd282615eab565b615e85565b818152915060208083019084810181840286018201871015614df857600080fd5b60005b84811015614e1757813584529282019290820190600101614dfb565b505050505092915050565b8051610b3081615f2e565b600082601f830112614e3d578081fd5b8135614e4b614dd282615eca565b9150808252836020828501011115614e6257600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112614e8b578081fd5b8151614e99614dd282615eca565b9150808252836020828501011115614eb057600080fd5b614ec1816020840160208601615eed565b5092915050565b600060408284031215614ed9578081fd5b614ee36040615e85565b9050614eef8383614f5f565b8152614efe8360208401614f5f565b602082015292915050565b600060608284031215614f1a578081fd5b614f246060615e85565b90508135614f3181615f19565b81526020820135614f4181615f19565b60208201526040820135614f5481615f2e565b604082015292915050565b805160ff81168114610b3057600080fd5b600060208284031215614f81578081fd5b8135610d7781615f19565b600060208284031215614f9d578081fd5b8151610d7781615f19565b60008060408385031215614fba578081fd5b8251614fc581615f19565b60208401519092506001600160401b03811115614fe0578182fd5b614fec85828601614e7b565b9150509250929050565b60008060408385031215615008578182fd5b823561501381615f19565b9150602083013561502381615f19565b809150509250929050565b600080600060608486031215615042578081fd5b833561504d81615f19565b9250602084013561505d81615f19565b929592945050506040919091013590565b60008060008060008060c08789031215615086578384fd5b863561509181615f19565b955060208701356150a181615f2e565b9450604087013593506060870135925060808701356001600160401b03808211156150ca578384fd5b6150d68a838b01614db4565b935060a08901359150808211156150eb578283fd5b506150f889828a01614db4565b9150509295509295509295565b600080600080600060a0868803121561511c578283fd5b853561512781615f19565b94506020860135935060408601356001600160401b0380821115615149578485fd5b61515589838a01614e2d565b9450606088013591508082111561516a578283fd5b5061517788828901614e2d565b95989497509295608001359392505050565b6000806040838503121561519b578182fd5b82356151a681615f19565b946020939093013593505050565b600080600080608085870312156151c9578182fd5b84356151d481615f19565b93506020850135925060408501356001600160401b03808211156151f6578384fd5b61520288838901614db4565b93506060870135915080821115615217578283fd5b5061522487828801614db4565b91505092959194509250565b60006020808385031215615242578182fd5b82516001600160401b03811115615257578283fd5b8301601f81018513615267578283fd5b8051615275614dd282615eab565b8181528381019083850185840285018601891015615291578687fd5b8694505b838510156152bc5780516152a881615f19565b835260019490940193918501918501615295565b50979650505050505050565b600060208083850312156152da578182fd5b82356001600160401b038111156152ef578283fd5b8301601f810185136152ff578283fd5b803561530d614dd282615eab565b81815283810190838501865b84811015615342576153308a888435890101614e2d565b84529286019290860190600101615319565b509098975050505050505050565b60006020808385031215615362578182fd5b82516001600160401b03811115615377578283fd5b8301601f81018513615387578283fd5b8051615395614dd282615eab565b81815283810190838501865b84811015615342576153b88a888451890101614e7b565b845292860192908601906001016153a1565b600060208083850312156153dc578182fd5b82356001600160401b038111156153f1578283fd5b8301601f81018513615401578283fd5b803561540f614dd282615eab565b818152838101908385016060808502860187018a101561542d578788fd5b8795505b84861015615342576154438a83614f09565b8452600195909501949286019290810190615431565b6000602080838503121561546b578182fd5b82516001600160401b03811115615480578283fd5b8301601f81018513615490578283fd5b805161549e614dd282615eab565b818152838101908385016060808502860187018a10156154bc578788fd5b8795505b848610156153425780828b0312156154d6578788fd5b6154df81615e85565b82516154ea81615f19565b8152828801516154f981615f19565b8189015260408381015161550c81615f2e565b9082015284526001959095019492860192908101906154c0565b600060208284031215615537578081fd5b8135610d7781615f2e565b600060208284031215615553578081fd5b8151610d7781615f2e565b60006020828403121561556f578081fd5b5035919050565b600060208284031215615587578081fd5b81516001600160401b038082111561559d578283fd5b9083019060e082860312156155b0578283fd5b6155ba60c0615e85565b825181526155cb8660208501614e22565b60208201526155dd8660408501614ec8565b60408201526155ef8660808501614e22565b606082015260a083015182811115615605578485fd5b61561187828601614e7b565b60808301525060c083015182811115615628578485fd5b61563487828601614e7b565b60a08301525095945050505050565b600060208284031215615654578081fd5b5051919050565b600080600080600060608688031215615672578283fd5b8535945060208601356001600160401b038082111561568f578485fd5b61569b89838a01614d6c565b909650945060408801359150808211156156b3578283fd5b506156c088828901614d6c565b969995985093965092949392505050565b600080604083850312156156e3578182fd5b50508035926020909101359150565b600080600060608486031215615706578081fd5b505081359360208301359350604090920135919050565b60006020828403121561572e578081fd5b610d778383614f5f565b60008151808452615750816020860160208601615eed565b601f01601f19169290920160200192915050565b60609190911b6bffffffffffffffffffffffff1916815260140190565b6bffffffffffffffffffffffff19606094851b811682529290931b9091166014830152151560f81b602882015260290190565b90815260200190565b600083825260208083018451828601845b828110156157ea578151845292840192908401906001016157ce565b5091979650505050505050565b918252602082015260400190565b60008251615817818460208701615eed565b9190910192915050565b60006106f760f41b8252835161583e816002850160208801615eed565b835190830190615855816002840160208801615eed565b01600201949350505050565b600062037b8160ed1b8252835161587f816003850160208801615eed565b600160fd1b60039184019182015283516158a0816004840160208801615eed565b01600401949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000919060409081850190868401855b828110156157ea57815180516001600160a01b039081168652878201511687860152850151151585850152606090930192908501906001016159a5565b901515815260200190565b6000831515825260406020830152612c1f6040830184615738565b600060208252610d776020830184615738565b6020808252601f908201527f63616c6c6572206973206e6f7420686176696e6720676f7665726e616e636500604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252601a908201527f63616c6c6572206973206e6f7420746865206f70657261746f72000000000000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f63616c6c6572206973206e6f74207468652066696e616e63654f70657261746f6040820152603960f91b606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600b908201526a085a5cd0dbdb9d1c9858dd60aa1b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b9283526020830191909152604082015260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ea357600080fd5b604052919050565b60006001600160401b03821115615ec0578081fd5b5060209081020190565b60006001600160401b03821115615edf578081fd5b50601f01601f191660200190565b60005b83811015615f08578181015183820152602001615ef0565b83811115612fcc5750506000910152565b6001600160a01b0381168114610ec057600080fd5b8015158114610ec057600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa164736f6c634300060c000a", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061038e5760003560e01c806387a53e7a116101de578063b1ff85221161010f578063d5802ec2116100ad578063dd62ed3e1161007c578063dd62ed3e1461071d578063ddf0b00914610730578063e940325614610751578063eb3349b9146107645761038e565b8063d5802ec2146106dc578063d952ca50146106ef578063da7058e414610702578063db7e5632146107155761038e565b8063c66da8e8116100e9578063c66da8e8146106a6578063c9dd6b24146106ae578063cf85f080146106b6578063d07c179b146106c95761038e565b8063b1ff852214610678578063b318b82d1461068b578063b8332c49146106935761038e565b8063a37085841161017c578063a91ee0dc11610156578063a91ee0dc14610642578063a9b497c814610655578063ae78b1b01461065d578063b00fce2a146106655761038e565b8063a370858414610614578063a457c2d71461061c578063a9059cbb1461062f5761038e565b80638c0e0357116101b85780638c0e0357146105e95780638d1efd78146105f157806395d89b4114610604578063a30b72711461060c5761038e565b806387a53e7a146105b0578063890ddde8146105c35780638aa2e4b4146105d65761038e565b80632e40939c116102c35780636889d6731161026157806376e57d031161023057806376e57d031461058557806377c7b8fc146105985780637c8eb82a146105a05780637d7c2a1c146105a85761038e565b80636889d6731461052a5780636db5eeb21461053d57806370a082311461055f57806371679bcb146105725761038e565b806337d62e541161029d57806337d62e54146104e957806339509351146104fc5780633c870dcf1461050f57806357a194ab146105175761038e565b80632e40939c146104b95780632e935aa7146104c1578063313ce567146104d45761038e565b806318160ddd116103305780632495a5991161030a5780632495a5991461048157806328c1f99b1461049657806329dc06581461049e5780632a4d7943146104a65761038e565b806318160ddd1461044457806323b872dd1461044c57806323bb5fac1461045f5761038e565b806306fdde031161036c57806306fdde03146103e757806307134773146103fc578063095ea7b31461041157806314c64402146104315761038e565b806301dcad0f1461039357806303f2e589146103bd5780630537df97146103d2575b600080fd5b6103a66103a13660046151b4565b610777565b6040516103b49291906159ed565b60405180910390f35b6103c561089e565b6040516103b491906157b4565b6103da6108a4565b6040516103b49190615988565b6103ef6109be565b6040516103b49190615a08565b61040f61040a36600461555e565b610a54565b005b61042461041f366004615189565b610b18565b6040516103b491906159e2565b61040f61043f366004615526565b610b36565b6103c5610cf0565b61042461045a36600461502e565b610cf6565b61047261046d3660046156d1565b610d7e565b6040516103b493929190615e61565b610489610dbd565b6040516103b491906158ac565b610489610dcc565b6103c5610de0565b61040f6104b43660046152c8565b610de6565b6103a6610ec3565b61040f6104cf3660046156f2565b610f14565b6104dc610fea565b6040516103b49190615e77565b61040f6104f7366004615526565b610ff3565b61042461050a366004615189565b6111a8565b61040f6111f6565b61040f61052536600461555e565b6112c9565b61040f61053836600461555e565b611388565b61055061054b36600461555e565b611447565b6040516103b493929190615927565b6103c561056d366004614f70565b61148a565b61040f61058036600461565b565b6114a9565b61040f610593366004615105565b6116a9565b6103c5611950565b6103a6611993565b61040f6119fc565b61040f6105be36600461555e565b611d00565b6103c56105d13660046153ca565b611dbb565b61040f6105e436600461555e565b611ee2565b6103c5611fa1565b6103c56105ff36600461555e565b611fa7565b6103ef611fef565b6103c5612050565b6103da612055565b61042461062a366004615189565b6120e2565b61042461063d366004615189565b61214a565b61040f610650366004614f70565b61215e565b6103c561226a565b6103c5612270565b6103a661067336600461506e565b612276565b6103c56106863660046153ca565b61242e565b6103c5612456565b6104246106a13660046156d1565b61245c565b6103c561248a565b6103c561250b565b61040f6106c436600461555e565b612511565b61040f6106d736600461555e565b6125cc565b6103c56106ea36600461555e565b612719565b61040f6106fd36600461555e565b612757565b61040f61071036600461565b565b612816565b6103c5612b21565b6103c561072b366004614ff6565b612b27565b61074361073e36600461555e565b612b52565b6040516103b492919061596f565b6103c561075f366004614f70565b612b87565b6103c5610772366004614f70565b612b99565b60006060604254600160fa1b166000141580156107a357506107a161079b87612bab565b85612bdb565b155b156107ca5750506040805180820190915260018152600760fb1b6020820152600090610895565b6001600160a01b03861632148015906107eb57506107e9868585612bea565b155b156108125750506040805180820190915260018152603960f81b6020820152600090610895565b604254600160f91b166108425750506040805180820190915260028152610c4d60f21b6020820152600090610895565b60008511801561085a57506108568661148a565b8511155b6108805750506040805180820190915260018152603160f81b6020820152600090610895565b50506040805160208101909152600081526001905b94509492505050565b60445481565b6060603960019054906101000a90046001600160a01b03166001600160a01b031663d71f05e66040518163ffffffff1660e01b815260040160206040518083038186803b1580156108f457600080fd5b505afa158015610908573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092c9190614f8c565b6001600160a01b031663a64e1e7b60f0604254901c60ff166047546040518363ffffffff1660e01b81526004016109649291906157f7565b60006040518083038186803b15801561097c57600080fd5b505afa158015610990573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526109b89190810190615459565b90505b90565b60378054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a4a5780601f10610a1f57610100808354040283529160200191610a4a565b820191906000526020600020905b815481529060010190602001808311610a2d57829003601f168201915b5050505050905090565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610aa257600080fd5b505afa158015610ab6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ada9190614f8c565b6001600160a01b0316336001600160a01b031614610b135760405162461bcd60e51b8152600401610b0a90615a1b565b60405180910390fd5b604455565b6000610b2c610b25612c27565b8484612c2b565b5060015b92915050565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610b8457600080fd5b505afa158015610b98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bbc9190614f8c565b6001600160a01b0316336001600160a01b031614610bec5760405162461bcd60e51b8152600401610b0a90615a1b565b60428054600160ff60f81b031690558015610cb65760428054600160f81b179055603f5415610cb657610ca36048805480602002602001604051908101604052809291908181526020016000905b82821015610c9a576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101610c3a565b50505050612cdf565b6000603f819055610cb690604890614c38565b6042546040513391600160f81b161515907f3f14e04c219cb203de89f60db463113cc68cf16c00a46ef96a1fce6ca8abb5bb90600090a350565b60365490565b6000610d03848484612cf1565b610d7384610d0f612c27565b610d6e85604051806060016040528060288152602001615f85602891396001600160a01b038a16600090815260356020526040812090610d4d612c27565b6001600160a01b031681526020810191909152604001600020549190612e06565b612c2b565b5060015b9392505050565b603e6020528160005260406000208181548110610d9757fe5b600091825260209091206003909102018054600182015460029092015490935090915083565b6043546001600160a01b031681565b60395461010090046001600160a01b031681565b60455481565b603960019054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b158015610e3457600080fd5b505afa158015610e48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6c9190614f8c565b6001600160a01b0316336001600160a01b031614610e9c5760405162461bcd60e51b8152600401610b0a90615b45565b610ec08160405180604001604052806002815260200161313560f01b815250612e32565b50565b60006060604254600160f91b1660001415610efb5750506040805180820190915260028152610c4d60f21b6020820152600090610f10565b50506040805160208101909152600081526001905b9091565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6257600080fd5b505afa158015610f76573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f9a9190614f8c565b6001600160a01b0316336001600160a01b031614610fca5760405162461bcd60e51b8152600401610b0a90615bf4565b610fd383612e63565b610fdc82612e96565b610fe581612ecb565b505050565b60395460ff1690565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561104157600080fd5b505afa158015611055573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110799190614f8c565b6001600160a01b0316336001600160a01b0316146110a95760405162461bcd60e51b8152600401610b0a90615a1b565b604280546001607f60f91b031690558061116157603f541561115c5761114960488054806020026020016040519081016040528092919081815260200160009082821015610c9a576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101610c3a565b6000603f81905561115c90604890614c38565b61116e565b60428054600160f91b1790555b6042546040513391600160f91b161515907fbef546d8099130f7f80a42b7eb7f2aa81c1dd73f07fc569fe30338e102bba27390600090a350565b6000610b2c6111b5612c27565b84610d6e85603560006111c6612c27565b6001600160a01b03908116825260208083019390935260409182016000908120918c168152925290205490612f00565b60006060611202611993565b915091508181906112265760405162461bcd60e51b8152600401610b0a9190615a08565b50603f54156112c5576112c56048805480602002602001604051908101604052809291908181526020016000905b828210156112b4576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101611254565b505050506112c061248a565b612f25565b5050565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b15801561131757600080fd5b505afa15801561132b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061134f9190614f8c565b6001600160a01b0316336001600160a01b03161461137f5760405162461bcd60e51b8152600401610b0a90615bf4565b610ec081612e63565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b1580156113d657600080fd5b505afa1580156113ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061140e9190614f8c565b6001600160a01b0316336001600160a01b03161461143e5760405162461bcd60e51b8152600401610b0a90615bf4565b610ec081612e96565b6048818154811061145457fe5b6000918252602090912060029091020180546001909101546001600160a01b03918216925090811690600160a01b900460ff1683565b6001600160a01b0381166000908152603460205260409020545b919050565b6002603a5414156114cc5760405162461bcd60e51b8152600401610b0a90615df3565b6002603a55600060606114dd611993565b915091508181906115015760405162461bcd60e51b8152600401610b0a9190615a08565b50505061151461150f612fd2565b613099565b600061151e6132e9565b9050600061152a61248a565b604354909150611545906001600160a01b031633308a6132fe565b600061154f61248a565b9050600061155d8284613356565b9050600061156a82612719565b905060006115788383613356565b90506115fd33600083858e8e80806020026020016040519081016040528093929190818152602001838360200280828437600081840152601f19601f820116905080830192505050505050508d8d8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061337e92505050565b336000908152603d60205260409020546116179082612f00565b336000908152603d6020526040902055811561164c5760425460435461164c916001600160a01b039091169060501c846133bf565b85158061165e575061165c610cf0565b155b156116725761166d33826133de565b611697565b611697336116928861168c611685610cf0565b869061349e565b906134d8565b6133de565b50506001603a55505050505050505050565b60006116b361350a565b60015490915060ff16806116ca57506116ca61350f565b806116d6575060005481115b6116f25760405162461bcd60e51b8152600401610b0a90615c35565b60015460ff16158015611711576001805460ff19168117905560008290555b6000855111604051806040016040528060018152602001600d60fa1b8152509061174e5760405162461bcd60e51b8152600401610b0a9190615a08565b506000845111604051806040016040528060018152602001600d60fa1b8152509061178c5760405162461bcd60e51b8152600401610b0a9190615a08565b5060398054610100600160a81b0319166101006001600160a01b038a16021790556117b5614c59565b603954604051639ec39e2f60e01b81526101009091046001600160a01b031690639ec39e2f906117e99087906004016157b4565b60006040518083038186803b15801561180157600080fd5b505afa158015611815573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261183d9190810190615576565b905061184d848260600151613515565b61185687613566565b611884868260800151604051602001611870929190615861565b604051602081830303815290604052613756565b6118b2858260a0015160405160200161189e929190615821565b604051602081830303815290604052613769565b6043546040805163313ce56760e01b81529051611935926001600160a01b03169163313ce567916004808301926020929190829003018186803b1580156118f857600080fd5b505afa15801561190c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611930919061571d565b61377c565b508015611947576001805460ff191690555b50505050505050565b600061195a610cf0565b1561198b5761198461196a610cf0565b61168c670de0b6b3a764000061197e6132e9565b9061349e565b90506109bb565b5060006109bb565b60006060604254600160f91b16600014156119cb5750506040805180820190915260028152610c4d60f21b6020820152600090610f10565b604254600160f81b1615610efb575050604080518082019091526002815261313360f01b6020820152600090610f10565b60006060611a08611993565b91509150818190611a2c5760405162461bcd60e51b8152600401610b0a9190615a08565b5060006060611a39610ec3565b91509150818190611a5d5760405162461bcd60e51b8152600401610b0a9190615a08565b50611a6e611a696108a4565b613792565b6000611afe6049805480602002602001604051908101604052809291908181526020016000905b82821015611af5576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101611a95565b50505050611dbb565b9050603f548114611c4657603f5415611b9557611b9560488054806020026020016040519081016040528092919081815260200160009082821015610c9a576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101610c3a565b611ba160486000614c38565b60005b604954811015611c3f57604860498281548110611bbd57fe5b6000918252602080832084546001818101875595855291909320600292830290930180549190920290920180546001600160a01b03199081166001600160a01b03948516178255918401805491850180549093169190931617808255915460ff600160a01b918290041615150260ff60a01b1990921691909117905501611ba4565b50603f8190555b6000611c5061248a565b603f5490915015801590611c645750600081115b15611cf857611cf86048805480602002602001604051908101604052809291908181526020016000905b82821015611cee576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101611c8e565b5050505082612f25565b505050505050565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d4e57600080fd5b505afa158015611d62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d869190614f8c565b6001600160a01b0316336001600160a01b031614611db65760405162461bcd60e51b8152600401610b0a90615a1b565b604655565b805160009015611eda57606082516001600160401b0381118015611dde57600080fd5b50604051908082528060200260200182016040528015611e08578160200160208202803683370190505b50905060005b8351811015611ea657838181518110611e2357fe5b602002602001015160000151848281518110611e3b57fe5b602002602001015160200151858381518110611e5357fe5b602002602001015160400151604051602001611e7193929190615781565b60405160208183030381529060405280519060200120828281518110611e9357fe5b6020908102919091010152600101611e0e565b5060475481604051602001611ebc9291906157bd565b604051602081830303815290604052805190602001209150506114a4565b506000919050565b603960019054906101000a90046001600160a01b03166001600160a01b031663054159966040518163ffffffff1660e01b815260040160206040518083038186803b158015611f3057600080fd5b505afa158015611f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f689190614f8c565b6001600160a01b0316336001600160a01b031614611f985760405162461bcd60e51b8152600401610b0a90615bf4565b610ec081612ecb565b60405481565b6000610b30611fb4610fea565b60ff16600a0a6020604254901c61ffff1602611fe961271061168c6030604254901c61ffff168761349e90919063ffffffff16565b90612f00565b60388054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015610a4a5780601f10610a1f57610100808354040283529160200191610a4a565b600381565b60606048805480602002602001604051908101604052809291908181526020016000905b828210156120d9576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101612079565b50505050905090565b6000610b2c6120ef612c27565b84610d6e85604051806060016040528060258152602001615fad6025913960356000612119612c27565b6001600160a01b03908116825260208083019390935260409182016000908120918d16815292529020549190612e06565b6000610b2c612157612c27565b8484612cf1565b603960019054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b1580156121ac57600080fd5b505afa1580156121c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121e49190614f8c565b6001600160a01b0316336001600160a01b0316146122145760405162461bcd60e51b8152600401610b0a90615b45565b612226816001600160a01b031661382c565b6122425760405162461bcd60e51b8152600401610b0a90615d09565b603980546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b603f5481565b60415481565b60006060604254600160fa1b1660001415801561229c575061229a61079b89612bab565b155b156122c35750506040805180820190915260018152600760fb1b6020820152600090612423565b6001600160a01b03881632148015906122e457506122e2888585612bea565b155b1561230b5750506040805180820190915260018152603960f81b6020820152600090612423565b604154861015612338575050604080518082019091526002815261031360f41b6020820152600090612423565b60006123426132e9565b90508715801561235c575060455461235a8288613356565b115b15612385575050604080518082019091526002815261313160f01b602082015260009150612423565b6045546123928289612f00565b11156123bc575050604080518082019091526002815261313160f01b602082015260009150612423565b604080546001600160a01b038b166000908152603d60205291909120546123e39089612f00565b111561240d575050604080518082019091526002815261189960f11b602082015260009150612423565b5050604080516020810190915260008152600191505b965096945050505050565b603954604354600091610b309184916001600160a01b03610100909104811691309116613832565b60465481565b60006040604254901c61ffff166124828361168c6127108761349e90919063ffffffff16565b109392505050565b6043546040516370a0823160e01b81526000916001600160a01b0316906370a08231906124bb9030906004016158ac565b60206040518083038186803b1580156124d357600080fd5b505afa1580156124e7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109b89190615643565b60475481565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561255f57600080fd5b505afa158015612573573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125979190614f8c565b6001600160a01b0316336001600160a01b0316146125c75760405162461bcd60e51b8152600401610b0a90615a1b565b604255565b603960019054906101000a90046001600160a01b03166001600160a01b031663289b3c0d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561261a57600080fd5b505afa15801561262e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126529190614f8c565b6001600160a01b0316336001600160a01b0316146126825760405162461bcd60e51b8152600401610b0a90615a1b565b603954604051639ec39e2f60e01b8152610ec09183916101009091046001600160a01b031690639ec39e2f906126bc9084906004016157b4565b60006040518083038186803b1580156126d457600080fd5b505afa1580156126e8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526127109190810190615576565b60600151613515565b6000610b30612726610fea565b60ff16600a0a60425461ffff1602611fe961271061168c6010604254901c61ffff168761349e90919063ffffffff16565b603960019054906101000a90046001600160a01b03166001600160a01b031663e7f43c686040518163ffffffff1660e01b815260040160206040518083038186803b1580156127a557600080fd5b505afa1580156127b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127dd9190614f8c565b6001600160a01b0316336001600160a01b03161461280d5760405162461bcd60e51b8152600401610b0a90615b45565b610ec081613566565b6002603a5414156128395760405162461bcd60e51b8152600401610b0a90615df3565b6002603a556000606061284a610ec3565b9150915081819061286e5760405162461bcd60e51b8152600401610b0a9190615a08565b50505061287c61150f612fd2565b6128eb338686868080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525050604080516020808a02828101820190935289825290935089925088918291850190849080828437600092019190915250613a8b92505050565b600061290a6128f8610cf0565b61168c6129036132e9565b899061349e565b90506129163387613abf565b600061292061248a565b905081811015612abf5760006129368383613356565b60395460435460488054604080516020808402820181019092528281529596506000956129f0956001600160a01b03610100909104811695169388939192909190889084015b828210156129dc576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff16151591830191909152908352909201910161297c565b50505050613b95909392919063ffffffff16565b9050612a816048805480602002602001604051908101604052809291908181526020016000905b82821015612a77576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101612a17565b5050505082613d0d565b6000612a8b61248a565b90506000612a998286613356565b905083811015612aba57612ab7612ab08583613356565b8790613356565b95505b505050505b6000612aca83611fa7565b90508015612af157604254604354612af1916001600160a01b039091169060501c836133bf565b612b1233612aff8584613356565b6043546001600160a01b031691906133bf565b50506001603a55505050505050565b60425481565b6001600160a01b03918216600090815260356020908152604080832093909416825291909152205490565b603b8181548110612b5f57fe5b6000918252602090912060029091020180546001909101546001600160a01b03909116915082565b603d6020526000908152604090205481565b603c6020526000908152604090205481565b600081604051602001612bbe9190615764565b604051602081830303815290604052805190602001209050919050565b6000610d778260445485613d9a565b6000612bfe612bf885612bab565b84612bdb565b8015612c1f5750612c1f612c19612c1486613e37565b613e3b565b83613e4e565b949350505050565b3390565b6001600160a01b038316612c515760405162461bcd60e51b8152600401610b0a90615d2e565b6001600160a01b038216612c775760405162461bcd60e51b8152600401610b0a90615a95565b6001600160a01b0380841660008181526035602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590612cd29085906157b4565b60405180910390a3505050565b610ec081612cec8361242e565b613d0d565b6001600160a01b038316612d175760405162461bcd60e51b8152600401610b0a90615cc4565b6001600160a01b038216612d3d5760405162461bcd60e51b8152600401610b0a90615a52565b612d48838383613e5d565b612d8581604051806060016040528060268152602001615f5f602691396001600160a01b0386166000908152603460205260409020549190612e06565b6001600160a01b038085166000908152603460205260408082209390935590841681522054612db49082612f00565b6001600160a01b0380841660008181526034602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90612cd29085906157b4565b60008184841115612e2a5760405162461bcd60e51b8152600401610b0a9190615a08565b505050900390565b60005b8251811015610fe557612e5b838281518110612e4d57fe5b602002602001015183613ea0565b600101612e35565b604081815551339082907f70c87424f133fbd8c8e63b0dc9c2d2702db0a79d7d4139b25a5035f250b9f73890600090a350565b6041819055604051339082907f7af95a1df120276e178a852832ba64d58429b2b5986955c772448d80c08ef39290600090a350565b6045819055604051339082907fae4cf6e16f407af30e4a8e158871dd4eb7d4ad22f2438ccc43c5855fcd6ebbee90600090a350565b600082820183811015610d775760405162461bcd60e51b8152600401610b0a90615ad7565b603954600090612f4490849061010090046001600160a01b0316613f3c565b905060005b81811015612fcc576040805160c0810182526039546001600160a01b03610100909104811682523060208301526043541691810191909152606081018490526080810182905260a08101839052612fc490612fa590869061406e565b604051806040016040528060018152602001601960f91b815250612e32565b600101612f49565b50505050565b603f54600090612fe35760006109b8565b60395460435460488054604080516020808402820181019092528281526109b8956001600160a01b036101009091048116953095911693919290919060009084015b82821015613085576000848152602090819020604080516060810182526002860290920180546001600160a01b03908116845260019182015490811684860152600160a01b900460ff161515918301919091529083529092019101613025565b50505050614455909392919063ffffffff16565b436000908152603e6020526040902054801561329357436000818152603e6020818152604080842081516060810190925287825294909352908152825490820190839060001986019081106130ea57fe5b906000526020600020906003020160010154851061313857436000908152603e602052604090208054600019860190811061312157fe5b90600052602060002090600302016001015461313a565b845b8152602001603e6000438152602001908152602001600020600185038154811061316057fe5b90600052602060002090600302016002015485116131ae57436000908152603e602052604090208054600019860190811061319757fe5b9060005260206000209060030201600201546131b0565b845b90528154600181810184556000938452602080852084516003909402019283558084015191830191909155604092830151600290920191909155438352603e9052902080546132549161324e918490811061320757fe5b906000526020600020906003020160010154603e6000438152602001908152602001600020848154811061323757fe5b90600052602060002090600302016002015461476b565b8361245c565b60405180604001604052806002815260200161189b60f11b8152509061328d5760405162461bcd60e51b8152600401610b0a9190615a08565b506112c5565b436000908152603e60209081526040808320815160608101835286815280840187815292810187815282546001818101855593875294909520905160039094020192835590519082015590516002909101555050565b60006109b86132f661248a565b611fe9612fd2565b612fcc846323b872dd60e01b85858560405160240161331f9392919061594b565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261478d565b6000828211156133785760405162461bcd60e51b8152600401610b0a90615b0e565b50900390565b60006060613390888888888888612276565b915091508181906133b45760405162461bcd60e51b8152600401610b0a9190615a08565b505050505050505050565b610fe58363a9059cbb60e01b848460405160240161331f92919061596f565b6001600160a01b0382166134045760405162461bcd60e51b8152600401610b0a90615e2a565b61341060008383613e5d565b60365461341d9082612f00565b6036556001600160a01b0382166000908152603460205260409020546134439082612f00565b6001600160a01b0383166000818152603460205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906134929085906157b4565b60405180910390a35050565b6000826134ad57506000610b30565b828202828482816134ba57fe5b0414610d775760405162461bcd60e51b8152600401610b0a90615bb3565b60008082116134f95760405162461bcd60e51b8152600401610b0a90615b7c565b81838161350257fe5b049392505050565b600390565b303b1590565b6040805180820190915260018152603560f81b60208201528161354b5760405162461bcd60e51b8152600401610b0a9190615a08565b5060425460ff60f01b191660f083901b176042819055505050565b603954604051638346525f60e01b815260609161010090046001600160a01b031690638346525f9061359c9085906004016157b4565b60006040518083038186803b1580156135b457600080fd5b505afa1580156135c8573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526135f09190810190615230565b9050805160011460405180604001604052806002815260200161313760f01b815250906136305760405162461bcd60e51b8152600401610b0a9190615a08565b50603960019054906101000a90046001600160a01b03166001600160a01b0316632d5ad3d58260008151811061366257fe5b60200260200101516040518263ffffffff1660e01b815260040161368691906158ac565b60206040518083038186803b15801561369e57600080fd5b505afa1580156136b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136d69190615542565b60405180604001604052806002815260200161313960f01b8152509061370f5760405162461bcd60e51b8152600401610b0a9190615a08565b50816047819055508060008151811061372457fe5b6020026020010151604360006101000a8154816001600160a01b0302191690836001600160a01b031602179055505050565b80516112c5906037906020840190614c91565b80516112c5906038906020840190614c91565b6039805460ff191660ff92909216919091179055565b61379e60496000614c38565b60005b81518110156112c55760498282815181106137b857fe5b602090810291909101810151825460018082018555600094855293839020825160029092020180546001600160a01b03199081166001600160a01b039384161782559383015190850180546040909401519390941691161760ff60a01b1916600160a01b91151591909102179055016137a1565b3b151590565b83516000908186600019830183811061384757fe5b60200260200101516000015190506000866001600160a01b031663923bb7ff836040518263ffffffff1660e01b815260040161388391906158ac565b60206040518083038186803b15801561389b57600080fd5b505afa1580156138af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138d39190614f8c565b905060018311156138fc578760028403815181106138ed57fe5b60200260200101516020015194505b6040516336d8bf9360e01b81526001600160a01b038216906336d8bf93906139289085906004016158ac565b60206040518083038186803b15801561394057600080fd5b505afa158015613954573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139789190615542565b613a01576040516390e6160560e01b81526001600160a01b038216906390e61605906139ac908990899087906004016158da565b60206040518083038186803b1580156139c457600080fd5b505afa1580156139d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139fc9190615643565b613a7f565b60405163afd908d960e01b81526001600160a01b0382169063afd908d990613a2f90899086906004016158c0565b60206040518083038186803b158015613a4757600080fd5b505afa158015613a5b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a7f9190615643565b98975050505050505050565b60006060613a9b86868686610777565b915091508181906119475760405162461bcd60e51b8152600401610b0a9190615a08565b6001600160a01b038216613ae55760405162461bcd60e51b8152600401610b0a90615c83565b613af182600083613e5d565b613b2e81604051806060016040528060228152602001615f3d602291396001600160a01b0385166000908152603460205260409020549190612e06565b6001600160a01b038316600090815260346020526040902055603654613b549082613356565b6036556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906134929085906157b4565b8351600090815b81811015613d03576000878281518110613bb257fe5b60200260200101516000015190506000876001600160a01b031663923bb7ff836040518263ffffffff1660e01b8152600401613bee91906158ac565b60206040518083038186803b158015613c0657600080fd5b505afa158015613c1a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c3e9190614f8c565b9050868315613c6557896001850381518110613c5657fe5b60200260200101516020015190505b6001600160a01b0382166385541e4482858715613c825789613c84565b8a5b6040518463ffffffff1660e01b8152600401613ca29392919061594b565b60206040518083038186803b158015613cba57600080fd5b505afa158015613cce573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613cf29190615643565b95505060019092019150613b9c9050565b5050949350505050565b815160005b81811015612fcc576040805160c0810182526039546001600160a01b036101009091048116825230602083015260435416918101919091526060810184905281830360001901608082015260a08101839052613d9290613d7390869061481c565b604051806040016040528060018152602001603360f81b815250612e32565b600101613d12565b600081815b8551811015613e2c576000868281518110613db657fe5b60200260200101519050808311613df7578281604051602001613dda9291906157f7565b604051602081830303815290604052805190602001209250613e23565b8083604051602001613e0a9291906157f7565b6040516020818303038152906040528051906020012092505b50600101613d9f565b509092149392505050565b3f90565b600081604051602001612bbe91906157b4565b6000610d778260465485613d9a565b604080518082019091526002815261062760f31b60208201526001600160a01b038316301415612fcc5760405162461bcd60e51b8152600401610b0a9190615a08565b6000606083806020019051810190613eb89190614fa8565b915091506000826001600160a01b031682604051613ed69190615805565b6000604051808303816000865af19150503d8060008114613f13576040519150601f19603f3d011682016040523d82523d6000602084013e613f18565b606091505b50509050808490611cf85760405162461bcd60e51b8152600401610b0a9190615a08565b815160009081846000198301838110613f5157fe5b6020026020010151600001519050836001600160a01b031663923bb7ff826040518263ffffffff1660e01b8152600401613f8b91906158ac565b60206040518083038186803b158015613fa357600080fd5b505afa158015613fb7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613fdb9190614f8c565b6001600160a01b03166336d8bf93826040518263ffffffff1660e01b815260040161400691906158ac565b60206040518083038186803b15801561401e57600080fd5b505afa158015614032573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906140569190615542565b1561406657506001019050610b30565b509392505050565b80516040820151606083810151855160808601519294939281141561426c576000876001886080015103815181106140a257fe5b60200260200101516000015190506000856001600160a01b031663923bb7ff836040518263ffffffff1660e01b81526004016140de91906158ac565b60206040518083038186803b1580156140f657600080fd5b505afa15801561410a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061412e9190614f8c565b90508860018960800151038151811061414357fe5b602002602001015160200151945087604001516001600160a01b03166370a0823189602001516040518263ffffffff1660e01b815260040161418591906158ac565b60206040518083038186803b15801561419d57600080fd5b505afa1580156141b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d59190615643565b9350806001600160a01b03166374df3b2f89602001518a60400151856040518463ffffffff1660e01b815260040161420f939291906158da565b60006040518083038186803b15801561422757600080fd5b505afa15801561423b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526142639190810190615350565b9650505061444b565b60008787608001518151811061427e57fe5b60200260200101516000015190506000856001600160a01b031663923bb7ff836040518263ffffffff1660e01b81526004016142ba91906158ac565b60206040518083038186803b1580156142d257600080fd5b505afa1580156142e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061430a9190614f8c565b905087608001516000146143bc578860018960800151038151811061432b57fe5b6020026020010151602001519450846001600160a01b03166370a0823189602001516040518263ffffffff1660e01b815260040161436991906158ac565b60206040518083038186803b15801561438157600080fd5b505afa158015614395573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143b99190615643565b93505b6020880151604051636fc9ab9160e11b81526001600160a01b0383169163df935722916143f29190899087908a906004016158fd565b60006040518083038186803b15801561440a57600080fd5b505afa15801561441e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526144469190810190615350565b965050505b5050505092915050565b835160009081805b828110156147605760008160018503039050600089828151811061447d57fe5b60200260200101516000015190506000896001600160a01b031663923bb7ff836040518263ffffffff1660e01b81526004016144b991906158ac565b60206040518083038186803b1580156144d157600080fd5b505afa1580156144e5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145099190614f8c565b9050878315614530578b600185038151811061452157fe5b60200260200101516020015190505b600187038414156146ca576040516336d8bf9360e01b81526001600160a01b038316906336d8bf93906145679086906004016158ac565b60206040518083038186803b15801561457f57600080fd5b505afa158015614593573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145b79190615542565b1561464357604051632627a09960e01b81526001600160a01b03831690632627a099906145ec908d90859088906004016158da565b60206040518083038186803b15801561460457600080fd5b505afa158015614618573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061463c9190615643565b97506146c5565b60405162c9babf60e71b81526001600160a01b038316906364dd5f8090614672908d90859088906004016158da565b60206040518083038186803b15801561468a57600080fd5b505afa15801561469e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906146c29190615643565b97505b61474d565b60405163ee665bed60e01b81526001600160a01b0383169063ee665bed906146fa90849087908b9060040161594b565b60206040518083038186803b15801561471257600080fd5b505afa158015614726573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061474a9190615643565b97505b50869450506001909201915061445d9050565b505050949350505050565b60008183116147835761477e8284613356565b610d77565b610d778383613356565b60606147e2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316614b559092919063ffffffff16565b805190915015610fe557808060200190518101906148009190615542565b610fe55760405162461bcd60e51b8152600401610b0a90615da9565b606060008383608001518151811061483057fe5b602090810291909101015151835160405163923bb7ff60e01b8152919250906000906001600160a01b0383169063923bb7ff906148719086906004016158ac565b60206040518083038186803b15801561488957600080fd5b505afa15801561489d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148c19190614f8c565b6040860151606087015160808801519293509091156148fc57876001886080015103815181106148ed57fe5b60200260200101516020015191505b60018760a00151038760800151146149ac578787608001518151811061491e57fe5b6020026020010151602001516001600160a01b03166370a0823188602001516040518263ffffffff1660e01b815260040161495991906158ac565b60206040518083038186803b15801561497157600080fd5b505afa158015614985573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149a99190615643565b90505b60018760a00151038760800151148015614a3d57506040516336d8bf9360e01b81526001600160a01b038416906336d8bf93906149ed9088906004016158ac565b60206040518083038186803b158015614a0557600080fd5b505afa158015614a19573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614a3d9190615542565b614acb576020870151604051636092577960e01b81526001600160a01b03851691636092577991614a77919086908a9087906004016158fd565b60006040518083038186803b158015614a8f57600080fd5b505afa158015614aa3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526139fc9190810190615350565b6020870151604051631496678160e11b81526001600160a01b0385169163292ccf0291614b01919086908a9087906004016158fd565b60006040518083038186803b158015614b1957600080fd5b505afa158015614b2d573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052613a7f9190810190615350565b6060612c1f848460008585614b698561382c565b614b855760405162461bcd60e51b8152600401610b0a90615d72565b60006060866001600160a01b03168587604051614ba29190615805565b60006040518083038185875af1925050503d8060008114614bdf576040519150601f19603f3d011682016040523d82523d6000602084013e614be4565b606091505b5091509150614bf4828286614bff565b979650505050505050565b60608315614c0e575081610d77565b825115614c1e5782518084602001fd5b8160405162461bcd60e51b8152600401610b0a9190615a08565b5080546000825560020290600052602060002090810190610ec09190614d0f565b6040805160c08101825260008082526020820152908101614c78614d40565b8152600060208201526060604082018190529081015290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614cd257805160ff1916838001178555614cff565b82800160010185558215614cff579182015b82811115614cff578251825591602001919060010190614ce4565b50614d0b929150614d57565b5090565b5b80821115614d0b5780546001600160a01b03191681556001810180546001600160a81b0319169055600201614d10565b604080518082019091526000808252602082015290565b5b80821115614d0b5760008155600101614d58565b60008083601f840112614d7d578182fd5b5081356001600160401b03811115614d93578182fd5b6020830191508360208083028501011115614dad57600080fd5b9250929050565b600082601f830112614dc4578081fd5b8135614dd7614dd282615eab565b615e85565b818152915060208083019084810181840286018201871015614df857600080fd5b60005b84811015614e1757813584529282019290820190600101614dfb565b505050505092915050565b8051610b3081615f2e565b600082601f830112614e3d578081fd5b8135614e4b614dd282615eca565b9150808252836020828501011115614e6257600080fd5b8060208401602084013760009082016020015292915050565b600082601f830112614e8b578081fd5b8151614e99614dd282615eca565b9150808252836020828501011115614eb057600080fd5b614ec1816020840160208601615eed565b5092915050565b600060408284031215614ed9578081fd5b614ee36040615e85565b9050614eef8383614f5f565b8152614efe8360208401614f5f565b602082015292915050565b600060608284031215614f1a578081fd5b614f246060615e85565b90508135614f3181615f19565b81526020820135614f4181615f19565b60208201526040820135614f5481615f2e565b604082015292915050565b805160ff81168114610b3057600080fd5b600060208284031215614f81578081fd5b8135610d7781615f19565b600060208284031215614f9d578081fd5b8151610d7781615f19565b60008060408385031215614fba578081fd5b8251614fc581615f19565b60208401519092506001600160401b03811115614fe0578182fd5b614fec85828601614e7b565b9150509250929050565b60008060408385031215615008578182fd5b823561501381615f19565b9150602083013561502381615f19565b809150509250929050565b600080600060608486031215615042578081fd5b833561504d81615f19565b9250602084013561505d81615f19565b929592945050506040919091013590565b60008060008060008060c08789031215615086578384fd5b863561509181615f19565b955060208701356150a181615f2e565b9450604087013593506060870135925060808701356001600160401b03808211156150ca578384fd5b6150d68a838b01614db4565b935060a08901359150808211156150eb578283fd5b506150f889828a01614db4565b9150509295509295509295565b600080600080600060a0868803121561511c578283fd5b853561512781615f19565b94506020860135935060408601356001600160401b0380821115615149578485fd5b61515589838a01614e2d565b9450606088013591508082111561516a578283fd5b5061517788828901614e2d565b95989497509295608001359392505050565b6000806040838503121561519b578182fd5b82356151a681615f19565b946020939093013593505050565b600080600080608085870312156151c9578182fd5b84356151d481615f19565b93506020850135925060408501356001600160401b03808211156151f6578384fd5b61520288838901614db4565b93506060870135915080821115615217578283fd5b5061522487828801614db4565b91505092959194509250565b60006020808385031215615242578182fd5b82516001600160401b03811115615257578283fd5b8301601f81018513615267578283fd5b8051615275614dd282615eab565b8181528381019083850185840285018601891015615291578687fd5b8694505b838510156152bc5780516152a881615f19565b835260019490940193918501918501615295565b50979650505050505050565b600060208083850312156152da578182fd5b82356001600160401b038111156152ef578283fd5b8301601f810185136152ff578283fd5b803561530d614dd282615eab565b81815283810190838501865b84811015615342576153308a888435890101614e2d565b84529286019290860190600101615319565b509098975050505050505050565b60006020808385031215615362578182fd5b82516001600160401b03811115615377578283fd5b8301601f81018513615387578283fd5b8051615395614dd282615eab565b81815283810190838501865b84811015615342576153b88a888451890101614e7b565b845292860192908601906001016153a1565b600060208083850312156153dc578182fd5b82356001600160401b038111156153f1578283fd5b8301601f81018513615401578283fd5b803561540f614dd282615eab565b818152838101908385016060808502860187018a101561542d578788fd5b8795505b84861015615342576154438a83614f09565b8452600195909501949286019290810190615431565b6000602080838503121561546b578182fd5b82516001600160401b03811115615480578283fd5b8301601f81018513615490578283fd5b805161549e614dd282615eab565b818152838101908385016060808502860187018a10156154bc578788fd5b8795505b848610156153425780828b0312156154d6578788fd5b6154df81615e85565b82516154ea81615f19565b8152828801516154f981615f19565b8189015260408381015161550c81615f2e565b9082015284526001959095019492860192908101906154c0565b600060208284031215615537578081fd5b8135610d7781615f2e565b600060208284031215615553578081fd5b8151610d7781615f2e565b60006020828403121561556f578081fd5b5035919050565b600060208284031215615587578081fd5b81516001600160401b038082111561559d578283fd5b9083019060e082860312156155b0578283fd5b6155ba60c0615e85565b825181526155cb8660208501614e22565b60208201526155dd8660408501614ec8565b60408201526155ef8660808501614e22565b606082015260a083015182811115615605578485fd5b61561187828601614e7b565b60808301525060c083015182811115615628578485fd5b61563487828601614e7b565b60a08301525095945050505050565b600060208284031215615654578081fd5b5051919050565b600080600080600060608688031215615672578283fd5b8535945060208601356001600160401b038082111561568f578485fd5b61569b89838a01614d6c565b909650945060408801359150808211156156b3578283fd5b506156c088828901614d6c565b969995985093965092949392505050565b600080604083850312156156e3578182fd5b50508035926020909101359150565b600080600060608486031215615706578081fd5b505081359360208301359350604090920135919050565b60006020828403121561572e578081fd5b610d778383614f5f565b60008151808452615750816020860160208601615eed565b601f01601f19169290920160200192915050565b60609190911b6bffffffffffffffffffffffff1916815260140190565b6bffffffffffffffffffffffff19606094851b811682529290931b9091166014830152151560f81b602882015260290190565b90815260200190565b600083825260208083018451828601845b828110156157ea578151845292840192908401906001016157ce565b5091979650505050505050565b918252602082015260400190565b60008251615817818460208701615eed565b9190910192915050565b60006106f760f41b8252835161583e816002850160208801615eed565b835190830190615855816002840160208801615eed565b01600201949350505050565b600062037b8160ed1b8252835161587f816003850160208801615eed565b600160fd1b60039184019182015283516158a0816004840160208801615eed565b01600401949350505050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b0393841681529183166020830152909116604082015260600190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b6001600160a01b039384168152919092166020820152901515604082015260600190565b6001600160a01b039384168152919092166020820152604081019190915260600190565b6001600160a01b03929092168252602082015260400190565b602080825282518282018190526000919060409081850190868401855b828110156157ea57815180516001600160a01b039081168652878201511687860152850151151585850152606090930192908501906001016159a5565b901515815260200190565b6000831515825260406020830152612c1f6040830184615738565b600060208252610d776020830184615738565b6020808252601f908201527f63616c6c6572206973206e6f7420686176696e6720676f7665726e616e636500604082015260600190565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252601a908201527f63616c6c6572206973206e6f7420746865206f70657261746f72000000000000604082015260600190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b60208082526021908201527f63616c6c6572206973206e6f74207468652066696e616e63654f70657261746f6040820152603960f91b606082015260800190565b6020808252602e908201527f436f6e747261637420696e7374616e63652068617320616c726561647920626560408201526d195b881a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b6020808252600b908201526a085a5cd0dbdb9d1c9858dd60aa1b604082015260600190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b9283526020830191909152604082015260600190565b60ff91909116815260200190565b6040518181016001600160401b0381118282101715615ea357600080fd5b604052919050565b60006001600160401b03821115615ec0578081fd5b5060209081020190565b60006001600160401b03821115615edf578081fd5b50601f01601f191660200190565b60005b83811015615f08578181015183820152602001615ef0565b83811115612fcc5750506000910152565b6001600160a01b0381168114610ec057600080fd5b8015158114610ec057600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa164736f6c634300060c000a" +} diff --git a/deployments/mainnet/opAAVEaggr_Proxy.json b/deployments/mainnet/opAAVEaggr_Proxy.json new file mode 100644 index 000000000..f49c97300 --- /dev/null +++ b/deployments/mainnet/opAAVEaggr_Proxy.json @@ -0,0 +1,212 @@ +{ + "address": "0xd610c0CcE9792321BfEd3c2f31dceA6784c84F19", + "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": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "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": "", + "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" + } + ], + "transactionHash": "0x167a201ee9dfeefb38ac820508adc84ca4c19d929bfce67b180a4efde6f32c55", + "receipt": { + "to": null, + "from": "0xD26Ec7401C198ADAc340d3A4Cb8B52b845F3A542", + "contractAddress": "0xd610c0CcE9792321BfEd3c2f31dceA6784c84F19", + "transactionIndex": 125, + "gasUsed": "658649", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x64028a0df37b2b6bbdaf66e4a9e172ce16ba006563ae7f11c955533d134e820e", + "transactionHash": "0x167a201ee9dfeefb38ac820508adc84ca4c19d929bfce67b180a4efde6f32c55", + "logs": [], + "blockNumber": 14976022, + "cumulativeGasUsed": "13098252", + "status": 1, + "byzantium": true + }, + "args": [ + "0x9fe0eebe0b82bc629ba75aa6d69127602f53de86", + "0xF980ea5758f71F418909688b6448B41ACb5522E9", + "0x76e57d0300000000000000000000000099fa011e33a8c6196869dec7bc407e896ba67fe31bcbc96de2b4142404b9827f220545e3cee1f75a00560c3bdd29c9658103f7e200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a4161766520546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044141564500000000000000000000000000000000000000000000000000000000" + ], + "solcInputHash": "671d40d1898428f733662d50d9454e10", + "metadata": "{\"compiler\":{\"version\":\"0.6.12+commit.27d51765\"},\"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\":\"implementation\",\"type\":\"address\"}],\"name\":\"Upgraded\",\"type\":\"event\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"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\":\"\",\"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\"}],\"devdoc\":{\"details\":\"Extends from BaseAdminUpgradeabilityProxy with a constructor for initializing the implementation, admin, and init data.\",\"kind\":\"dev\",\"methods\":{\"admin()\":{\"returns\":{\"_0\":\"The address of the proxy admin.\"}},\"changeAdmin(address)\":{\"details\":\"Changes the admin of the proxy. Only the current admin can call this function.\",\"params\":{\"newAdmin\":\"Address to transfer proxy administration to.\"}},\"constructor\":{\"params\":{\"_admin\":\"Address of the proxy administrator.\",\"_data\":\"Data to send as msg.data to the implementation to initialize the proxied contract. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\",\"_logic\":\"address of the initial implementation.\"}},\"implementation()\":{\"returns\":{\"_0\":\"The address of the implementation.\"}},\"upgradeTo(address)\":{\"details\":\"Upgrade the backing implementation of the proxy. Only the admin can call this function.\",\"params\":{\"newImplementation\":\"Address of the new implementation.\"}},\"upgradeToAndCall(address,bytes)\":{\"details\":\"Upgrade the backing implementation of the proxy and call a function on the new implementation. This is useful to initialize the proxied contract.\",\"params\":{\"data\":\"Data to send as msg.data in the low level call. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\",\"newImplementation\":\"Address of the new implementation.\"}}},\"title\":\"AdminUpgradeabilityProxy\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"constructor\":\"Contract constructor.\"},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/protocol/tokenization/VaultProxyV2.sol\":\"AdminUpgradeabilityProxy\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"none\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity >=0.6.2 <0.8.0;\\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 function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize, which returns 0 for contracts in\\n // construction, since the code is only stored at the end of the\\n // constructor execution.\\n\\n uint256 size;\\n // solhint-disable-next-line no-inline-assembly\\n assembly { size := extcodesize(account) }\\n return size > 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 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\\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(address target, bytes memory data, string memory errorMessage) 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(address target, bytes memory data, uint256 value) 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(address target, bytes memory data, uint256 value, string memory errorMessage) 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 // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\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(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n // solhint-disable-next-line avoid-low-level-calls\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return _verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly\\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\":\"0x28911e614500ae7c607a432a709d35da25f3bc5ddc8bd12b278b66358070c0ea\",\"license\":\"MIT\"},\"contracts/protocol/tokenization/VaultProxyV2.sol\":{\"content\":\"// solhint-disable\\n// SPDX-License-Identifier: MIT\\npragma solidity 0.6.12;\\n\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\n/**\\n * @title Proxy\\n * @dev Implements delegation of calls to other contracts, with proper\\n * forwarding of return values and bubbling of failures.\\n * It defines a fallback function that delegates all calls to the address\\n * returned by the abstract _implementation() internal function.\\n */\\nabstract contract Proxy {\\n /**\\n * @dev Fallback function.\\n * Implemented entirely in `_fallback`.\\n */\\n fallback() external payable {\\n _fallback();\\n }\\n\\n /**\\n * @return The Address of the implementation.\\n */\\n function _implementation() internal view virtual returns (address);\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * This is a low level function that doesn't return to its internal call site.\\n * It will return to the external caller whatever the implementation returns.\\n * @param implementation Address to delegate.\\n */\\n function _delegate(address implementation) internal {\\n //solium-disable-next-line\\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 Function that is run as the first thing in the fallback function.\\n * Can be redefined in derived contracts to add functionality.\\n * Redefinitions must call super._willFallback().\\n */\\n function _willFallback() internal virtual {}\\n\\n /**\\n * @dev fallback implementation.\\n * Extracted to enable manual triggering.\\n */\\n function _fallback() internal {\\n _willFallback();\\n _delegate(_implementation());\\n }\\n}\\n\\n/**\\n * @title BaseUpgradeabilityProxy\\n * @dev This contract implements a proxy that allows to change the\\n * implementation address to which it will delegate.\\n * Such a change is called an implementation upgrade.\\n */\\ncontract BaseUpgradeabilityProxy is Proxy {\\n /**\\n * @dev Emitted when the implementation is upgraded.\\n * @param implementation Address of the new implementation.\\n */\\n event Upgraded(address indexed implementation);\\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 Returns the current implementation.\\n * @return impl Address of the current implementation\\n */\\n function _implementation() internal view override returns (address impl) {\\n bytes32 slot = IMPLEMENTATION_SLOT;\\n //solium-disable-next-line\\n assembly {\\n impl := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Upgrades the proxy to a new implementation.\\n * @param newImplementation Address of the new implementation.\\n */\\n function _upgradeTo(address newImplementation) internal {\\n _setImplementation(newImplementation);\\n emit Upgraded(newImplementation);\\n }\\n\\n /**\\n * @dev Sets the implementation address of the proxy.\\n * @param newImplementation Address of the new implementation.\\n */\\n function _setImplementation(address newImplementation) internal {\\n require(Address.isContract(newImplementation), \\\"Cannot set a proxy implementation to a non-contract address\\\");\\n\\n bytes32 slot = IMPLEMENTATION_SLOT;\\n\\n //solium-disable-next-line\\n assembly {\\n sstore(slot, newImplementation)\\n }\\n }\\n}\\n\\n/**\\n * @title UpgradeabilityProxy\\n * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing\\n * implementation and init data.\\n */\\ncontract UpgradeabilityProxy is BaseUpgradeabilityProxy {\\n /**\\n * @dev Contract constructor.\\n * @param _logic Address of the initial implementation.\\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\\n * It should include the signature and the parameters of the function to be called, as described in\\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\\n */\\n constructor(address _logic, bytes memory _data) public payable {\\n assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.implementation\\\")) - 1));\\n _setImplementation(_logic);\\n if (_data.length > 0) {\\n (bool success, ) = _logic.delegatecall(_data);\\n require(success);\\n }\\n }\\n}\\n\\n/**\\n * @title BaseAdminUpgradeabilityProxy\\n * @dev This contract combines an upgradeability proxy with an authorization\\n * mechanism for administrative tasks.\\n * All external functions in this contract must be guarded by the\\n * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity\\n * feature proposal that would enable this to be done automatically.\\n */\\ncontract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {\\n /**\\n * @dev Emitted when the administration has been transferred.\\n * @param previousAdmin Address of the previous admin.\\n * @param newAdmin Address of the new admin.\\n */\\n event AdminChanged(address previousAdmin, address newAdmin);\\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 Modifier to check whether the `msg.sender` is the admin.\\n * If it is, it will run the function. Otherwise, it will delegate the call\\n * to the implementation.\\n */\\n modifier ifAdmin() {\\n if (msg.sender == _admin()) {\\n _;\\n } else {\\n _fallback();\\n }\\n }\\n\\n /**\\n * @return The address of the proxy admin.\\n */\\n function admin() external ifAdmin returns (address) {\\n return _admin();\\n }\\n\\n /**\\n * @return The address of the implementation.\\n */\\n function implementation() external ifAdmin returns (address) {\\n return _implementation();\\n }\\n\\n /**\\n * @dev Changes the admin of the proxy.\\n * Only the current admin can call this function.\\n * @param newAdmin Address to transfer proxy administration to.\\n */\\n function changeAdmin(address newAdmin) external ifAdmin {\\n require(newAdmin != address(0), \\\"Cannot change the admin of a proxy to the zero address\\\");\\n emit AdminChanged(_admin(), newAdmin);\\n _setAdmin(newAdmin);\\n }\\n\\n /**\\n * @dev Upgrade the backing implementation of the proxy.\\n * Only the admin can call this function.\\n * @param newImplementation Address of the new implementation.\\n */\\n function upgradeTo(address newImplementation) external ifAdmin {\\n _upgradeTo(newImplementation);\\n }\\n\\n /**\\n * @dev Upgrade the backing implementation of the proxy and call a function\\n * on the new implementation.\\n * This is useful to initialize the proxied contract.\\n * @param newImplementation Address of the new implementation.\\n * @param data Data to send as msg.data in the low level call.\\n * It should include the signature and the parameters of the function to be called, as described in\\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\\n */\\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\\n _upgradeTo(newImplementation);\\n (bool success, ) = newImplementation.delegatecall(data);\\n require(success);\\n }\\n\\n /**\\n * @return adm The admin slot.\\n */\\n function _admin() internal view returns (address adm) {\\n bytes32 slot = ADMIN_SLOT;\\n //solium-disable-next-line\\n assembly {\\n adm := sload(slot)\\n }\\n }\\n\\n /**\\n * @dev Sets the address of the proxy admin.\\n * @param newAdmin Address of the new proxy admin.\\n */\\n function _setAdmin(address newAdmin) internal {\\n bytes32 slot = ADMIN_SLOT;\\n //solium-disable-next-line\\n assembly {\\n sstore(slot, newAdmin)\\n }\\n }\\n\\n /**\\n * @dev Only fall back when the sender is not the admin.\\n */\\n function _willFallback() internal virtual override {\\n require(msg.sender != _admin(), \\\"Cannot call fallback function from the proxy admin\\\");\\n super._willFallback();\\n }\\n}\\n\\n/**\\n * @title AdminUpgradeabilityProxy\\n * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for\\n * initializing the implementation, admin, and init data.\\n */\\ncontract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {\\n /**\\n * Contract constructor.\\n * @param _logic address of the initial implementation.\\n * @param _admin Address of the proxy administrator.\\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\\n * It should include the signature and the parameters of the function to be called, as described in\\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\\n */\\n constructor(\\n address _logic,\\n address _admin,\\n bytes memory _data\\n ) public payable UpgradeabilityProxy(_logic, _data) {\\n assert(ADMIN_SLOT == bytes32(uint256(keccak256(\\\"eip1967.proxy.admin\\\")) - 1));\\n _setAdmin(_admin);\\n }\\n\\n /**\\n * @dev Only fall back when the sender is not the admin.\\n */\\n function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) {\\n BaseAdminUpgradeabilityProxy._willFallback();\\n }\\n}\\n\",\"keccak256\":\"0x73bee0e9ca8a8ccd6b7f75816034c58f08a2d89ec8d9f3056ed08d1e37e26b36\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040526040516108a03803806108a08339818101604052606081101561002657600080fd5b8151602083015160408085018051915193959294830192918464010000000082111561005157600080fd5b90830190602082018581111561006657600080fd5b825164010000000081118282018810171561008057600080fd5b82525081516020918201929091019080838360005b838110156100ad578181015183820152602001610095565b50505050905090810190601f1680156100da5780820380516001836020036101000a031916815260200191505b50604052508491508290506100ee826101bf565b8051156101a6576000826001600160a01b0316826040518082805190602001908083835b602083106101315780518252601f199092019160209182019101610112565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114610191576040519150601f19603f3d011682016040523d82523d6000602084013e610196565b606091505b50509050806101a457600080fd5b505b506101ae9050565b6101b782610231565b50505061025b565b6101d28161025560201b6103a31760201c565b61020d5760405162461bcd60e51b815260040180806020018281038252603b815260200180610865603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc55565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b3b151590565b6105fb8061026a6000396000f3fe60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101d4565b34801561011357600080fd5b5061011c610281565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b03166102be565b34801561017757600080fd5b5061011c610378565b6101886103a9565b6101986101936103b1565b6103d6565b565b6101a26103fa565b6001600160a01b0316336001600160a01b031614156101c9576101c48161041f565b6101d1565b6101d1610180565b50565b6101dc6103fa565b6001600160a01b0316336001600160a01b03161415610274576101fe8361041f565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d806000811461025b576040519150601f19603f3d011682016040523d82523d6000602084013e610260565b606091505b505090508061026e57600080fd5b5061027c565b61027c610180565b505050565b600061028b6103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103b1565b90506102bb565b6102bb610180565b90565b6102c66103fa565b6001600160a01b0316336001600160a01b031614156101c9576001600160a01b0381166103245760405162461bcd60e51b815260040180806020018281038252603681526020018061057e6036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61034d6103fa565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c48161045f565b60006103826103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103fa565b3b151590565b610198610483565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156103f5573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b610428816104e3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61048b6103fa565b6001600160a01b0316336001600160a01b031614156104db5760405162461bcd60e51b815260040180806020018281038252603281526020018061054c6032913960400191505060405180910390fd5b610198610198565b6104ec816103a3565b6105275760405162461bcd60e51b815260040180806020018281038252603b8152602001806105b4603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a164736f6c634300060c000a43616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373", + "deployedBytecode": "0x60806040526004361061004a5760003560e01c80633659cfe6146100545780634f1ef286146100875780635c60da1b146101075780638f28397014610138578063f851a4401461016b575b610052610180565b005b34801561006057600080fd5b506100526004803603602081101561007757600080fd5b50356001600160a01b031661019a565b6100526004803603604081101561009d57600080fd5b6001600160a01b0382351691908101906040810160208201356401000000008111156100c857600080fd5b8201836020820111156100da57600080fd5b803590602001918460018302840111640100000000831117156100fc57600080fd5b5090925090506101d4565b34801561011357600080fd5b5061011c610281565b604080516001600160a01b039092168252519081900360200190f35b34801561014457600080fd5b506100526004803603602081101561015b57600080fd5b50356001600160a01b03166102be565b34801561017757600080fd5b5061011c610378565b6101886103a9565b6101986101936103b1565b6103d6565b565b6101a26103fa565b6001600160a01b0316336001600160a01b031614156101c9576101c48161041f565b6101d1565b6101d1610180565b50565b6101dc6103fa565b6001600160a01b0316336001600160a01b03161415610274576101fe8361041f565b6000836001600160a01b031683836040518083838082843760405192019450600093509091505080830381855af49150503d806000811461025b576040519150601f19603f3d011682016040523d82523d6000602084013e610260565b606091505b505090508061026e57600080fd5b5061027c565b61027c610180565b505050565b600061028b6103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103b1565b90506102bb565b6102bb610180565b90565b6102c66103fa565b6001600160a01b0316336001600160a01b031614156101c9576001600160a01b0381166103245760405162461bcd60e51b815260040180806020018281038252603681526020018061057e6036913960400191505060405180910390fd5b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f61034d6103fa565b604080516001600160a01b03928316815291841660208301528051918290030190a16101c48161045f565b60006103826103fa565b6001600160a01b0316336001600160a01b031614156102b3576102ac6103fa565b3b151590565b610198610483565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5490565b3660008037600080366000845af43d6000803e8080156103f5573d6000f35b3d6000fd5b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035490565b610428816104e3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b7fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d610355565b61048b6103fa565b6001600160a01b0316336001600160a01b031614156104db5760405162461bcd60e51b815260040180806020018281038252603281526020018061054c6032913960400191505060405180910390fd5b610198610198565b6104ec816103a3565b6105275760405162461bcd60e51b815260040180806020018281038252603b8152602001806105b4603b913960400191505060405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5556fe43616e6e6f742063616c6c2066616c6c6261636b2066756e6374696f6e2066726f6d207468652070726f78792061646d696e43616e6e6f74206368616e6765207468652061646d696e206f6620612070726f787920746f20746865207a65726f206164647265737343616e6e6f742073657420612070726f787920696d706c656d656e746174696f6e20746f2061206e6f6e2d636f6e74726163742061646472657373a164736f6c634300060c000a", + "devdoc": { + "details": "Extends from BaseAdminUpgradeabilityProxy with a constructor for initializing the implementation, admin, and init data.", + "kind": "dev", + "methods": { + "admin()": { + "returns": { + "_0": "The address of the proxy admin." + } + }, + "changeAdmin(address)": { + "details": "Changes the admin of the proxy. Only the current admin can call this function.", + "params": { + "newAdmin": "Address to transfer proxy administration to." + } + }, + "constructor": { + "params": { + "_admin": "Address of the proxy administrator.", + "_data": "Data to send as msg.data to the implementation to initialize the proxied contract. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding. This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.", + "_logic": "address of the initial implementation." + } + }, + "implementation()": { + "returns": { + "_0": "The address of the implementation." + } + }, + "upgradeTo(address)": { + "details": "Upgrade the backing implementation of the proxy. Only the admin can call this function.", + "params": { + "newImplementation": "Address of the new implementation." + } + }, + "upgradeToAndCall(address,bytes)": { + "details": "Upgrade the backing implementation of the proxy and call a function on the new implementation. This is useful to initialize the proxied contract.", + "params": { + "data": "Data to send as msg.data in the low level call. It should include the signature and the parameters of the function to be called, as described in https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.", + "newImplementation": "Address of the new implementation." + } + } + }, + "title": "AdminUpgradeabilityProxy", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "constructor": "Contract constructor." + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} diff --git a/deployments/mainnet/solcInputs/671d40d1898428f733662d50d9454e10.json b/deployments/mainnet/solcInputs/671d40d1898428f733662d50d9454e10.json new file mode 100644 index 000000000..9596a2565 --- /dev/null +++ b/deployments/mainnet/solcInputs/671d40d1898428f733662d50d9454e10.json @@ -0,0 +1,477 @@ +{ + "language": "Solidity", + "sources": { + "contracts/dependencies/compound/ExponentialNoError.sol": { + "content": "// solhint-disable\n// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n uint256 constant expScale = 1e18;\n uint256 constant doubleScale = 1e36;\n uint256 constant halfExpScale = expScale / 2;\n uint256 constant mantissaOne = expScale;\n\n struct Exp {\n uint256 mantissa;\n }\n\n struct Double {\n uint256 mantissa;\n }\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint256) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / expScale;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mul_ScalarTruncate(Exp memory a, uint256 scalar) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mul_ScalarTruncateAddUInt(\n Exp memory a,\n uint256 scalar,\n uint256 addend\n ) internal pure returns (uint256) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp <= right Exp.\n */\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa <= right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp > right Exp.\n */\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa > right.mantissa;\n }\n\n /**\n * @dev returns true if Exp is exactly zero\n */\n function isZeroExp(Exp memory value) internal pure returns (bool) {\n return value.mantissa == 0;\n }\n\n function safe224(uint256 n, string memory errorMessage) internal pure returns (uint224) {\n require(n < 2**224, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2**32, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint256 a, uint256 b) internal pure returns (uint256) {\n return add_(a, b, \"addition overflow\");\n }\n\n function add_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub_(a, b, \"subtraction underflow\");\n }\n\n function sub_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\n }\n\n function mul_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / expScale;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\n }\n\n function mul_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint256 a, Double memory b) internal pure returns (uint256) {\n return mul_(a, b.mantissa) / doubleScale;\n }\n\n function mul_(uint256 a, uint256 b) internal pure returns (uint256) {\n return mul_(a, b, \"multiplication overflow\");\n }\n\n function mul_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n if (a == 0 || b == 0) {\n return 0;\n }\n uint256 c = a * b;\n require(c / a == b, errorMessage);\n return c;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\n }\n\n function div_(Exp memory a, uint256 b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Exp memory b) internal pure returns (uint256) {\n return div_(mul_(a, expScale), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\n }\n\n function div_(Double memory a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint256 a, Double memory b) internal pure returns (uint256) {\n return div_(mul_(a, doubleScale), b.mantissa);\n }\n\n function div_(uint256 a, uint256 b) internal pure returns (uint256) {\n return div_(a, b, \"divide by zero\");\n }\n\n function div_(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n function fraction(uint256 a, uint256 b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\n }\n}\n" + }, + "contracts/protocol/partnership/ODEFIVaultBooster.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { DataTypes } from \"../earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { ODEFIVaultBoosterStorage } from \"./ODEFIVaultBoosterStorage.sol\";\nimport { Modifiers } from \"../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { ExponentialNoError } from \"../../dependencies/compound/ExponentialNoError.sol\";\n\n// interfaces\nimport { IODEFIVaultBooster } from \"../../interfaces/opty/IODEFIVaultBooster.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title ODEFIVaultBooster Contract\n * @author Opty.fi inspired by Compound.finance\n * @notice Contract for managing the ODEFI rewards\n * @dev Contract contains math for calculating the ODEFI rewards for all the users\n */\ncontract ODEFIVaultBooster is IODEFIVaultBooster, ODEFIVaultBoosterStorage, ExponentialNoError, Modifiers {\n using SafeERC20 for IERC20;\n using Address for address;\n\n constructor(address _registry, address _odefi) public Modifiers(_registry) {\n _setODEFIAddress(_odefi);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function claimODEFI(address _holder) external override returns (uint256) {\n address[] memory holders = new address[](1);\n holders[0] = _holder;\n _claimODEFI(holders, allOdefiVaults);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function updateUserStateInVault(address _odefiVault, address _user) external override {\n require(_odefiVault.isContract(), \"!isContract\");\n if (odefiVaultRatePerSecond[_odefiVault] > 0) {\n odefiUserStateInVault[_odefiVault][_user].index = odefiVaultState[_odefiVault].index;\n odefiUserStateInVault[_odefiVault][_user].timestamp = odefiVaultState[_odefiVault].timestamp;\n }\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function updateOdefiVaultRatePerSecondAndVaultToken(address _odefiVault) external override returns (bool) {\n require(_odefiVault.isContract(), \"!isContract\");\n if (odefiVaultRatePerSecond[_odefiVault] > 0) {\n odefiVaultRatePerSecondAndVaultToken[_odefiVault] = IERC20(_odefiVault).totalSupply() > 0\n ? div_(mul_(odefiVaultRatePerSecond[_odefiVault], 1e18), IERC20(_odefiVault).totalSupply())\n : uint256(0);\n }\n return true;\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function updateOdefiVaultIndex(address _odefiVault) external override returns (uint224) {\n require(_odefiVault.isContract(), \"!isContract\");\n if (odefiVaultRatePerSecond[_odefiVault] > 0) {\n if (odefiVaultState[_odefiVault].index == uint224(0)) {\n odefiVaultStartTimestamp[_odefiVault] = _getBlockTimestamp();\n odefiVaultState[_odefiVault].timestamp = uint32(odefiVaultStartTimestamp[_odefiVault]);\n odefiVaultState[_odefiVault].index = uint224(odefiVaultRatePerSecondAndVaultToken[_odefiVault]);\n return odefiVaultState[_odefiVault].index;\n } else {\n uint256 _deltaSeconds = sub_(_getBlockTimestamp(), uint256(odefiVaultState[_odefiVault].timestamp));\n if (_deltaSeconds > 0) {\n uint256 _deltaSecondsSinceStart = sub_(_getBlockTimestamp(), odefiVaultStartTimestamp[_odefiVault]);\n uint256 _supplyTokens = IERC20(_odefiVault).totalSupply();\n uint256 _odefiAccrued = mul_(_deltaSeconds, odefiVaultRatePerSecond[_odefiVault]);\n uint256 _ratio = _supplyTokens > 0 ? div_(mul_(_odefiAccrued, 1e18), _supplyTokens) : uint256(0);\n uint256 _index =\n div_(\n add_(\n mul_(\n odefiVaultState[_odefiVault].index,\n sub_(\n uint256(odefiVaultState[_odefiVault].timestamp),\n odefiVaultStartTimestamp[_odefiVault]\n )\n ),\n _ratio\n ),\n _deltaSecondsSinceStart\n );\n odefiVaultState[_odefiVault] = DataTypes.RewardsState({\n index: safe224(_index, \"new index exceeds 224 bits\"),\n timestamp: safe32(_getBlockTimestamp(), \"block number exceeds 32 bits\")\n });\n }\n return odefiVaultState[_odefiVault].index;\n }\n }\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function setOdefiVaultRate(address _odefiVault, uint256 _rate) external override returns (bool) {\n require(_odefiVault.isContract(), \"!isContract\");\n require(msg.sender == rewarders[_odefiVault], \"!rewarder\");\n odefiVaultRatePerSecond[_odefiVault] = _rate;\n return true;\n }\n\n function setODEFIRewarder(address _odefiVault, address _rewarder) external onlyOperator returns (bool) {\n require(_odefiVault.isContract(), \"!isContract\");\n require(_rewarder != address(0), \"!_rewarder.address(0)\");\n rewarders[_odefiVault] = _rewarder;\n return true;\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function addOdefiVault(address _odefiVault) external override onlyOperator returns (bool) {\n require(_odefiVault.isContract(), \"!isContract\");\n for (uint256 i = 0; i < allOdefiVaults.length; i++) {\n require(allOdefiVaults[i] != _odefiVault, \"odefiVault already added\");\n }\n allOdefiVaults.push(_odefiVault);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function setOdefiVault(address _odefiVault, bool _enable) external override onlyOperator returns (bool) {\n require(_odefiVault.isContract(), \"!isContract\");\n odefiVaultEnabled[_odefiVault] = _enable;\n return true;\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function claimODEFI(address _holder, address[] memory _odefiVaults) external override returns (uint256) {\n address[] memory holders = new address[](1);\n holders[0] = _holder;\n _claimODEFI(holders, _odefiVaults);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function claimODEFI(address[] memory _holders, address[] memory _odefiVaults) external override returns (uint256) {\n _claimODEFI(_holders, _odefiVaults);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function updateUserRewards(address _odefiVault, address _user) public override {\n if (odefiVaultRatePerSecond[_odefiVault] > 0) {\n if (\n IERC20(_odefiVault).balanceOf(_user) > 0 && lastUserUpdate[_odefiVault][_user] != _getBlockTimestamp()\n ) {\n uint256 _deltaSecondsVault = sub_(_getBlockTimestamp(), odefiVaultStartTimestamp[_odefiVault]);\n uint256 _deltaSecondsUser;\n if (\n lastUserUpdate[_odefiVault][_user] != uint256(0) &&\n lastUserUpdate[_odefiVault][_user] > odefiVaultStartTimestamp[_odefiVault]\n ) {\n _deltaSecondsUser = sub_(lastUserUpdate[_odefiVault][_user], odefiVaultStartTimestamp[_odefiVault]);\n } else {\n _deltaSecondsUser = sub_(\n odefiUserStateInVault[_odefiVault][_user].timestamp,\n odefiVaultStartTimestamp[_odefiVault]\n );\n }\n uint256 _userTokens = IERC20(_odefiVault).balanceOf(_user);\n uint256 _currentOdefiVaultIndex = currentOdefiVaultIndex(_odefiVault);\n uint256 _userDelta =\n mul_(\n _userTokens,\n sub_(\n mul_(_currentOdefiVaultIndex, _deltaSecondsVault),\n mul_(odefiUserStateInVault[_odefiVault][_user].index, _deltaSecondsUser)\n )\n );\n uint256 _userAccrued = add_(odefiAccrued[_user], _userDelta);\n odefiAccrued[_user] = _userAccrued;\n }\n lastUserUpdate[_odefiVault][_user] = _getBlockTimestamp();\n }\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function rewardDepletionSeconds() public view override returns (uint256) {\n uint256 totalOdefiRate;\n for (uint256 i = 0; i < allOdefiVaults.length; i++) {\n add_(totalOdefiRate, odefiVaultRatePerSecond[allOdefiVaults[i]]);\n }\n return div_(balance(), totalOdefiRate);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function claimableODEFI(address _holder, address[] memory _odefiVaults) public view override returns (uint256) {\n uint256 claimableOdefiAmount;\n for (uint256 i = 0; i < _odefiVaults.length; i++) {\n address _odefiVault = _odefiVaults[i];\n if (odefiVaultEnabled[_odefiVault] == true) {\n uint256 _deltaSecondsUser;\n if (\n lastUserUpdate[_odefiVault][_holder] != uint256(0) &&\n lastUserUpdate[_odefiVault][_holder] > odefiVaultStartTimestamp[_odefiVault]\n ) {\n _deltaSecondsUser = sub_(\n lastUserUpdate[_odefiVault][_holder],\n odefiVaultStartTimestamp[_odefiVault]\n );\n } else {\n _deltaSecondsUser = sub_(\n odefiUserStateInVault[_odefiVault][_holder].timestamp,\n odefiVaultStartTimestamp[_odefiVault]\n );\n }\n uint256 _currentODEFIVaultIndex = currentOdefiVaultIndex(_odefiVault);\n uint256 _userDelta =\n mul_(\n IERC20(_odefiVault).balanceOf(_holder),\n sub_(\n mul_(\n _currentODEFIVaultIndex,\n sub_(_getBlockTimestamp(), odefiVaultStartTimestamp[_odefiVault])\n ),\n mul_(odefiUserStateInVault[_odefiVault][_holder].index, _deltaSecondsUser)\n )\n );\n claimableOdefiAmount = add_(claimableOdefiAmount, _userDelta);\n }\n }\n return div_(add_(claimableOdefiAmount, odefiAccrued[_holder]), 1e18);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function currentOdefiVaultIndex(address _odefiVault) public view override returns (uint256) {\n uint256 _deltaSecondsSinceStart = sub_(_getBlockTimestamp(), odefiVaultStartTimestamp[_odefiVault]);\n uint256 _deltaSeconds = sub_(_getBlockTimestamp(), uint256(odefiVaultState[_odefiVault].timestamp));\n uint256 _supplyTokens = IERC20(_odefiVault).totalSupply();\n uint256 _odefiAccrued = mul_(_deltaSeconds, odefiVaultRatePerSecond[_odefiVault]);\n uint256 _ratio = _supplyTokens > 0 ? div_(mul_(_odefiAccrued, 1e18), _supplyTokens) : uint256(0);\n uint256 _index =\n div_(\n add_(\n mul_(\n odefiVaultState[_odefiVault].index,\n sub_(uint256(odefiVaultState[_odefiVault].timestamp), odefiVaultStartTimestamp[_odefiVault])\n ),\n _ratio\n ),\n _deltaSecondsSinceStart\n );\n return _index;\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function getOdefiAddress() public view override returns (address) {\n return odefiAddress;\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function claimableODEFI(address _holder) public view override returns (uint256) {\n return claimableODEFI(_holder, allOdefiVaults);\n }\n\n /**\n * @inheritdoc IODEFIVaultBooster\n */\n function balance() public view override returns (uint256) {\n return IERC20(odefiAddress).balanceOf(address(this));\n }\n\n /**\n * @notice Claim all odefi accrued by the holders\n * @param _holders The addresses to claim ODEFI for\n * @param _odefiVaults The list of vaults to claim ODEFI in\n * @return _total amount of claimed ODEFI tokens\n */\n function _claimODEFI(address[] memory _holders, address[] memory _odefiVaults) internal returns (uint256 _total) {\n for (uint256 i = 0; i < _odefiVaults.length; i++) {\n address _odefiVault = _odefiVaults[i];\n require(odefiVaultEnabled[_odefiVault], \"odefiVault must be enabled\");\n for (uint256 j = 0; j < _holders.length; j++) {\n updateUserRewards(address(_odefiVault), _holders[j]);\n uint256 _amount = div_(odefiAccrued[_holders[j]], 1e18);\n odefiAccrued[_holders[j]] = uint256(0);\n IERC20(odefiAddress).safeTransfer(_holders[j], _amount);\n _total = add_(_total, _amount);\n }\n }\n }\n\n /**\n * @notice Set the ODEFI token's contract address\n * @param _odefi Address of ODEFI Contract\n * @return A boolean value indicating whether the operation succeeded\n */\n function _setODEFIAddress(address _odefi) internal returns (bool) {\n require(_odefi != address(0), \"!zeroAddress\");\n odefiAddress = _odefi;\n return true;\n }\n\n /**\n * @notice Get the current block timestamp\n * @return Returns the current block timestamp\n */\n function _getBlockTimestamp() internal view returns (uint256) {\n return block.timestamp;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/libraries/types/DataTypes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nlibrary DataTypes {\n /**\n * @notice Container for User Deposit/withdraw operations\n * @param account User's address\n * @param isDeposit True if it is deposit and false if it withdraw\n * @param value Amount to deposit/withdraw\n */\n struct UserDepositOperation {\n address account;\n uint256 value;\n }\n\n /**\n * @notice Container for token balance in vault contract in a specific block\n * @param actualVaultValue current balance of the vault contract\n * @param blockMinVaultValue minimum balance recorded for vault contract in the same block\n * @param blockMaxVaultValue maximum balance recorded for vault contract in the same block\n */\n struct BlockVaultValue {\n uint256 actualVaultValue;\n uint256 blockMinVaultValue;\n uint256 blockMaxVaultValue;\n }\n\n /**\n * @notice Container for Strategy Steps used by Strategy\n * @param pool Liquidity Pool address\n * @param outputToken Output token of the liquidity pool\n * @param isBorrow If borrow is allowed or not for the liquidity pool\n */\n struct StrategyStep {\n address pool;\n address outputToken;\n bool isBorrow;\n }\n\n /**\n * @notice Container for pool's configuration\n * @param rating Rating of the liquidity pool\n * @param isLiquidityPool If pool is enabled as liquidity pool\n */\n struct LiquidityPool {\n uint8 rating;\n bool isLiquidityPool;\n }\n\n /**\n * @notice Container for Strategy used by Vault contract\n * @param index Index at which strategy is stored\n * @param strategySteps StrategySteps consisting pool, outputToken and isBorrow\n */\n struct Strategy {\n uint256 index;\n StrategyStep[] strategySteps;\n }\n\n /**\n * @notice Container for all Tokens\n * @param index Index at which token is stored\n * @param tokens List of token addresses\n */\n struct Token {\n uint256 index;\n address[] tokens;\n }\n\n /**\n * @notice Container for pool and its rating\n * @param pool Address of liqudity pool\n * @param rate Value to be set as rate for the liquidity pool\n */\n struct PoolRate {\n address pool;\n uint8 rate;\n }\n\n /**\n * @notice Container for mapping the liquidity pool and adapter\n * @param pool liquidity pool address\n * @param adapter adapter contract address corresponding to pool\n */\n struct PoolAdapter {\n address pool;\n address adapter;\n }\n\n /**\n * @notice Container for having limit range for the pools\n * @param lowerLimit liquidity pool rate's lower limit\n * @param upperLimit liquidity pool rate's upper limit\n */\n struct PoolRatingsRange {\n uint8 lowerLimit;\n uint8 upperLimit;\n }\n\n /**\n * @notice Container for having limit range for withdrawal fee\n * @param lowerLimit withdrawal fee's lower limit\n * @param upperLimit withdrawal fee's upper limit\n */\n struct WithdrawalFeeRange {\n uint256 lowerLimit;\n uint256 upperLimit;\n }\n\n /**\n * @notice Container for containing risk Profile's configuration\n * @param index Index at which risk profile is stored\n * @param canBorrow True if borrow is allowed for the risk profile\n * @param poolRatingsRange Container for having limit range for the pools\n * @param exists if risk profile exists or not\n */\n struct RiskProfile {\n uint256 index;\n bool canBorrow;\n PoolRatingsRange poolRatingsRange;\n bool exists;\n string name;\n string symbol;\n }\n\n /**\n * @notice Container for holding percentage of reward token to hold and convert\n * @param hold reward token hold percentage in basis point\n * @param convert reward token convert percentage in basis point\n */\n struct VaultRewardStrategy {\n uint256 hold; // should be in basis eg: 50% means 5000\n uint256 convert; // should be in basis eg: 50% means 5000\n }\n\n /**\n * @notice Container for token hash details\n * @param tokensHash the hash of tokens\n * @param tokens the array of tokens' addresses\n */\n struct TokensHashDetail {\n bytes32 tokensHash;\n address[] tokens;\n }\n\n /** @notice Named Constants for defining max exposure state */\n enum MaxExposure { Number, Pct }\n\n /** @notice Named Constants for defining default strategy state */\n enum DefaultStrategyState { Zero, CompoundOrAave }\n\n /**\n * @notice Container for persisting ODEFI contract's state\n * @param index The market's last index\n * @param timestamp The block number the index was last updated at\n */\n struct RewardsState {\n uint224 index;\n uint32 timestamp;\n }\n\n /**\n * @notice Container for Treasury accounts along with their shares\n * @param treasury treasury account address\n * @param share treasury's share in percentage from the withdrawal fee\n */\n struct TreasuryShare {\n address treasury;\n uint256 share; // should be in basis eg: 5% means 500\n }\n\n /**\n * @notice Container for combining Vault contract's configuration\n * @param discontinued If the vault contract is discontinued or not\n * @param unpaused If the vault contract is paused or unpaused\n * @param withdrawalFee withdrawal fee for a particular vault contract\n * @param treasuryShares Treasury accounts along with their shares\n * @param isLimitedState If the vault contract has a limit for total user deposits\n * @param allowWhitelistedState If the vault contract require whitelisted users or not\n * @param userDepositCap Maximum total amount that can be deposited by an address\n * @param minimumDepositAmount Minimum deposit without rebalance allowed\n * @param totalValueLockedLimitInUnderlying Maximum TVL in underlying allowed for the vault\n * @param queueCap Maximum length of the deposits without rebalance queue\n */\n struct VaultConfiguration {\n bool discontinued;\n bool unpaused;\n bool isLimitedState;\n bool allowWhitelistedState;\n TreasuryShare[] treasuryShares;\n uint256 withdrawalFee; // should be in basis eg: 15% means 1500\n uint256 userDepositCap;\n uint256 minimumDepositAmount;\n uint256 totalValueLockedLimitInUnderlying;\n uint256 queueCap;\n }\n\n /**\n * @notice Container for combining Vault contract's configuration\n * @param emergencyShutdown If the vault contract is in emergencyShutdown\n * state or not\n * @param unpaused If the vault contract is paused or unpaused\n * Following operations cannot happen if vault is paused:\n * - deposit of underlying tokens\n * - withdraw and transfer of vault tokens\n * @param allowWhitelistedState vault's whitelisted state flag\n * @param vaultFeeCollector address that collects vault deposit and withdraw fee\n * @param depositFeeFlatUT flat deposit fee in underlying token\n * @param depositFeePct deposit fee in percentage basis points\n * @param withdrawalFeeFlatUT flat withdrawal fee in underlying token\n * @param withdrawalFeePct withdrawal fee in percentage basis points\n */\n struct VaultConfigurationV2 {\n bool emergencyShutdown;\n bool unpaused;\n bool allowWhitelistedState;\n address vaultFeeCollector;\n uint256 depositFeeFlatUT;\n uint256 depositFeePct;\n uint256 withdrawalFeeFlatUT;\n uint256 withdrawalFeePct;\n }\n\n /**\n * @notice Container for persisting all strategy related contract's configuration\n * @param investStrategyRegistry investStrategyRegistry contract address\n * @param strategyProvider strategyProvider contract address\n * @param aprOracle aprOracle contract address\n */\n struct StrategyConfiguration {\n address investStrategyRegistry;\n address strategyProvider;\n address aprOracle;\n }\n\n /**\n * @notice Container for persisting contract addresses required by vault contract\n * @param strategyManager strategyManager contract address\n * @param riskManager riskManager contract address\n * @param optyDistributor optyDistributor contract address\n * @param operator operator contract address\n */\n struct VaultStrategyConfiguration {\n address strategyManager;\n address riskManager;\n address optyDistributor;\n address odefiVaultBooster;\n address operator;\n }\n\n /**\n * @notice Container for strategy configuration parameters\n * @param registryContract address of Registry contract\n * @param vault address of vault contract\n * @param underlyingToken address of the underlying token\n * @param initialStepInputAmount value in lp token or underlying token at initial strategy step\n * @param internalTransactionIndex index of the internal transaction for a strategy to execute\n * @param internalTransactionCount count of internal transaction for a strategy to execute\n */\n struct StrategyConfigurationParams {\n address registryContract;\n address payable vault;\n address underlyingToken;\n uint256 initialStepInputAmount;\n uint256 internalTransactionIndex;\n uint256 internalTransactionCount;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.2 <0.8.0;\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 function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n uint256 size;\n // solhint-disable-next-line no-inline-assembly\n assembly { size := extcodesize(account) }\n return size > 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 // solhint-disable-next-line avoid-low-level-calls, avoid-call-value\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(address target, bytes memory data, string memory errorMessage) 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(address target, bytes memory data, uint256 value) 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(address target, bytes memory data, uint256 value, string memory errorMessage) 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 // solhint-disable-next-line avoid-low-level-calls\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(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\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(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return _verifyCallResult(success, returndata, errorMessage);\n }\n\n function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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 // solhint-disable-next-line no-inline-assembly\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/protocol/partnership/ODEFIVaultBoosterStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { DataTypes } from \"../earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\n\n/**\n * @title VaultBoosterStorage Contract\n * @author Opty.fi\n * @notice Contract stores VaultBooster's state variables data\n */\ncontract ODEFIVaultBoosterStorage {\n /** @notice ODEFI token address */\n address public odefiAddress;\n\n /** @notice Mapping ODEFI vault address to ODEFI community address */\n mapping(address => address) public rewarders;\n\n /** @notice Mapping of ODEFI vault address to first interaction timestamp */\n mapping(address => uint256) public odefiVaultStartTimestamp;\n\n /** @notice List of all ODEFI vaults */\n address[] public allOdefiVaults;\n\n /** @notice If the ODEFI vault is enabled or not */\n mapping(address => bool) public odefiVaultEnabled;\n\n /** @notice The rate at which the flywheel distributes ODEFI, per block */\n uint256 public odefiTotalRate;\n\n /** @notice The portion of odefiRate that each market currently receives */\n mapping(address => uint256) public odefiVaultRatePerSecond;\n\n /** @notice The portion of odefiRate that each market currently receives divided by the amount of LP tokens */\n mapping(address => uint256) public odefiVaultRatePerSecondAndVaultToken;\n\n /** @notice The ODEFI accrued but not yet transferred to each user */\n mapping(address => uint256) public odefiAccrued;\n\n /** @notice The ODEFI market supply state for each pool */\n mapping(address => DataTypes.RewardsState) public odefiVaultState;\n\n /** @notice The ODEFI index for each market for each user as of the last time they accrued ODEFI */\n mapping(address => mapping(address => DataTypes.RewardsState)) public odefiUserStateInVault;\n\n /** @notice Mapping of ODEFI vault address to user address to user last interaction timestamp */\n mapping(address => mapping(address => uint256)) public lastUserUpdate;\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/Modifiers.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n// interfaces\nimport { IRegistry } from \"./interfaces/opty/IRegistry.sol\";\nimport { IModifiers } from \"./interfaces/opty/IModifiers.sol\";\n\n/**\n * @title Modifiers Contract\n * @author Opty.fi\n * @notice Contract used to keep all the modifiers at one place\n * @dev Contract is used throughout the contracts expect registry contract\n */\nabstract contract Modifiers is IModifiers {\n /**\n * @notice Registry contract instance address\n */\n IRegistry public registryContract;\n\n using Address for address;\n\n constructor(address _registry) internal {\n registryContract = IRegistry(_registry);\n }\n\n /**\n * @inheritdoc IModifiers\n */\n function setRegistry(address _registry) external override onlyOperator {\n require(_registry.isContract(), \"!isContract\");\n registryContract = IRegistry(_registry);\n }\n\n /**\n * @notice Modifier to check if the address is zero address or not\n */\n modifier onlyValidAddress() {\n require(msg.sender != address(0), \"caller is zero address\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is governance or not\n */\n modifier onlyGovernance() {\n require(msg.sender == registryContract.getGovernance(), \"caller is not having governance\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is financeOperator or not\n */\n modifier onlyFinanceOperator() {\n require(msg.sender == registryContract.getFinanceOperator(), \"caller is not the financeOperator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is riskOperator or not\n */\n modifier onlyRiskOperator() {\n require(msg.sender == registryContract.getRiskOperator(), \"caller is not the riskOperator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is operator or not\n */\n modifier onlyStrategyOperator() {\n require(msg.sender == registryContract.getStrategyOperator(), \"caller is not the strategyOperator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is operator or not\n */\n modifier onlyOperator() {\n require(msg.sender == registryContract.getOperator(), \"caller is not the operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is optyDistributor or not\n */\n modifier onlyOPTYDistributor() {\n require(msg.sender == registryContract.getOPTYDistributor(), \"!optyDistributor\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is registry or not\n */\n modifier onlyRegistry() {\n require(msg.sender == address(registryContract), \"!Registry Contract\");\n _;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.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 SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(IERC20 token, address from, address to, uint256 value) 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(IERC20 token, address spender, uint256 value) 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 // solhint-disable-next-line max-line-length\n require((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(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n uint256 newAllowance = token.allowance(address(this), spender).sub(value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\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) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "contracts/interfaces/opty/IODEFIVaultBooster.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { DataTypes } from \"../../protocol/earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for ODEFIVaultBooster Contract\n * @author Opty.fi inspired by Compound.finance\n * @notice Interface for managing the ODEFI rewards\n */\ninterface IODEFIVaultBooster {\n /**\n * @notice Claim all the ODEFI accrued by holder in all markets\n * @param _holder User's address to claim ODEFI\n * @return Total No. of ODEFI tokens accrued by holder in all markets\n */\n function claimODEFI(address _holder) external returns (uint256);\n\n /**\n * @notice Claim all the ODEFI accrued by holder in the specified markets\n * @param _holder User's address to claim ODEFI\n * @param _odefiVaults The list of ODEFI vaults to claim ODEFI\n * @return Total No. of ODEFI tokens accrued by holder in specified odefiVaults\n */\n function claimODEFI(address _holder, address[] memory _odefiVaults) external returns (uint256);\n\n /**\n * @notice Claim all ODEFI accrued by the holders\n * @param _holders The addresses to claim ODEFI for\n * @param _odefiVaults The list of vaults to claim ODEFI in\n * @return Total No. of ODEFI tokens accrued by holders in specified odefiVaults\n */\n function claimODEFI(address[] memory _holders, address[] memory _odefiVaults) external returns (uint256);\n\n /**\n * @notice Calculate additional accrued ODEFI for a contributor since last accrual\n * @dev Update user rewards acc. to user state and ODEFI vault index in the ODEFI vault\n * @param _odefiVault ODEFI Vault's address to update ODEFI reward token\n * @param _user User address to calculate contributor rewards\n */\n function updateUserRewards(address _odefiVault, address _user) external;\n\n /**\n * @notice Update the user's state in ODEFI vault contract\n * @dev Updates the last ODEFI vault index and timestamp\n * @param _odefiVault ODEFI Vault's address\n * @param _user User address to update his last ODEFI index and timestamp\n */\n function updateUserStateInVault(address _odefiVault, address _user) external;\n\n /**\n * @notice Set the ODEFI rate for a specific pool\n * @dev Set the ODEFI rate in ODEFI per second per vault token for a specific pool\n * @param _odefiVault ODEFI Vault's address\n * @return Returns a boolean whether the operation succeeded or not\n */\n function updateOdefiVaultRatePerSecondAndVaultToken(address _odefiVault) external returns (bool);\n\n /**\n * @notice Updates the vault's state\n * @dev Stores the last ODEFI vault rate as well as timestamp\n * @param _odefiVault ODEFI Vault's address\n * @return Returns the ODEFI vault index\n */\n function updateOdefiVaultIndex(address _odefiVault) external returns (uint224);\n\n /**\n * @notice Set the ODEFI rate for a specific pool\n * @dev Sets the rate in reward tokens per second\n * @param _odefiVault ODEFI Vault's address\n * @param _rate Rate to be set for ODEFI token\n * @return Returns a boolean whether opertaion succeeded or not\n */\n function setOdefiVaultRate(address _odefiVault, uint256 _rate) external returns (bool);\n\n /**\n * @notice Adding new ODEFI vault address\n * @param _odefiVault ODEFI Vault's address\n * @return Returns a boolean whether opertaion is succeeded or not\n */\n function addOdefiVault(address _odefiVault) external returns (bool);\n\n /**\n * @notice Enabling the ODEFI vault\n * @param _odefiVault ODEFI Vault's address\n * @param _enable ODEFI vault is enabled or not\n * @return Returns a boolean whether opertaion is succeeded or not\n */\n function setOdefiVault(address _odefiVault, bool _enable) external returns (bool);\n\n /**\n * @notice Claim all the ODEFI accrued by holder in all markets\n * @param _holder The address to claim ODEFI for\n * @return Returns the no. of claimable ODEFI tokens\n */\n function claimableODEFI(address _holder) external view returns (uint256);\n\n /**\n * @notice Claim all the ODEFI accrued by holder in the specified markets\n * @param _holder The address to claim ODEFI for\n * @param _odefiVaults The list of vaults to claim ODEFI in\n * @return Returns the no. of claimable ODEFI tokens\n */\n function claimableODEFI(address _holder, address[] memory _odefiVaults) external view returns (uint256);\n\n /**\n * @notice Get the index of the specified ODEFI vault\n * @param _odefiVault The list of vaults to claim ODEFI in\n * @return Returns the index of ODEFI vault\n */\n function currentOdefiVaultIndex(address _odefiVault) external view returns (uint256);\n\n /**\n * @notice Get the no. of ODEFI tokens balance in the Vault booster contract\n * @return Returns the no. of ODEFI tokens in the Vault booster contract\n */\n function balance() external view returns (uint256);\n\n /**\n * @notice Get the no. of seconds until the ODEFI distribution has ended\n * @dev Divides the ODEFI tokens balance by the sum of all the ODEFI rates per second in all the vaults\n * @return Returns the no. of seconds until ODEFI distribution has ended\n */\n function rewardDepletionSeconds() external view returns (uint256);\n\n /**\n * @notice Get the ODEFI token address\n * @return Returns the address of ODEFI token\n */\n function getOdefiAddress() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <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 `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, 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 `sender` to `recipient` 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(address sender, address recipient, uint256 amount) 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/protocol/earn-protocol-configuration/contracts/interfaces/opty/IRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for Registry Contract\n * @author Opty.fi\n * @notice Interface of the opty.fi's protocol reegistry to store all the mappings, governance\n * operator, minter, strategist and all optyFi's protocol contract addresses\n */\ninterface IRegistry {\n /**\n * @notice Set the treasury's address for optyfi's earn protocol\n * @param _treasury Treasury's address\n */\n function setTreasury(address _treasury) external;\n\n /**\n * @notice Set the StrategyProvider contract address\n * @param _strategyProvider Address of StrategyProvider Contract\n */\n function setStrategyProvider(address _strategyProvider) external;\n\n /**\n * @notice Set the RiskManager's contract address\n * @param _riskManager Address of RiskManager Contract\n */\n function setRiskManager(address _riskManager) external;\n\n /**\n * @notice Set the HarvestCodeProvider contract address\n * @param _harvestCodeProvider Address of HarvestCodeProvider Contract\n */\n function setHarvestCodeProvider(address _harvestCodeProvider) external;\n\n /**\n * @notice Set the $OPTY token's contract address\n * @param _opty Address of Opty Contract\n */\n function setOPTY(address _opty) external;\n\n /**\n * @notice Set the ODEFIVaultBooster contract address\n * @dev Can only be called by the current governance\n * @param _odefiVaultBooster address of the ODEFIVaultBooster Contract\n */\n function setODEFIVaultBooster(address _odefiVaultBooster) external;\n\n /**\n * @dev Sets multiple `_token` from the {tokens} mapping.\n * @notice Approves multiple tokens in one transaction\n * @param _tokens List of tokens to approve\n */\n function approveToken(address[] memory _tokens) external;\n\n /**\n * @notice Approves the token provided\n * @param _token token to approve\n */\n function approveToken(address _token) external;\n\n /**\n * @notice Disable multiple tokens in one transaction\n * @param _tokens List of tokens to revoke\n */\n function revokeToken(address[] memory _tokens) external;\n\n /**\n * @notice Disable the token\n * @param _token token to revoke\n */\n function revokeToken(address _token) external;\n\n /**\n * @notice Approves multiple liquidity pools in one transaction\n * @param _pools list of liquidity/credit pools to approve\n */\n function approveLiquidityPool(address[] memory _pools) external;\n\n /**\n * @notice For approving single liquidity pool\n * @param _pool liquidity/credit pool to approve\n */\n function approveLiquidityPool(address _pool) external;\n\n /**\n * @notice Revokes multiple liquidity pools in one transaction\n * @param _pools list of liquidity/credit pools to revoke\n */\n function revokeLiquidityPool(address[] memory _pools) external;\n\n /**\n * @notice Revokes the liquidity pool\n * @param _pool liquidity/credit pool to revoke\n */\n function revokeLiquidityPool(address _pool) external;\n\n /**\n * @notice Sets multiple pool rates and liquidity pools provided\n * @param _poolRates List of pool rates ([_pool, _rate]) to set\n */\n function rateLiquidityPool(DataTypes.PoolRate[] memory _poolRates) external;\n\n /**\n * @notice Sets the pool rate for the liquidity pool provided\n * @param _pool liquidityPool to map with its rating\n * @param _rate rate for the liquidityPool provided\n */\n function rateLiquidityPool(address _pool, uint8 _rate) external;\n\n /**\n * @notice Approve and map the multiple pools to their adapter\n * @param _poolAdapters List of [pool, adapter] pairs to set\n */\n function approveLiquidityPoolAndMapToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters) external;\n\n /**\n * @notice Approve and map the pool to the adapter\n * @param _pool the address of liquidity pool\n * @param _adapter the address of adapter\n */\n function approveLiquidityPoolAndMapToAdapter(address _pool, address _adapter) external;\n\n /**\n * @notice Approves multiple credit pools in one transaction\n * @param _pools List of pools for approval to be considered as creditPool\n */\n function approveCreditPool(address[] memory _pools) external;\n\n /**\n * @notice Approves the credit pool\n * @param _pool credit pool address to be approved\n */\n function approveCreditPool(address _pool) external;\n\n /**\n * @notice Revokes multiple credit pools in one transaction\n * @param _pools List of pools for revoking from being used as creditPool\n */\n function revokeCreditPool(address[] memory _pools) external;\n\n /**\n * @notice Revokes the credit pool\n * @param _pool pool for revoking from being used as creditPool\n */\n function revokeCreditPool(address _pool) external;\n\n /**\n * @notice Sets the multiple pool rates and credit pools provided\n * @param _poolRates List of pool rates ([_pool, _rate]) to set for creditPool\n */\n function rateCreditPool(DataTypes.PoolRate[] memory _poolRates) external;\n\n /**\n * @notice Sets the pool rate for the credit pool provided\n * @param _pool creditPool to map with its rating\n * @param _rate rate for the creaditPool provided\n */\n function rateCreditPool(address _pool, uint8 _rate) external;\n\n /**\n * @notice Maps multiple liquidity pools to their protocol adapters\n * @param _poolAdapters List of [pool, adapter] pairs to set\n */\n function setLiquidityPoolToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters) external;\n\n /**\n * @notice Maps liquidity pool to its protocol adapter\n * @param _pool liquidityPool to map with its adapter\n * @param _adapter adapter for the liquidityPool provided\n */\n function setLiquidityPoolToAdapter(address _pool, address _adapter) external;\n\n /**\n * @notice Maps multiple token pairs to their keccak256 hash\n * @param _tokensHashesDetails List of mulitple tokens' hashes details\n */\n function setTokensHashToTokens(DataTypes.TokensHashDetail[] memory _tokensHashesDetails) external;\n\n /**\n * @notice Sets token pair to its keccak256 hash\n * @param _tokensHash Hash of tokens\n * @param _tokens List of tokens\n */\n function setTokensHashToTokens(bytes32 _tokensHash, address[] memory _tokens) external;\n\n /**\n * @notice Approve tokens and map tokens hash\n * @param _tokensHash Hash of tokens\n * @param _tokens List of tokens\n */\n function approveTokenAndMapToTokensHash(bytes32 _tokensHash, address[] memory _tokens) external;\n\n /**\n * @notice Approve tokens and map multiple tokens'hashes\n * @param _tokensHashesDetails List of mulitple tokens' hashes details\n */\n function approveTokenAndMapToTokensHash(DataTypes.TokensHashDetail[] memory _tokensHashesDetails) external;\n\n /**\n * @notice Adds the risk profile in Registry contract Storage\n * @param _riskProfileCode code of riskProfile\n * @param _name name of riskProfile\n * @param _symbol symbol of riskProfile\n * @param _canBorrow A boolean value indicating whether the riskProfile allows borrow step\n * @param _poolRatingRange pool rating range ([lowerLimit, upperLimit]) supported by given risk profile\n */\n function addRiskProfile(\n uint256 _riskProfileCode,\n string memory _name,\n string memory _symbol,\n bool _canBorrow,\n DataTypes.PoolRatingsRange memory _poolRatingRange\n ) external;\n\n /**\n * @notice Adds list of the risk profiles in Registry contract Storage in one transaction\n * @dev All parameters must be in the same order.\n * @param _riskProfileCodes codes of riskProfiles\n * @param _names names of riskProfiles\n * @param _symbols symbols of riskProfiles\n * @param _canBorrow List of boolean values indicating whether the riskProfile allows borrow step\n * @param _poolRatingRanges List of pool rating range supported by given list of risk profiles\n */\n function addRiskProfile(\n uint256[] memory _riskProfileCodes,\n string[] memory _names,\n string[] memory _symbols,\n bool[] memory _canBorrow,\n DataTypes.PoolRatingsRange[] memory _poolRatingRanges\n ) external;\n\n /**\n * @notice Change the borrow permission for existing risk profile\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * to update with strategy steps\n * @param _canBorrow A boolean value indicating whether the riskProfile allows borrow step\n */\n function updateRiskProfileBorrow(uint256 _riskProfileCode, bool _canBorrow) external;\n\n /**\n * @notice Update the pool ratings for existing risk profile\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * to update with pool rating range\n * @param _poolRatingRange pool rating range ([lowerLimit, upperLimit]) to update for given risk profile\n */\n function updateRPPoolRatings(uint256 _riskProfileCode, DataTypes.PoolRatingsRange memory _poolRatingRange) external;\n\n /**\n * @notice Remove the existing risk profile in Registry contract Storage\n * @param _index Index of risk profile to be removed\n */\n function removeRiskProfile(uint256 _index) external;\n\n /**\n * @notice Get the list of tokensHash\n * @return Returns the list of tokensHash.\n */\n function getTokenHashes() external view returns (bytes32[] memory);\n\n /**\n * @notice Get list of token given the tokensHash\n * @return Returns the list of tokens corresponding to tokensHash\n */\n function getTokensHashToTokenList(bytes32 _tokensHash) external view returns (address[] memory);\n\n /**\n * @notice Get the list of all the riskProfiles\n * @return Returns the list of all riskProfiles stored in Registry Storage\n */\n function getRiskProfileList() external view returns (uint256[] memory);\n\n /**\n * @notice Retrieve the StrategyProvider contract address\n * @return Returns the StrategyProvider contract address\n */\n function getStrategyProvider() external view returns (address);\n\n /**\n * @notice Retrieve the RiskManager contract address\n * @return Returns the RiskManager contract address\n */\n function getRiskManager() external view returns (address);\n\n /**\n * @notice Retrieve the OPTYDistributor contract address\n * @return Returns the OPTYDistributor contract address\n */\n function getOPTYDistributor() external view returns (address);\n\n /**\n * @notice Retrieve the ODEFIVaultBooster contract address\n * @return Returns the ODEFIVaultBooster contract address\n */\n function getODEFIVaultBooster() external view returns (address);\n\n /**\n * @notice Retrieve the Governance address\n * @return Returns the Governance address\n */\n function getGovernance() external view returns (address);\n\n /**\n * @notice Retrieve the FinanceOperator address\n * @return Returns the FinanceOperator address\n */\n function getFinanceOperator() external view returns (address);\n\n /**\n * @notice Retrieve the RiskOperator address\n * @return Returns the RiskOperator address\n */\n function getRiskOperator() external view returns (address);\n\n /**\n * @notice Retrieve the StrategyOperator address\n * @return Returns the StrategyOperator address\n */\n function getStrategyOperator() external view returns (address);\n\n /**\n * @notice Retrieve the Operator address\n * @return Returns the Operator address\n */\n function getOperator() external view returns (address);\n\n /**\n * @notice Retrieve the HarvestCodeProvider contract address\n * @return Returns the HarvestCodeProvider contract address\n */\n function getHarvestCodeProvider() external view returns (address);\n\n /**\n * @notice Get the properties corresponding to riskProfile code provided\n * @return _riskProfile Returns the properties corresponding to riskProfile provided\n */\n function getRiskProfile(uint256) external view returns (DataTypes.RiskProfile memory _riskProfile);\n\n /**\n * @notice Get the index corresponding to tokensHash provided\n * @param _tokensHash Hash of token address/addresses\n * @return _index Returns the index corresponding to tokensHash provided\n */\n function getTokensHashIndexByHash(bytes32 _tokensHash) external view returns (uint256 _index);\n\n /**\n * @notice Get the tokensHash available at the index provided\n * @param _index Index at which you want to get the tokensHash\n * @return _tokensHash Returns the tokensHash available at the index provided\n */\n function getTokensHashByIndex(uint256 _index) external view returns (bytes32 _tokensHash);\n\n /**\n * @notice Get the rating and Is pool a liquidity pool for the _pool provided\n * @param _pool Liquidity Pool (like cDAI etc.) address\n * @return _liquidityPool Returns the rating and Is pool a liquidity pool for the _pool provided\n */\n function getLiquidityPool(address _pool) external view returns (DataTypes.LiquidityPool memory _liquidityPool);\n\n /**\n * @notice Get the adapter address mapped to the _pool provided\n * @param _pool Liquidity Pool (like cDAI etc.) address\n * @return _adapter Returns the adapter address mapped to the _pool provided\n */\n function getLiquidityPoolToAdapter(address _pool) external view returns (address _adapter);\n\n /**\n * @notice Check if the token is approved or not\n * @param _token Token address for which to check if it is approved or not\n * @return _isTokenApproved Returns a boolean for token approved or not\n */\n function isApprovedToken(address _token) external view returns (bool _isTokenApproved);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IModifiers.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Interface for Modifiers Contract\n * @author Opty.fi\n * @notice Interface used to set the registry contract address\n */\ninterface IModifiers {\n /**\n * @notice Sets the regsitry contract address\n * @param _registry address of registry contract\n */\n function setRegistry(address _registry) external;\n}\n" + }, + "@openzeppelin/contracts/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b <= a, \"SafeMath: subtraction overflow\");\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n if (a == 0) return 0;\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: division by zero\");\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n require(b > 0, \"SafeMath: modulo by zero\");\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryDiv}.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b > 0, errorMessage);\n return a % b;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/sushiswap-farm/SushiswapMasterChefV1Adapter.sol": { + "content": "// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { ISushiswapMasterChef } from \"@optyfi/defi-legos/ethereum/sushiswap/contracts/ISushiswapMasterChef.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for Sushiswap protocol\n * @author Opty.fi\n * @dev Abstraction layer to Sushiswap's MasterChef contract\n */\n\ncontract SushiswapMasterChefV1Adapter is IAdapter, IAdapterInvestLimit, IAdapterHarvestReward, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice Sushiswap router contract address */\n address public constant SUSHISWAP_ROUTER = address(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F);\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n /** @notice Maps underlyingToken to the ID of its pool */\n mapping(address => uint256) public underlyingTokenToPid;\n\n /** @notice List of Sushiswap pairs */\n address public constant USDC_WETH = address(0x397FF1542f962076d0BFE58eA045FfA2d347ACa0);\n address public constant DAI_WETH = address(0xC3D03e4F041Fd4cD388c549Ee2A29a9E5075882f);\n address public constant COMP_WETH = address(0x31503dcb60119A812feE820bb7042752019F2355);\n address public constant SNX_WETH = address(0xA1d7b2d891e3A1f9ef4bBC5be20630C2FEB1c470);\n address public constant LINK_WETH = address(0xC40D16476380e4037e6b1A2594cAF6a6cc8Da967);\n address public constant SUSHI_WETH = address(0x795065dCc9f64b5614C407a6EFDC400DA6221FB0);\n address public constant UNI_WETH = address(0xDafd66636E2561b0284EDdE37e42d192F2844D40);\n address public constant XSUSHI_WETH = address(0x36e2FCCCc59e5747Ff63a03ea2e5C0c2C14911e7);\n address public constant WBTC_WETH = address(0xCEfF51756c56CeFFCA006cD410B03FFC46dd3a58);\n address public constant AAVE_WETH = address(0xD75EA151a61d06868E31F8988D28DFE5E9df57B4);\n address public constant LDO_WETH = address(0xC558F600B34A5f69dD2f0D06Cb8A88d829B7420a);\n address public constant MANA_WETH = address(0x1bEC4db6c3Bc499F3DbF289F5499C30d541FEc97);\n address public constant ILV_WETH = address(0x6a091a3406E0073C3CD6340122143009aDac0EDa);\n\n constructor(address _registry) public Modifiers(_registry) {\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n underlyingTokenToPid[USDC_WETH] = uint256(1);\n underlyingTokenToPid[DAI_WETH] = uint256(2);\n underlyingTokenToPid[COMP_WETH] = uint256(4);\n underlyingTokenToPid[SNX_WETH] = uint256(6);\n underlyingTokenToPid[LINK_WETH] = uint256(8);\n underlyingTokenToPid[SUSHI_WETH] = uint256(12);\n underlyingTokenToPid[UNI_WETH] = uint256(18);\n underlyingTokenToPid[XSUSHI_WETH] = uint256(19);\n underlyingTokenToPid[WBTC_WETH] = uint256(21);\n underlyingTokenToPid[AAVE_WETH] = uint256(37);\n underlyingTokenToPid[LDO_WETH] = uint256(109);\n underlyingTokenToPid[MANA_WETH] = uint256(240);\n underlyingTokenToPid[ILV_WETH] = uint256(244);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _underlyingToken, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_underlyingToken] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _masterChef,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_masterChef][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_masterChef][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _masterChef\n ) external view override returns (bytes[] memory) {\n return getDepositSomeCodes(_vault, _underlyingToken, _masterChef, IERC20(_underlyingToken).balanceOf(_vault));\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _masterChef\n ) external view override returns (bytes[] memory) {\n return\n getWithdrawSomeCodes(\n _vault,\n _underlyingToken,\n _masterChef,\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _masterChef)\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address, address) external view override returns (address[] memory) {\n revert(\"!empty\");\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address,\n uint256 _amount\n ) external view override returns (uint256) {\n return _amount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address,\n uint256 _amount\n ) external view override returns (uint256) {\n return _amount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _masterChef,\n uint256\n ) external view override returns (uint256) {\n return ISushiswapMasterChef(_masterChef).userInfo(underlyingTokenToPid[_underlyingToken], _vault).amount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _masterChef,\n uint256 _redeemAmount\n ) external view override returns (bool) {\n return getAllAmountInToken(_vault, _underlyingToken, _masterChef) >= _redeemAmount;\n }\n\n /* solhint-disable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable, address) external view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _masterChef\n ) external view override returns (bytes[] memory) {\n return\n getHarvestSomeCodes(\n _vault,\n _underlyingToken,\n _masterChef,\n IERC20(getRewardToken(_masterChef)).balanceOf(_vault)\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) external view override returns (bool) {\n return false;\n }\n\n /**\n * @notice Map underlyingToken to its pool ID\n * @param _underlyingTokens pair contract addresses to be mapped with pool ID\n * @param _pids pool IDs to be linked with pair address\n */\n function setUnderlyingTokenToPid(address[] memory _underlyingTokens, uint256[] memory _pids) public onlyOperator {\n uint256 _underlyingTokensLen = _underlyingTokens.length;\n uint256 _pidsLen = _pids.length;\n require(_underlyingTokensLen == _pidsLen, \"inequal length of underlyingtokens and pids\");\n for (uint256 _i; _i < _underlyingTokensLen; _i++) {\n underlyingTokenToPid[_underlyingTokens[_i]] = _pids[_i];\n }\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /* solhint-disable no-unused-vars */\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable,\n address _underlyingToken,\n address _masterChef,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n uint256 _depositAmount = _getDepositAmount(_masterChef, _underlyingToken, _amount);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _masterChef, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _masterChef, _depositAmount)\n );\n _codes[2] = abi.encode(\n _masterChef,\n abi.encodeWithSignature(\n \"deposit(uint256,uint256)\",\n underlyingTokenToPid[_underlyingToken],\n _depositAmount\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable,\n address _underlyingToken,\n address _masterChef,\n uint256 _redeemAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_redeemAmount > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _masterChef,\n abi.encodeWithSignature(\n \"withdraw(uint256,uint256)\",\n underlyingTokenToPid[_underlyingToken],\n _redeemAmount\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _masterChef, address _underlyingToken) public view override returns (uint256) {\n return IERC20(_underlyingToken).balanceOf(_masterChef);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address _underlyingToken, address) public view override returns (address) {\n return _underlyingToken;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _masterChef\n ) public view override returns (uint256) {\n return ISushiswapMasterChef(_masterChef).userInfo(underlyingTokenToPid[_underlyingToken], _vault).amount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _masterChef\n ) public view override returns (uint256) {\n return ISushiswapMasterChef(_masterChef).userInfo(underlyingTokenToPid[_underlyingToken], _vault).amount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _masterChef) public view override returns (address) {\n return ISushiswapMasterChef(_masterChef).sushi();\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable _vault,\n address _masterChef,\n address _underlyingToken\n ) public view override returns (uint256) {\n return ISushiswapMasterChef(_masterChef).pendingSushi(underlyingTokenToPid[_underlyingToken], _vault);\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _masterChef,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_masterChef),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable _vault, address _underlyingToken)\n public\n view\n override\n returns (bytes[] memory)\n {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getAddLiquidityCodes(\n SUSHISWAP_ROUTER,\n _vault,\n _underlyingToken\n );\n }\n\n function _getDepositAmount(\n address _masterChef,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_masterChef, _underlyingToken)\n : maxDepositAmount[_masterChef][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _masterChef, address _underlyingToken) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_masterChef, _underlyingToken);\n uint256 _poolPct = maxDepositPoolPct[_underlyingToken];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/Modifiers.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n// interfaces\nimport { IRegistry } from \"./interfaces/opty/IRegistry.sol\";\nimport { IModifiers } from \"./interfaces/opty/IModifiers.sol\";\n\n/**\n * @title Modifiers Contract\n * @author Opty.fi\n * @notice Contract used to keep all the modifiers at one place\n * @dev Contract is used throughout the contracts expect registry contract\n */\nabstract contract Modifiers is IModifiers {\n /**\n * @notice Registry contract instance address\n */\n IRegistry public registryContract;\n\n using Address for address;\n\n constructor(address _registry) internal {\n registryContract = IRegistry(_registry);\n }\n\n /**\n * @inheritdoc IModifiers\n */\n function setRegistry(address _registry) external override onlyOperator {\n require(_registry.isContract(), \"!isContract\");\n registryContract = IRegistry(_registry);\n }\n\n /**\n * @notice Modifier to check if the address is zero address or not\n */\n modifier onlyValidAddress() {\n require(msg.sender != address(0), \"caller is zero address\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is governance or not\n */\n modifier onlyGovernance() {\n require(msg.sender == registryContract.getGovernance(), \"caller is not having governance\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is financeOperator or not\n */\n modifier onlyFinanceOperator() {\n require(msg.sender == registryContract.getFinanceOperator(), \"caller is not the financeOperator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is riskOperator or not\n */\n modifier onlyRiskOperator() {\n require(msg.sender == registryContract.getRiskOperator(), \"caller is not the riskOperator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is operator or not\n */\n modifier onlyStrategyOperator() {\n require(msg.sender == registryContract.getStrategyOperator(), \"caller is not the strategyOperator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is operator or not\n */\n modifier onlyOperator() {\n require(msg.sender == registryContract.getOperator(), \"caller is not the operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is optyDistributor or not\n */\n modifier onlyOPTYDistributor() {\n require(msg.sender == registryContract.getOPTYDistributor(), \"!optyDistributor\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is registry or not\n */\n modifier onlyRegistry() {\n require(msg.sender == address(registryContract), \"!Registry Contract\");\n _;\n }\n}\n" + }, + "@optyfi/defi-legos/ethereum/sushiswap/contracts/ISushiswapMasterChef.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\ninterface ISushiswapMasterChef {\n /*\n * @notice Struct that stores each of the user's states for each pair token\n */\n struct UserInfo {\n uint256 amount; // How many LP tokens the user has provided\n uint256 rewardDebt; // Reward debt\n }\n\n /*\n * @notice Function that returns the state of the user regarding a specific pair token (e.g., SUSHI-WETH-USDC)\n * @param _pid Pool ID in MasterChef contract\n * @param _user User's address\n */\n function userInfo(uint256 _pid, address _user) external view returns (UserInfo memory);\n\n /*\n * @notice Function that returns the amount of accrued SUSHI corresponding to a specific pair token\n * (e.g., SUSHI-WETH-USDC) that hasn't been claimed yet\n * @param _pid Pool ID in MasterChef contract\n * @param _user User address\n */\n function pendingSushi(uint256 _pid, address _user) external view returns (uint256);\n\n function sushi() external view returns (address);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/interfaces/IHarvestCodeProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface for HarvestCodeProvider Contract\n * @author Opty.fi\n * @notice Abstraction layer to DeFi exchanges like Uniswap\n * @dev Interface for facilitating the logic for harvest reward token codes\n */\ninterface IHarvestCodeProvider {\n /**\n * @dev Get the codes for harvesting the tokens using uniswap router\n * @param _vault Vault contract address\n * @param _rewardToken Reward token address\n * @param _underlyingToken Token address acting as underlying Asset for the vault contract\n * @param _rewardTokenAmount reward token amount to harvest\n * @return _codes List of harvest codes for harvesting reward tokens\n */\n function getHarvestCodes(\n address payable _vault,\n address _rewardToken,\n address _underlyingToken,\n uint256 _rewardTokenAmount\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @dev Get the codes for adding liquidity using Sushiswap or Uniswap router\n * @param _router Address of Router Contract\n * @param _vault Address of Vault Contract\n * @param _underlyingToken Token address acting as underlying Asset for the vault contract\n * @return _codes List of codes for adding liquidity on Uniswap or Sushiswap\n */\n function getAddLiquidityCodes(\n address _router,\n address payable _vault,\n address _underlyingToken\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @dev Get the optimal amount for the token while borrow\n * @param _borrowToken Address of token which has to be borrowed\n * @param _underlyingToken Token address acting as underlying Asset for the vault contract\n * @param _borrowTokenAmount amount of token to borrow\n * @return borrow token's optimal amount\n */\n function getOptimalTokenAmount(\n address _borrowToken,\n address _underlyingToken,\n uint256 _borrowTokenAmount\n ) external view returns (uint256);\n\n /**\n * @dev Get the underlying token amount equivalent to reward token amount\n * @param _rewardToken Reward token address\n * @param _underlyingToken Token address acting as underlying Asset for the vault contract\n * @param _amount reward token balance amount\n * @return equivalent reward token balance in Underlying token value\n */\n function rewardBalanceInUnderlyingTokens(\n address _rewardToken,\n address _underlyingToken,\n uint256 _amount\n ) external view returns (uint256);\n\n /**\n * @dev Get the no. of tokens equivalent to the amount provided\n * @param _underlyingToken Underlying token address\n * @param _amount amount in weth\n * @return equivalent WETH token balance in Underlying token value\n */\n function getWETHInToken(address _underlyingToken, uint256 _amount) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface for all the DeFi adapters\n * @author Opty.fi\n * @notice Interface with minimal functions to be inhertied in all DeFi adapters\n * @dev Abstraction layer to different DeFi protocols like AaveV1, Compound etc.\n * It is used as a layer for adding any new function which will be used in all DeFi adapters\n * Conventions used:\n * - lpToken: liquidity pool token\n */\ninterface IAdapter {\n /**\n * @notice Returns pool value in underlying token (for all adapters except Curve for which the poolValue is\n * in US dollar) for the given liquidity pool and underlyingToken\n * @dev poolValue can be in US dollar for protocols like Curve if explicitly specified, underlyingToken otherwise\n * for protocols like Compound etc.\n * @param _liquidityPool Liquidity pool's contract address\n * @param _underlyingToken Contract address of the liquidity pool's underlying token\n * @return Pool value in underlying token for the given liquidity pool and underlying token\n */\n function getPoolValue(address _liquidityPool, address _underlyingToken) external view returns (uint256);\n\n /**\n * @dev Get batch of function calls for depositing specified amount of underlying token in given liquidity pool\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where to deposit\n * @param _amount Underlying token's amount\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @dev Get batch of function calls for depositing vault's full balance in underlying tokens in given liquidity pool\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where to deposit\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @notice Get batch of function calls for redeeming specified amount of lpTokens held in the vault\n * @dev Redeem specified `amount` of `liquidityPoolToken` and send the `underlyingToken` to the caller`\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to withdraw\n * @param _amount Amount of underlying token to redeem from the given liquidity pool\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @notice Get batch of function calls for redeeming full balance of lpTokens held in the vault\n * @dev Redeem full `amount` of `liquidityPoolToken` and send the `underlyingToken` to the caller`\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to withdraw\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @notice Get the lpToken address\n * @param _underlyingToken Underlying token address\n * @param _liquidityPool Liquidity pool's contract address from where to get the lpToken\n * @return Returns the lpToken address\n */\n function getLiquidityPoolToken(address _underlyingToken, address _liquidityPool) external view returns (address);\n\n /**\n * @notice Get the underlying token addresses given the liquidity pool and/or lpToken\n * @dev there are some defi pools which requires liqudiity pool and lpToken's address to return underlying token\n * @param _liquidityPool Liquidity pool's contract address from where to get the lpToken\n * @param _liquidityPoolToken LpToken's address\n * @return _underlyingTokens Returns the array of underlying token addresses\n */\n function getUnderlyingTokens(address _liquidityPool, address _liquidityPoolToken)\n external\n view\n returns (address[] memory _underlyingTokens);\n\n /**\n * @dev Returns the market value in underlying for all the lpTokens held in a specified liquidity pool\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for which to get the balance\n * @param _liquidityPool Liquidity pool's contract address which holds the given underlying token\n * @return Returns the amount of underlying token balance\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (uint256);\n\n /**\n * @notice Get the balance of vault in lpTokens in the specified liquidity pool\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address supported by given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to get the balance of lpToken\n * @return Returns the balance of lpToken (lpToken)\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (uint256);\n\n /**\n * @notice Returns the equivalent value of underlying token for given amount of lpToken\n * @param _underlyingToken Underlying token address supported by given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to get the balance of lpToken\n * @param _liquidityPoolTokenAmount LpToken amount for which to get equivalent underlyingToken amount\n * @return Returns the equivalent amount of underlying token for given lpToken amount\n */\n function getSomeAmountInToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) external view returns (uint256);\n\n /**\n * @dev Returns the equivalent value of lpToken for given amount of underlying token\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to redeem the tokens\n * @param _underlyingTokenAmount Amount of underlying token to be calculated w.r.t. lpToken\n * @return Returns the calculated amount of lpToken equivalent to underlyingTokenAmount\n */\n function calculateAmountInLPToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _underlyingTokenAmount\n ) external view returns (uint256);\n\n /**\n * @dev Returns the market value in underlying token of the shares in the specified liquidity pool\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to redeem the tokens\n * @param _redeemAmount Amount of token to be redeemed\n * @return _amount Returns the market value in underlying token of the shares in the given liquidity pool\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external view returns (uint256 _amount);\n\n /**\n * @notice Checks whether the vault has enough lpToken (+ rewards) to redeem for the specified amount of shares\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to redeem the tokens\n * @param _redeemAmount Amount of lpToken (+ rewards) enough to redeem\n * @return Returns a boolean true if lpToken (+ rewards) to redeem for given amount is enough else it returns false\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external view returns (bool);\n\n /**\n * @notice Returns reward token address for the liquidity pool provided\n * @param _liquidityPool Liquidity pool's contract address for which to get the reward token address\n * @return Returns the reward token supported by given liquidity pool\n */\n function getRewardToken(address _liquidityPool) external view returns (address);\n\n /**\n * @notice Returns whether the protocol can stake lpToken\n * @param _liquidityPool Liquidity pool's contract address for which to check if staking is enabled or not\n * @return Returns a boolean true if lpToken staking is allowed else false if it not enabled\n */\n function canStake(address _liquidityPool) external view returns (bool);\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface for Reward tokens and Swapping tokens for the DeFi adapters\n * @author Opty.fi\n * @notice Interface of the DeFi protocol code adapter for reward tokens and swapping tokens functionality\n * @dev Abstraction layer to different DeFi protocols like Compound, Cream etc.\n * It is used as a layer for adding any new function related to reward token feature to be used in DeFi-adapters.\n * It is also used as a middleware for adding functionality of swapping/harvesting of tokens used in DeFi-adapters.\n */\ninterface IAdapterHarvestReward {\n /**\n * @notice Returns the amount of accrued reward tokens\n * @param _vault Vault contract address\n * @param _liquidityPool Liquidity pool's contract address from where to claim reward tokens\n * @param _underlyingToken Underlying token's contract address for which to claim reward tokens\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getUnclaimedRewardTokenAmount(\n address payable _vault,\n address _liquidityPool,\n address _underlyingToken\n ) external view returns (uint256 _codes);\n\n /**\n * @notice Get batch of function calls for claiming the reward tokens (eg: COMP etc.)\n * @param _vault Vault contract address\n * @param _liquidityPool Liquidity pool's contract address from where to claim reward tokens\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getClaimRewardTokenCode(address payable _vault, address _liquidityPool)\n external\n view\n returns (bytes[] memory _codes);\n\n /**\n * @dev Get batch of function calls for swapping specified amount of rewards in vault to underlying tokens\n * via DEX like Uniswap\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where the vault's deposit is generating rewards\n * @param _rewardTokenAmount Amount of reward token to be harvested to underlyingTokens via DEX\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @dev Get batch of function calls for adding liquidity in a DEX like Uniswap\n * @param _vault Vault contract address\n * @param _underlyingToken Pair token's contract address where the vault is going to provide liquidity\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getAddLiquidityCodes(address payable _vault, address _underlyingToken)\n external\n view\n returns (bytes[] memory _codes);\n\n /**\n * @dev Get batch of function calls for swapping full balance of rewards in vault to underlying tokens\n * via DEX like Uniswap\n * @param _vault Vault contract address\n * @param _underlyingToken List of underlying token addresses for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where the vault's deposit is generating rewards\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (bytes[] memory _codes);\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/** @notice Named Constants for defining max exposure state */\nenum MaxExposure { Number, Pct }\n\n/**\n * @title Interface for setting deposit invest limit for DeFi adapters except Curve\n * @author Opty.fi\n * @notice Interface of the DeFi protocol adapter for setting invest limit for deposit\n * @dev Abstraction layer to different DeFi protocols like AaveV1, Compound etc except Curve.\n * It is used as an interface layer for setting max invest limit and its type in number or percentage for DeFi adapters\n */\ninterface IAdapterInvestLimit {\n /**\n * @notice Notify when Max Deposit Protocol mode is set\n * @param maxDepositProtocolMode Mode of maxDeposit set (can be absolute value or percentage)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMaxDepositProtocolMode(MaxExposure indexed maxDepositProtocolMode, address indexed caller);\n\n /**\n * @notice Notify when Max Deposit Protocol percentage is set\n * @param maxDepositProtocolPct Protocol's max deposit percentage (in basis points, For eg: 50% means 5000)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMaxDepositProtocolPct(uint256 indexed maxDepositProtocolPct, address indexed caller);\n\n /**\n * @notice Notify when Max Deposit Pool percentage is set\n * @param maxDepositPoolPct Liquidity pool's max deposit percentage (in basis points, For eg: 50% means 5000)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMaxDepositPoolPct(uint256 indexed maxDepositPoolPct, address indexed caller);\n\n /**\n * @notice Notify when Max Deposit Amount is set\n * @param maxDepositAmount Absolute max deposit amount in underlying set for the given liquidity pool\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMaxDepositAmount(uint256 indexed maxDepositAmount, address indexed caller);\n\n /**\n * @notice Sets the absolute max deposit value in underlying for the given liquidity pool\n * @param _liquidityPool liquidity pool address for which to set max deposit value (in absolute value)\n * @param _underlyingToken address of underlying token\n * @param _maxDepositAmount absolute max deposit amount in underlying to be set for given liquidity pool\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external;\n\n /**\n * @notice Sets the percentage of max deposit value for the given liquidity pool\n * @param _liquidityPool liquidity pool address\n * @param _maxDepositPoolPct liquidity pool's max deposit percentage (in basis points, For eg: 50% means 5000)\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct) external;\n\n /**\n * @notice Sets the percentage of max deposit protocol value\n * @param _maxDepositProtocolPct protocol's max deposit percentage (in basis points, For eg: 50% means 5000)\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external;\n\n /**\n * @notice Sets the type of investment limit\n * 1. Percentage of pool value\n * 2. Amount in underlying token\n * @dev Types (can be number or percentage) supported for the maxDeposit value\n * @param _mode Mode of maxDeposit to be set (can be absolute value or percentage)\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/libraries/types/DataTypes.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nlibrary DataTypes {\n /**\n * @notice Container for User Deposit/withdraw operations\n * @param account User's address\n * @param isDeposit True if it is deposit and false if it withdraw\n * @param value Amount to deposit/withdraw\n */\n struct UserDepositOperation {\n address account;\n uint256 value;\n }\n\n /**\n * @notice Container for token balance in vault contract in a specific block\n * @param actualVaultValue current balance of the vault contract\n * @param blockMinVaultValue minimum balance recorded for vault contract in the same block\n * @param blockMaxVaultValue maximum balance recorded for vault contract in the same block\n */\n struct BlockVaultValue {\n uint256 actualVaultValue;\n uint256 blockMinVaultValue;\n uint256 blockMaxVaultValue;\n }\n\n /**\n * @notice Container for Strategy Steps used by Strategy\n * @param pool Liquidity Pool address\n * @param outputToken Output token of the liquidity pool\n * @param isBorrow If borrow is allowed or not for the liquidity pool\n */\n struct StrategyStep {\n address pool;\n address outputToken;\n bool isBorrow;\n }\n\n /**\n * @notice Container for pool's configuration\n * @param rating Rating of the liquidity pool\n * @param isLiquidityPool If pool is enabled as liquidity pool\n */\n struct LiquidityPool {\n uint8 rating;\n bool isLiquidityPool;\n }\n\n /**\n * @notice Container for Strategy used by Vault contract\n * @param index Index at which strategy is stored\n * @param strategySteps StrategySteps consisting pool, outputToken and isBorrow\n */\n struct Strategy {\n uint256 index;\n StrategyStep[] strategySteps;\n }\n\n /**\n * @notice Container for all Tokens\n * @param index Index at which token is stored\n * @param tokens List of token addresses\n */\n struct Token {\n uint256 index;\n address[] tokens;\n }\n\n /**\n * @notice Container for pool and its rating\n * @param pool Address of liqudity pool\n * @param rate Value to be set as rate for the liquidity pool\n */\n struct PoolRate {\n address pool;\n uint8 rate;\n }\n\n /**\n * @notice Container for mapping the liquidity pool and adapter\n * @param pool liquidity pool address\n * @param adapter adapter contract address corresponding to pool\n */\n struct PoolAdapter {\n address pool;\n address adapter;\n }\n\n /**\n * @notice Container for having limit range for the pools\n * @param lowerLimit liquidity pool rate's lower limit\n * @param upperLimit liquidity pool rate's upper limit\n */\n struct PoolRatingsRange {\n uint8 lowerLimit;\n uint8 upperLimit;\n }\n\n /**\n * @notice Container for having limit range for withdrawal fee\n * @param lowerLimit withdrawal fee's lower limit\n * @param upperLimit withdrawal fee's upper limit\n */\n struct WithdrawalFeeRange {\n uint256 lowerLimit;\n uint256 upperLimit;\n }\n\n /**\n * @notice Container for containing risk Profile's configuration\n * @param index Index at which risk profile is stored\n * @param canBorrow True if borrow is allowed for the risk profile\n * @param poolRatingsRange Container for having limit range for the pools\n * @param exists if risk profile exists or not\n */\n struct RiskProfile {\n uint256 index;\n bool canBorrow;\n PoolRatingsRange poolRatingsRange;\n bool exists;\n string name;\n string symbol;\n }\n\n /**\n * @notice Container for holding percentage of reward token to hold and convert\n * @param hold reward token hold percentage in basis point\n * @param convert reward token convert percentage in basis point\n */\n struct VaultRewardStrategy {\n uint256 hold; // should be in basis eg: 50% means 5000\n uint256 convert; // should be in basis eg: 50% means 5000\n }\n\n /**\n * @notice Container for token hash details\n * @param tokensHash the hash of tokens\n * @param tokens the array of tokens' addresses\n */\n struct TokensHashDetail {\n bytes32 tokensHash;\n address[] tokens;\n }\n\n /** @notice Named Constants for defining max exposure state */\n enum MaxExposure { Number, Pct }\n\n /** @notice Named Constants for defining default strategy state */\n enum DefaultStrategyState { Zero, CompoundOrAave }\n\n /**\n * @notice Container for persisting ODEFI contract's state\n * @param index The market's last index\n * @param timestamp The block number the index was last updated at\n */\n struct RewardsState {\n uint224 index;\n uint32 timestamp;\n }\n\n /**\n * @notice Container for Treasury accounts along with their shares\n * @param treasury treasury account address\n * @param share treasury's share in percentage from the withdrawal fee\n */\n struct TreasuryShare {\n address treasury;\n uint256 share; // should be in basis eg: 5% means 500\n }\n\n /**\n * @notice Container for combining Vault contract's configuration\n * @param discontinued If the vault contract is discontinued or not\n * @param unpaused If the vault contract is paused or unpaused\n * @param withdrawalFee withdrawal fee for a particular vault contract\n * @param treasuryShares Treasury accounts along with their shares\n * @param isLimitedState If the vault contract has a limit for total user deposits\n * @param allowWhitelistedState If the vault contract require whitelisted users or not\n * @param userDepositCap Maximum total amount that can be deposited by an address\n * @param minimumDepositAmount Minimum deposit without rebalance allowed\n * @param totalValueLockedLimitInUnderlying Maximum TVL in underlying allowed for the vault\n * @param queueCap Maximum length of the deposits without rebalance queue\n */\n struct VaultConfiguration {\n bool discontinued;\n bool unpaused;\n bool isLimitedState;\n bool allowWhitelistedState;\n TreasuryShare[] treasuryShares;\n uint256 withdrawalFee; // should be in basis eg: 15% means 1500\n uint256 userDepositCap;\n uint256 minimumDepositAmount;\n uint256 totalValueLockedLimitInUnderlying;\n uint256 queueCap;\n }\n\n /**\n * @notice Container for combining Vault contract's configuration\n * @param emergencyShutdown If the vault contract is in emergencyShutdown\n * state or not\n * @param unpaused If the vault contract is paused or unpaused\n * Following operations cannot happen if vault is paused:\n * - deposit of underlying tokens\n * - withdraw and transfer of vault tokens\n * @param allowWhitelistedState vault's whitelisted state flag\n * @param vaultFeeCollector address that collects vault deposit and withdraw fee\n * @param depositFeeFlatUT flat deposit fee in underlying token\n * @param depositFeePct deposit fee in percentage basis points\n * @param withdrawalFeeFlatUT flat withdrawal fee in underlying token\n * @param withdrawalFeePct withdrawal fee in percentage basis points\n */\n struct VaultConfigurationV2 {\n bool emergencyShutdown;\n bool unpaused;\n bool allowWhitelistedState;\n address vaultFeeCollector;\n uint256 depositFeeFlatUT;\n uint256 depositFeePct;\n uint256 withdrawalFeeFlatUT;\n uint256 withdrawalFeePct;\n }\n\n /**\n * @notice Container for persisting all strategy related contract's configuration\n * @param investStrategyRegistry investStrategyRegistry contract address\n * @param strategyProvider strategyProvider contract address\n * @param aprOracle aprOracle contract address\n */\n struct StrategyConfiguration {\n address investStrategyRegistry;\n address strategyProvider;\n address aprOracle;\n }\n\n /**\n * @notice Container for persisting contract addresses required by vault contract\n * @param strategyManager strategyManager contract address\n * @param riskManager riskManager contract address\n * @param optyDistributor optyDistributor contract address\n * @param operator operator contract address\n */\n struct VaultStrategyConfiguration {\n address strategyManager;\n address riskManager;\n address optyDistributor;\n address odefiVaultBooster;\n address operator;\n }\n\n /**\n * @notice Container for strategy configuration parameters\n * @param registryContract address of Registry contract\n * @param vault address of vault contract\n * @param underlyingToken address of the underlying token\n * @param initialStepInputAmount value in lp token or underlying token at initial strategy step\n * @param internalTransactionIndex index of the internal transaction for a strategy to execute\n * @param internalTransactionCount count of internal transaction for a strategy to execute\n */\n struct StrategyConfigurationParams {\n address registryContract;\n address payable vault;\n address underlyingToken;\n uint256 initialStepInputAmount;\n uint256 internalTransactionIndex;\n uint256 internalTransactionCount;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for Registry Contract\n * @author Opty.fi\n * @notice Interface of the opty.fi's protocol reegistry to store all the mappings, governance\n * operator, minter, strategist and all optyFi's protocol contract addresses\n */\ninterface IRegistry {\n /**\n * @notice Set the treasury's address for optyfi's earn protocol\n * @param _treasury Treasury's address\n */\n function setTreasury(address _treasury) external;\n\n /**\n * @notice Set the StrategyProvider contract address\n * @param _strategyProvider Address of StrategyProvider Contract\n */\n function setStrategyProvider(address _strategyProvider) external;\n\n /**\n * @notice Set the RiskManager's contract address\n * @param _riskManager Address of RiskManager Contract\n */\n function setRiskManager(address _riskManager) external;\n\n /**\n * @notice Set the HarvestCodeProvider contract address\n * @param _harvestCodeProvider Address of HarvestCodeProvider Contract\n */\n function setHarvestCodeProvider(address _harvestCodeProvider) external;\n\n /**\n * @notice Set the $OPTY token's contract address\n * @param _opty Address of Opty Contract\n */\n function setOPTY(address _opty) external;\n\n /**\n * @notice Set the ODEFIVaultBooster contract address\n * @dev Can only be called by the current governance\n * @param _odefiVaultBooster address of the ODEFIVaultBooster Contract\n */\n function setODEFIVaultBooster(address _odefiVaultBooster) external;\n\n /**\n * @dev Sets multiple `_token` from the {tokens} mapping.\n * @notice Approves multiple tokens in one transaction\n * @param _tokens List of tokens to approve\n */\n function approveToken(address[] memory _tokens) external;\n\n /**\n * @notice Approves the token provided\n * @param _token token to approve\n */\n function approveToken(address _token) external;\n\n /**\n * @notice Disable multiple tokens in one transaction\n * @param _tokens List of tokens to revoke\n */\n function revokeToken(address[] memory _tokens) external;\n\n /**\n * @notice Disable the token\n * @param _token token to revoke\n */\n function revokeToken(address _token) external;\n\n /**\n * @notice Approves multiple liquidity pools in one transaction\n * @param _pools list of liquidity/credit pools to approve\n */\n function approveLiquidityPool(address[] memory _pools) external;\n\n /**\n * @notice For approving single liquidity pool\n * @param _pool liquidity/credit pool to approve\n */\n function approveLiquidityPool(address _pool) external;\n\n /**\n * @notice Revokes multiple liquidity pools in one transaction\n * @param _pools list of liquidity/credit pools to revoke\n */\n function revokeLiquidityPool(address[] memory _pools) external;\n\n /**\n * @notice Revokes the liquidity pool\n * @param _pool liquidity/credit pool to revoke\n */\n function revokeLiquidityPool(address _pool) external;\n\n /**\n * @notice Sets multiple pool rates and liquidity pools provided\n * @param _poolRates List of pool rates ([_pool, _rate]) to set\n */\n function rateLiquidityPool(DataTypes.PoolRate[] memory _poolRates) external;\n\n /**\n * @notice Sets the pool rate for the liquidity pool provided\n * @param _pool liquidityPool to map with its rating\n * @param _rate rate for the liquidityPool provided\n */\n function rateLiquidityPool(address _pool, uint8 _rate) external;\n\n /**\n * @notice Approve and map the multiple pools to their adapter\n * @param _poolAdapters List of [pool, adapter] pairs to set\n */\n function approveLiquidityPoolAndMapToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters) external;\n\n /**\n * @notice Approve and map the pool to the adapter\n * @param _pool the address of liquidity pool\n * @param _adapter the address of adapter\n */\n function approveLiquidityPoolAndMapToAdapter(address _pool, address _adapter) external;\n\n /**\n * @notice Approves multiple credit pools in one transaction\n * @param _pools List of pools for approval to be considered as creditPool\n */\n function approveCreditPool(address[] memory _pools) external;\n\n /**\n * @notice Approves the credit pool\n * @param _pool credit pool address to be approved\n */\n function approveCreditPool(address _pool) external;\n\n /**\n * @notice Revokes multiple credit pools in one transaction\n * @param _pools List of pools for revoking from being used as creditPool\n */\n function revokeCreditPool(address[] memory _pools) external;\n\n /**\n * @notice Revokes the credit pool\n * @param _pool pool for revoking from being used as creditPool\n */\n function revokeCreditPool(address _pool) external;\n\n /**\n * @notice Sets the multiple pool rates and credit pools provided\n * @param _poolRates List of pool rates ([_pool, _rate]) to set for creditPool\n */\n function rateCreditPool(DataTypes.PoolRate[] memory _poolRates) external;\n\n /**\n * @notice Sets the pool rate for the credit pool provided\n * @param _pool creditPool to map with its rating\n * @param _rate rate for the creaditPool provided\n */\n function rateCreditPool(address _pool, uint8 _rate) external;\n\n /**\n * @notice Maps multiple liquidity pools to their protocol adapters\n * @param _poolAdapters List of [pool, adapter] pairs to set\n */\n function setLiquidityPoolToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters) external;\n\n /**\n * @notice Maps liquidity pool to its protocol adapter\n * @param _pool liquidityPool to map with its adapter\n * @param _adapter adapter for the liquidityPool provided\n */\n function setLiquidityPoolToAdapter(address _pool, address _adapter) external;\n\n /**\n * @notice Maps multiple token pairs to their keccak256 hash\n * @param _tokensHashesDetails List of mulitple tokens' hashes details\n */\n function setTokensHashToTokens(DataTypes.TokensHashDetail[] memory _tokensHashesDetails) external;\n\n /**\n * @notice Sets token pair to its keccak256 hash\n * @param _tokensHash Hash of tokens\n * @param _tokens List of tokens\n */\n function setTokensHashToTokens(bytes32 _tokensHash, address[] memory _tokens) external;\n\n /**\n * @notice Approve tokens and map tokens hash\n * @param _tokensHash Hash of tokens\n * @param _tokens List of tokens\n */\n function approveTokenAndMapToTokensHash(bytes32 _tokensHash, address[] memory _tokens) external;\n\n /**\n * @notice Approve tokens and map multiple tokens'hashes\n * @param _tokensHashesDetails List of mulitple tokens' hashes details\n */\n function approveTokenAndMapToTokensHash(DataTypes.TokensHashDetail[] memory _tokensHashesDetails) external;\n\n /**\n * @notice Adds the risk profile in Registry contract Storage\n * @param _riskProfileCode code of riskProfile\n * @param _name name of riskProfile\n * @param _symbol symbol of riskProfile\n * @param _canBorrow A boolean value indicating whether the riskProfile allows borrow step\n * @param _poolRatingRange pool rating range ([lowerLimit, upperLimit]) supported by given risk profile\n */\n function addRiskProfile(\n uint256 _riskProfileCode,\n string memory _name,\n string memory _symbol,\n bool _canBorrow,\n DataTypes.PoolRatingsRange memory _poolRatingRange\n ) external;\n\n /**\n * @notice Adds list of the risk profiles in Registry contract Storage in one transaction\n * @dev All parameters must be in the same order.\n * @param _riskProfileCodes codes of riskProfiles\n * @param _names names of riskProfiles\n * @param _symbols symbols of riskProfiles\n * @param _canBorrow List of boolean values indicating whether the riskProfile allows borrow step\n * @param _poolRatingRanges List of pool rating range supported by given list of risk profiles\n */\n function addRiskProfile(\n uint256[] memory _riskProfileCodes,\n string[] memory _names,\n string[] memory _symbols,\n bool[] memory _canBorrow,\n DataTypes.PoolRatingsRange[] memory _poolRatingRanges\n ) external;\n\n /**\n * @notice Change the borrow permission for existing risk profile\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * to update with strategy steps\n * @param _canBorrow A boolean value indicating whether the riskProfile allows borrow step\n */\n function updateRiskProfileBorrow(uint256 _riskProfileCode, bool _canBorrow) external;\n\n /**\n * @notice Update the pool ratings for existing risk profile\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * to update with pool rating range\n * @param _poolRatingRange pool rating range ([lowerLimit, upperLimit]) to update for given risk profile\n */\n function updateRPPoolRatings(uint256 _riskProfileCode, DataTypes.PoolRatingsRange memory _poolRatingRange) external;\n\n /**\n * @notice Remove the existing risk profile in Registry contract Storage\n * @param _index Index of risk profile to be removed\n */\n function removeRiskProfile(uint256 _index) external;\n\n /**\n * @notice Get the list of tokensHash\n * @return Returns the list of tokensHash.\n */\n function getTokenHashes() external view returns (bytes32[] memory);\n\n /**\n * @notice Get list of token given the tokensHash\n * @return Returns the list of tokens corresponding to tokensHash\n */\n function getTokensHashToTokenList(bytes32 _tokensHash) external view returns (address[] memory);\n\n /**\n * @notice Get the list of all the riskProfiles\n * @return Returns the list of all riskProfiles stored in Registry Storage\n */\n function getRiskProfileList() external view returns (uint256[] memory);\n\n /**\n * @notice Retrieve the StrategyProvider contract address\n * @return Returns the StrategyProvider contract address\n */\n function getStrategyProvider() external view returns (address);\n\n /**\n * @notice Retrieve the RiskManager contract address\n * @return Returns the RiskManager contract address\n */\n function getRiskManager() external view returns (address);\n\n /**\n * @notice Retrieve the OPTYDistributor contract address\n * @return Returns the OPTYDistributor contract address\n */\n function getOPTYDistributor() external view returns (address);\n\n /**\n * @notice Retrieve the ODEFIVaultBooster contract address\n * @return Returns the ODEFIVaultBooster contract address\n */\n function getODEFIVaultBooster() external view returns (address);\n\n /**\n * @notice Retrieve the Governance address\n * @return Returns the Governance address\n */\n function getGovernance() external view returns (address);\n\n /**\n * @notice Retrieve the FinanceOperator address\n * @return Returns the FinanceOperator address\n */\n function getFinanceOperator() external view returns (address);\n\n /**\n * @notice Retrieve the RiskOperator address\n * @return Returns the RiskOperator address\n */\n function getRiskOperator() external view returns (address);\n\n /**\n * @notice Retrieve the StrategyOperator address\n * @return Returns the StrategyOperator address\n */\n function getStrategyOperator() external view returns (address);\n\n /**\n * @notice Retrieve the Operator address\n * @return Returns the Operator address\n */\n function getOperator() external view returns (address);\n\n /**\n * @notice Retrieve the HarvestCodeProvider contract address\n * @return Returns the HarvestCodeProvider contract address\n */\n function getHarvestCodeProvider() external view returns (address);\n\n /**\n * @notice Get the properties corresponding to riskProfile code provided\n * @return _riskProfile Returns the properties corresponding to riskProfile provided\n */\n function getRiskProfile(uint256) external view returns (DataTypes.RiskProfile memory _riskProfile);\n\n /**\n * @notice Get the index corresponding to tokensHash provided\n * @param _tokensHash Hash of token address/addresses\n * @return _index Returns the index corresponding to tokensHash provided\n */\n function getTokensHashIndexByHash(bytes32 _tokensHash) external view returns (uint256 _index);\n\n /**\n * @notice Get the tokensHash available at the index provided\n * @param _index Index at which you want to get the tokensHash\n * @return _tokensHash Returns the tokensHash available at the index provided\n */\n function getTokensHashByIndex(uint256 _index) external view returns (bytes32 _tokensHash);\n\n /**\n * @notice Get the rating and Is pool a liquidity pool for the _pool provided\n * @param _pool Liquidity Pool (like cDAI etc.) address\n * @return _liquidityPool Returns the rating and Is pool a liquidity pool for the _pool provided\n */\n function getLiquidityPool(address _pool) external view returns (DataTypes.LiquidityPool memory _liquidityPool);\n\n /**\n * @notice Get the adapter address mapped to the _pool provided\n * @param _pool Liquidity Pool (like cDAI etc.) address\n * @return _adapter Returns the adapter address mapped to the _pool provided\n */\n function getLiquidityPoolToAdapter(address _pool) external view returns (address _adapter);\n\n /**\n * @notice Check if the token is approved or not\n * @param _token Token address for which to check if it is approved or not\n * @return _isTokenApproved Returns a boolean for token approved or not\n */\n function isApprovedToken(address _token) external view returns (bool _isTokenApproved);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IModifiers.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Interface for Modifiers Contract\n * @author Opty.fi\n * @notice Interface used to set the registry contract address\n */\ninterface IModifiers {\n /**\n * @notice Sets the regsitry contract address\n * @param _registry address of registry contract\n */\n function setRegistry(address _registry) external;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/mocks/contracts/Imports.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { DataTypes } from \"../../earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterBorrow } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterBorrow.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport { IAdapterStaking } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol\";\nimport { IAdapterStakingCurve } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStakingCurve.sol\";\nimport { IAdapterFull } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterFull.sol\";\nimport { IWETH } from \"@optyfi/defi-legos/interfaces/misc/contracts/IWETH.sol\";\nimport { IYWETH } from \"@optyfi/defi-legos/interfaces/misc/contracts/IYWETH.sol\";\nimport { IAaveV1PriceOracle } from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1PriceOracle.sol\";\nimport {\n IAaveV1LendingPoolAddressesProvider\n} from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1LendingPoolAddressesProvider.sol\";\nimport {\n IAaveV1,\n UserReserveData,\n ReserveConfigurationData,\n ReserveDataV1,\n UserAccountData\n} from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1.sol\";\nimport { IAaveV1Token } from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1Token.sol\";\nimport { IAaveV1LendingPoolCore } from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1LendingPoolCore.sol\";\nimport { IAaveV2PriceOracle } from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2PriceOracle.sol\";\nimport {\n IAaveV2LendingPoolAddressesProvider\n} from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2LendingPoolAddressesProvider.sol\";\nimport {\n IAaveV2LendingPoolAddressProviderRegistry\n} from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2LendingPoolAddressProviderRegistry.sol\";\nimport { IAaveV2, ReserveDataV2 } from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2.sol\";\nimport { IAaveV2Token } from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2Token.sol\";\nimport {\n IAaveV2ProtocolDataProvider,\n ReserveDataProtocol\n} from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2ProtocolDataProvider.sol\";\nimport { ICompound } from \"@optyfi/defi-legos/ethereum/compound/contracts/ICompound.sol\";\nimport { IETHGateway } from \"@optyfi/defi-legos/interfaces/misc/contracts/IETHGateway.sol\";\nimport { ICream } from \"@optyfi/defi-legos/ethereum/cream/contracts/ICream.sol\";\nimport { ICurveDeposit } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveDeposit.sol\";\nimport { ICurveGauge } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveGauge.sol\";\nimport {\n ICurveAddressProvider\n} from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveAddressProvider.sol\";\nimport { ICurveSwap } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveSwap.sol\";\nimport { ICurveRegistry } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveRegistry.sol\";\nimport { ITokenMinter } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ITokenMinter.sol\";\nimport { IDForceDeposit } from \"@optyfi/defi-legos/ethereum/dforce/contracts/IDForceDeposit.sol\";\nimport { IDForceStake } from \"@optyfi/defi-legos/ethereum/dforce/contracts/IDForceStake.sol\";\nimport {\n IdYdX,\n AccountInfo,\n AssetAmount,\n AssetDenomination,\n AssetReference,\n ActionArgs,\n AssetReference,\n ActionType\n} from \"@optyfi/defi-legos/ethereum/dydx/contracts/IdYdX.sol\";\nimport { IFulcrum } from \"@optyfi/defi-legos/ethereum/fulcrum/contracts/IFulcrum.sol\";\nimport { IHarvestController } from \"@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestController.sol\";\nimport { IHarvestDeposit } from \"@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestDeposit.sol\";\nimport { IHarvestFarm } from \"@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestFarm.sol\";\nimport { ISushiswapMasterChef } from \"@optyfi/defi-legos/ethereum/sushiswap/contracts/ISushiswapMasterChef.sol\";\nimport { IYearn } from \"@optyfi/defi-legos/ethereum/yearn/contracts/IYearn.sol\";\nimport { IYVault } from \"@optyfi/defi-legos/ethereum/yvault/contracts/IYVault.sol\";\n\ncontract Imports {\n /* solhint-disable no-empty-blocks */\n constructor() public {}\n /* solhint-disable no-empty-blocks */\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterBorrow.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface for borrow feature for DeFi adapters\n * @author Opty.fi\n * @notice Interface of the DeFi protocol adapter for borrow functionality\n * @dev Abstraction layer to different DeFi protocols like AaveV1, AaveV2 etc. which has borrow feature\n * It is used as a layer for adding any new functions in DeFi adapters if they include borrow functionality\n * Conventions used:\n * - lpToken: liquidity pool token\n */\ninterface IAdapterBorrow {\n /**\n * @dev Get batch of function calls for token amount that can be borrowed safely against the underlying token\n * when kept as collateral\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to borrow\n * @param _outputToken Token address to borrow\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getBorrowAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n address _outputToken\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @dev Get batch of function calls require to repay debt, unlock collateral and redeem lpToken\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address for all protocols except for Aave where it is\n * liquidity pool address provider's contract address\n * @param _outputToken Token address to borrow\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getRepayAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n address _outputToken\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @notice Get the amount in underlying token that you'll receive if borrowed token is repaid\n * @dev Returns the amount in underlying token for _liquidityPoolTokenAmount collateral if\n * _borrowAmount in _borrowToken is repaid.\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to borrow the tokens\n * @param _borrowToken Token address to borrow\n * @param _borrowAmount Amount of token to borrow\n * @return Returns the amount in underlying token that can be received if borrowed token is repaid\n */\n function getSomeAmountInTokenBorrow(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount,\n address _borrowToken,\n uint256 _borrowAmount\n ) external view returns (uint256);\n\n /**\n * @notice Get the amount in underlying token that you'll receive if whole balance of vault borrowed token is repaid\n * @dev Returns the amount in underlying token for whole collateral of _vault balance if\n * _borrowAmount in _borrowToken is repaid.\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to borrow the tokens\n * @param _borrowToken Token address to borrow\n * @param _borrowAmount Amount of token to borrow\n * @return Returns amount in underlyingToken that you'll receive if whole balance of vault borrowed token is repaid\n */\n function getAllAmountInTokenBorrow(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n address _borrowToken,\n uint256 _borrowAmount\n ) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface for staking feature for DeFi adapters\n * @author Opty.fi\n * @notice Interface of the DeFi protocol adapter for staking functionality\n * @dev Abstraction layer to different DeFi protocols like Harvest.finance, DForce etc.\n * It is used as a layer for adding any new staking functions being used in DeFi adapters.\n * Conventions used:\n * - lpToken: liquidity pool token\n */\ninterface IAdapterStaking {\n /**\n * @notice Get batch of function calls for staking specified amount of lpToken held in a vault\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to stake some lpTokens\n * @param _stakeAmount Amount of lpToken (held in vault) to be staked\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getStakeSomeCodes(address _liquidityPool, uint256 _stakeAmount)\n external\n view\n returns (bytes[] memory _codes);\n\n /**\n * @notice Get batch of function calls for staking full balance of lpTokens held in a vault\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to stake all lpTokens\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getStakeAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @notice Get batch of function calls for unstaking specified amount of lpTokens held in a vault\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to unstake some lpTokens\n * @param _unstakeAmount Amount of lpToken (held in a vault) to be unstaked\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getUnstakeSomeCodes(address _liquidityPool, uint256 _unstakeAmount) external view returns (bytes[] memory);\n\n /**\n * @notice Get the batch of function calls for unstaking whole balance of lpTokens held in a vault\n * @param _vault Vault contract address\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to unstake all lpTokens\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getUnstakeAllCodes(address payable _vault, address _liquidityPool)\n external\n view\n returns (bytes[] memory _codes);\n\n /**\n * @notice Returns the balance in underlying for staked lpToken balance of vault\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address which is associated with staking pool from where to\n * get amount of staked lpToken\n * @return Returns the underlying token amount for the staked lpToken\n */\n function getAllAmountInTokenStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (uint256);\n\n /**\n * @notice Returns amount of lpTokens staked by the vault\n * @param _vault Vault contract address\n * @param _liquidityPool Liquidity pool's contract address from where to get the lpToken balance\n * @return Returns the lpToken balance that is staked by the specified vault\n */\n function getLiquidityPoolTokenBalanceStake(address payable _vault, address _liquidityPool)\n external\n view\n returns (uint256);\n\n /**\n * @notice Returns the equivalent amount in underlying token if the given amount of lpToken is unstaked and redeemed\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to get amount to redeem\n * @param _redeemAmount Amount of lpToken to redeem for staking\n * @return _amount Returns the lpToken amount that can be redeemed\n */\n function calculateRedeemableLPTokenAmountStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external view returns (uint256 _amount);\n\n /**\n * @notice Checks whether the given amount of underlying token can be received for full balance of staked lpToken\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where to check the redeem amt is enough to stake\n * @param _redeemAmount amount specified underlying token that can be received for full balance of staking lpToken\n * @return Returns a boolean true if _redeemAmount is enough to stake and false if not enough\n */\n function isRedeemableAmountSufficientStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external view returns (bool);\n\n /**\n * @notice Get the batch of function calls for unstake and redeem specified amount of shares\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address associated to a staking pool from where to unstake\n * and then withdraw\n * @param _redeemAmount Amount of lpToken to unstake and redeem\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getUnstakeAndWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external view returns (bytes[] memory _codes);\n\n /**\n * @notice Get the batch of function calls for unstake and redeem whole balance of shares held in a vault\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address associated to a staking pool from where to unstake\n * and then withdraw\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getUnstakeAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external view returns (bytes[] memory _codes);\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStakingCurve.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface for staking feature for Curve adapters\n * @author Opty.fi\n * @notice Interface of CurveDeposit and CurveSwap adapters for staking functionality\n * @dev Abstraction layer to Curve.fi adapters\n * It is used as a layer for adding any new staking functions being used in Curve adapters.\n * Conventions used:\n * - lpToken: liquidity pool token\n */\ninterface IAdapterStakingCurve {\n /**\n * @notice Returns the balance in underlying for staked liquidityPoolToken balance of holder\n * @dev It should only be implemented in Curve adapters\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to stake all lpTokens\n * @return Returns the equivalent amount of underlying tokens to the staked amount of liquidityPoolToken\n */\n function getAllAmountInTokenStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external returns (uint256);\n\n /**\n * @notice Returns the equivalent amount in underlying token if the given amount of lpToken is unstaked and redeemed\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address from where to get amount to redeem\n * @param _redeemAmount Amount of lpToken to redeem for staking\n * @return _amount Returns the lpToken amount that can be redeemed\n */\n function calculateRedeemableLPTokenAmountStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external returns (uint256);\n\n /**\n * @notice Checks whether the given amount of underlying token can be received for full balance of staked lpToken\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token's address supported by the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where to check the redeem amt is enough to stake\n * @param _redeemAmount amount specified underlying token that can be received for full balance of staking lpToken\n * @return Returns a boolean true if _redeemAmount is enough to stake and false if not enough\n */\n function isRedeemableAmountSufficientStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external returns (bool);\n\n /**\n * @notice Returns the amount of accrued reward tokens\n * @param _vault Vault contract address\n * @param _liquidityPool Liquidity pool's contract address from where to claim reward tokens\n * @param _underlyingToken Underlying token's contract address for which to claim reward tokens\n * @return _codes Returns an array of bytes in sequence that can be executed by vault\n */\n function getUnclaimedRewardTokenAmountWrite(\n address payable _vault,\n address _liquidityPool,\n address _underlyingToken\n ) external returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterFull.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\nimport { IAdapter } from \"./IAdapter.sol\";\nimport { IAdapterBorrow } from \"./IAdapterBorrow.sol\";\nimport { IAdapterHarvestReward } from \"./IAdapterHarvestReward.sol\";\nimport { IAdapterStaking } from \"./IAdapterStaking.sol\";\nimport { IAdapterStakingCurve } from \"./IAdapterStakingCurve.sol\";\nimport \"./IAdapterInvestLimit.sol\";\n\n/**\n * @title Interface containing all functions from different DeFi adapter interfaces\n * @author Opty.fi\n * @notice Interface of the DeFi protocol adapter to be used where all DeFi adapter features are required\n * @dev Abstraction layer to different tokenization contracts like StrategyManager etc.\n * It can also be used as an interface layer for any new DeFi protocol. It contains all the\n * functions being used in all the DeFi adapters from different interfaces\n */\n\n/* solhint-disable no-empty-blocks */\ninterface IAdapterFull is\n IAdapter,\n IAdapterBorrow,\n IAdapterHarvestReward,\n IAdapterStaking,\n IAdapterStakingCurve,\n IAdapterInvestLimit\n{\n\n}\n/* solhint-disable no-empty-blocks */\n" + }, + "@optyfi/defi-legos/interfaces/misc/contracts/IWETH.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\ninterface IWETH {\n function deposit() external payable;\n\n function transfer(address to, uint256 value) external returns (bool);\n\n function withdraw(uint256) external;\n}\n" + }, + "@optyfi/defi-legos/interfaces/misc/contracts/IYWETH.sol": { + "content": "// SPDX-License-Identifier:MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\ninterface IYWETH {\n function depositETH() external payable;\n\n function transfer(address recipient, uint256 amount) external;\n\n function balanceOf(address _holder) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1PriceOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV1PriceOracle {\n function getAssetPrice(address _asset) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1LendingPoolAddressesProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV1LendingPoolAddressesProvider {\n function getLendingPool() external view returns (address);\n\n function getLendingPoolCore() external view returns (address);\n\n function getPriceOracle() external view returns (address);\n\n function getLendingPoolDataProvider() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\nstruct UserReserveData {\n uint256 currentATokenBalance;\n uint256 currentBorrowBalance;\n uint256 principalBorrowBalance;\n uint256 borrowRateMode;\n uint256 borrowRate;\n uint256 liquidityRate;\n uint256 originationFee;\n uint256 variableBorrowIndex;\n uint256 lastUpdateTimestamp;\n bool enabled;\n}\n\nstruct UserAccountData {\n uint256 totalLiquidityETH;\n uint256 totalCollateralETH;\n uint256 totalBorrowsETH;\n uint256 totalFeesETH;\n uint256 availableBorrowsETH;\n uint256 currentLiquidationThreshold;\n uint256 ltv;\n uint256 healthFactor;\n}\n\nstruct ReserveDataV1 {\n uint256 totalLiquidity;\n uint256 availableLiquidity;\n uint256 totalBorrowsStable;\n uint256 totalBorrowsVariable;\n uint256 liquidityRate;\n uint256 variableBorrowRate;\n uint256 stableBorrowRate;\n uint256 averageStableBorrowRate;\n uint256 utilizationRate;\n uint256 liquidityIndex;\n uint256 variableBorrowIndex;\n address aTokenAddress;\n uint40 lastUpdateTimestamp;\n}\n\nstruct ReserveConfigurationData {\n uint256 ltv;\n uint256 liquidationThreshold;\n uint256 liquidationBonus;\n address rateStrategyAddress;\n bool usageAsCollateralEnabled;\n bool borrowingEnabled;\n bool stableBorrowRateEnabled;\n bool isActive;\n}\n\ninterface IAaveV1 {\n function deposit(\n address _reserve,\n uint256 _amount,\n uint16 _referralCode\n ) external;\n\n function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) external;\n\n function borrow(\n address _reserve,\n uint256 _amount,\n uint256 _interestRateMode,\n uint16 _referralCode\n ) external;\n\n function repay(\n address _reserve,\n uint256 _amount,\n address payable _onBehalfOf\n ) external;\n\n function getReserveConfigurationData(address _reserve) external view returns (ReserveConfigurationData memory);\n\n function getUserAccountData(address _user) external view returns (UserAccountData memory);\n\n function getUserReserveData(address _reserve, address _user) external view returns (UserReserveData memory);\n\n function getReserveData(address _reserve) external view returns (ReserveDataV1 memory);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1Token.sol": { + "content": "// SPDX-License-Identifier:MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV1Token {\n function redeem(uint256 amount) external;\n\n function isTransferAllowed(address user, uint256 amount) external view returns (bool);\n\n function underlyingAssetAddress() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1LendingPoolCore.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\ninterface IAaveV1LendingPoolCore {\n function getReserveCurrentLiquidityRate(address _reserve) external view returns (uint256 liquidityRate);\n\n function getReserveATokenAddress(address _reserve) external view returns (address);\n\n function getReserveConfiguration(address _reserve)\n external\n view\n returns (\n uint256,\n uint256,\n uint256,\n bool\n );\n}\n" + }, + "@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2PriceOracle.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV2PriceOracle {\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 (uint256);\n\n function getFallbackOracle() external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2LendingPoolAddressesProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV2LendingPoolAddressesProvider {\n function getMarketId() external view returns (string memory);\n\n function getAddress(bytes32 _id) external view returns (address);\n\n function getLendingPool() external view returns (address);\n\n function getLendingPoolCollateralManager() external view returns (address);\n\n function getPriceOracle() external view returns (address);\n\n function getLendingRateOracle() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2LendingPoolAddressProviderRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV2LendingPoolAddressProviderRegistry {\n function getAddressesProvidersList() external view returns (address[] memory);\n\n function getAddressesProviderIdByAddress(address addressesProvider) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\nstruct UserAccountData {\n uint256 totalCollateralETH;\n uint256 totalDebtETH;\n uint256 availableBorrowsETH;\n uint256 currentLiquidationThreshold;\n uint256 ltv;\n uint256 healthFactor;\n}\n\nstruct ReserveDataV2 {\n ReserveConfigurationMap configuration;\n uint128 liquidityIndex;\n uint128 variableBorrowIndex;\n uint128 currentLiquidityRate;\n uint128 currentVariableBorrowRate;\n uint128 currentStableBorrowRate;\n uint40 lastUpdateTimestamp;\n address aTokenAddress;\n address stableDebtTokenAddress;\n address variableDebtTokenAddress;\n address interestRateStrategyAddress;\n uint8 id;\n}\n\nstruct 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\ninterface IAaveV2 {\n function deposit(\n address _asset,\n uint256 _amount,\n address _onBehalfOf,\n uint16 _referralCode\n ) external;\n\n function setUserUseReserveAsCollateral(address _asset, bool _useAsCollateral) external;\n\n function withdraw(\n address _asset,\n uint256 _amount,\n address _to\n ) external;\n\n function borrow(\n address _asset,\n uint256 _amount,\n uint256 _interestRateMode,\n uint16 _referralCode,\n address _onBehalfOf\n ) external;\n\n function repay(\n address _asset,\n uint256 _amount,\n uint256 _rateMode,\n address _onBehalfOf\n ) external;\n\n function getUserAccountData(address _user) external view returns (UserAccountData memory);\n\n function getConfiguration(address _asset) external view returns (ReserveConfigurationMap memory);\n\n function getUserConfiguration(address user) external view returns (ReserveConfigurationMap memory);\n\n function getReserveData(address _asset) external view returns (ReserveDataV2 memory);\n\n function paused() external view returns (bool);\n\n function getReservesList() external view returns (address[] memory);\n\n function getAddressesProvider() external view returns (address);\n\n function getReserveNormalizedIncome(address _asset) external view returns (uint256);\n\n function getReserveNormalizedVariableDebt(address _asset) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2Token.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IAaveV2Token {\n /* solhint-disable func-name-mixedcase */\n function UNDERLYING_ASSET_ADDRESS() external view returns (address);\n\n function RESERVE_TREASURY_ADDRESS() external view returns (address);\n\n function POOL() external view returns (address);\n\n /* solhint-disable func-name-mixedcase */\n\n function scaledBalanceOf(address user) external view returns (uint256);\n\n function getScaledUserBalanceAndSupply(address user) external view returns (uint256, uint256);\n\n function scaledTotalSupply() external view returns (uint256);\n\n function isTransferAllowed(address user, uint256 amount) external view returns (bool);\n}\n" + }, + "@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2ProtocolDataProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\npragma experimental ABIEncoderV2;\n\nimport { IAaveV2LendingPoolAddressesProvider } from \"./IAaveV2LendingPoolAddressesProvider.sol\";\n\nstruct TokenData {\n string symbol;\n address tokenAddress;\n}\n\nstruct ReserveConfigurationData {\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\nstruct ReserveDataProtocol {\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\nstruct UserReserveData {\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\nstruct ReserveTokensAddresses {\n address aTokenAddress;\n address stableDebtTokenAddress;\n address variableDebtTokenAddress;\n}\n\ninterface IAaveV2ProtocolDataProvider {\n // solhint-disable-next-line func-name-mixedcase\n function ADDRESSES_PROVIDER() external view returns (IAaveV2LendingPoolAddressesProvider);\n\n function getAllReservesTokens() external view returns (TokenData[] memory);\n\n function getAllATokens() external view returns (TokenData[] memory);\n\n function getReserveConfigurationData(address _asset) external view returns (ReserveConfigurationData memory);\n\n function getReserveData(address _asset) external view returns (ReserveDataProtocol memory);\n\n function getUserReserveData(address _asset, address _user) external view returns (UserReserveData memory);\n\n function getReserveTokensAddresses(address _asset) external view returns (ReserveTokensAddresses memory);\n}\n" + }, + "@optyfi/defi-legos/ethereum/compound/contracts/ICompound.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\ninterface ICompound {\n enum PriceSource {\n FIXED_ETH, /// implies the fixedPrice is a constant multiple of the ETH price (which varies)\n FIXED_USD, /// implies the fixedPrice is a constant multiple of the USD price (which is 1)\n REPORTER /// implies the price is set by the reporter\n }\n\n struct TokenConfig {\n address cToken;\n address underlying;\n bytes32 symbolHash;\n uint256 baseUnit;\n PriceSource priceSource;\n uint256 fixedPrice;\n address uniswapMarket;\n bool isUniswapReversed;\n }\n\n struct CompBalanceMetadata {\n uint256 balance;\n uint256 votes;\n address delegate;\n }\n\n struct CompBalanceMetadataExt {\n uint256 balance;\n uint256 votes;\n address delegate;\n uint256 allocated;\n }\n\n function getCompBalanceMetadataExt(\n address comp,\n address comptroller,\n address account\n ) external returns (CompBalanceMetadataExt memory);\n\n function mint(uint256 mintAmount) external returns (uint256);\n\n function mint() external payable;\n\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n function exchangeRateCurrent() external returns (uint256);\n\n function claimComp(address holder) external;\n\n function getCompBalanceMetadata(address comp, address account) external view returns (CompBalanceMetadata memory);\n\n function exchangeRateStored() external view returns (uint256);\n\n function totalBorrows() external view returns (uint256);\n\n function totalReserves() external view returns (uint256);\n\n function getCash() external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function underlying() external view returns (address);\n\n function decimals() external view returns (uint8);\n\n function compAccrued(address holder) external view returns (uint256);\n\n function getTokenConfigByUnderlying(address) external view returns (TokenConfig memory);\n\n function supplyRatePerBlock() external view returns (uint256);\n\n function comptroller() external view returns (address);\n\n function getCompAddress() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/interfaces/misc/contracts/IETHGateway.sol": { + "content": "// SPDX-License-Identifier:MIT\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\n/**\n * @title Interface of ETH gateway for opty-fi adapter\n * @author Opty.fi\n * @dev Inspired from Aave WETH gateway\n */\ninterface IETHGateway {\n /**\n * @dev deposits ETH into the reserve, using native ETH. A corresponding amount of the overlying asset\n * is minted.\n * @param _vault address of the user who will receive the lpTokens representing the deposit\n * @param _liquidityPool address of the targeted lending pool\n * @param _liquidityPoolToken address of the targeted lpToken\n * @param _amounts list of amounts of coins.\n * @param _tokenIndex index of the coin to redeem\n **/\n function depositETH(\n address _vault,\n address _liquidityPool,\n address _liquidityPoolToken,\n uint256[2] memory _amounts,\n int128 _tokenIndex\n ) external;\n\n /**\n * @dev withdraws the ETH _reserves of vault.\n * @param _vault address that will receive WETH\n * @param _liquidityPool address of the targeted cToken pool\n * @param _liquidityPoolToken address of the targeted lpToken\n * @param _amount amount of lpToken to redeem\n * @param _tokenIndex index of the coin to redeem\n */\n function withdrawETH(\n address _vault,\n address _liquidityPool,\n address _liquidityPoolToken,\n uint256 _amount,\n int128 _tokenIndex\n ) external;\n\n /**\n * @dev transfer ERC20 from the utility contract, for ERC20 recovery in case of stuck tokens due\n * direct transfers to the contract address.\n * @param _token token to transfer\n * @param _to recipient of the transfer\n * @param _amount amount to send\n */\n function emergencyTokenTransfer(\n address _token,\n address _to,\n uint256 _amount\n ) external;\n\n /**\n * @dev transfer native Ether from the utility contract, for native Ether recovery in case of stuck Ether\n * due selfdestructs or transfer ether to pre-computated contract address before deployment.\n * @param _to recipient of the transfer\n * @param _amount amount to send\n */\n function emergencyEtherTransfer(address _to, uint256 _amount) external;\n\n /**\n * @dev Get WETH address used by WETHGateway\n */\n function getWETHAddress() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/cream/contracts/ICream.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\ninterface ICream {\n struct CompBalanceMetadata {\n uint256 balance;\n uint256 votes;\n address delegate;\n }\n\n struct CompBalanceMetadataExt {\n uint256 balance;\n uint256 votes;\n address delegate;\n uint256 allocated;\n }\n\n function getCompBalanceMetadataExt(\n address comp,\n address comptroller,\n address account\n ) external returns (CompBalanceMetadataExt memory);\n\n function mint(uint256 mintAmount) external returns (uint256);\n\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n function claimComp(address holder) external;\n\n function getCompBalanceMetadata(address comp, address account) external view returns (CompBalanceMetadata memory);\n\n function exchangeRateStored() external view returns (uint256);\n\n function underlying() external view returns (address);\n\n function compAccrued(address holder) external view returns (uint256);\n\n function getCash() external view returns (uint256);\n\n function comptroller() external view returns (address);\n\n function getCompAddress() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveDeposit.sol": { + "content": "// solhint-disable func-name-mixedcase\n// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ICurveDeposit {\n /// @dev Function for every 2token pool.\n function add_liquidity(uint256[2] calldata amountsIn, uint256 minAmountOut) external;\n\n /// @dev Function for every 3token pool.\n function add_liquidity(uint256[3] calldata amountsIn, uint256 minAmountOut) external;\n\n /// @dev Function for every 4token pool.\n function add_liquidity(uint256[4] calldata amountsIn, uint256 minAmountOut) external;\n\n function remove_liquidity_one_coin(\n uint256 amountIn,\n int128 i,\n uint256 minAmountOut,\n bool donateDust\n ) external;\n\n function remove_liquidity(uint256 _amount, uint256[2] calldata minAmountOut) external;\n\n function remove_liquidity(uint256 _amount, uint256[3] calldata minAmountOut) external;\n\n function remove_liquidity(uint256 _amount, uint256[4] calldata minAmountOut) external;\n\n function calc_token_amount(uint256[3] calldata amountsIn, bool deposit) external view returns (uint256);\n\n function calc_token_amount(uint256[4] calldata amountsIn, bool deposit) external view returns (uint256);\n\n function calc_withdraw_one_coin(uint256 _balance, int128 _tokenIndex) external view returns (uint256);\n\n function token() external view returns (address);\n\n /// @dev returns swap contract from old curve deposit zap\n function curve() external view returns (address);\n\n /// @dev returns swap contract from new curve deposit zap\n function pool() external view returns (address);\n\n function base_coins(uint256 arg0) external view returns (address);\n\n function underlying_coins(int128 arg0) external view returns (address);\n\n function underlying_coins(uint256 arg0) external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveGauge.sol": { + "content": "// solhint-disable func-name-mixedcase\n// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ICurveGauge {\n function deposit(uint256 _value) external;\n\n function withdraw(uint256 _value) external;\n\n function claimable_tokens(address _holder) external returns (uint256);\n\n function minter() external view returns (address);\n\n function balanceOf(address _holder) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveAddressProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ICurveAddressProvider {\n // solhint-disable-next-line func-name-mixedcase\n function get_registry() external view returns (address);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveSwap.sol": { + "content": "// solhint-disable func-name-mixedcase\n// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ICurveSwap {\n function remove_liquidity_one_coin(\n uint256 amountIn,\n int128 i,\n uint256 minAmountOut\n ) external;\n\n /// @dev Function for every 2token pool.\n function add_liquidity(uint256[2] calldata amountsIn, uint256 minAmountOut) external;\n\n /// @dev Function for every 3token pool.\n function add_liquidity(uint256[3] calldata amountsIn, uint256 minAmountOut) external;\n\n /// @dev Function for every 4token pool.\n function add_liquidity(uint256[4] calldata amountsIn, uint256 minAmountOut) external;\n\n function remove_liquidity(uint256 _amount, uint256[2] calldata minAmountOut) external;\n\n function remove_liquidity(uint256 _amount, uint256[3] calldata minAmountOut) external;\n\n function remove_liquidity(uint256 _amount, uint256[4] calldata minAmountOut) external;\n\n function calc_token_amount(uint256[2] calldata amountsIn, bool deposit) external view returns (uint256);\n\n function calc_token_amount(uint256[3] calldata amountsIn, bool deposit) external view returns (uint256);\n\n function calc_token_amount(uint256[4] calldata amountsIn, bool deposit) external view returns (uint256);\n\n function get_virtual_price() external view returns (uint256);\n\n function coins(int128 arg0) external view returns (address);\n\n function coins(uint256 arg0) external view returns (address);\n\n function underlying_coins(uint256 arg0) external view returns (address);\n\n function calc_withdraw_one_coin(uint256 _balance, int128 _tokenIndex) external view returns (uint256);\n\n function calc_withdraw_one_coin(\n uint256 _liquidityPoolTokenAmount,\n int128 _tokenIndex,\n bool _useUnderlying\n ) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveRegistry.sol": { + "content": "// solhint-disable func-name-mixedcase\n// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ICurveRegistry {\n function get_lp_token(address) external view returns (address);\n\n function get_coins(address) external view returns (address[8] memory);\n\n function get_n_coins(address) external view returns (uint256[2] memory);\n\n function get_gauges(address) external view returns (address[10] memory, int128[10] memory);\n\n function get_underlying_coins(address) external view returns (address[8] memory);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ITokenMinter.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ITokenMinter {\n function mint(address _gauge) external;\n\n function token() external view returns (address);\n\n function minted(address _gauge, address _account) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/dforce/contracts/IDForceDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.9.0;\n\ninterface IDForceDeposit {\n function mint(address receiver, uint256 depositAmount) external;\n\n function redeem(address receiver, uint256 redeemAmount) external;\n\n function getExchangeRate() external view returns (uint256);\n\n function token() external view returns (address);\n\n function decimals() external view returns (uint256);\n\n function getTokenBalance(address _holder) external view returns (uint256);\n\n function getTotalBalance() external view returns (uint256);\n\n function getLiquidity() external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/dforce/contracts/IDForceStake.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.9.0;\n\ninterface IDForceStake {\n function stake(uint256 _value) external;\n\n function withdraw(uint256 _value) external;\n\n function exit() external;\n\n function getReward() external;\n\n function earned(address _holder) external view returns (uint256);\n\n function balanceOf(address _account) external view returns (uint256);\n\n function decimals() external view returns (uint256);\n\n function df() external view returns (address);\n\n function lockedDetails() external view returns (bool, uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/dydx/contracts/IdYdX.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\npragma experimental ABIEncoderV2;\n\nenum ActionType {\n Deposit, // supply tokens\n Withdraw, // borrow tokens\n Transfer, // transfer balance between accounts\n Buy, // buy an amount of some token (externally)\n Sell, // sell an amount of some token (externally)\n Trade, // trade tokens against another account\n Liquidate, // liquidate an undercollateralized or expiring account\n Vaporize, // use excess tokens to zero-out a completely negative account\n Call // send arbitrary data to an address\n}\n\nenum AssetDenomination {\n Wei, // the amount is denominated in wei\n Par // the amount is denominated in par\n}\n\nenum AssetReference {\n Delta, // the amount is given as a delta from the current value\n Target // the amount is given as an exact number to end up at\n}\n\nstruct AssetAmount {\n bool sign; // true if positive\n AssetDenomination denomination;\n AssetReference ref;\n uint256 value;\n}\n\nstruct AccountInfo {\n address owner;\n uint256 number;\n}\n\nstruct ActionArgs {\n ActionType actionType;\n uint256 accountId;\n AssetAmount amount;\n uint256 primaryMarketId;\n uint256 secondaryMarketId;\n address otherAddress;\n uint256 otherAccountId;\n bytes data;\n}\n\nstruct OperatorArg {\n address operator;\n bool trusted;\n}\n\nstruct TotalPar {\n uint128 borrow;\n uint128 supply;\n}\n\ninterface IdYdX {\n function operate(AccountInfo[] memory _accountInfo, ActionArgs[] memory _actionArgs) external;\n\n function setOperators(OperatorArg[] memory args) external;\n\n function getAccountWei(AccountInfo calldata _accountInfo, uint256 marketId) external view returns (bool, uint256);\n\n function getMarketTotalPar(uint256 marketId) external view returns (TotalPar memory);\n}\n" + }, + "@optyfi/defi-legos/ethereum/fulcrum/contracts/IFulcrum.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.9.0;\n\ninterface IFulcrum {\n function mint(address receiver, uint256 depositAmount) external;\n\n function burn(address receiver, uint256 burnAmount) external;\n\n function tokenPrice() external view returns (uint256);\n\n function loanTokenAddress() external view returns (address);\n\n function decimals() external view returns (uint256);\n\n function assetBalanceOf(address holder) external view returns (uint256);\n\n function marketLiquidity() external view returns (uint256);\n\n function balanceOf(address _holder) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestController.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IHarvestController {\n function greyList(address _addr) external view returns (bool);\n\n // Only smart contracts will be affected by the whitelist.\n function addToWhitelist(address _target) external;\n\n function addMultipleToWhitelist(address[] memory _targets) external;\n\n function removeFromWhitelist(address _target) external;\n\n function removeMultipleFromWhitelist(address[] memory _targets) external;\n\n function addCodeToWhitelist(address _target) external;\n\n function removeCodeFromWhitelist(address _target) external;\n}\n" + }, + "@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestDeposit.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IHarvestDeposit {\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _shares) external;\n\n function getPricePerFullShare() external view returns (uint256);\n\n function underlying() external view returns (address);\n\n function decimals() external view returns (uint256);\n\n function underlyingBalanceWithInvestment() external view returns (uint256);\n\n function governance() external view returns (address);\n\n function controller() external view returns (address);\n\n function balanceOf(address account) external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestFarm.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IHarvestFarm {\n event Migrated(address indexed account, uint256 legacyShare, uint256 newShare);\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n event RewardAdded(uint256 reward);\n event RewardDenied(address indexed user, uint256 reward);\n event RewardPaid(address indexed user, uint256 reward);\n event SmartContractRecorded(address indexed smartContractAddress, address indexed smartContractInitiator);\n event Staked(address indexed user, uint256 amount);\n event Withdrawn(address indexed user, uint256 amount);\n\n function balanceOf(address account) external view returns (uint256);\n\n function canMigrate() external view returns (bool);\n\n function controller() external view returns (address);\n\n function duration() external view returns (uint256);\n\n function earned(address account) external view returns (uint256);\n\n function exit() external;\n\n function getReward() external;\n\n function governance() external view returns (address);\n\n function isOwner() external view returns (bool);\n\n function lastTimeRewardApplicable() external view returns (uint256);\n\n function lastUpdateTime() external view returns (uint256);\n\n function lpToken() external view returns (address);\n\n function migrate() external;\n\n function migrationStrategy() external view returns (address);\n\n function notifyRewardAmount(uint256 reward) external;\n\n function owner() external view returns (address);\n\n function periodFinish() external view returns (uint256);\n\n function pullFromStrategy() external;\n\n function pushReward(address recipient) external;\n\n function renounceOwnership() external;\n\n function rewardPerToken() external view returns (uint256);\n\n function rewardPerTokenStored() external view returns (uint256);\n\n function rewardRate() external view returns (uint256);\n\n function rewardToken() external view returns (address);\n\n function rewards(address) external view returns (uint256);\n\n function setCanMigrate(bool _canMigrate) external;\n\n function setRewardDistribution(address _rewardDistribution) external;\n\n function setStorage(address _store) external;\n\n function sourceVault() external view returns (address);\n\n function stake(uint256 amount) external;\n\n function store() external view returns (address);\n\n function totalSupply() external view returns (uint256);\n\n function transferOwnership(address newOwner) external;\n\n function userRewardPerTokenPaid(address) external view returns (uint256);\n\n function withdraw(uint256 amount) external;\n}\n" + }, + "@optyfi/defi-legos/ethereum/yearn/contracts/IYearn.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IYearn {\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _shares) external;\n\n function getPricePerFullShare() external view returns (uint256);\n\n function token() external view returns (address);\n\n function decimals() external view returns (uint256);\n\n function calcPoolValueInToken() external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/yvault/contracts/IYVault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface IYVault {\n function deposit(uint256 _amount) external;\n\n function withdraw(uint256 _shares) external;\n\n function getPricePerFullShare() external view returns (uint256);\n\n function token() external view returns (address);\n\n function decimals() external view returns (uint256);\n\n function balance() external view returns (uint256);\n\n function balanceOf(address _address) external view returns (uint256);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/yearn/YVaultAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IYVault } from \"@optyfi/defi-legos/ethereum/yvault/contracts/IYVault.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for YVault pools\n * @author Opty.fi\n * @dev Abstraction layer to yVault's pools\n */\n\ncontract YVaultAdapter is IAdapter, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IYVault(_liquidityPool).token();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return\n _depositAmount.mul(10**IYVault(_liquidityPool).decimals()).div(\n IYVault(_liquidityPool).getPricePerFullShare()\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n require(_balanceInToken > 0, \"!balance\");\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _depositAmount)\n );\n _codes[2] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"deposit(uint256)\", _depositAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable,\n address,\n address _liquidityPool,\n uint256 _shares\n ) public view override returns (bytes[] memory _codes) {\n if (_shares > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"withdraw(uint256)\", _shares));\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return IYVault(_liquidityPool).balance();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n return\n getSomeAmountInToken(\n _underlyingToken,\n _liquidityPool,\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool)\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(getLiquidityPoolToken(_underlyingToken, _liquidityPool)).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount\n .mul(IYVault(_liquidityPool).getPricePerFullShare())\n .div(10**IYVault(_liquidityPool).decimals());\n }\n return _liquidityPoolTokenAmount;\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\nimport \"../../utils/Context.sol\";\nimport \"./IERC20.sol\";\nimport \"../../math/SafeMath.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 guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 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 {\n using SafeMath for uint256;\n\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 uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor (string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual 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 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 {_setupDecimals} is\n * called.\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 returns (uint8) {\n return _decimals;\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 * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, 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 * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), 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 * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\"));\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 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\"));\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is 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 * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(address sender, address recipient, uint256 amount) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, 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 * - `to` 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 = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(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 _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(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(address owner, address spender, uint256 amount) 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 Sets {decimals} to a value other than the default one of 18.\n *\n * WARNING: This function should only be called from the constructor. Most\n * applications that interact with token contracts will not expect\n * {decimals} to ever change, and may work incorrectly if it does.\n */\n function _setupDecimals(uint8 decimals_) internal virtual {\n _decimals = decimals_;\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 to 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(address from, address to, uint256 amount) internal virtual { }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <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 GSN 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 payable) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes memory) {\n this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691\n return msg.data;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/mocks/contracts/TestDeFiAdapter.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { MultiCall } from \"../../utils/MultiCall.sol\";\nimport {\n ICurveLiquidityGauge as ICurveGauge\n} from \"@optyfi/defi-legos/ethereum/curve/contracts/ICurveLiquidityGauge.sol\";\nimport { ICurveZap as ICurveDeposit } from \"@optyfi/defi-legos/ethereum/curve/contracts/ICurveZap.sol\";\nimport { ICurveSwap } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveSwap.sol\";\n\nimport \"../../1_ethereum/interfaces/IHarvestCodeProvider.sol\";\n\ninterface IUniswapV2Factory {\n function getPair(address tokenA, address tokenB) external view returns (address pair);\n}\n\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterBorrow } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterBorrow.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport { IAdapterStaking } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol\";\nimport { IAdapterStakingCurve } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStakingCurve.sol\";\nimport { IAdapterFull } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterFull.sol\";\n\ncontract TestDeFiAdapter is MultiCall {\n using SafeMath for uint256;\n\n /** @notice Curve's iron bank swap contract address */\n address public constant Y_SWAP_POOL = address(0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF);\n address public constant DAI = address(0x6B175474E89094C44Da98b954EedeAC495271d0F);\n address public constant USDC = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n address public constant USDT = address(0xdAC17F958D2ee523a2206206994597C13D831ec7);\n uint256 public allAmountInTokenStakeWrite;\n uint256 public calculateRedeemableLPTokenAmountStakeWrite;\n uint256 public unclaimedRewardTokenAmountWrite;\n uint256 public underlyingTokenBalance;\n bool public isRedeemableAmountSufficientStakeWrite;\n\n mapping(address => bool) public yearnCurveStableCoin;\n\n constructor() public {\n yearnCurveStableCoin[DAI] = true;\n yearnCurveStableCoin[USDC] = true;\n yearnCurveStableCoin[USDT] = true;\n }\n\n function testGetDepositAllCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getDepositAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"depositAll\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetDepositSomeCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter,\n uint256 _amount\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getDepositSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _amount\n ),\n \"depositSome\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetBorrowAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _outputToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getBorrowAllCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _outputToken\n ),\n \"borrowAll\"\n );\n }\n\n function testGetStakeAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getStakeAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"stakeAll!\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetStakeSomeCodes(\n address _liquidityPool,\n uint256 _stakeAmount,\n address _adapter\n ) external {\n executeCodes(IAdapterFull(_adapter).getStakeSomeCodes(_liquidityPool, _stakeAmount), \"stakeSome!\");\n }\n\n function testGetAllAmountInTokenStakeWrite(\n address _underlyingToken,\n address _liquidityPool,\n address _liquidityGauge,\n address _rewardToken,\n address _harvestCodeProvider,\n int128 _tokenIndex,\n address _adapter\n ) external {\n uint256 _stakedLpTokenBalance = ERC20(_liquidityGauge).balanceOf(address(this));\n uint256 _amountInToken = 0;\n if (_stakedLpTokenBalance > 0) {\n _amountInToken = _getAmountInToken(_liquidityPool, _underlyingToken, _stakedLpTokenBalance, _tokenIndex);\n }\n uint256 _curveClaimableTokensWrite = ICurveGauge(_liquidityGauge).claimable_tokens(address(this));\n uint256 _amountInTokenHarvest =\n IHarvestCodeProvider(_harvestCodeProvider).rewardBalanceInUnderlyingTokens(\n _rewardToken,\n _underlyingToken,\n _curveClaimableTokensWrite\n );\n uint256 _allAmountInToken = _amountInToken.add(_amountInTokenHarvest);\n allAmountInTokenStakeWrite = IAdapterFull(_adapter).getAllAmountInTokenStakeWrite(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool\n );\n assert(_allAmountInToken == allAmountInTokenStakeWrite);\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testIsRedeemableAmountSufficientStakeWrite(\n address _underlyingToken,\n address _liquidityPool,\n address _liquidityGauge,\n address _rewardToken,\n address _harvestCodeProvider,\n int128 _tokenIndex,\n address _adapter\n ) external {\n uint256 _stakedLpTokenBalance = ERC20(_liquidityGauge).balanceOf(address(this));\n uint256 _amountInToken = 0;\n if (_stakedLpTokenBalance > 0) {\n _amountInToken = _getAmountInToken(_liquidityPool, _underlyingToken, _stakedLpTokenBalance, _tokenIndex);\n }\n uint256 _curveClaimableTokensWrite = ICurveGauge(_liquidityGauge).claimable_tokens(address(this));\n uint256 _amountInTokenHarvest =\n IHarvestCodeProvider(_harvestCodeProvider).rewardBalanceInUnderlyingTokens(\n _rewardToken,\n _underlyingToken,\n _curveClaimableTokensWrite\n );\n uint256 _allAmountInToken = _amountInToken.add(_amountInTokenHarvest);\n isRedeemableAmountSufficientStakeWrite = IAdapterFull(_adapter).isRedeemableAmountSufficientStakeWrite(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _allAmountInToken\n );\n assert(isRedeemableAmountSufficientStakeWrite == true);\n uint256 _redeemAmount = _allAmountInToken.mul(2);\n isRedeemableAmountSufficientStakeWrite = IAdapterFull(_adapter).isRedeemableAmountSufficientStakeWrite(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _redeemAmount\n );\n assert(isRedeemableAmountSufficientStakeWrite == false);\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testCalculateRedeemableLPTokenAmountStakeWrite(\n address _underlyingToken,\n address _liquidityPool,\n address _liquidityGauge,\n address _rewardToken,\n address _harvestCodeProvider,\n int128 _tokenIndex,\n address _adapter\n ) external {\n uint256 _stakedLpTokenBalance = ERC20(_liquidityGauge).balanceOf(address(this));\n uint256 _amountInToken;\n uint256 _allAmountInToken;\n {\n if (_stakedLpTokenBalance > 0) {\n _amountInToken = _getAmountInToken(\n _liquidityPool,\n _underlyingToken,\n _stakedLpTokenBalance,\n _tokenIndex\n );\n }\n uint256 _curveClaimableTokensWrite = ICurveGauge(_liquidityGauge).claimable_tokens(address(this));\n uint256 _amountInTokenHarvest =\n IHarvestCodeProvider(_harvestCodeProvider).rewardBalanceInUnderlyingTokens(\n _rewardToken,\n _underlyingToken,\n _curveClaimableTokensWrite\n );\n\n _allAmountInToken = _amountInToken.add(_amountInTokenHarvest);\n }\n uint256 _redeemAmount = _allAmountInToken.mul(3).div(4);\n uint256 _calculated = _stakedLpTokenBalance.mul(_redeemAmount).div(_allAmountInToken).add(1);\n {\n calculateRedeemableLPTokenAmountStakeWrite = IAdapterFull(_adapter)\n .calculateRedeemableLPTokenAmountStakeWrite(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _redeemAmount\n );\n }\n assert(_calculated == calculateRedeemableLPTokenAmountStakeWrite);\n\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetUnclaimedRewardTokenAmountWrite(\n address _liquidityPool,\n address _underlyingToken,\n address _liquidityGauge,\n address _adapter\n ) external {\n uint256 _curveClaimableTokensWrite = ICurveGauge(_liquidityGauge).claimable_tokens(address(this));\n unclaimedRewardTokenAmountWrite = IAdapterFull(_adapter).getUnclaimedRewardTokenAmountWrite(\n payable(address(this)),\n _liquidityPool,\n _underlyingToken\n );\n assert(_curveClaimableTokensWrite == unclaimedRewardTokenAmountWrite);\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetClaimRewardTokenCode(address _liquidityPool, address _adapter) external {\n executeCodes(\n IAdapterFull(_adapter).getClaimRewardTokenCode(payable(address(this)), _liquidityPool),\n \"claimReward\"\n );\n }\n\n function testGetHarvestAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getHarvestAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"harvestAll\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetHarvestSomeCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter,\n uint256 _rewardTokenAmount\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getHarvestSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _rewardTokenAmount\n ),\n \"harvestSome\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetUnstakeAllCodes(address _liquidityPool, address _adapter) external {\n executeCodes(IAdapterFull(_adapter).getUnstakeAllCodes(payable(address(this)), _liquidityPool), \"unstakeAll\");\n }\n\n function testGetUnstakeSomeCodes(\n address _liquidityPool,\n uint256 _stakeAmount,\n address _adapter\n ) external {\n executeCodes(IAdapterFull(_adapter).getUnstakeSomeCodes(_liquidityPool, _stakeAmount), \"unstakeAll\");\n }\n\n function testGetWithdrawAllCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getWithdrawAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"withdrawAll\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetWithdrawSomeCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter,\n uint256 _amount\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getWithdrawSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _amount\n ),\n \"withdrawSome\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetRepayAndWithdrawAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _outputToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getRepayAndWithdrawAllCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _outputToken\n ),\n \"repayAndWithdrawAll\"\n );\n }\n\n function testGetUnstakeAndWithdrawAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getUnstakeAndWithdrawAllCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool\n ),\n \"unstakeAndWithdrawAll\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetUnstakeAndWithdrawSomeCodes(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _redeemAmount,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getUnstakeAndWithdrawSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _redeemAmount\n ),\n \"unstakeAndWithdrawSome\"\n );\n underlyingTokenBalance = ERC20(_underlyingToken).balanceOf(address(this));\n }\n\n function testGetAddLiquidityCodes(address _underlyingToken, address _adapter) external {\n executeCodes(\n IAdapterFull(_adapter).getAddLiquidityCodes(payable(address(this)), _underlyingToken),\n \"addLiquidity\"\n );\n }\n\n function burnBorrowTokens(address _borrowToken) external {\n ERC20(_borrowToken).transfer(\n address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE),\n ERC20(_borrowToken).balanceOf(address(this))\n );\n }\n\n function _getAmountInToken(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _stakedLpTokenBalance,\n int128 _tokenIndex\n ) internal view returns (uint256) {\n if (yearnCurveStableCoin[_underlyingToken] && _liquidityPool == Y_SWAP_POOL) {\n return ICurveSwap(_liquidityPool).calc_withdraw_one_coin(_stakedLpTokenBalance, _tokenIndex, true);\n } else {\n return ICurveDeposit(_liquidityPool).calc_withdraw_one_coin(_stakedLpTokenBalance, _tokenIndex);\n }\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/utils/MultiCall.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n/**\n * @title MultiCall Contract\n * @author Opty.fi\n * @dev Provides functions used commonly for decoding codes and execute\n * the code calls for Opty.fi contracts\n */\nabstract contract MultiCall {\n /**\n * @notice Executes any functionlaity and check if it is working or not\n * @dev Execute the code and revert with error message if code provided is incorrect\n * @param _code Encoded data in bytes which acts as code to execute\n * @param _errorMsg Error message to throw when code execution call fails\n */\n function executeCode(bytes memory _code, string memory _errorMsg) internal {\n (address _contract, bytes memory _data) = abi.decode(_code, (address, bytes));\n (bool _success, ) = _contract.call(_data); //solhint-disable-line avoid-low-level-calls\n require(_success, _errorMsg);\n }\n\n /**\n * @notice Executes bunch of functionlaities and check if they are working or not\n * @dev Execute the codes array and revert with error message if code provided is incorrect\n * @param _codes Array of encoded data in bytes which acts as code to execute\n * @param _errorMsg Error message to throw when code execution call fails\n */\n function executeCodes(bytes[] memory _codes, string memory _errorMsg) internal {\n for (uint256 _j = 0; _j < _codes.length; _j++) {\n executeCode(_codes[_j], _errorMsg);\n }\n }\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/ICurveLiquidityGauge.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.9.0;\n\ninterface ICurveLiquidityGauge {\n event Deposit(address indexed provider, uint256 value);\n event Withdraw(address indexed provider, uint256 value);\n event UpdateLiquidityLimit(\n address user,\n uint256 original_balance,\n uint256 original_supply,\n uint256 working_balance,\n uint256 working_supply\n );\n\n function user_checkpoint(address addr) external returns (bool);\n\n function claimable_tokens(address addr) external returns (uint256);\n\n function kick(address addr) external;\n\n function set_approve_deposit(address addr, bool can_deposit) external;\n\n function deposit(uint256 _value) external;\n\n function deposit(uint256 _value, address addr) external;\n\n function withdraw(uint256 _value) external;\n\n function integrate_checkpoint() external view returns (uint256);\n\n function minter() external view returns (address);\n\n function crv_token() external view returns (address);\n\n function lp_token() external view returns (address);\n\n function controller() external view returns (address);\n\n function voting_escrow() external view returns (address);\n\n function balanceOf(address arg0) external view returns (uint256);\n\n function totalSupply() external view returns (uint256);\n\n function future_epoch_time() external view returns (uint256);\n\n function approved_to_deposit(address arg0, address arg1) external view returns (bool);\n\n function working_balances(address arg0) external view returns (uint256);\n\n function working_supply() external view returns (uint256);\n\n function period() external view returns (int128);\n\n function period_timestamp(uint256 arg0) external view returns (uint256);\n\n function integrate_inv_supply(uint256 arg0) external view returns (uint256);\n\n function integrate_inv_supply_of(address arg0) external view returns (uint256);\n\n function integrate_checkpoint_of(address arg0) external view returns (uint256);\n\n function integrate_fraction(address arg0) external view returns (uint256);\n\n function inflation_rate() external view returns (uint256);\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/ICurveZap.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.9.0;\n\ninterface ICurveZap {\n function add_liquidity(uint256[2] memory uamounts, uint256 min_mint_amount) external;\n\n function remove_liquidity(uint256 _amount, uint256[2] memory min_uamounts) external;\n\n function remove_liquidity_imbalance(uint256[2] memory uamounts, uint256 max_burn_amount) external;\n\n function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _token_amount,\n int128 i,\n uint256 min_uamount\n ) external;\n\n function remove_liquidity_one_coin(\n uint256 _token_amount,\n int128 i,\n uint256 min_uamount,\n bool donate_dust\n ) external;\n\n function withdraw_donated_dust() external;\n\n function coins(int128 arg0) external view returns (address);\n\n function underlying_coins(int128 arg0) external view returns (address);\n\n function curve() external view returns (address);\n\n function token() external view returns (address);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/curve/CurveSwapPoolAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { CurveSwapETHGateway } from \"./CurveSwapETHGateway.sol\";\n\n// interfaces\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { IAdapterStaking } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol\";\nimport { IAdapterStakingCurve } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStakingCurve.sol\";\nimport { ICurveDeposit } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveDeposit.sol\";\nimport { ICurveSwap } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveSwap.sol\";\nimport { ICurveGauge } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveGauge.sol\";\nimport {\n ICurveAddressProvider\n} from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveAddressProvider.sol\";\nimport { ICurveRegistry } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveRegistry.sol\";\nimport { ITokenMinter } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ITokenMinter.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\n\n/**\n * @title Adapter for Curve Swap pools\n * @author Opty.fi\n * @dev Abstraction layer to Curve's swap pools\n * Note 1 : In this adapter, a liquidity pool is actually swap pool\n * Note 2 : In this adapter, a swap pool is defined as a single-sided liquidity pool\n * Note 3 : In this adapter, lp token can be redemeed into more than one underlying token\n */\ncontract CurveSwapPoolAdapter is\n IAdapter,\n IAdapterHarvestReward,\n IAdapterStaking,\n IAdapterInvestLimit,\n IAdapterStakingCurve,\n Modifiers\n{\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @dev ETH gateway contract for curveSwap adapter */\n address public immutable curveSwapETHGatewayContract;\n\n /** @notice Curve Registry Address Provider */\n address public constant ADDRESS_PROVIDER = address(0x0000000022D53366457F9d5E68Ec105046FC4383);\n\n /** @notice HBTC token contract address */\n address public constant HBTC = address(0x0316EB71485b0Ab14103307bf65a021042c6d380);\n\n /** @notice Curve ETH/sETH StableSwap contract address*/\n address public constant ETH_sETH_STABLESWAP = address(0xc5424B857f758E906013F3555Dad202e4bdB4567);\n\n /** @notice Curve ETH/ankrETH StableSwap contract address*/\n address public constant ETH_ankrETH_STABLESWAP = address(0xA96A65c051bF88B4095Ee1f2451C2A9d43F53Ae2);\n\n /** @notice Curve ETH/rETH StableSwap contract address*/\n address public constant ETH_rETH_STABLESWAP = address(0xF9440930043eb3997fc70e1339dBb11F341de7A8);\n\n /** @notice Curve ETH/stETH StableSwap contract address*/\n address public constant ETH_stETH_STABLESWAP = address(0xDC24316b9AE028F1497c275EB9192a3Ea0f67022);\n\n /** @notice Curve's iron bank swap contract address */\n address public constant Y_SWAP_POOL = address(0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF);\n\n /** WETH ERC20 token address */\n address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n /** Address with no private key */\n address public constant ETH = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\n\n /** @notice max deposit's default value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to absolute max deposit value in underlying */\n mapping(address => uint256) public maxDepositAmount;\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /**\n * @dev mapp coins and tokens to curve deposit pool\n */\n constructor(address _registry) public Modifiers(_registry) {\n curveSwapETHGatewayContract = address(\n new CurveSwapETHGateway(\n WETH,\n _registry,\n [ETH_sETH_STABLESWAP, ETH_ankrETH_STABLESWAP, ETH_rETH_STABLESWAP, ETH_stETH_STABLESWAP]\n )\n );\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n // Note : use 18 as decimals for USD, BTC and ETH\n maxDepositAmount[_liquidityPool] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function getAllAmountInTokenStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external override returns (uint256) {\n uint256 _liquidityPoolTokenAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return _getAllAmountInTokenStakeWrite(_vault, _underlyingToken, _liquidityPool, _liquidityPoolTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function getUnclaimedRewardTokenAmountWrite(\n address payable _vault,\n address _liquidityPool,\n address\n ) external override returns (uint256) {\n return _getUnclaimedRewardTokenAmountWrite(_vault, _liquidityPool);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function calculateRedeemableLPTokenAmountStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external override returns (uint256) {\n uint256 _stakedLiquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInTokenStaked =\n _getAllAmountInTokenStakeWrite(_vault, _underlyingToken, _liquidityPool, _stakedLiquidityPoolTokenBalance);\n // can have unintentional rounding errors\n return (_stakedLiquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInTokenStaked).add(1);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function isRedeemableAmountSufficientStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external override returns (bool) {\n uint256 _liquidityPoolTokenAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInTokenStaked =\n _getAllAmountInTokenStakeWrite(_vault, _underlyingToken, _liquidityPool, _liquidityPoolTokenAmount);\n return _balanceInTokenStaked >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n uint256 _virtualPrice = ICurveSwap(_liquidityPool).get_virtual_price();\n uint256 _totalSupply = ERC20(getLiquidityPoolToken(address(0), _liquidityPool)).totalSupply();\n // the pool value will be in USD for US dollar stablecoin pools\n // the pool value will be in BTC for BTC pools\n return (_virtualPrice.mul(_totalSupply)).div(10**18);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = ERC20(_underlyingToken).balanceOf(_vault);\n return _getDepositCode(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = getLiquidityPoolTokenBalance(_vault, address(0), _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n address _curveRegistry = _getCurveRegistry();\n address[8] memory _underlyingCoins = _getUnderlyingTokens(_liquidityPool, _curveRegistry);\n uint256 _nCoins = _getNCoins(_liquidityPool, _curveRegistry);\n _underlyingTokens = new address[](_nCoins);\n for (uint256 _i = 0; _i < _nCoins; _i++) {\n _underlyingTokens[_i] = _underlyingCoins[_i];\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _underlyingTokenAmount\n ) public view override returns (uint256) {\n if (_underlyingTokenAmount > 0) {\n uint256 _nCoins = _getNCoins(_liquidityPool, _getCurveRegistry());\n address[8] memory _underlyingTokens = _getUnderlyingTokens(_liquidityPool, _getCurveRegistry());\n uint256[] memory _amounts = new uint256[](_nCoins);\n for (uint256 _i; _i < _nCoins; _i++) {\n if (_underlyingTokens[_i] == _underlyingToken) {\n _amounts[_i] = _underlyingTokenAmount;\n }\n }\n if (_nCoins == 2) {\n return ICurveSwap(_liquidityPool).calc_token_amount([_amounts[0], _amounts[1]], true);\n } else if (_nCoins == 3) {\n return ICurveSwap(_liquidityPool).calc_token_amount([_amounts[0], _amounts[1], _amounts[2]], true);\n } else if (_nCoins == 4) {\n return\n ICurveSwap(_liquidityPool).calc_token_amount(\n [_amounts[0], _amounts[1], _amounts[2], _amounts[3]],\n true\n );\n }\n }\n return uint256(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, address(0), _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n address _curveRegistry = _getCurveRegistry();\n address _liquidityGauge = _getLiquidityGauge(_liquidityPool, _curveRegistry);\n if (_liquidityGauge != address(0)) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _getMinter(_liquidityGauge),\n abi.encodeWithSignature(\"mint(address)\", _liquidityGauge)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _rewardTokenAmount = ERC20(getRewardToken(_liquidityPool)).balanceOf(_vault);\n return getHarvestSomeCodes(_vault, _underlyingToken, _liquidityPool, _rewardTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address _liquidityPool) public view override returns (bool) {\n address _curveRegistry = _getCurveRegistry();\n if (_getLiquidityGauge(_liquidityPool, _curveRegistry) != address(0)) {\n return true;\n }\n return false;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeAllCodes(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _stakeAmount = getLiquidityPoolTokenBalance(_vault, address(0), _liquidityPool);\n return getStakeSomeCodes(_liquidityPool, _stakeAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAllCodes(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory)\n {\n uint256 _unstakeAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeSomeCodes(_liquidityPool, _unstakeAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function calculateRedeemableLPTokenAmountStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n // Note : This function does not take into account unclaimed reward tokens\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInToken = getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function isRedeemableAmountSufficientStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n // Note : This function does not take into account unclaimed reward tokens\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInToken = getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeAndWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory) {\n return _getDepositCode(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n * @dev Note : swap pools of compound,usdt,pax,y,susd and busd\n * does not have remove_liquidity_one_coin function\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n address _lendingPool = _underlyingToken == WETH ? curveSwapETHGatewayContract : _liquidityPool;\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _liquidityPool);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _amount)\n );\n\n _codes[2] = _underlyingToken == WETH\n ? abi.encode(\n curveSwapETHGatewayContract,\n // solhint-disable-next-line max-line-length\n abi.encodeWithSignature(\n \"withdrawETH(address,address,address,uint256,int128)\",\n _vault,\n _liquidityPool,\n _liquidityPoolToken,\n _amount,\n _getTokenIndex(_liquidityPool, _underlyingToken)\n )\n )\n : abi.encode(\n _lendingPool,\n // solhint-disable-next-line max-line-length\n abi.encodeWithSignature(\n \"remove_liquidity_one_coin(uint256,int128,uint256)\",\n _amount,\n _getTokenIndex(_liquidityPool, _underlyingToken),\n getSomeAmountInToken(_underlyingToken, _liquidityPool, _amount).mul(95).div(100)\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return ICurveRegistry(_getCurveRegistry()).get_lp_token(_liquidityPool);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenAmount = getLiquidityPoolTokenBalance(_vault, address(0), _liquidityPool);\n return getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return ERC20(getLiquidityPoolToken(address(0), _liquidityPool)).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n return\n ICurveDeposit(_liquidityPool).calc_withdraw_one_coin(\n _liquidityPoolTokenAmount,\n _getTokenIndex(_liquidityPool, _underlyingToken)\n );\n }\n return 0;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _liquidityPool) public view override returns (address) {\n address _curveRegistry = _getCurveRegistry();\n address _liquidityGauge = _getLiquidityGauge(_liquidityPool, _curveRegistry);\n if (_liquidityGauge != address(0)) {\n return ITokenMinter(_getMinter(_liquidityGauge)).token();\n }\n return address(0);\n }\n\n /* solhint-disable no-empty-blocks */\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable,\n address _liquidityPool,\n address\n ) public view override returns (uint256) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /* solhint-disable no-empty-blocks */\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable, address) public view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeSomeCodes(address _liquidityPool, uint256 _stakeAmount)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_stakeAmount > 0) {\n address _curveRegistry = _getCurveRegistry();\n address _liquidityGauge = _getLiquidityGauge(_liquidityPool, _curveRegistry);\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _liquidityPool);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityGauge, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityGauge, _stakeAmount)\n );\n _codes[2] = abi.encode(_liquidityGauge, abi.encodeWithSignature(\"deposit(uint256)\", _stakeAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeSomeCodes(address _liquidityPool, uint256 _unstakeAmount)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_unstakeAmount > 0) {\n address _curveRegistry = _getCurveRegistry();\n address _liquidityGauge = _getLiquidityGauge(_liquidityPool, _curveRegistry);\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_liquidityGauge, abi.encodeWithSignature(\"withdraw(uint256)\", _unstakeAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getAllAmountInTokenStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n // Note : This function does not take into account unclaimed reward tokens\n uint256 _liquidityPoolTokenBalanceStake = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalanceStake);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getLiquidityPoolTokenBalanceStake(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (uint256)\n {\n return ICurveGauge(_getLiquidityGauge(_liquidityPool, _getCurveRegistry())).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_redeemAmount > 0) {\n _codes = new bytes[](4);\n _codes[0] = getUnstakeSomeCodes(_liquidityPool, _redeemAmount)[0];\n bytes[] memory _withdrawCodes =\n getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n _codes[1] = _withdrawCodes[0];\n _codes[2] = _withdrawCodes[1];\n _codes[3] = _withdrawCodes[2];\n }\n }\n\n /**\n * @notice Returns the balance in underlying for staked liquidityPoolToken balance of holder\n * @dev It should only be implemented in Curve adapters\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to stake all lpTokens\n * @return Returns the equivalent amount of underlying tokens to the staked amount of liquidityPoolToken\n */\n function _getAllAmountInTokenStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) internal returns (uint256) {\n uint256 _b = getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenAmount);\n _b = _b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _getUnclaimedRewardTokenAmountWrite(_vault, _liquidityPool)\n )\n );\n return _b;\n }\n\n /**\n * @notice Get the Curve Minter's address\n */\n function _getMinter(address _gauge) internal view returns (address) {\n return ICurveGauge(_gauge).minter();\n }\n\n /**\n * @dev This function composes the configuration required to construct fuction calls\n * @param _underlyingToken address of the underlying asset\n * @param _swapPool swap pool address\n * @param _amount amount in underlying token\n * @return _underlyingTokenIndex index of _underlyingToken\n * @return _nCoins number of underlying tokens in swap pool\n * @return _underlyingTokens underlying tokens in a swap pool\n * @return _amounts value in an underlying token for each underlying token\n * @return _codeLength number of function call required for deposit\n */\n function _getDepositCodeConfig(\n address _underlyingToken,\n address _swapPool,\n uint256 _amount\n )\n internal\n view\n returns (\n int128 _underlyingTokenIndex,\n uint256 _nCoins,\n address[8] memory _underlyingTokens,\n uint256[] memory _amounts,\n uint256 _codeLength,\n uint256 _minMintAmount\n )\n {\n address _curveRegistry = _getCurveRegistry();\n _nCoins = _getNCoins(_swapPool, _curveRegistry);\n _underlyingTokens = _getUnderlyingTokens(_swapPool, _curveRegistry);\n address _curveishCoin = _underlyingToken == WETH ? ETH : _underlyingToken;\n _underlyingTokenIndex = _getTokenIndex(_swapPool, _curveishCoin);\n _amounts = new uint256[](_nCoins);\n _codeLength = 1;\n for (uint256 _i = 0; _i < _nCoins; _i++) {\n if (_underlyingTokens[_i] == _curveishCoin) {\n _amounts[_i] = _getDepositAmount(_swapPool, _underlyingToken, _amount);\n if (_amounts[_i] > 0) {\n if (_underlyingTokens[_i] == HBTC) {\n _codeLength++;\n } else {\n _codeLength += 2;\n }\n }\n }\n }\n if (_nCoins == uint256(2)) {\n _minMintAmount = ICurveSwap(_swapPool).calc_token_amount([_amounts[0], _amounts[1]], true).mul(95).div(100);\n } else if (_nCoins == uint256(3)) {\n _minMintAmount = ICurveSwap(_swapPool)\n .calc_token_amount([_amounts[0], _amounts[1], _amounts[2]], true)\n .mul(95)\n .div(100);\n } else if (_nCoins == uint256(4)) {\n _minMintAmount = ICurveSwap(_swapPool)\n .calc_token_amount([_amounts[0], _amounts[1], _amounts[2], _amounts[3]], true)\n .mul(95)\n .div(100);\n }\n }\n\n /**\n * @dev This functions returns the token index for a underlying token\n * @param _underlyingToken address of the underlying asset\n * @param _swapPool swap pool address\n * @return _tokenIndex index of coin in swap pool\n */\n function _getTokenIndex(address _swapPool, address _underlyingToken) internal view returns (int128) {\n address _inputToken = _underlyingToken == WETH ? ETH : _underlyingToken;\n address[8] memory _underlyingTokens = _getUnderlyingTokens(_swapPool, _getCurveRegistry());\n for (uint256 _i = 0; _i < _underlyingTokens.length; _i++) {\n if (_underlyingTokens[_i] == _inputToken) {\n return int128(_i);\n }\n }\n return int128(0);\n }\n\n /**\n * @dev Returns the amount of accrued reward tokens for a specific OptyFi's vault\n * @param _vault Address of the OptyFi's vault contract\n * @param _swapPool Address of the swap pool contract\n * @return Returns the amount of accrued reward tokens\n */\n function _getUnclaimedRewardTokenAmountWrite(address payable _vault, address _swapPool) internal returns (uint256) {\n address _liquidityGauge = _getLiquidityGauge(_swapPool, _getCurveRegistry());\n if (_liquidityGauge != address(0)) {\n return ICurveGauge(_liquidityGauge).claimable_tokens(_vault);\n }\n return uint256(0);\n }\n\n /**\n * @dev This functions composes the function calls to deposit asset into deposit pool\n * @param _underlyingToken address of the underlying asset\n * @param _swapPool swap pool address\n * @param _amount the amount in underlying token\n * @return _codes bytes array of function calls to be executed from vault\n */\n function _getDepositCode(\n address payable _vault,\n address _underlyingToken,\n address _swapPool,\n uint256 _amount\n ) internal view returns (bytes[] memory _codes) {\n (\n int128 _underlyingTokenIndex,\n uint256 _nCoins,\n address[8] memory _underlyingTokens,\n uint256[] memory _amounts,\n uint256 _codeLength,\n uint256 _minAmount\n ) = _getDepositCodeConfig(_underlyingToken, _swapPool, _amount);\n address _lendingPool = _underlyingToken == WETH ? curveSwapETHGatewayContract : _swapPool;\n if (_codeLength > 1) {\n _codes = new bytes[](_codeLength);\n uint256 _j = 0;\n for (uint256 i = 0; i < _nCoins; i++) {\n address _inputToken = _underlyingTokens[i] == ETH ? WETH : _underlyingTokens[i];\n if (_amounts[i] > 0) {\n if (_inputToken == HBTC) {\n _codes[_j++] = abi.encode(\n _inputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _amounts[i])\n );\n } else {\n _codes[_j++] = abi.encode(\n _inputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[_j++] = abi.encode(\n _inputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _amounts[i])\n );\n }\n }\n }\n if (_nCoins == uint256(2)) {\n uint256[2] memory _depositAmounts = [_amounts[0], _amounts[1]];\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _swapPool);\n _codes[_j] = _underlyingToken == WETH\n ? abi.encode(\n curveSwapETHGatewayContract,\n abi.encodeWithSignature(\n \"depositETH(address,address,address,uint256[2],int128)\",\n _vault,\n _swapPool,\n _liquidityPoolToken,\n _depositAmounts,\n _underlyingTokenIndex\n )\n )\n : abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"add_liquidity(uint256[2],uint256)\", _depositAmounts, _minAmount)\n );\n } else if (_nCoins == uint256(3)) {\n uint256[3] memory _depositAmounts = [_amounts[0], _amounts[1], _amounts[2]];\n _codes[_j] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"add_liquidity(uint256[3],uint256)\", _depositAmounts, _minAmount)\n );\n } else if (_nCoins == uint256(4)) {\n uint256[4] memory _depositAmounts = [_amounts[0], _amounts[1], _amounts[2], _amounts[3]];\n _codes[_j] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"add_liquidity(uint256[4],uint256)\", _depositAmounts, _minAmount)\n );\n }\n }\n }\n\n /**\n * @dev Get the underlying tokens within a swap pool.\n * Note: For pools using lending, these are the\n * wrapped coin addresses\n * @param _swapPool the swap pool address\n * @param _curveRegistry the address of the Curve registry\n * @return list of coin addresses\n */\n function _getUnderlyingTokens(address _swapPool, address _curveRegistry) internal view returns (address[8] memory) {\n return ICurveRegistry(_curveRegistry).get_coins(_swapPool);\n }\n\n /**\n * @dev Get a liquidity gauge address associated with a swap pool\n * @param _swapPool the swap pool address\n * @param _curveRegistry the Curve registry's address\n * @return gauge address\n */\n function _getLiquidityGauge(address _swapPool, address _curveRegistry) internal view returns (address) {\n (address[10] memory _liquidityGauges, ) = ICurveRegistry(_curveRegistry).get_gauges(_swapPool);\n return _liquidityGauges[0];\n }\n\n /**\n * @dev Get the address of the main registry contract\n * @return Address of the main registry contract\n */\n function _getCurveRegistry() internal view returns (address) {\n return ICurveAddressProvider(ADDRESS_PROVIDER).get_registry();\n }\n\n /**\n * @dev Get number of underlying tokens in a liquidity pool\n * @param _swapPool swap pool address associated with liquidity pool\n * @param _curveRegistry address of the main registry contract\n * @return Number of underlying tokens\n */\n function _getNCoins(address _swapPool, address _curveRegistry) internal view returns (uint256) {\n return ICurveRegistry(_curveRegistry).get_n_coins(_swapPool)[0];\n }\n\n /**\n * @dev Get the final value of amount in underlying token to be deposited\n * @param _swapPool swap pool address\n * @param _underlyingToken underlying token address\n * @param _amount amount in underlying token\n * @return amount in underlying token to be deposited affected by investment limitation\n */\n function _getDepositAmount(\n address _swapPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n return\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountPct(_swapPool, _underlyingToken, _amount)\n : _getMaxDepositAmount(_swapPool, _underlyingToken, _amount);\n }\n\n /**\n * @dev Gets the maximum amount in underlying token limited by percentage\n * @param _swapPool swap pool address\n * @param _underlyingToken underlying token address\n * @param _amount amount in underlying token\n * @return amount in underlying token to be deposited affected by\n * investment limit in percentage\n */\n function _getMaxDepositAmountPct(\n address _swapPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_swapPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_swapPool];\n uint256 _decimals = ERC20(_underlyingToken).decimals();\n uint256 _actualAmount = _amount.mul(10**(uint256(18).sub(_decimals)));\n uint256 _limit =\n _poolPct == 0 ? _poolValue.mul(maxDepositProtocolPct).div(10000) : _poolValue.mul(_poolPct).div(10000);\n return _actualAmount > _limit ? _limit.div(10**(uint256(18).sub(_decimals))) : _amount;\n }\n\n /**\n * @dev Gets the maximum amount in underlying token affected by investment\n * limit set for swap pool in amount\n * @param _swapPool swap pool address\n * @param _underlyingToken underlying token address\n * @param _amount amount in underlying token\n * @return amount in underlying token to be deposited affected by\n * investment limit set for swap pool in amount\n */\n function _getMaxDepositAmount(\n address _swapPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _decimals = ERC20(_underlyingToken).decimals();\n uint256 _maxAmount = maxDepositAmount[_swapPool].div(10**(uint256(18).sub(_decimals)));\n return _amount > _maxAmount ? _maxAmount : _amount;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/curve/CurveSwapETHGateway.sol": { + "content": "// SPDX-License-Identifier:MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\n// helper contracts\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IWETH } from \"@optyfi/defi-legos/interfaces/misc/contracts/IWETH.sol\";\nimport { IETHGateway } from \"@optyfi/defi-legos/interfaces/misc/contracts/IETHGateway.sol\";\nimport { ICurveETHSwapV1 as ICurveETHSwap } from \"@optyfi/defi-legos/ethereum/curve/contracts/ICurveETHSwapV1.sol\";\n\n/**\n * @title ETH gateway for opty-fi's Curve Swap adapter\n * @author Opty.fi\n * @dev Inspired from Aave WETH gateway\n */\ncontract CurveSwapETHGateway is IETHGateway, Modifiers {\n using SafeMath for uint256;\n // solhint-disable-next-line var-name-mixedcase\n IWETH internal immutable WETH;\n\n // solhint-disable-next-line var-name-mixedcase\n mapping(address => bool) public ethPools;\n\n /**\n * @dev Initializes the WETH address, registry and curve's Eth pools\n * @param _weth Address of the Wrapped Ether contract\n * @param _registry Address of the registry\n * @param _ethPools Array of Curve's Eth pools\n **/\n constructor(\n address _weth,\n address _registry,\n address[4] memory _ethPools\n ) public Modifiers(_registry) {\n WETH = IWETH(_weth);\n for (uint256 _i = 0; _i < _ethPools.length; _i++) {\n ethPools[_ethPools[_i]] = true;\n }\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function depositETH(\n address _vault,\n address _liquidityPool,\n address _liquidityPoolToken,\n uint256[2] memory _amounts,\n int128 _tokenIndex\n ) external override {\n IERC20(address(WETH)).transferFrom(_vault, address(this), _amounts[uint256(_tokenIndex)]);\n WETH.withdraw(_amounts[uint256(_tokenIndex)]);\n uint256 _minAmount =\n (_amounts[uint256(_tokenIndex)].mul(10**18).mul(95)).div(\n ICurveETHSwap(_liquidityPool).get_virtual_price().mul(100)\n );\n ICurveETHSwap(_liquidityPool).add_liquidity{ value: address(this).balance }(_amounts, _minAmount);\n IERC20(_liquidityPoolToken).transfer(_vault, IERC20(_liquidityPoolToken).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function withdrawETH(\n address _vault,\n address _liquidityPool,\n address _liquidityPoolToken,\n uint256 _amount,\n int128 _tokenIndex\n ) external override {\n IERC20(_liquidityPoolToken).transferFrom(_vault, address(this), _amount);\n uint256 _minAmount =\n ICurveETHSwap(_liquidityPool).calc_withdraw_one_coin(_amount, _tokenIndex).mul(95).div(100);\n ICurveETHSwap(_liquidityPool).remove_liquidity_one_coin(_amount, _tokenIndex, _minAmount);\n WETH.deposit{ value: address(this).balance }();\n IERC20(address(WETH)).transfer(_vault, IERC20(address(WETH)).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function emergencyTokenTransfer(\n address _token,\n address _to,\n uint256 _amount\n ) external override onlyOperator {\n IERC20(_token).transfer(_to, _amount);\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function emergencyEtherTransfer(address to, uint256 amount) external override onlyOperator {\n _safeTransferETH(to, amount);\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function getWETHAddress() external view override returns (address) {\n return address(WETH);\n }\n\n /**\n * @dev transfer ETH to an address, revert if it fails.\n * @param _to recipient of the transfer\n * @param _value the amount to send\n */\n function _safeTransferETH(address _to, uint256 _value) internal {\n // solhint-disable-next-line avoid-low-level-calls\n (bool _success, ) = _to.call{ value: _value }(new bytes(0));\n require(_success, \"ETH_TRANSFER_FAILED\");\n }\n\n /**\n * @dev Only WETH and ethPool contracts are allowed to transfer ETH here. Prevent other addresses\n * to send Ether to this contract.\n */\n receive() external payable {\n require(msg.sender == address(WETH) || ethPools[msg.sender], \"Receive not allowed\");\n }\n\n /**\n * @dev Revert fallback calls\n */\n fallback() external payable {\n revert(\"Fallback not allowed\");\n }\n}\n" + }, + "@optyfi/defi-legos/ethereum/curve/contracts/ICurveETHSwapV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\ninterface ICurveETHSwapV1 {\n event TokenExchange(\n address indexed buyer,\n int128 sold_id,\n uint256 tokens_sold,\n int128 bought_id,\n uint256 tokens_bought\n );\n event AddLiquidity(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 invariant,\n uint256 token_supply\n );\n event RemoveLiquidity(address indexed provider, uint256[2] token_amounts, uint256[2] fees, uint256 token_supply);\n event RemoveLiquidityOne(address indexed provider, uint256 token_amount, uint256 coin_amount);\n event RemoveLiquidityImbalance(\n address indexed provider,\n uint256[2] token_amounts,\n uint256[2] fees,\n uint256 invariant,\n uint256 token_supply\n );\n event CommitNewAdmin(uint256 indexed deadline, address indexed admin);\n event NewAdmin(address indexed admin);\n event CommitNewFee(uint256 indexed deadline, uint256 fee, uint256 admin_fee);\n event NewFee(uint256 fee, uint256 admin_fee);\n event RampA(uint256 old_A, uint256 new_A, uint256 initial_time, uint256 future_time);\n event StopRampA(uint256 A, uint256 t);\n\n function A() external view returns (uint256);\n\n function A_precise() external view returns (uint256);\n\n function get_virtual_price() external view returns (uint256);\n\n function calc_token_amount(uint256[2] memory amounts, bool is_deposit) external view returns (uint256);\n\n function add_liquidity(uint256[2] memory amounts, uint256 min_mint_amount) external payable returns (uint256);\n\n function get_dy(\n int128 i,\n int128 j,\n uint256 dx\n ) external view returns (uint256);\n\n function exchange(\n int128 i,\n int128 j,\n uint256 dx,\n uint256 min_dy\n ) external payable returns (uint256);\n\n function remove_liquidity(uint256 _amount, uint256[2] memory min_amounts) external returns (uint256[2] memory);\n\n function remove_liquidity_imbalance(uint256[2] memory amounts, uint256 max_burn_amount) external returns (uint256);\n\n function calc_withdraw_one_coin(uint256 _token_amount, int128 i) external view returns (uint256);\n\n function remove_liquidity_one_coin(\n uint256 _token_amount,\n int128 i,\n uint256 _min_amount\n ) external returns (uint256);\n\n function ramp_A(uint256 _future_A, uint256 _future_time) external;\n\n function stop_ramp_A() external;\n\n function commit_new_fee(uint256 new_fee, uint256 new_admin_fee) external;\n\n function apply_new_fee() external;\n\n function revert_new_parameters() external;\n\n function commit_transfer_ownership(address _owner) external;\n\n function apply_transfer_ownership() external;\n\n function revert_transfer_ownership() external;\n\n function admin_balances(uint256 i) external view returns (uint256);\n\n function withdraw_admin_fees() external;\n\n function donate_admin_fees() external;\n\n function kill_me() external;\n\n function unkill_me() external;\n\n function coins(uint256 arg0) external view returns (address);\n\n function balances(uint256 arg0) external view returns (uint256);\n\n function fee() external view returns (uint256);\n\n function admin_fee() external view returns (uint256);\n\n function owner() external view returns (address);\n\n function initial_A() external view returns (uint256);\n\n function future_A() external view returns (uint256);\n\n function initial_A_time() external view returns (uint256);\n\n function future_A_time() external view returns (uint256);\n\n function admin_actions_deadline() external view returns (uint256);\n\n function transfer_ownership_deadline() external view returns (uint256);\n\n function future_fee() external view returns (uint256);\n\n function future_admin_fee() external view returns (uint256);\n\n function future_owner() external view returns (address);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/mock/TestHarvestCodeProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { MultiCall } from \"../../utils/MultiCall.sol\";\n\ncontract TestHarvestCodeProvider is MultiCall {\n using SafeERC20 for ERC20;\n\n function testGetHarvestCodes(\n address _rewardToken,\n address _underlyingToken,\n address _harvestCodeProvider,\n uint256 _rewardTokenAmount\n ) external {\n executeCodes(\n IHarvestCodeProvider(_harvestCodeProvider).getHarvestCodes(\n payable(address(this)),\n _rewardToken,\n _underlyingToken,\n _rewardTokenAmount\n ),\n \"harvest\"\n );\n }\n\n function testGetAddLiquidityCodes(\n address _router,\n address _underlyingToken,\n address _harvestCodeProvider\n ) external {\n executeCodes(\n IHarvestCodeProvider(_harvestCodeProvider).getAddLiquidityCodes(\n _router,\n payable(address(this)),\n _underlyingToken\n ),\n \"addLiquidity\"\n );\n }\n\n function burnTokens(address _token) external {\n ERC20(_token).safeTransfer(\n address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE),\n ERC20(_token).balanceOf(address(this))\n );\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/HarvestCodeProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// helper contracts\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { Modifiers } from \"../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IUniswapV2Router02 } from \"@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol\";\nimport { IUniswapV2Pair } from \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IHarvestCodeProvider } from \"./interfaces/IHarvestCodeProvider.sol\";\n\n/**\n * @title HarvestCodeProvider Contract\n * @author Opty.fi\n * @notice Abstraction layer to DeFi exchanges like Uniswap\n * @dev Contract for generating the codes for harvest tokens\n */\ncontract HarvestCodeProvider is IHarvestCodeProvider, Modifiers {\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n /**\n * @notice Uniswap V2 router contract address\n */\n address public constant uniswapV2Router02 = address(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);\n\n /**\n * @notice Sushiswap router contract address\n */\n address public constant sushiswapRouter = address(0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F);\n\n /**\n * @notice SUSHI token contract address\n */\n address public constant SUSHI = address(0x6B3595068778DD592e39A122f4f5a5cF09C90fE2);\n\n /**\n * @notice UNI token contract address\n */\n address public constant UNI = address(0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984);\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /* solhint-disable no-empty-blocks */\n\n /**\n * @inheritdoc IHarvestCodeProvider\n */\n function getHarvestCodes(\n address payable _vault,\n address _rewardToken,\n address _underlyingToken,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_rewardTokenAmount > 0) {\n if (_rewardToken == SUSHI) {\n _codes = _getHarvestSushiOrUniCodes(\n _vault,\n _rewardToken,\n _underlyingToken,\n _rewardTokenAmount,\n sushiswapRouter\n );\n } else if (_rewardToken == UNI) {\n _codes = _getHarvestSushiOrUniCodes(\n _vault,\n _rewardToken,\n _underlyingToken,\n _rewardTokenAmount,\n sushiswapRouter\n );\n } else if (_rewardToken != _underlyingToken) {\n uint256[] memory _amounts =\n IUniswapV2Router02(uniswapV2Router02).getAmountsOut(\n _rewardTokenAmount,\n _getPath(_rewardToken, _underlyingToken)\n );\n if (_amounts[_amounts.length - 1] > 0) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _rewardToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", uniswapV2Router02, uint256(0))\n );\n _codes[1] = abi.encode(\n _rewardToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", uniswapV2Router02, _rewardTokenAmount)\n );\n _codes[2] = abi.encode(\n uniswapV2Router02,\n abi.encodeWithSignature(\n \"swapExactTokensForTokens(uint256,uint256,address[],address,uint256)\",\n _rewardTokenAmount,\n uint256(0),\n _getPath(_rewardToken, _underlyingToken),\n _vault,\n uint256(-1)\n )\n );\n }\n }\n }\n }\n\n /**\n * @inheritdoc IHarvestCodeProvider\n */\n function getAddLiquidityCodes(\n address _router,\n address payable _vault,\n address _underlyingToken\n ) public view override returns (bytes[] memory _codes) {\n address _token0 = IUniswapV2Pair(_underlyingToken).token0();\n address _token1 = IUniswapV2Pair(_underlyingToken).token1();\n if (IERC20(_token0).balanceOf(_vault) > 0 && IERC20(_token1).balanceOf(_vault) > 0) {\n _codes = new bytes[](5);\n _codes[0] = abi.encode(_token0, abi.encodeWithSignature(\"approve(address,uint256)\", _router, uint256(0)));\n _codes[1] = abi.encode(\n _token0,\n abi.encodeWithSignature(\"approve(address,uint256)\", _router, IERC20(_token0).balanceOf(_vault))\n );\n _codes[2] = abi.encode(_token1, abi.encodeWithSignature(\"approve(address,uint256)\", _router, uint256(0)));\n _codes[3] = abi.encode(\n _token1,\n abi.encodeWithSignature(\"approve(address,uint256)\", _router, IERC20(_token1).balanceOf(_vault))\n );\n _codes[4] = abi.encode(\n _router,\n abi.encodeWithSignature(\n \"addLiquidity(address,address,uint256,uint256,uint256,uint256,address,uint256)\",\n _token0,\n _token1,\n IERC20(_token0).balanceOf(_vault),\n IERC20(_token1).balanceOf(_vault),\n uint256(0),\n uint256(0),\n _vault,\n uint256(-1)\n )\n );\n }\n }\n\n /**\n * @inheritdoc IHarvestCodeProvider\n */\n function getOptimalTokenAmount(\n address _borrowToken,\n address _underlyingToken,\n uint256 _borrowTokenAmount\n ) public view override returns (uint256) {\n if (_borrowTokenAmount > 0) {\n try\n IUniswapV2Router02(uniswapV2Router02).getAmountsOut(\n _borrowTokenAmount,\n _getPath(_borrowToken, _underlyingToken)\n )\n returns (uint256[] memory _amounts) {\n return _amounts[_amounts.length - 1];\n } catch {\n return uint256(0);\n }\n }\n return uint256(0);\n }\n\n /**\n * @inheritdoc IHarvestCodeProvider\n */\n function rewardBalanceInUnderlyingTokens(\n address _rewardToken,\n address _underlyingToken,\n uint256 _amount\n ) public view override returns (uint256) {\n if (_amount > 0) {\n if (_rewardToken == SUSHI) {\n return\n _getRewardBalanceInUnderlyingTokensSushiOrUni(\n _rewardToken,\n _underlyingToken,\n _amount,\n sushiswapRouter\n );\n } else if (_rewardToken == UNI) {\n return\n _getRewardBalanceInUnderlyingTokensSushiOrUni(\n _rewardToken,\n _underlyingToken,\n _amount,\n uniswapV2Router02\n );\n } else {\n try\n IUniswapV2Router02(uniswapV2Router02).getAmountsOut(\n _amount,\n _getPath(_rewardToken, _underlyingToken)\n )\n returns (uint256[] memory _amountsA) {\n return _amountsA[_amountsA.length - 1];\n } catch {\n return uint256(0);\n }\n }\n }\n }\n\n /**\n * @inheritdoc IHarvestCodeProvider\n */\n function getWETHInToken(address _underlyingToken, uint256 _amount) public view override returns (uint256) {\n address _weth = IUniswapV2Router02(uniswapV2Router02).WETH();\n if (_underlyingToken == _weth) {\n return _amount;\n }\n uint256[] memory _amounts =\n IUniswapV2Router02(uniswapV2Router02).getAmountsOut(_amount, _getPath(_weth, _underlyingToken));\n return _amounts[1];\n }\n\n function _getHarvestSushiOrUniCodes(\n address payable _vault,\n address _rewardToken,\n address _underlyingToken,\n uint256 _rewardTokenAmount,\n address _router\n ) internal view returns (bytes[] memory _codes) {\n address _token0 = IUniswapV2Pair(_underlyingToken).token0();\n address _token1 = IUniswapV2Pair(_underlyingToken).token1();\n uint256[] memory _amounts0 =\n IUniswapV2Router02(_router).getAmountsOut(\n _rewardTokenAmount.div(uint256(2)),\n _getPath(_rewardToken, _token0)\n );\n uint256[] memory _amounts1 =\n IUniswapV2Router02(_router).getAmountsOut(\n _rewardTokenAmount.sub(_rewardTokenAmount.div(uint256(2))),\n _getPath(_rewardToken, _token1)\n );\n if (_amounts0[_amounts0.length - 1] > 0 && _amounts1[_amounts1.length - 1] > 0) {\n uint8 maxLength = 4;\n if (_token0 == _rewardToken || _token1 == _rewardToken) {\n maxLength--;\n }\n _codes = new bytes[](maxLength);\n _codes[0] = abi.encode(\n _rewardToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _router, uint256(0))\n );\n _codes[1] = abi.encode(\n _rewardToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _router, _rewardTokenAmount)\n );\n uint8 count = 2;\n if (_token0 != _rewardToken) {\n _codes[count] = abi.encode(\n _router,\n abi.encodeWithSignature(\n \"swapExactTokensForTokens(uint256,uint256,address[],address,uint256)\",\n _rewardTokenAmount.div(uint256(2)),\n uint256(0),\n _getPath(_rewardToken, _token0),\n _vault,\n uint256(-1)\n )\n );\n count++;\n }\n if (_token1 != _rewardToken) {\n _codes[count] = abi.encode(\n _router,\n abi.encodeWithSignature(\n \"swapExactTokensForTokens(uint256,uint256,address[],address,uint256)\",\n _rewardTokenAmount.sub(_rewardTokenAmount.div(uint256(2))),\n uint256(0),\n _getPath(_rewardToken, _token1),\n _vault,\n uint256(-1)\n )\n );\n }\n }\n }\n\n function _getRewardBalanceInUnderlyingTokensSushiOrUni(\n address _rewardToken,\n address _underlyingToken,\n uint256 _amount,\n address _router\n ) internal view returns (uint256 _finalAmount) {\n address _tokenA = IUniswapV2Pair(_underlyingToken).token0();\n address _tokenB = IUniswapV2Pair(_underlyingToken).token1();\n\n try\n IUniswapV2Router02(_router).getAmountsOut(_amount.div(uint256(2)), _getPath(_rewardToken, _tokenA))\n returns (uint256[] memory _amountsA) {\n try\n IUniswapV2Router02(_router).getAmountsOut(_amount.div(uint256(2)), _getPath(_rewardToken, _tokenB))\n returns (uint256[] memory _amountsB) {\n try IUniswapV2Pair(_underlyingToken).getReserves() returns (\n uint112 reserve0,\n uint112 reserve1,\n uint32\n ) {\n try IUniswapV2Router02(_router).quote(_amountsA[_amountsA.length - 1], reserve0, reserve1) returns (\n uint256 _quoteAmount\n ) {\n if (_quoteAmount >= _amountsB[_amountsB.length - 1]) {\n _finalAmount = _amountsB[_amountsB.length - 1]\n .mul(IUniswapV2Pair(_underlyingToken).totalSupply())\n .div(reserve1);\n } else {\n _finalAmount = _quoteAmount.mul(IUniswapV2Pair(_underlyingToken).totalSupply()).div(\n reserve1\n );\n }\n } catch {}\n } catch {}\n } catch {}\n } catch {}\n }\n\n function _getPath(address _initialToken, address _finalToken) internal pure returns (address[] memory _path) {\n address _weth = IUniswapV2Router02(uniswapV2Router02).WETH();\n if (_finalToken == _weth) {\n _path = new address[](2);\n _path[0] = _initialToken;\n _path[1] = _weth;\n } else if (_initialToken == _weth) {\n _path = new address[](2);\n _path[0] = _weth;\n _path[1] = _finalToken;\n } else {\n _path = new address[](3);\n _path[0] = _initialToken;\n _path[1] = _weth;\n _path[2] = _finalToken;\n }\n }\n}\n" + }, + "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol": { + "content": "pragma solidity >=0.6.2;\n\nimport './IUniswapV2Router01.sol';\n\ninterface IUniswapV2Router02 is IUniswapV2Router01 {\n function removeLiquidityETHSupportingFeeOnTransferTokens(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external returns (uint amountETH);\n function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountETH);\n\n function swapExactTokensForTokensSupportingFeeOnTransferTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external;\n function swapExactETHForTokensSupportingFeeOnTransferTokens(\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external payable;\n function swapExactTokensForETHSupportingFeeOnTransferTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external;\n}\n" + }, + "@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol": { + "content": "pragma solidity >=0.5.0;\n\ninterface IUniswapV2Pair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint);\n function balanceOf(address owner) external view returns (uint);\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n function transfer(address to, uint value) external returns (bool);\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n function factory() external view returns (address);\n function token0() external view returns (address);\n function token1() external view returns (address);\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n function price0CumulativeLast() external view returns (uint);\n function price1CumulativeLast() external view returns (uint);\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n function burn(address to) external returns (uint amount0, uint amount1);\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n function skim(address to) external;\n function sync() external;\n\n function initialize(address, address) external;\n}\n" + }, + "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router01.sol": { + "content": "pragma solidity >=0.6.2;\n\ninterface IUniswapV2Router01 {\n function factory() external pure returns (address);\n function WETH() external pure returns (address);\n\n function addLiquidity(\n address tokenA,\n address tokenB,\n uint amountADesired,\n uint amountBDesired,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline\n ) external returns (uint amountA, uint amountB, uint liquidity);\n function addLiquidityETH(\n address token,\n uint amountTokenDesired,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external payable returns (uint amountToken, uint amountETH, uint liquidity);\n function removeLiquidity(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETH(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline\n ) external returns (uint amountToken, uint amountETH);\n function removeLiquidityWithPermit(\n address tokenA,\n address tokenB,\n uint liquidity,\n uint amountAMin,\n uint amountBMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountA, uint amountB);\n function removeLiquidityETHWithPermit(\n address token,\n uint liquidity,\n uint amountTokenMin,\n uint amountETHMin,\n address to,\n uint deadline,\n bool approveMax, uint8 v, bytes32 r, bytes32 s\n ) external returns (uint amountToken, uint amountETH);\n function swapExactTokensForTokens(\n uint amountIn,\n uint amountOutMin,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapTokensForExactTokens(\n uint amountOut,\n uint amountInMax,\n address[] calldata path,\n address to,\n uint deadline\n ) external returns (uint[] memory amounts);\n function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)\n external\n returns (uint[] memory amounts);\n function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)\n external\n payable\n returns (uint[] memory amounts);\n\n function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);\n function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);\n function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);\n function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);\n function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/StrategyProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// helper contracts\nimport { Modifiers } from \"./Modifiers.sol\";\n\n// interfaces\nimport { IStrategyProvider } from \"./interfaces/opty/IStrategyProvider.sol\";\nimport { Constants } from \"./utils/Constants.sol\";\n\n/**\n * @title StrategyProvider Contract\n * @author Opty.fi\n * @notice Serves as an oracle service of opty-fi's earn protocol\n * @dev Contracts contains logic for setting and getting the best and default strategy\n * as well as vault reward token strategy\n */\ncontract StrategyProvider is IStrategyProvider, Modifiers {\n using SafeMath for uint256;\n\n /**\n * @notice Mapping of RiskProfile (eg: RP1, RP2, etc) to tokensHash to the best strategy hash\n */\n mapping(uint256 => mapping(bytes32 => DataTypes.StrategyStep[])) public rpToTokenToBestStrategy;\n\n /**\n * @notice Mapping of RiskProfile (eg: RP1, RP2, etc) to tokensHash to best default strategy hash\n */\n mapping(uint256 => mapping(bytes32 => DataTypes.StrategyStep[])) public rpToTokenToDefaultStrategy;\n\n /**\n * @notice Mapping of vaultRewardToken address hash to vault reward token strategy\n */\n mapping(bytes32 => DataTypes.VaultRewardStrategy) public vaultRewardTokenHashToVaultRewardTokenStrategy;\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function setBestStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external override onlyStrategyOperator {\n delete rpToTokenToBestStrategy[_riskProfileCode][_underlyingTokensHash];\n for (uint256 _i = 0; _i < _strategySteps.length; _i++) {\n rpToTokenToBestStrategy[_riskProfileCode][_underlyingTokensHash].push(_strategySteps[_i]);\n }\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function setBestDefaultStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external override onlyStrategyOperator {\n delete rpToTokenToDefaultStrategy[_riskProfileCode][_underlyingTokensHash];\n for (uint256 _i = 0; _i < _strategySteps.length; _i++) {\n rpToTokenToDefaultStrategy[_riskProfileCode][_underlyingTokensHash].push(_strategySteps[_i]);\n }\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function setVaultRewardStrategy(\n bytes32 _vaultRewardTokenHash,\n DataTypes.VaultRewardStrategy memory _vaultRewardStrategy\n ) external override onlyStrategyOperator returns (DataTypes.VaultRewardStrategy memory) {\n vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash].hold = _vaultRewardStrategy.hold;\n vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash].convert = _vaultRewardStrategy.convert;\n return vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash];\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function getVaultRewardTokenHashToVaultRewardTokenStrategy(bytes32 _vaultRewardTokenHash)\n public\n view\n override\n returns (DataTypes.VaultRewardStrategy memory)\n {\n return vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash];\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function getRpToTokenToBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n override\n returns (DataTypes.StrategyStep[] memory)\n {\n return rpToTokenToBestStrategy[_riskProfileCode][_underlyingTokensHash];\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function getRpToTokenToDefaultStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n override\n returns (DataTypes.StrategyStep[] memory)\n {\n return rpToTokenToDefaultStrategy[_riskProfileCode][_underlyingTokensHash];\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IStrategyProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for StrategyProvider Contract\n * @author Opty.fi\n * @notice Contains functions for setting and getting the best and default strategy\n * as well as vault reward token strategy\n */\ninterface IStrategyProvider {\n /**\n * @notice Set the best stratetgy for the given riskProfile and tokenHash\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @param _strategySteps Strategy steps to be set as best strategy\n */\n function setBestStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external;\n\n /**\n * @notice Set the best default stratetgy for the given riskProfile and tokenHash\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @param _strategySteps Strategy steps to be set as best default strategy\n */\n function setBestDefaultStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external;\n\n /**\n * @dev Assign strategy in form of vaultRewardStrategy to the vaultRewardTokenHash\n * @param _vaultRewardTokenHash Hash of vault contract and reward token address\n * @param _vaultRewardStrategy Vault reward token's strategy for the specified vaultRewardTokenHash\n * @return Returns a vaultRewardStrategy hash value indicating successful operation\n */\n function setVaultRewardStrategy(\n bytes32 _vaultRewardTokenHash,\n DataTypes.VaultRewardStrategy memory _vaultRewardStrategy\n ) external returns (DataTypes.VaultRewardStrategy memory);\n\n /**\n * @notice Get the Best strategy corresponding to riskProfile and tokenHash provided\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @return Returns the best strategy corresponding to riskProfile and tokenHash provided\n */\n function getRpToTokenToBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice Get the Best Default strategy corresponding to riskProfile and tokenHash provided\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @return Returns the best default strategy corresponding to riskProfile and tokenHash provided\n */\n function getRpToTokenToDefaultStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice Get the Vault reward token's strategy corresponding to the tokensHash provided\n * @param _vaultRewardTokenHash Hash of Vault contract and reward token address\n * @return Returns the Vault reward token's strategy corresponding to the tokensHash provided\n */\n function getVaultRewardTokenHashToVaultRewardTokenStrategy(bytes32 _vaultRewardTokenHash)\n external\n view\n returns (DataTypes.VaultRewardStrategy memory);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/utils/Constants.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nlibrary Constants {\n /** @notice Zero value constant of bytes32 datatype */\n bytes32 public constant ZERO_BYTES32 = 0x0000000000000000000000000000000000000000000000000000000000000000;\n\n /** @notice Decimals considered upto 10**18 */\n uint256 public constant WEI_DECIMAL = 10**18;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/RiskManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n// helper contracts\nimport { Modifiers } from \"./Modifiers.sol\";\nimport { RiskManagerStorage } from \"./RiskManagerStorage.sol\";\nimport { RiskManagerProxy } from \"./RiskManagerProxy.sol\";\n\n// interfaces\nimport { IStrategyProvider } from \"./interfaces/opty/IStrategyProvider.sol\";\nimport { IRiskManager } from \"./interfaces/opty/IRiskManager.sol\";\nimport { Constants } from \"./utils/Constants.sol\";\n\n/**\n * @title RiskManager Contract\n * @author Opty.fi\n * @dev Contract contains functionality for getting the best invest and vaultRewardToken strategy\n */\ncontract RiskManager is IRiskManager, RiskManagerStorage, Modifiers {\n using Address for address;\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /**\n * @dev Set RiskManagerProxy to act as RiskManager\n * @param _riskManagerProxy RiskManagerProxy contract address to act as RiskManager\n */\n function become(RiskManagerProxy _riskManagerProxy) external onlyGovernance {\n require(_riskManagerProxy.acceptImplementation() == 0, \"!unauthorized\");\n }\n\n /**\n * @inheritdoc IRiskManager\n */\n function getBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n public\n view\n override\n returns (DataTypes.StrategyStep[] memory)\n {\n return _getBestStrategy(_riskProfileCode, _underlyingTokensHash);\n }\n\n /**\n * @inheritdoc IRiskManager\n */\n function getVaultRewardTokenStrategy(bytes32 _underlyingTokensHash)\n public\n view\n override\n returns (DataTypes.VaultRewardStrategy memory)\n {\n return\n IStrategyProvider(registryContract.getStrategyProvider()).getVaultRewardTokenHashToVaultRewardTokenStrategy(\n _underlyingTokensHash\n );\n }\n\n function _getBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n internal\n view\n returns (DataTypes.StrategyStep[] memory)\n {\n address[] memory _tokens = registryContract.getTokensHashToTokenList(_underlyingTokensHash);\n require(_tokens.length > 0, \"!TokenHashExists\");\n\n for (uint256 _i; _i < _tokens.length; _i++) {\n require(registryContract.isApprovedToken(_tokens[_i]), \"!Token\");\n }\n\n DataTypes.RiskProfile memory _riskProfileStruct = registryContract.getRiskProfile(_riskProfileCode);\n require(_riskProfileStruct.exists, \"!Rp_Exists\");\n\n DataTypes.StrategyStep[] memory _strategySteps =\n IStrategyProvider(registryContract.getStrategyProvider()).getRpToTokenToBestStrategy(\n _riskProfileCode,\n _underlyingTokensHash\n );\n if (_strategySteps.length == 0 || _isInValidStrategy(_strategySteps, _riskProfileStruct)) {\n _strategySteps = IStrategyProvider(registryContract.getStrategyProvider()).getRpToTokenToDefaultStrategy(\n _riskProfileCode,\n _underlyingTokensHash\n );\n }\n\n return _strategySteps;\n }\n\n function _isInValidStrategy(\n DataTypes.StrategyStep[] memory _strategySteps,\n DataTypes.RiskProfile memory _riskProfileStruct\n ) internal view returns (bool) {\n for (uint256 _i = 0; _i < _strategySteps.length; _i++) {\n DataTypes.LiquidityPool memory _liquidityPool = registryContract.getLiquidityPool(_strategySteps[_i].pool);\n bool _isStrategyInvalid =\n !_liquidityPool.isLiquidityPool ||\n !(_liquidityPool.rating >= _riskProfileStruct.poolRatingsRange.lowerLimit &&\n _liquidityPool.rating <= _riskProfileStruct.poolRatingsRange.upperLimit);\n\n _isStrategyInvalid = !_riskProfileStruct.canBorrow && !_isStrategyInvalid\n ? _strategySteps[_i].isBorrow\n : _isStrategyInvalid;\n\n if (_isStrategyInvalid) {\n return _isStrategyInvalid;\n }\n }\n\n return false;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/RiskManagerStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title RiskManagerStorage Contract\n * @author Opty.fi\n * @notice Contract to store the state variables of the RiskManager Contract\n */\ncontract RiskManagerStorage {\n /**\n * @notice Active brains of Risk Manager\n */\n address public riskManagerImplementation;\n\n /**\n * @notice Pending brains of Risk Manager\n */\n address public pendingRiskManagerImplementation;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/RiskManagerProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// helper contracts\nimport { Modifiers } from \"./Modifiers.sol\";\nimport { RiskManagerStorage } from \"./RiskManagerStorage.sol\";\n\n/**\n * @title RiskManagerProxy Contract\n * @author Opty.fi\n * @dev Storage for the RiskManager is at this address, while execution is delegated to the\n * riskManagerImplementation. RiskManager should reference this contract as their controller.\n * It defines a fallback function that delegates all calls to the address returned by the\n * abstract _implementation() internal function.\n */\ncontract RiskManagerProxy is RiskManagerStorage, Modifiers {\n /**\n * @notice Emitted when pendingRiskManagerImplementation is changed\n * @param oldPendingImplementation Old RiskManager contract's implementation address which is still pending\n * @param newPendingImplementation New RiskManager contract's implementation address which is still pending\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when RiskManager implementation is updated\n * @param oldImplementation Old RiskManager Contract's implementation address\n * @param newImplementation New RiskManager Contract's implementation address\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /* solhint-disable */\n receive() external payable {\n revert();\n }\n\n /**\n * @notice Delegates execution to an riskManager implementation contract\n * @dev Returns to external caller whatever implementation returns or forwards reverts\n */\n fallback() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = riskManagerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n\n /* solhint-disable */\n\n /*** Admin Functions ***/\n /**\n * @dev Set the riskManager contract as pending implementation initally\n * @param newPendingImplementation riskManager address to act as pending implementation\n */\n function setPendingImplementation(address newPendingImplementation) external onlyOperator {\n address oldPendingImplementation = pendingRiskManagerImplementation;\n\n pendingRiskManagerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingRiskManagerImplementation);\n }\n\n /**\n * @notice Accepts new implementation of riskManager\n * @dev Governance function for new implementation to accept it's role as implementation\n */\n function acceptImplementation() external returns (uint256) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n require(\n msg.sender == pendingRiskManagerImplementation && pendingRiskManagerImplementation != address(0),\n \"!pendingRiskManagerImplementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = riskManagerImplementation;\n address oldPendingImplementation = pendingRiskManagerImplementation;\n\n riskManagerImplementation = pendingRiskManagerImplementation;\n\n pendingRiskManagerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, riskManagerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingRiskManagerImplementation);\n\n return uint256(0);\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IRiskManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for RiskManager contract\n * @author Opty.fi\n * @notice A layer between vault and registry contract to get the best invest strategy as well\n * as vault reward token strategy\n */\ninterface IRiskManager {\n /**\n * @notice Get the best strategy for respective RiskProfiles\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * corresponding to which get the best strategy\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @return Returns the hash of the best strategy corresponding to the riskProfile provided\n */\n function getBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice Get the VaultRewardToken strategy for respective VaultRewardToken hash\n * @param _underlyingTokensHash Hash of vault contract address and reward token address\n * @return _vaultRewardStrategy Returns the VaultRewardToken strategy for given vaultRewardTokenHash\n */\n function getVaultRewardTokenStrategy(bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.VaultRewardStrategy memory _vaultRewardStrategy);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/Registry.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n// helper contracts\nimport { ModifiersController } from \"./ModifiersController.sol\";\nimport { RegistryProxy } from \"./RegistryProxy.sol\";\n\n// interfaces\nimport { IVault } from \"./interfaces/opty/IVault.sol\";\nimport { IRegistry } from \"./interfaces/opty/IRegistry.sol\";\nimport { IContractRegistry } from \"./interfaces/opty/IContractRegistry.sol\";\nimport { Constants } from \"./utils/Constants.sol\";\n\n/**\n * @title Registry Contract\n * @author Opty.fi\n * @dev Contract to persit status of tokens,lpTokens,lp/cp and Vaults\n */\ncontract Registry is IRegistry, ModifiersController {\n using Address for address;\n using SafeMath for uint256;\n\n /**\n * @dev Set RegistryProxy to act as Registry\n * @param _registryProxy RegistryProxy Contract address to act as Registry\n */\n function become(RegistryProxy _registryProxy) external {\n require(msg.sender == _registryProxy.governance(), \"!governance\");\n require(_registryProxy.acceptImplementation() == 0, \"!unauthorized\");\n investStrategyRegistry = address(0);\n aprOracle = address(0);\n strategyManager = address(0);\n optyStakingRateBalancer = address(0);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setTreasury(address _treasury) external override onlyGovernance {\n require(_treasury != address(0), \"!address(0)\");\n treasury = _treasury;\n emit TransferTreasury(treasury, msg.sender);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setStrategyProvider(address _strategyProvider) external override onlyOperator {\n require(IContractRegistry(_strategyProvider).registryContract() == address(this), \"!registryContract\");\n strategyProvider = _strategyProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setRiskManager(address _riskManager) external override onlyOperator {\n require(IContractRegistry(_riskManager).registryContract() == address(this), \"!registryContract\");\n riskManager = _riskManager;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setHarvestCodeProvider(address _harvestCodeProvider) external override onlyOperator {\n require(IContractRegistry(_harvestCodeProvider).registryContract() == address(this), \"!registryContract\");\n harvestCodeProvider = _harvestCodeProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setOPTY(address _opty) external override onlyOperator {\n opty = _opty;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setODEFIVaultBooster(address _odefiVaultBooster) external override onlyOperator {\n require(IContractRegistry(_odefiVaultBooster).registryContract() == address(this), \"!registryContract\");\n odefiVaultBooster = _odefiVaultBooster;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveToken(address[] memory _tokens) external override onlyOperator {\n for (uint256 _i; _i < _tokens.length; _i++) {\n _approveToken(_tokens[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveToken(address _token) external override onlyOperator {\n _approveToken(_token);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeToken(address[] memory _tokens) external override onlyOperator {\n for (uint256 _i; _i < _tokens.length; _i++) {\n _revokeToken(_tokens[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeToken(address _token) external override onlyOperator {\n _revokeToken(_token);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _approveLiquidityPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPool(address _pool) external override onlyOperator {\n _approveLiquidityPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeLiquidityPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _revokeLiquidityPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeLiquidityPool(address _pool) external override onlyOperator {\n _revokeLiquidityPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateLiquidityPool(DataTypes.PoolRate[] memory _poolRates) external override onlyRiskOperator {\n for (uint256 _i; _i < _poolRates.length; _i++) {\n _rateLiquidityPool(_poolRates[_i].pool, _poolRates[_i].rate);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateLiquidityPool(address _pool, uint8 _rate) external override onlyRiskOperator {\n _rateLiquidityPool(_pool, _rate);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPoolAndMapToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _poolAdapters.length; _i++) {\n _approveLiquidityPool(_poolAdapters[_i].pool);\n _setLiquidityPoolToAdapter(_poolAdapters[_i].pool, _poolAdapters[_i].adapter);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPoolAndMapToAdapter(address _pool, address _adapter) external override onlyOperator {\n _approveLiquidityPool(_pool);\n _setLiquidityPoolToAdapter(_pool, _adapter);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveCreditPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _approveCreditPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveCreditPool(address _pool) external override onlyOperator {\n _approveCreditPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeCreditPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _revokeCreditPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeCreditPool(address _pool) external override onlyOperator {\n _revokeCreditPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateCreditPool(DataTypes.PoolRate[] memory _poolRates) external override onlyRiskOperator {\n for (uint256 _i; _i < _poolRates.length; _i++) {\n _rateCreditPool(_poolRates[_i].pool, _poolRates[_i].rate);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateCreditPool(address _pool, uint8 _rate) external override onlyRiskOperator {\n _rateCreditPool(_pool, _rate);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setLiquidityPoolToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters) external override onlyOperator {\n for (uint256 _i; _i < _poolAdapters.length; _i++) {\n require(liquidityPools[_poolAdapters[_i].pool].isLiquidityPool, \"!liquidityPools\");\n _setLiquidityPoolToAdapter(_poolAdapters[_i].pool, _poolAdapters[_i].adapter);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setLiquidityPoolToAdapter(address _pool, address _adapter) external override onlyOperator {\n require(liquidityPools[_pool].isLiquidityPool, \"!liquidityPools\");\n _setLiquidityPoolToAdapter(_pool, _adapter);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveTokenAndMapToTokensHash(DataTypes.TokensHashDetail[] memory _tokensHashesDetails)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _tokensHashesDetails.length; _i++) {\n for (uint256 _j; _j < _tokensHashesDetails[_i].tokens.length; _j++) {\n _approveToken(_tokensHashesDetails[_i].tokens[_j]);\n }\n _setTokensHashToTokens(_tokensHashesDetails[_i].tokensHash, _tokensHashesDetails[_i].tokens);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveTokenAndMapToTokensHash(bytes32 _tokensHash, address[] memory _tokens)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _tokens.length; _i++) {\n _approveToken(_tokens[_i]);\n }\n _setTokensHashToTokens(_tokensHash, _tokens);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setTokensHashToTokens(DataTypes.TokensHashDetail[] memory _tokensHashesDetails)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _tokensHashesDetails.length; _i++) {\n require(_areTokensApproved(_tokensHashesDetails[_i].tokens), \"!tokens\");\n _setTokensHashToTokens(_tokensHashesDetails[_i].tokensHash, _tokensHashesDetails[_i].tokens);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setTokensHashToTokens(bytes32 _tokensHash, address[] memory _tokens) external override onlyOperator {\n require(_areTokensApproved(_tokens), \"!tokens\");\n _setTokensHashToTokens(_tokensHash, _tokens);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function updateRiskProfileBorrow(uint256 _riskProfileCode, bool _canBorrow) external override onlyRiskOperator {\n _updateRiskProfileBorrow(_riskProfileCode, _canBorrow);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function addRiskProfile(\n uint256 _riskProfileCode,\n string memory _name,\n string memory _symbol,\n bool _canBorrow,\n DataTypes.PoolRatingsRange memory _poolRatingRange\n ) external override onlyRiskOperator {\n _addRiskProfile(_riskProfileCode, _name, _symbol, _canBorrow, _poolRatingRange);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function addRiskProfile(\n uint256[] memory _riskProfileCodes,\n string[] memory _names,\n string[] memory _symbols,\n bool[] memory _canBorrow,\n DataTypes.PoolRatingsRange[] memory _poolRatingRanges\n ) external override onlyRiskOperator {\n require(_riskProfileCodes.length > 0, \"!length>0\");\n require(_riskProfileCodes.length == _poolRatingRanges.length, \"!RP_PoolRatingsLength\");\n require(_riskProfileCodes.length == _canBorrow.length, \"!RP_canBorrowLength\");\n require(_riskProfileCodes.length == _names.length, \"!RP_namesLength\");\n require(_riskProfileCodes.length == _symbols.length, \"!RP_symbolsLength\");\n\n for (uint256 _i; _i < _riskProfileCodes.length; _i++) {\n _addRiskProfile(_riskProfileCodes[_i], _names[_i], _symbols[_i], _canBorrow[_i], _poolRatingRanges[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function updateRPPoolRatings(uint256 _riskProfileCode, DataTypes.PoolRatingsRange memory _poolRatingRange)\n external\n override\n onlyRiskOperator\n {\n _updateRPPoolRatings(_riskProfileCode, _poolRatingRange);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function removeRiskProfile(uint256 _index) external override onlyRiskOperator {\n _removeRiskProfile(_index);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokenHashes() public view override returns (bytes32[] memory) {\n return tokensHashIndexes;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokensHashToTokenList(bytes32 _tokensHash) public view override returns (address[] memory) {\n return tokensHashToTokens[_tokensHash].tokens;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskProfileList() public view override returns (uint256[] memory) {\n return riskProfilesArray;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokensHashIndexByHash(bytes32 _tokensHash) public view override returns (uint256) {\n return tokensHashToTokens[_tokensHash].index;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokensHashByIndex(uint256 _index) public view override returns (bytes32) {\n return tokensHashIndexes[_index];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function isApprovedToken(address _token) public view override returns (bool) {\n return tokens[_token];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getStrategyProvider() public view override returns (address) {\n return strategyProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskProfile(uint256 _riskProfileCode) public view override returns (DataTypes.RiskProfile memory) {\n return riskProfiles[_riskProfileCode];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskManager() public view override returns (address) {\n return riskManager;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getOPTYDistributor() public view override returns (address) {\n return optyDistributor;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getODEFIVaultBooster() external view override returns (address) {\n return odefiVaultBooster;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getGovernance() public view override returns (address) {\n return governance;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getFinanceOperator() public view override returns (address) {\n return financeOperator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskOperator() public view override returns (address) {\n return riskOperator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getStrategyOperator() public view override returns (address) {\n return strategyOperator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getOperator() public view override returns (address) {\n return operator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getHarvestCodeProvider() public view override returns (address) {\n return harvestCodeProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getLiquidityPool(address _pool) public view override returns (DataTypes.LiquidityPool memory) {\n return liquidityPools[_pool];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getLiquidityPoolToAdapter(address _pool) public view override returns (address) {\n return liquidityPoolToAdapter[_pool];\n }\n\n function _approveToken(address _token) internal {\n tokens[_token] = true;\n emit LogToken(_token, tokens[_token], msg.sender);\n }\n\n function _revokeToken(address _token) internal {\n tokens[_token] = false;\n emit LogToken(_token, tokens[_token], msg.sender);\n }\n\n function _approveLiquidityPool(address _pool) internal {\n liquidityPools[_pool].isLiquidityPool = true;\n emit LogLiquidityPool(_pool, liquidityPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _revokeLiquidityPool(address _pool) internal {\n liquidityPools[_pool].isLiquidityPool = false;\n emit LogLiquidityPool(_pool, liquidityPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _rateLiquidityPool(address _pool, uint8 _rate) internal {\n require(liquidityPools[_pool].isLiquidityPool, \"!liquidityPools\");\n liquidityPools[_pool].rating = _rate;\n emit LogRateLiquidityPool(_pool, liquidityPools[_pool].rating, msg.sender);\n }\n\n function _approveCreditPool(address _pool) internal {\n creditPools[_pool].isLiquidityPool = true;\n emit LogCreditPool(_pool, creditPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _revokeCreditPool(address _pool) internal {\n creditPools[_pool].isLiquidityPool = false;\n emit LogCreditPool(_pool, creditPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _rateCreditPool(address _pool, uint8 _rate) internal {\n require(creditPools[_pool].isLiquidityPool, \"!creditPools\");\n creditPools[_pool].rating = _rate;\n emit LogRateCreditPool(_pool, creditPools[_pool].rating, msg.sender);\n }\n\n function _setLiquidityPoolToAdapter(address _pool, address _adapter) internal {\n require(IContractRegistry(_adapter).registryContract() == address(this), \"!registryContract\");\n liquidityPoolToAdapter[_pool] = _adapter;\n emit LogLiquidityPoolToAdapter(_pool, _adapter, msg.sender);\n }\n\n function _setTokensHashToTokens(bytes32 _tokensHash, address[] memory _tokens) internal {\n require(_isNewTokensHash(_tokensHash), \"!_isNewTokensHash\");\n tokensHashIndexes.push(_tokensHash);\n tokensHashToTokens[_tokensHash].index = tokensHashIndexes.length - 1;\n tokensHashToTokens[_tokensHash].tokens = _tokens;\n emit LogTokensToTokensHash(_tokensHash, msg.sender);\n }\n\n function _addRiskProfile(\n uint256 _riskProfileCode,\n string memory _name,\n string memory _symbol,\n bool _canBorrow,\n DataTypes.PoolRatingsRange memory _poolRatingRange\n ) internal {\n require(!riskProfiles[_riskProfileCode].exists, \"RP_already_exists\");\n require(bytes(_name).length > 0, \"RP_name_empty\");\n require(bytes(_symbol).length > 0, \"RP_symbol_empty\");\n riskProfilesArray.push(_riskProfileCode);\n riskProfiles[_riskProfileCode].name = _name;\n riskProfiles[_riskProfileCode].symbol = _symbol;\n riskProfiles[_riskProfileCode].canBorrow = _canBorrow;\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit = _poolRatingRange.lowerLimit;\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit = _poolRatingRange.upperLimit;\n riskProfiles[_riskProfileCode].index = riskProfilesArray.length - 1;\n riskProfiles[_riskProfileCode].exists = true;\n\n emit LogRiskProfile(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].exists,\n riskProfiles[_riskProfileCode].canBorrow,\n msg.sender\n );\n emit LogRPPoolRatings(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit,\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit,\n msg.sender\n );\n }\n\n function _updateRiskProfileBorrow(uint256 _riskProfileCode, bool _canBorrow) internal {\n require(riskProfiles[_riskProfileCode].exists, \"!Rp_Exists\");\n riskProfiles[_riskProfileCode].canBorrow = _canBorrow;\n emit LogRiskProfile(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].exists,\n riskProfiles[_riskProfileCode].canBorrow,\n msg.sender\n );\n }\n\n function _updateRPPoolRatings(uint256 _riskProfileCode, DataTypes.PoolRatingsRange memory _poolRatingRange)\n internal\n {\n require(riskProfiles[_riskProfileCode].exists, \"!Rp_Exists\");\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit = _poolRatingRange.lowerLimit;\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit = _poolRatingRange.upperLimit;\n emit LogRPPoolRatings(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit,\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit,\n msg.sender\n );\n }\n\n function _removeRiskProfile(uint256 _index) internal {\n require(_index <= riskProfilesArray.length, \"Invalid_Rp_index\");\n uint256 _riskProfileCode = riskProfilesArray[_index];\n require(riskProfiles[_riskProfileCode].exists, \"!Rp_Exists\");\n riskProfiles[_riskProfileCode].exists = false;\n emit LogRiskProfile(\n _index,\n riskProfiles[_riskProfileCode].exists,\n riskProfiles[_riskProfileCode].canBorrow,\n msg.sender\n );\n }\n\n /**\n * @dev Checks duplicate tokensHash\n * @param _hash Hash of the token address/addresses\n * @return A boolean value indicating whether duplicate _hash exists or not\n */\n function _isNewTokensHash(bytes32 _hash) internal view returns (bool) {\n if (tokensHashIndexes.length == 0) {\n return true;\n }\n return (tokensHashIndexes[tokensHashToTokens[_hash].index] != _hash);\n }\n\n /**\n * @dev Checks approved tokens\n * @param _tokens List of the token addresses\n */\n function _areTokensApproved(address[] memory _tokens) internal view returns (bool) {\n for (uint256 _i; _i < _tokens.length; _i++) {\n if (!tokens[_tokens[_i]]) {\n return false;\n }\n }\n return true;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/ModifiersController.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { RegistryStorage } from \"./RegistryStorage.sol\";\n\n// interfaces\nimport { IModifiersController } from \"./interfaces/opty/IModifiersController.sol\";\n\n/**\n * @title ModifiersController Contract\n * @author Opty.fi\n * @notice Contract used by registry contract and acts as source of truth\n * @dev It manages operator, optyDistributor addresses as well as modifiers\n */\nabstract contract ModifiersController is IModifiersController, RegistryStorage {\n using Address for address;\n\n /**\n * @inheritdoc IModifiersController\n */\n function setFinanceOperator(address _financeOperator) public override onlyGovernance {\n require(_financeOperator != address(0), \"!address(0)\");\n financeOperator = _financeOperator;\n emit TransferFinanceOperator(financeOperator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setRiskOperator(address _riskOperator) public override onlyGovernance {\n require(_riskOperator != address(0), \"!address(0)\");\n riskOperator = _riskOperator;\n emit TransferRiskOperator(riskOperator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setStrategyOperator(address _strategyOperator) public override onlyGovernance {\n require(_strategyOperator != address(0), \"!address(0)\");\n strategyOperator = _strategyOperator;\n emit TransferStrategyOperator(strategyOperator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setOperator(address _operator) public override onlyGovernance {\n require(_operator != address(0), \"!address(0)\");\n operator = _operator;\n emit TransferOperator(operator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setOPTYDistributor(address _optyDistributor) public override onlyGovernance {\n require(_optyDistributor.isContract(), \"!isContract\");\n optyDistributor = _optyDistributor;\n emit TransferOPTYDistributor(optyDistributor, msg.sender);\n }\n\n /**\n * @notice Modifier to check caller is governance or not\n */\n modifier onlyGovernance() {\n require(msg.sender == governance, \"caller is not having governance\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is financeOperator or not\n */\n modifier onlyFinanceOperator() {\n require(msg.sender == financeOperator, \"caller is not the finance operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is riskOperator or not\n */\n modifier onlyRiskOperator() {\n require(msg.sender == riskOperator, \"caller is not the risk operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is operator or not\n */\n modifier onlyOperator() {\n require(msg.sender == operator, \"caller is not the operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is optyDistributor or not\n */\n modifier onlyOptyDistributor() {\n require(msg.sender == optyDistributor, \"caller is not the optyDistributor\");\n _;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/RegistryProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// helper contracts\nimport { RegistryStorage } from \"./RegistryStorage.sol\";\nimport { ModifiersController } from \"./ModifiersController.sol\";\n\n/**\n * @title RegistryProxy Contract\n * @author Opty.fi\n * @dev Storage for the Registry is at this address,\n * while execution is delegated to the `registryImplementation`.\n * Registry should reference this contract as their controller.\n * It defines a fallback function that delegates all calls to the address\n * returned by the abstract _implementation() internal function.\n */\ncontract RegistryProxy is RegistryStorage, ModifiersController {\n /**\n * @notice Emitted when pendingComptrollerImplementation is changed\n * @param oldPendingImplementation Old Registry contract's implementation address which is still pending\n * @param newPendingImplementation New Registry contract's implementation address which is still pending\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is updated\n * @param oldImplementation Old Registry Contract's implementation address\n * @param newImplementation New Registry Contract's implementation address\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingGovernance is changed\n * @param oldPendingGovernance Old Governance's address which is still pending\n * @param newPendingGovernance New Governance's address which is still pending\n */\n event NewPendingGovernance(address oldPendingGovernance, address newPendingGovernance);\n\n /**\n * @notice Emitted when pendingGovernance is accepted, which means governance is updated\n * @param oldGovernance Old Governance's address\n * @param newGovernance New Governance's address\n */\n event NewGovernance(address oldGovernance, address newGovernance);\n\n constructor() public {\n governance = msg.sender;\n setFinanceOperator(msg.sender);\n setRiskOperator(msg.sender);\n setStrategyOperator(msg.sender);\n setOperator(msg.sender);\n }\n\n /* solhint-disable */\n receive() external payable {\n revert();\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev Returns to external caller whatever implementation returns or forwards reverts\n */\n fallback() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = registryImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n\n /* solhint-disable */\n\n /*** Admin Functions ***/\n /**\n * @dev Set the registry contract as pending implementation initally\n * @param newPendingImplementation registry address to act as pending implementation\n */\n function setPendingImplementation(address newPendingImplementation) external onlyOperator {\n address oldPendingImplementation = pendingRegistryImplementation;\n\n pendingRegistryImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingRegistryImplementation);\n }\n\n /**\n * @notice Accepts new implementation of registry\n * @dev Governance function for new implementation to accept it's role as implementation\n */\n function acceptImplementation() external returns (uint256) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n require(\n msg.sender == pendingRegistryImplementation && pendingRegistryImplementation != address(0),\n \"!pendingRegistryImplementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = registryImplementation;\n address oldPendingImplementation = pendingRegistryImplementation;\n\n registryImplementation = pendingRegistryImplementation;\n\n pendingRegistryImplementation = address(0);\n\n emit NewImplementation(oldImplementation, registryImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingRegistryImplementation);\n\n return uint256(0);\n }\n\n /**\n * @notice Transfers the governance rights\n * @dev The newPendingGovernance must call acceptGovernance() to finalize the transfer\n * @param newPendingGovernance New pending governance address\n */\n function setPendingGovernance(address newPendingGovernance) external onlyOperator {\n // Save current value, if any, for inclusion in log\n address oldPendingGovernance = pendingGovernance;\n\n // Store pendingGovernance with value newPendingGovernance\n pendingGovernance = newPendingGovernance;\n\n // Emit NewPendingGovernance(oldPendingGovernance, newPendingGovernance)\n emit NewPendingGovernance(oldPendingGovernance, newPendingGovernance);\n }\n\n /**\n * @notice Accepts transfer of Governance rights\n * @dev Governance function for pending governance to accept role and update Governance\n */\n function acceptGovernance() external returns (uint256) {\n require(msg.sender == pendingGovernance && msg.sender != address(0), \"!pendingGovernance\");\n\n // Save current values for inclusion in log\n address oldGovernance = governance;\n address oldPendingGovernance = pendingGovernance;\n\n // Store admin with value pendingGovernance\n governance = pendingGovernance;\n\n // Clear the pending value\n pendingGovernance = address(0);\n\n emit NewGovernance(oldGovernance, governance);\n emit NewPendingGovernance(oldPendingGovernance, pendingGovernance);\n return uint256(0);\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IVault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for opty.fi's interest bearing vault\n * @author opty.fi\n * @notice Contains mix of permissioned and permissionless vault methods\n */\ninterface IVault {\n /**\n * @notice Set maximum standard deviation of vault value in a single block\n * @dev the maximum vault value jump is in percentage basis points set by governance\n * @param _maxVaultValueJump the standard deviation from a vault value in basis points\n */\n function setMaxVaultValueJump(uint256 _maxVaultValueJump) external;\n\n /**\n * @notice Calculate the value of a vault share in underlying token\n * @dev It should only be called if the current strategy's last step is Curve\n * @return the underlying token worth a vault share is\n */\n function getPricePerFullShareWrite() external returns (uint256);\n\n /**\n * @notice Withdraw the underying asset of vault from previous strategy if any,\n * claims and swaps the reward tokens for the underlying token\n * performs batch minting of shares for users deposited previously without rebalance,\n * deposits the assets into the new strategy if any or holds the same in the vault\n * @dev the vault will be charged to compensate gas fees if operator calls this function\n */\n function rebalance() external;\n\n /**\n * @notice Claim the rewards if any strategy have it and swap for underlying token\n * @param _investStrategyHash vault invest strategy hash\n */\n function harvest(bytes32 _investStrategyHash) external;\n\n /**\n * @notice A cheap function to deposit whole underlying token's balance\n * @dev this function does not rebalance, hence vault shares will be minted on the next rebalance\n */\n function userDepositAll() external;\n\n /**\n * @notice A cheap function to deposit _amount of underlying token to the vault\n * @dev the user will receive vault shares on next rebalance\n * @param _amount the amount of the underlying token to be deposited\n */\n function userDeposit(uint256 _amount) external;\n\n /**\n * @notice Deposit full balance in underlying token of the caller and rebalance\n * @dev the vault shares are minted right away\n */\n function userDepositAllRebalance() external;\n\n /**\n * @notice Deposit amount of underlying token of caller and rebalance\n * @dev the vault shares are minted right away\n * @param _amount the amount of the underlying token\n */\n function userDepositRebalance(uint256 _amount) external;\n\n /**\n * @notice Redeem full balance of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault\n */\n function userWithdrawAllRebalance() external;\n\n /**\n * @notice Redeem the amount of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault\n * @param _redeemAmount the vault shares to redeem\n */\n function userWithdrawRebalance(uint256 _redeemAmount) external;\n\n /**\n * @notice A cheap function to deposit whole underlying token's balance of caller\n * @dev the gas fees are paid in $CHI tokens and vault shares are minted on next rebalance\n */\n function userDepositAllWithCHI() external;\n\n /**\n * @notice A cheap function to deposit amount of underlying token's balance of caller\n * @dev the gas fees are paid in $CHI tokens and vault shares are minted on next rebalance\n * @param _amount the amount of underlying tokens to be deposited\n */\n function userDepositWithCHI(uint256 _amount) external;\n\n /**\n * @notice Deposit full balance in underlying token of the caller and rebalance\n * @dev the vault shares are minted right away and gas fees are paid in $CHI tokens\n */\n function userDepositAllRebalanceWithCHI() external;\n\n /**\n * @notice Deposit amount of underlying token of caller and rebalance\n * @dev the vault shares are minted right away and gas fees are paid in $CHI tokens\n * @param _amount the amount of the underlying token\n */\n function userDepositRebalanceWithCHI(uint256 _amount) external;\n\n /**\n * @notice Redeem full balance of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault and gas fees are paid in $CHI tokens\n */\n function userWithdrawAllRebalanceWithCHI() external;\n\n /**\n * @notice Redeem the amount of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault and gas fees are paid in $CHI tokens\n * @param _redeemAmount the amount of vault shares\n */\n function userWithdrawRebalanceWithCHI(uint256 _redeemAmount) external;\n\n /**\n * @notice Recall vault investments from current strategy, restricts deposits\n * and allows redemption of the shares\n * @dev this function can be invoked by governance via registry\n */\n function discontinue() external;\n\n /**\n * @notice This function can temporarily restrict user from depositing\n * or withdrawing assets to and from the vault\n * @dev this function can be invoked by governance via registry\n * @param _unpaused for invoking/revoking pause over the vault\n */\n function setUnpaused(bool _unpaused) external;\n\n /**\n * @notice Retrieve underlying token balance in the vault\n * @return The balance of underlying token in the vault\n */\n function balance() external view returns (uint256);\n\n /**\n * @notice Calculate the value of a vault share in underlying token\n * @return The underlying token worth a vault share is\n */\n function getPricePerFullShare() external view returns (uint256);\n\n /**\n * @notice Assign a risk profile name\n * @dev name of the risk profile should be approved by governance\n * @param _riskProfileCode code of the risk profile\n */\n function setRiskProfileCode(uint256 _riskProfileCode) external;\n\n /**\n * @notice Assign the address of the underlying asset of the vault\n * @dev the underlying asset should be approved by the governance\n * @param _underlyingToken the address of the underlying asset\n */\n function setToken(address _underlyingToken) external;\n\n /**\n * @dev A helper function to validate the vault value will not be deviated from max vault value\n * within the same block\n * @param _diff absolute difference between minimum and maximum vault value within a block\n * @param _currentVaultValue the underlying token balance of the vault\n * @return bool returns true if vault value jump is within permissible limits\n */\n function isMaxVaultValueJumpAllowed(uint256 _diff, uint256 _currentVaultValue) external view returns (bool);\n\n /**\n * @notice A function to be called in case vault needs to claim and harvest tokens in case a strategy\n * provides multiple reward tokens\n * @param _codes Array of encoded data in bytes which acts as code to execute\n */\n function adminCall(bytes[] memory _codes) external;\n\n /**\n * @notice A function to get deposit queue\n * @return return queue\n */\n function getDepositQueue() external view returns (DataTypes.UserDepositOperation[] memory);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IContractRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Interface for Contracts deployed with registry contract\n * @author Opty.fi\n * @notice Interface to get registry contract\n */\ninterface IContractRegistry {\n /**\n * @notice Get the address of registry contract\n * @return address of registry contract\n */\n function registryContract() external view returns (address);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/RegistryStorage.sol": { + "content": "/* solhint-disable max-states-count */\n// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n/**\n * @title RegistryAdminStorage Contract\n * @author Opty.fi\n * @dev Contract used to store registry's admin account\n */\ncontract RegistryAdminStorage {\n /**\n * @notice Governance of optyfi's earn protocol\n */\n address public governance;\n\n /**\n * @notice Finance operator of optyfi's earn protocol\n * @dev Handle functions having withdrawal fee, treasury and finance related logic\n */\n address public financeOperator;\n\n /**\n * @notice Risk operator of optyfi's earn protocol\n * @dev Handle functions for maintaining the risk profiles and rating of liquidity/credit pools\n */\n address public riskOperator;\n\n /**\n * @notice Strategy operator of optyfi's earn protocol\n * @dev Handle functions related to strategies/vault strategies to be used\n */\n address public strategyOperator;\n\n /**\n * @notice Operator of optyfi's earn protocol\n */\n address public operator;\n\n /**\n * @notice Treasury of optyfi's earn protocol\n */\n address public treasury;\n\n /**\n * @notice Distributor for OPTY token\n */\n address public optyDistributor;\n\n /**\n * @notice Pending governance for optyfi's earn protocol\n */\n address public pendingGovernance;\n\n /**\n * @notice Active brains of Registry\n */\n address public registryImplementation;\n\n /**\n * @notice Pending brains of Registry\n */\n address public pendingRegistryImplementation;\n\n /**\n * @notice notify when transfer operation of financeOperator occurs\n * @param financeOperator address of Finance operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferFinanceOperator(address indexed financeOperator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of riskOperator occurs\n * @param riskOperator address of Risk operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferRiskOperator(address indexed riskOperator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of strategyOperator occurs\n * @param strategyOperator address of Strategy operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferStrategyOperator(address indexed strategyOperator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of operator occurs\n * @param operator address of Operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferOperator(address indexed operator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of treasury occurs\n * @param treasury address of Treasury of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferTreasury(address indexed treasury, address indexed caller);\n\n /**\n * @notice notify when transfer operation of optyDistributor occurs\n * @param optyDistributor address of Opty distributor of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferOPTYDistributor(address indexed optyDistributor, address indexed caller);\n}\n\n/**\n * @title RegistryStorage Contract\n * @author Opty.fi\n * @dev Contract used to store registry's contract state variables and events\n */\ncontract RegistryStorage is RegistryAdminStorage {\n /**\n * @notice token address status which are approved or not\n */\n mapping(address => bool) public tokens;\n\n /**\n * @notice token data mapped to token/tokens address/addresses hash\n */\n mapping(bytes32 => DataTypes.Token) public tokensHashToTokens;\n\n /**\n * @notice liquidityPool address mapped to its struct having `pool`, `outputToken`, `isBorrow`\n */\n mapping(address => DataTypes.LiquidityPool) public liquidityPools;\n\n /**\n * @notice creaditPool address mapped to its struct having `pool`, `outputToken`, `isBorrow`\n */\n mapping(address => DataTypes.LiquidityPool) public creditPools;\n\n /**\n * @notice liquidityPool address mapped to its adapter\n */\n mapping(address => address) public liquidityPoolToAdapter;\n\n /**\n * @dev riskProfileCode mapped to its struct `RiskProfile`\n */\n mapping(uint256 => DataTypes.RiskProfile) internal riskProfiles;\n\n /**\n * @notice vault contract address mapped to VaultConfiguration\n */\n mapping(address => DataTypes.VaultConfiguration) public vaultToVaultConfiguration;\n\n /**\n * @dev Mapping of users that are allowed to interact with a given vault\n */\n mapping(address => mapping(address => bool)) public whitelistedUsers;\n\n /**\n * @notice withdrawal fee's range\n */\n DataTypes.WithdrawalFeeRange public withdrawalFeeRange;\n\n /**\n * @notice List of all the tokenHashes\n */\n bytes32[] public tokensHashIndexes;\n\n /**\n * @notice List of all the riskProfiles\n */\n uint256[] public riskProfilesArray;\n\n /**\n * @notice strategyProvider contract address\n */\n address public strategyProvider;\n\n /**\n * @notice investStrategyRegistry contract address\n */\n address public investStrategyRegistry;\n\n /**\n * @notice riskManager contract address\n */\n address public riskManager;\n\n /**\n * @notice harvestCodeProvider contract address\n */\n address public harvestCodeProvider;\n\n /**\n * @notice strategyManager contract address\n */\n address public strategyManager;\n\n /**\n * @notice opty contract address\n */\n address public opty;\n\n /**\n * @notice aprOracle contract address\n */\n address public aprOracle;\n\n /**\n * @notice optyStakingRateBalancer contract address\n */\n address public optyStakingRateBalancer;\n\n /**\n * @notice OD vaultBooster contract address\n */\n address public odefiVaultBooster;\n\n /**\n * @notice Emitted when token is approved or revoked\n * @param token Underlying Token's address which is approved or revoked\n * @param enabled Token is approved (true) or revoked (false)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogToken(address indexed token, bool indexed enabled, address indexed caller);\n\n /**\n * @notice Emitted when pool is approved or revoked as liquidity pool\n * @param pool Liquidity Pool's address which is approved or revoked\n * @param enabled Liquidity Pool is approved (true) or revoked (false)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogLiquidityPool(address indexed pool, bool indexed enabled, address indexed caller);\n\n /**\n * @notice Emitted when pool is approved or revoked as credit pool\n * @param pool Credit Pool's address which is approved or revoked\n * @param enabled Credit pool is approved (true) or revoked (false)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogCreditPool(address indexed pool, bool indexed enabled, address indexed caller);\n\n /**\n * @notice Emitted when liquidity pool is rated\n * @param pool Liquidity Pool's address which is rated\n * @param rate Rating of Liquidity Pool set\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRateLiquidityPool(address indexed pool, uint8 indexed rate, address indexed caller);\n\n /**\n * @notice Emitted when credit pool is rated\n * @param pool Credit Pool's address which is rated\n * @param rate Rating of Credit Pool set\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRateCreditPool(address indexed pool, uint8 indexed rate, address indexed caller);\n\n /**\n * @notice Emitted when liquidity pool pool is assigned to adapter\n * @param pool Liquidity Pool's address which is mapped to the adapter\n * @param adapter Address of the respective OptyFi's defi-adapter contract which is mapped to the Liquidity Pool\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogLiquidityPoolToAdapter(address indexed pool, address indexed adapter, address indexed caller);\n\n /**\n * @notice Emitted when tokens are assigned to tokensHash\n * @param tokensHash Hash of the token/list of tokens mapped to the provided token/list of tokens\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogTokensToTokensHash(bytes32 indexed tokensHash, address indexed caller);\n\n /**\n * @dev Emitted when Discontinue over vault is activated\n * @param vault OptyFi's Vault contract address which is discontinued from being operational\n * @param discontinued Discontinue status (true) of OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogDiscontinueVault(address indexed vault, bool indexed discontinued, address indexed caller);\n\n /**\n * @notice Emitted when Pause over vault is activated/deactivated\n * @param vault OptyFi's Vault contract address\n * @param unpaused Unpause status of OptyFi's Vault contract - false (if paused) and true (if unpaused)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogUnpauseVault(address indexed vault, bool indexed unpaused, address indexed caller);\n\n /**\n * @notice Emitted when setLimitStatus is called\n * @param vault OptyFi's Vault contract address\n * @param isLimitedState Limit state of OptyFi's Vault contract - false (if not limited) and true (if limited)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogLimitStateVault(address indexed vault, bool indexed isLimitedState, address indexed caller);\n\n /**\n * @notice Emitted when setLimitStatus is called\n * @param vault OptyFi's Vault contract address\n * @param allowWhitelistedState Whitelisted state of OptyFi's Vault contract - false (if not ) and true (if limited)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogAllowWhitelistedStateVault(\n address indexed vault,\n bool indexed allowWhitelistedState,\n address indexed caller\n );\n\n /**\n * @notice Emitted when setUserDepositCap is called\n * @param vault OptyFi's Vault contract address\n * @param userDepositCap Cap for user deposits in OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogUserDepositCapVault(address indexed vault, uint256 indexed userDepositCap, address indexed caller);\n\n /**\n * @notice Emitted when setMinimumDepositAmount is called\n * @param vault OptyFi's Vault contract address\n * @param minimumDepositAmount Minimum deposit in OptyFi's Vault contract - only for deposits (without rebalance)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMinimumDepositAmountVault(\n address indexed vault,\n uint256 indexed minimumDepositAmount,\n address indexed caller\n );\n\n /**\n * @notice Emitted when setTotalValueLockedLimitInUnderlying is called\n * @param vault OptyFi's Vault contract address\n * @param totalValueLockedLimitInUnderlying Maximum limit for total value locked of OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogVaultTotalValueLockedLimitInUnderlying(\n address indexed vault,\n uint256 indexed totalValueLockedLimitInUnderlying,\n address indexed caller\n );\n\n /**\n * @notice Emitted when setQueueCap is called\n * @param vault OptyFi's Vault contract address\n * @param queueCap Maximum queue length in OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogQueueCapVault(address indexed vault, uint256 indexed queueCap, address indexed caller);\n\n /**\n * @notice Emitted when RiskProfile is added\n * @param index Index of an array at which risk profile is added\n * @param exists Status of risk profile if it exists (true) or not (false)\n * @param canBorrow Borrow is allowed (true) or not (false) for the specified risk profile\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRiskProfile(uint256 indexed index, bool indexed exists, bool indexed canBorrow, address caller);\n\n /**\n * @notice Emitted when Risk profile is added/updated\n * @param index Index of an array at which risk profile is added or updated\n * @param lowerLimit Lower limit of the pool for the specified risk profile\n * @param upperLimit Upper limit of the pool for the specified risk profile\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRPPoolRatings(uint256 indexed index, uint8 indexed lowerLimit, uint8 indexed upperLimit, address caller);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IModifiersController.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Interface for ModifiersController Contract\n * @author Opty.fi\n * @notice Interface used to authorize operator and minter accounts\n */\ninterface IModifiersController {\n /**\n * @notice Transfers financeOperator to a new account (`_financeOperator`)\n * @param _financeOperator address of financeOperator's account\n */\n function setFinanceOperator(address _financeOperator) external;\n\n /**\n * @notice Transfers riskOperator to a new account (`_riskOperator`)\n * @param _riskOperator address of riskOperator's account\n */\n function setRiskOperator(address _riskOperator) external;\n\n /**\n * @notice Transfers strategyOperator to a new account (`_strategyOperator`)\n * @param _strategyOperator address of strategyOperator's account\n */\n function setStrategyOperator(address _strategyOperator) external;\n\n /**\n * @notice Transfers operator to a new account (`_operator`)\n * @param _operator address of Operator's account\n */\n function setOperator(address _operator) external;\n\n /**\n * @notice Transfers optyDistributor to a new account (`_optyDistributor`)\n * @param _optyDistributor address of optyDistributor contract\n */\n function setOPTYDistributor(address _optyDistributor) external;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/mocks/contracts/TestRegistryNewImplementation.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { ModifiersController } from \"../../ModifiersController.sol\";\nimport { RegistryProxy } from \"../../RegistryProxy.sol\";\nimport { RegistryStorage } from \"../../RegistryStorage.sol\";\nimport { TestStorage } from \"./TestStorage.sol\";\n\ncontract TestRegistryNewImplementation is RegistryStorage, TestStorage, ModifiersController {\n /**\n * @dev Set TestRegistryNewImplementation to act as Registry\n * @param _registryProxy RegistryProxy Contract address to act as Registry\n */\n function become(RegistryProxy _registryProxy) external {\n require(msg.sender == _registryProxy.governance(), \"!governance\");\n require(_registryProxy.acceptImplementation() == 0, \"!unauthorized\");\n }\n\n function isNewContract() external pure returns (bool) {\n return isNewVariable;\n }\n\n function getTokensHashToTokenList(bytes32 _tokensHash) public view returns (address[] memory) {\n return tokensHashToTokens[_tokensHash].tokens;\n }\n\n function getTokensHashByIndex(uint256 _index) public view returns (bytes32) {\n return tokensHashIndexes[_index];\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/mocks/contracts/TestStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title NewImplementationStorage Contract\n * @author Opty.fi\n * @notice Contract to store the state variables of the New Implementation Contract\n */\ncontract TestStorage {\n bool public constant isNewVariable = true;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/mocks/contracts/TestRiskManagerNewImplementation.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { RiskManagerStorage } from \"../../RiskManagerStorage.sol\";\nimport { RiskManagerProxy } from \"../../RiskManagerProxy.sol\";\nimport { Modifiers } from \"../../Modifiers.sol\";\nimport { TestStorage } from \"./TestStorage.sol\";\n\ncontract TestRiskManagerNewImplementation is RiskManagerStorage, TestStorage, Modifiers {\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /**\n * @dev Set TestRiskManagerNewImplementation to act as RiskManager\n * @param _riskManagerProxy RiskManagerProxy contract address to act as RiskManager\n */\n function become(RiskManagerProxy _riskManagerProxy) external onlyGovernance {\n require(_riskManagerProxy.acceptImplementation() == 0, \"!unauthorized\");\n }\n\n function isNewContract() external pure returns (bool) {\n return isNewVariable;\n }\n}\n" + }, + "contracts/protocol/tokenization/VaultProxyV2.sol": { + "content": "// solhint-disable\n// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title Proxy\n * @dev Implements delegation of calls to other contracts, with proper\n * forwarding of return values and bubbling of failures.\n * It defines a fallback function that delegates all calls to the address\n * returned by the abstract _implementation() internal function.\n */\nabstract contract Proxy {\n /**\n * @dev Fallback function.\n * Implemented entirely in `_fallback`.\n */\n fallback() external payable {\n _fallback();\n }\n\n /**\n * @return The Address of the implementation.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates execution to an implementation contract.\n * This is a low level function that doesn't return to its internal call site.\n * It will return to the external caller whatever the implementation returns.\n * @param implementation Address to delegate.\n */\n function _delegate(address implementation) internal {\n //solium-disable-next-line\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 Function that is run as the first thing in the fallback function.\n * Can be redefined in derived contracts to add functionality.\n * Redefinitions must call super._willFallback().\n */\n function _willFallback() internal virtual {}\n\n /**\n * @dev fallback implementation.\n * Extracted to enable manual triggering.\n */\n function _fallback() internal {\n _willFallback();\n _delegate(_implementation());\n }\n}\n\n/**\n * @title BaseUpgradeabilityProxy\n * @dev This contract implements a proxy that allows to change the\n * implementation address to which it will delegate.\n * Such a change is called an implementation upgrade.\n */\ncontract BaseUpgradeabilityProxy is Proxy {\n /**\n * @dev Emitted when the implementation is upgraded.\n * @param implementation Address of the new implementation.\n */\n event Upgraded(address indexed implementation);\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 Returns the current implementation.\n * @return impl Address of the current implementation\n */\n function _implementation() internal view override returns (address impl) {\n bytes32 slot = IMPLEMENTATION_SLOT;\n //solium-disable-next-line\n assembly {\n impl := sload(slot)\n }\n }\n\n /**\n * @dev Upgrades the proxy to a new implementation.\n * @param newImplementation Address of the new implementation.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Sets the implementation address of the proxy.\n * @param newImplementation Address of the new implementation.\n */\n function _setImplementation(address newImplementation) internal {\n require(Address.isContract(newImplementation), \"Cannot set a proxy implementation to a non-contract address\");\n\n bytes32 slot = IMPLEMENTATION_SLOT;\n\n //solium-disable-next-line\n assembly {\n sstore(slot, newImplementation)\n }\n }\n}\n\n/**\n * @title UpgradeabilityProxy\n * @dev Extends BaseUpgradeabilityProxy with a constructor for initializing\n * implementation and init data.\n */\ncontract UpgradeabilityProxy is BaseUpgradeabilityProxy {\n /**\n * @dev Contract constructor.\n * @param _logic Address of the initial implementation.\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\n */\n constructor(address _logic, bytes memory _data) public payable {\n assert(IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _setImplementation(_logic);\n if (_data.length > 0) {\n (bool success, ) = _logic.delegatecall(_data);\n require(success);\n }\n }\n}\n\n/**\n * @title BaseAdminUpgradeabilityProxy\n * @dev This contract combines an upgradeability proxy with an authorization\n * mechanism for administrative tasks.\n * All external functions in this contract must be guarded by the\n * `ifAdmin` modifier. See ethereum/solidity#3864 for a Solidity\n * feature proposal that would enable this to be done automatically.\n */\ncontract BaseAdminUpgradeabilityProxy is BaseUpgradeabilityProxy {\n /**\n * @dev Emitted when the administration has been transferred.\n * @param previousAdmin Address of the previous admin.\n * @param newAdmin Address of the new admin.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\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 Modifier to check whether the `msg.sender` is the admin.\n * If it is, it will run the function. Otherwise, it will delegate the call\n * to the implementation.\n */\n modifier ifAdmin() {\n if (msg.sender == _admin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @return The address of the proxy admin.\n */\n function admin() external ifAdmin returns (address) {\n return _admin();\n }\n\n /**\n * @return The address of the implementation.\n */\n function implementation() external ifAdmin returns (address) {\n return _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n * Only the current admin can call this function.\n * @param newAdmin Address to transfer proxy administration to.\n */\n function changeAdmin(address newAdmin) external ifAdmin {\n require(newAdmin != address(0), \"Cannot change the admin of a proxy to the zero address\");\n emit AdminChanged(_admin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the backing implementation of the proxy.\n * Only the admin can call this function.\n * @param newImplementation Address of the new implementation.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeTo(newImplementation);\n }\n\n /**\n * @dev Upgrade the backing implementation of the proxy and call a function\n * on the new implementation.\n * This is useful to initialize the proxied contract.\n * @param newImplementation Address of the new implementation.\n * @param data Data to send as msg.data in the low level call.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeTo(newImplementation);\n (bool success, ) = newImplementation.delegatecall(data);\n require(success);\n }\n\n /**\n * @return adm The admin slot.\n */\n function _admin() internal view returns (address adm) {\n bytes32 slot = ADMIN_SLOT;\n //solium-disable-next-line\n assembly {\n adm := sload(slot)\n }\n }\n\n /**\n * @dev Sets the address of the proxy admin.\n * @param newAdmin Address of the new proxy admin.\n */\n function _setAdmin(address newAdmin) internal {\n bytes32 slot = ADMIN_SLOT;\n //solium-disable-next-line\n assembly {\n sstore(slot, newAdmin)\n }\n }\n\n /**\n * @dev Only fall back when the sender is not the admin.\n */\n function _willFallback() internal virtual override {\n require(msg.sender != _admin(), \"Cannot call fallback function from the proxy admin\");\n super._willFallback();\n }\n}\n\n/**\n * @title AdminUpgradeabilityProxy\n * @dev Extends from BaseAdminUpgradeabilityProxy with a constructor for\n * initializing the implementation, admin, and init data.\n */\ncontract AdminUpgradeabilityProxy is BaseAdminUpgradeabilityProxy, UpgradeabilityProxy {\n /**\n * Contract constructor.\n * @param _logic address of the initial implementation.\n * @param _admin Address of the proxy administrator.\n * @param _data Data to send as msg.data to the implementation to initialize the proxied contract.\n * It should include the signature and the parameters of the function to be called, as described in\n * https://solidity.readthedocs.io/en/v0.4.24/abi-spec.html#function-selector-and-argument-encoding.\n * This parameter is optional, if no data is given the initialization call to proxied contract will be skipped.\n */\n constructor(\n address _logic,\n address _admin,\n bytes memory _data\n ) public payable UpgradeabilityProxy(_logic, _data) {\n assert(ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _setAdmin(_admin);\n }\n\n /**\n * @dev Only fall back when the sender is not the admin.\n */\n function _willFallback() internal override(BaseAdminUpgradeabilityProxy, Proxy) {\n BaseAdminUpgradeabilityProxy._willFallback();\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/RiskManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n// helper contracts\nimport { Modifiers } from \"./Modifiers.sol\";\nimport { RiskManagerStorage } from \"./RiskManagerStorage.sol\";\nimport { RiskManagerProxy } from \"./RiskManagerProxy.sol\";\n\n// interfaces\nimport { IStrategyProvider } from \"./interfaces/opty/IStrategyProvider.sol\";\nimport { IRiskManager } from \"./interfaces/opty/IRiskManager.sol\";\nimport { Constants } from \"./utils/Constants.sol\";\n\n/**\n * @title RiskManager Contract\n * @author Opty.fi\n * @dev Contract contains functionality for getting the best invest and vaultRewardToken strategy\n */\ncontract RiskManager is IRiskManager, RiskManagerStorage, Modifiers {\n using Address for address;\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /**\n * @dev Set RiskManagerProxy to act as RiskManager\n * @param _riskManagerProxy RiskManagerProxy contract address to act as RiskManager\n */\n function become(RiskManagerProxy _riskManagerProxy) external onlyGovernance {\n require(_riskManagerProxy.acceptImplementation() == 0, \"!unauthorized\");\n }\n\n /**\n * @inheritdoc IRiskManager\n */\n function getBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n public\n view\n override\n returns (DataTypes.StrategyStep[] memory)\n {\n return _getBestStrategy(_riskProfileCode, _underlyingTokensHash);\n }\n\n /**\n * @inheritdoc IRiskManager\n */\n function getVaultRewardTokenStrategy(bytes32 _underlyingTokensHash)\n public\n view\n override\n returns (DataTypes.VaultRewardStrategy memory)\n {\n return\n IStrategyProvider(registryContract.getStrategyProvider()).getVaultRewardTokenHashToVaultRewardTokenStrategy(\n _underlyingTokensHash\n );\n }\n\n function _getBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n internal\n view\n returns (DataTypes.StrategyStep[] memory)\n {\n address[] memory _tokens = registryContract.getTokensHashToTokenList(_underlyingTokensHash);\n require(_tokens.length > 0, \"!TokenHashExists\");\n\n for (uint256 _i; _i < _tokens.length; _i++) {\n require(registryContract.isApprovedToken(_tokens[_i]), \"!Token\");\n }\n\n DataTypes.RiskProfile memory _riskProfileStruct = registryContract.getRiskProfile(_riskProfileCode);\n require(_riskProfileStruct.exists, \"!Rp_Exists\");\n\n DataTypes.StrategyStep[] memory _strategySteps =\n IStrategyProvider(registryContract.getStrategyProvider()).getRpToTokenToBestStrategy(\n _riskProfileCode,\n _underlyingTokensHash\n );\n if (_strategySteps.length == 0 || _isInValidStrategy(_strategySteps, _riskProfileStruct)) {\n _strategySteps = IStrategyProvider(registryContract.getStrategyProvider()).getRpToTokenToDefaultStrategy(\n _riskProfileCode,\n _underlyingTokensHash\n );\n }\n\n return _strategySteps;\n }\n\n function _isInValidStrategy(\n DataTypes.StrategyStep[] memory _strategySteps,\n DataTypes.RiskProfile memory _riskProfileStruct\n ) internal view returns (bool) {\n for (uint256 _i = 0; _i < _strategySteps.length; _i++) {\n DataTypes.LiquidityPool memory _liquidityPool = registryContract.getLiquidityPool(_strategySteps[_i].pool);\n bool _isStrategyInvalid =\n !_liquidityPool.isLiquidityPool ||\n !(_liquidityPool.rating >= _riskProfileStruct.poolRatingsRange.lowerLimit &&\n _liquidityPool.rating <= _riskProfileStruct.poolRatingsRange.upperLimit);\n\n _isStrategyInvalid = !_riskProfileStruct.canBorrow && !_isStrategyInvalid\n ? _strategySteps[_i].isBorrow\n : _isStrategyInvalid;\n\n if (_isStrategyInvalid) {\n return _isStrategyInvalid;\n }\n }\n\n return false;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/RiskManagerStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title RiskManagerStorage Contract\n * @author Opty.fi\n * @notice Contract to store the state variables of the RiskManager Contract\n */\ncontract RiskManagerStorage {\n /**\n * @notice Active brains of Risk Manager\n */\n address public riskManagerImplementation;\n\n /**\n * @notice Pending brains of Risk Manager\n */\n address public pendingRiskManagerImplementation;\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/RiskManagerProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// helper contracts\nimport { Modifiers } from \"./Modifiers.sol\";\nimport { RiskManagerStorage } from \"./RiskManagerStorage.sol\";\n\n/**\n * @title RiskManagerProxy Contract\n * @author Opty.fi\n * @dev Storage for the RiskManager is at this address, while execution is delegated to the\n * riskManagerImplementation. RiskManager should reference this contract as their controller.\n * It defines a fallback function that delegates all calls to the address returned by the\n * abstract _implementation() internal function.\n */\ncontract RiskManagerProxy is RiskManagerStorage, Modifiers {\n /**\n * @notice Emitted when pendingRiskManagerImplementation is changed\n * @param oldPendingImplementation Old RiskManager contract's implementation address which is still pending\n * @param newPendingImplementation New RiskManager contract's implementation address which is still pending\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when RiskManager implementation is updated\n * @param oldImplementation Old RiskManager Contract's implementation address\n * @param newImplementation New RiskManager Contract's implementation address\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /* solhint-disable */\n receive() external payable {\n revert();\n }\n\n /**\n * @notice Delegates execution to an riskManager implementation contract\n * @dev Returns to external caller whatever implementation returns or forwards reverts\n */\n fallback() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = riskManagerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n\n /* solhint-disable */\n\n /*** Admin Functions ***/\n /**\n * @dev Set the riskManager contract as pending implementation initally\n * @param newPendingImplementation riskManager address to act as pending implementation\n */\n function setPendingImplementation(address newPendingImplementation) external onlyOperator {\n address oldPendingImplementation = pendingRiskManagerImplementation;\n\n pendingRiskManagerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingRiskManagerImplementation);\n }\n\n /**\n * @notice Accepts new implementation of riskManager\n * @dev Governance function for new implementation to accept it's role as implementation\n */\n function acceptImplementation() external returns (uint256) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n require(\n msg.sender == pendingRiskManagerImplementation && pendingRiskManagerImplementation != address(0),\n \"!pendingRiskManagerImplementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = riskManagerImplementation;\n address oldPendingImplementation = pendingRiskManagerImplementation;\n\n riskManagerImplementation = pendingRiskManagerImplementation;\n\n pendingRiskManagerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, riskManagerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingRiskManagerImplementation);\n\n return uint256(0);\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IStrategyProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for StrategyProvider Contract\n * @author Opty.fi\n * @notice Contains functions for setting and getting the best and default strategy\n * as well as vault reward token strategy\n */\ninterface IStrategyProvider {\n /**\n * @notice Set the best stratetgy for the given riskProfile and tokenHash\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @param _strategySteps Strategy steps to be set as best strategy\n */\n function setBestStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external;\n\n /**\n * @notice Set the best default stratetgy for the given riskProfile and tokenHash\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @param _strategySteps Strategy steps to be set as best default strategy\n */\n function setBestDefaultStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external;\n\n /**\n * @dev Assign strategy in form of vaultRewardStrategy to the vaultRewardTokenHash\n * @param _vaultRewardTokenHash Hash of vault contract and reward token address\n * @param _vaultRewardStrategy Vault reward token's strategy for the specified vaultRewardTokenHash\n * @return Returns a vaultRewardStrategy hash value indicating successful operation\n */\n function setVaultRewardStrategy(\n bytes32 _vaultRewardTokenHash,\n DataTypes.VaultRewardStrategy memory _vaultRewardStrategy\n ) external returns (DataTypes.VaultRewardStrategy memory);\n\n /**\n * @notice Get the Best strategy corresponding to riskProfile and tokenHash provided\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @return Returns the best strategy corresponding to riskProfile and tokenHash provided\n */\n function getRpToTokenToBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice Get the Best Default strategy corresponding to riskProfile and tokenHash provided\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @return Returns the best default strategy corresponding to riskProfile and tokenHash provided\n */\n function getRpToTokenToDefaultStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice Get the Vault reward token's strategy corresponding to the tokensHash provided\n * @param _vaultRewardTokenHash Hash of Vault contract and reward token address\n * @return Returns the Vault reward token's strategy corresponding to the tokensHash provided\n */\n function getVaultRewardTokenHashToVaultRewardTokenStrategy(bytes32 _vaultRewardTokenHash)\n external\n view\n returns (DataTypes.VaultRewardStrategy memory);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IRiskManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for RiskManager contract\n * @author Opty.fi\n * @notice A layer between vault and registry contract to get the best invest strategy as well\n * as vault reward token strategy\n */\ninterface IRiskManager {\n /**\n * @notice Get the best strategy for respective RiskProfiles\n * @param _riskProfileCode Risk profile code (Eg: 1,2, and so on where 0 is reserved for 'no strategy')\n * corresponding to which get the best strategy\n * @param _underlyingTokensHash Hash of the underlying token address/addresses and chainId (like 0x1 etc.)\n * @return Returns the hash of the best strategy corresponding to the riskProfile provided\n */\n function getBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice Get the VaultRewardToken strategy for respective VaultRewardToken hash\n * @param _underlyingTokensHash Hash of vault contract address and reward token address\n * @return _vaultRewardStrategy Returns the VaultRewardToken strategy for given vaultRewardTokenHash\n */\n function getVaultRewardTokenStrategy(bytes32 _underlyingTokensHash)\n external\n view\n returns (DataTypes.VaultRewardStrategy memory _vaultRewardStrategy);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/utils/Constants.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nlibrary Constants {\n /** @notice Zero value constant of bytes32 datatype */\n bytes32 public constant ZERO_BYTES32 = 0x0000000000000000000000000000000000000000000000000000000000000000;\n\n /** @notice Decimals considered upto 10**18 */\n uint256 public constant WEI_DECIMAL = 10**18;\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/StrategyProvider.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// helper contracts\nimport { Modifiers } from \"./Modifiers.sol\";\n\n// interfaces\nimport { IStrategyProvider } from \"./interfaces/opty/IStrategyProvider.sol\";\nimport { Constants } from \"./utils/Constants.sol\";\n\n/**\n * @title StrategyProvider Contract\n * @author Opty.fi\n * @notice Serves as an oracle service of opty-fi's earn protocol\n * @dev Contracts contains logic for setting and getting the best and default strategy\n * as well as vault reward token strategy\n */\ncontract StrategyProvider is IStrategyProvider, Modifiers {\n using SafeMath for uint256;\n\n /**\n * @notice Mapping of RiskProfile (eg: RP1, RP2, etc) to tokensHash to the best strategy hash\n */\n mapping(uint256 => mapping(bytes32 => DataTypes.StrategyStep[])) public rpToTokenToBestStrategy;\n\n /**\n * @notice Mapping of RiskProfile (eg: RP1, RP2, etc) to tokensHash to best default strategy hash\n */\n mapping(uint256 => mapping(bytes32 => DataTypes.StrategyStep[])) public rpToTokenToDefaultStrategy;\n\n /**\n * @notice Mapping of vaultRewardToken address hash to vault reward token strategy\n */\n mapping(bytes32 => DataTypes.VaultRewardStrategy) public vaultRewardTokenHashToVaultRewardTokenStrategy;\n\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function setBestStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external override onlyStrategyOperator {\n delete rpToTokenToBestStrategy[_riskProfileCode][_underlyingTokensHash];\n for (uint256 _i = 0; _i < _strategySteps.length; _i++) {\n rpToTokenToBestStrategy[_riskProfileCode][_underlyingTokensHash].push(_strategySteps[_i]);\n }\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function setBestDefaultStrategy(\n uint256 _riskProfileCode,\n bytes32 _underlyingTokensHash,\n DataTypes.StrategyStep[] memory _strategySteps\n ) external override onlyStrategyOperator {\n delete rpToTokenToDefaultStrategy[_riskProfileCode][_underlyingTokensHash];\n for (uint256 _i = 0; _i < _strategySteps.length; _i++) {\n rpToTokenToDefaultStrategy[_riskProfileCode][_underlyingTokensHash].push(_strategySteps[_i]);\n }\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function setVaultRewardStrategy(\n bytes32 _vaultRewardTokenHash,\n DataTypes.VaultRewardStrategy memory _vaultRewardStrategy\n ) external override onlyStrategyOperator returns (DataTypes.VaultRewardStrategy memory) {\n vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash].hold = _vaultRewardStrategy.hold;\n vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash].convert = _vaultRewardStrategy.convert;\n return vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash];\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function getVaultRewardTokenHashToVaultRewardTokenStrategy(bytes32 _vaultRewardTokenHash)\n public\n view\n override\n returns (DataTypes.VaultRewardStrategy memory)\n {\n return vaultRewardTokenHashToVaultRewardTokenStrategy[_vaultRewardTokenHash];\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function getRpToTokenToBestStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n override\n returns (DataTypes.StrategyStep[] memory)\n {\n return rpToTokenToBestStrategy[_riskProfileCode][_underlyingTokensHash];\n }\n\n /**\n * @inheritdoc IStrategyProvider\n */\n function getRpToTokenToDefaultStrategy(uint256 _riskProfileCode, bytes32 _underlyingTokensHash)\n external\n view\n override\n returns (DataTypes.StrategyStep[] memory)\n {\n return rpToTokenToDefaultStrategy[_riskProfileCode][_underlyingTokensHash];\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/Registry.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n// helper contracts\nimport { ModifiersController } from \"./ModifiersController.sol\";\nimport { RegistryProxy } from \"./RegistryProxy.sol\";\n\n// interfaces\nimport { IVault } from \"./interfaces/opty/IVault.sol\";\nimport { IRegistry } from \"./interfaces/opty/IRegistry.sol\";\nimport { IContractRegistry } from \"./interfaces/opty/IContractRegistry.sol\";\nimport { Constants } from \"./utils/Constants.sol\";\n\n/**\n * @title Registry Contract\n * @author Opty.fi\n * @dev Contract to persit status of tokens,lpTokens,lp/cp and Vaults\n */\ncontract Registry is IRegistry, ModifiersController {\n using Address for address;\n using SafeMath for uint256;\n\n /**\n * @dev Set RegistryProxy to act as Registry\n * @param _registryProxy RegistryProxy Contract address to act as Registry\n */\n function become(RegistryProxy _registryProxy) external {\n require(msg.sender == _registryProxy.governance(), \"!governance\");\n require(_registryProxy.acceptImplementation() == 0, \"!unauthorized\");\n investStrategyRegistry = address(0);\n aprOracle = address(0);\n strategyManager = address(0);\n optyStakingRateBalancer = address(0);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setTreasury(address _treasury) external override onlyGovernance {\n require(_treasury != address(0), \"!address(0)\");\n treasury = _treasury;\n emit TransferTreasury(treasury, msg.sender);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setStrategyProvider(address _strategyProvider) external override onlyOperator {\n require(IContractRegistry(_strategyProvider).registryContract() == address(this), \"!registryContract\");\n strategyProvider = _strategyProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setRiskManager(address _riskManager) external override onlyOperator {\n require(IContractRegistry(_riskManager).registryContract() == address(this), \"!registryContract\");\n riskManager = _riskManager;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setHarvestCodeProvider(address _harvestCodeProvider) external override onlyOperator {\n require(IContractRegistry(_harvestCodeProvider).registryContract() == address(this), \"!registryContract\");\n harvestCodeProvider = _harvestCodeProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setOPTY(address _opty) external override onlyOperator {\n opty = _opty;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setODEFIVaultBooster(address _odefiVaultBooster) external override onlyOperator {\n require(IContractRegistry(_odefiVaultBooster).registryContract() == address(this), \"!registryContract\");\n odefiVaultBooster = _odefiVaultBooster;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveToken(address[] memory _tokens) external override onlyOperator {\n for (uint256 _i; _i < _tokens.length; _i++) {\n _approveToken(_tokens[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveToken(address _token) external override onlyOperator {\n _approveToken(_token);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeToken(address[] memory _tokens) external override onlyOperator {\n for (uint256 _i; _i < _tokens.length; _i++) {\n _revokeToken(_tokens[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeToken(address _token) external override onlyOperator {\n _revokeToken(_token);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _approveLiquidityPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPool(address _pool) external override onlyOperator {\n _approveLiquidityPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeLiquidityPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _revokeLiquidityPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeLiquidityPool(address _pool) external override onlyOperator {\n _revokeLiquidityPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateLiquidityPool(DataTypes.PoolRate[] memory _poolRates) external override onlyRiskOperator {\n for (uint256 _i; _i < _poolRates.length; _i++) {\n _rateLiquidityPool(_poolRates[_i].pool, _poolRates[_i].rate);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateLiquidityPool(address _pool, uint8 _rate) external override onlyRiskOperator {\n _rateLiquidityPool(_pool, _rate);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPoolAndMapToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _poolAdapters.length; _i++) {\n _approveLiquidityPool(_poolAdapters[_i].pool);\n _setLiquidityPoolToAdapter(_poolAdapters[_i].pool, _poolAdapters[_i].adapter);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveLiquidityPoolAndMapToAdapter(address _pool, address _adapter) external override onlyOperator {\n _approveLiquidityPool(_pool);\n _setLiquidityPoolToAdapter(_pool, _adapter);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveCreditPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _approveCreditPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveCreditPool(address _pool) external override onlyOperator {\n _approveCreditPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeCreditPool(address[] memory _pools) external override onlyOperator {\n for (uint256 _i; _i < _pools.length; _i++) {\n _revokeCreditPool(_pools[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function revokeCreditPool(address _pool) external override onlyOperator {\n _revokeCreditPool(_pool);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateCreditPool(DataTypes.PoolRate[] memory _poolRates) external override onlyRiskOperator {\n for (uint256 _i; _i < _poolRates.length; _i++) {\n _rateCreditPool(_poolRates[_i].pool, _poolRates[_i].rate);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function rateCreditPool(address _pool, uint8 _rate) external override onlyRiskOperator {\n _rateCreditPool(_pool, _rate);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setLiquidityPoolToAdapter(DataTypes.PoolAdapter[] memory _poolAdapters) external override onlyOperator {\n for (uint256 _i; _i < _poolAdapters.length; _i++) {\n require(liquidityPools[_poolAdapters[_i].pool].isLiquidityPool, \"!liquidityPools\");\n _setLiquidityPoolToAdapter(_poolAdapters[_i].pool, _poolAdapters[_i].adapter);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setLiquidityPoolToAdapter(address _pool, address _adapter) external override onlyOperator {\n require(liquidityPools[_pool].isLiquidityPool, \"!liquidityPools\");\n _setLiquidityPoolToAdapter(_pool, _adapter);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveTokenAndMapToTokensHash(DataTypes.TokensHashDetail[] memory _tokensHashesDetails)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _tokensHashesDetails.length; _i++) {\n for (uint256 _j; _j < _tokensHashesDetails[_i].tokens.length; _j++) {\n _approveToken(_tokensHashesDetails[_i].tokens[_j]);\n }\n _setTokensHashToTokens(_tokensHashesDetails[_i].tokensHash, _tokensHashesDetails[_i].tokens);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function approveTokenAndMapToTokensHash(bytes32 _tokensHash, address[] memory _tokens)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _tokens.length; _i++) {\n _approveToken(_tokens[_i]);\n }\n _setTokensHashToTokens(_tokensHash, _tokens);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setTokensHashToTokens(DataTypes.TokensHashDetail[] memory _tokensHashesDetails)\n external\n override\n onlyOperator\n {\n for (uint256 _i; _i < _tokensHashesDetails.length; _i++) {\n require(_areTokensApproved(_tokensHashesDetails[_i].tokens), \"!tokens\");\n _setTokensHashToTokens(_tokensHashesDetails[_i].tokensHash, _tokensHashesDetails[_i].tokens);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function setTokensHashToTokens(bytes32 _tokensHash, address[] memory _tokens) external override onlyOperator {\n require(_areTokensApproved(_tokens), \"!tokens\");\n _setTokensHashToTokens(_tokensHash, _tokens);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function updateRiskProfileBorrow(uint256 _riskProfileCode, bool _canBorrow) external override onlyRiskOperator {\n _updateRiskProfileBorrow(_riskProfileCode, _canBorrow);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function addRiskProfile(\n uint256 _riskProfileCode,\n string memory _name,\n string memory _symbol,\n bool _canBorrow,\n DataTypes.PoolRatingsRange memory _poolRatingRange\n ) external override onlyRiskOperator {\n _addRiskProfile(_riskProfileCode, _name, _symbol, _canBorrow, _poolRatingRange);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function addRiskProfile(\n uint256[] memory _riskProfileCodes,\n string[] memory _names,\n string[] memory _symbols,\n bool[] memory _canBorrow,\n DataTypes.PoolRatingsRange[] memory _poolRatingRanges\n ) external override onlyRiskOperator {\n require(_riskProfileCodes.length > 0, \"!length>0\");\n require(_riskProfileCodes.length == _poolRatingRanges.length, \"!RP_PoolRatingsLength\");\n require(_riskProfileCodes.length == _canBorrow.length, \"!RP_canBorrowLength\");\n require(_riskProfileCodes.length == _names.length, \"!RP_namesLength\");\n require(_riskProfileCodes.length == _symbols.length, \"!RP_symbolsLength\");\n\n for (uint256 _i; _i < _riskProfileCodes.length; _i++) {\n _addRiskProfile(_riskProfileCodes[_i], _names[_i], _symbols[_i], _canBorrow[_i], _poolRatingRanges[_i]);\n }\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function updateRPPoolRatings(uint256 _riskProfileCode, DataTypes.PoolRatingsRange memory _poolRatingRange)\n external\n override\n onlyRiskOperator\n {\n _updateRPPoolRatings(_riskProfileCode, _poolRatingRange);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function removeRiskProfile(uint256 _index) external override onlyRiskOperator {\n _removeRiskProfile(_index);\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokenHashes() public view override returns (bytes32[] memory) {\n return tokensHashIndexes;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokensHashToTokenList(bytes32 _tokensHash) public view override returns (address[] memory) {\n return tokensHashToTokens[_tokensHash].tokens;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskProfileList() public view override returns (uint256[] memory) {\n return riskProfilesArray;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokensHashIndexByHash(bytes32 _tokensHash) public view override returns (uint256) {\n return tokensHashToTokens[_tokensHash].index;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getTokensHashByIndex(uint256 _index) public view override returns (bytes32) {\n return tokensHashIndexes[_index];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function isApprovedToken(address _token) public view override returns (bool) {\n return tokens[_token];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getStrategyProvider() public view override returns (address) {\n return strategyProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskProfile(uint256 _riskProfileCode) public view override returns (DataTypes.RiskProfile memory) {\n return riskProfiles[_riskProfileCode];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskManager() public view override returns (address) {\n return riskManager;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getOPTYDistributor() public view override returns (address) {\n return optyDistributor;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getODEFIVaultBooster() external view override returns (address) {\n return odefiVaultBooster;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getGovernance() public view override returns (address) {\n return governance;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getFinanceOperator() public view override returns (address) {\n return financeOperator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getRiskOperator() public view override returns (address) {\n return riskOperator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getStrategyOperator() public view override returns (address) {\n return strategyOperator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getOperator() public view override returns (address) {\n return operator;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getHarvestCodeProvider() public view override returns (address) {\n return harvestCodeProvider;\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getLiquidityPool(address _pool) public view override returns (DataTypes.LiquidityPool memory) {\n return liquidityPools[_pool];\n }\n\n /**\n * @inheritdoc IRegistry\n */\n function getLiquidityPoolToAdapter(address _pool) public view override returns (address) {\n return liquidityPoolToAdapter[_pool];\n }\n\n function _approveToken(address _token) internal {\n tokens[_token] = true;\n emit LogToken(_token, tokens[_token], msg.sender);\n }\n\n function _revokeToken(address _token) internal {\n tokens[_token] = false;\n emit LogToken(_token, tokens[_token], msg.sender);\n }\n\n function _approveLiquidityPool(address _pool) internal {\n liquidityPools[_pool].isLiquidityPool = true;\n emit LogLiquidityPool(_pool, liquidityPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _revokeLiquidityPool(address _pool) internal {\n liquidityPools[_pool].isLiquidityPool = false;\n emit LogLiquidityPool(_pool, liquidityPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _rateLiquidityPool(address _pool, uint8 _rate) internal {\n require(liquidityPools[_pool].isLiquidityPool, \"!liquidityPools\");\n liquidityPools[_pool].rating = _rate;\n emit LogRateLiquidityPool(_pool, liquidityPools[_pool].rating, msg.sender);\n }\n\n function _approveCreditPool(address _pool) internal {\n creditPools[_pool].isLiquidityPool = true;\n emit LogCreditPool(_pool, creditPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _revokeCreditPool(address _pool) internal {\n creditPools[_pool].isLiquidityPool = false;\n emit LogCreditPool(_pool, creditPools[_pool].isLiquidityPool, msg.sender);\n }\n\n function _rateCreditPool(address _pool, uint8 _rate) internal {\n require(creditPools[_pool].isLiquidityPool, \"!creditPools\");\n creditPools[_pool].rating = _rate;\n emit LogRateCreditPool(_pool, creditPools[_pool].rating, msg.sender);\n }\n\n function _setLiquidityPoolToAdapter(address _pool, address _adapter) internal {\n require(IContractRegistry(_adapter).registryContract() == address(this), \"!registryContract\");\n liquidityPoolToAdapter[_pool] = _adapter;\n emit LogLiquidityPoolToAdapter(_pool, _adapter, msg.sender);\n }\n\n function _setTokensHashToTokens(bytes32 _tokensHash, address[] memory _tokens) internal {\n require(_isNewTokensHash(_tokensHash), \"!_isNewTokensHash\");\n tokensHashIndexes.push(_tokensHash);\n tokensHashToTokens[_tokensHash].index = tokensHashIndexes.length - 1;\n tokensHashToTokens[_tokensHash].tokens = _tokens;\n emit LogTokensToTokensHash(_tokensHash, msg.sender);\n }\n\n function _addRiskProfile(\n uint256 _riskProfileCode,\n string memory _name,\n string memory _symbol,\n bool _canBorrow,\n DataTypes.PoolRatingsRange memory _poolRatingRange\n ) internal {\n require(!riskProfiles[_riskProfileCode].exists, \"RP_already_exists\");\n require(bytes(_name).length > 0, \"RP_name_empty\");\n require(bytes(_symbol).length > 0, \"RP_symbol_empty\");\n riskProfilesArray.push(_riskProfileCode);\n riskProfiles[_riskProfileCode].name = _name;\n riskProfiles[_riskProfileCode].symbol = _symbol;\n riskProfiles[_riskProfileCode].canBorrow = _canBorrow;\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit = _poolRatingRange.lowerLimit;\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit = _poolRatingRange.upperLimit;\n riskProfiles[_riskProfileCode].index = riskProfilesArray.length - 1;\n riskProfiles[_riskProfileCode].exists = true;\n\n emit LogRiskProfile(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].exists,\n riskProfiles[_riskProfileCode].canBorrow,\n msg.sender\n );\n emit LogRPPoolRatings(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit,\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit,\n msg.sender\n );\n }\n\n function _updateRiskProfileBorrow(uint256 _riskProfileCode, bool _canBorrow) internal {\n require(riskProfiles[_riskProfileCode].exists, \"!Rp_Exists\");\n riskProfiles[_riskProfileCode].canBorrow = _canBorrow;\n emit LogRiskProfile(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].exists,\n riskProfiles[_riskProfileCode].canBorrow,\n msg.sender\n );\n }\n\n function _updateRPPoolRatings(uint256 _riskProfileCode, DataTypes.PoolRatingsRange memory _poolRatingRange)\n internal\n {\n require(riskProfiles[_riskProfileCode].exists, \"!Rp_Exists\");\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit = _poolRatingRange.lowerLimit;\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit = _poolRatingRange.upperLimit;\n emit LogRPPoolRatings(\n riskProfiles[_riskProfileCode].index,\n riskProfiles[_riskProfileCode].poolRatingsRange.lowerLimit,\n riskProfiles[_riskProfileCode].poolRatingsRange.upperLimit,\n msg.sender\n );\n }\n\n function _removeRiskProfile(uint256 _index) internal {\n require(_index <= riskProfilesArray.length, \"Invalid_Rp_index\");\n uint256 _riskProfileCode = riskProfilesArray[_index];\n require(riskProfiles[_riskProfileCode].exists, \"!Rp_Exists\");\n riskProfiles[_riskProfileCode].exists = false;\n emit LogRiskProfile(\n _index,\n riskProfiles[_riskProfileCode].exists,\n riskProfiles[_riskProfileCode].canBorrow,\n msg.sender\n );\n }\n\n /**\n * @dev Checks duplicate tokensHash\n * @param _hash Hash of the token address/addresses\n * @return A boolean value indicating whether duplicate _hash exists or not\n */\n function _isNewTokensHash(bytes32 _hash) internal view returns (bool) {\n if (tokensHashIndexes.length == 0) {\n return true;\n }\n return (tokensHashIndexes[tokensHashToTokens[_hash].index] != _hash);\n }\n\n /**\n * @dev Checks approved tokens\n * @param _tokens List of the token addresses\n */\n function _areTokensApproved(address[] memory _tokens) internal view returns (bool) {\n for (uint256 _i; _i < _tokens.length; _i++) {\n if (!tokens[_tokens[_i]]) {\n return false;\n }\n }\n return true;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/ModifiersController.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { RegistryStorage } from \"./RegistryStorage.sol\";\n\n// interfaces\nimport { IModifiersController } from \"./interfaces/opty/IModifiersController.sol\";\n\n/**\n * @title ModifiersController Contract\n * @author Opty.fi\n * @notice Contract used by registry contract and acts as source of truth\n * @dev It manages operator, optyDistributor addresses as well as modifiers\n */\nabstract contract ModifiersController is IModifiersController, RegistryStorage {\n using Address for address;\n\n /**\n * @inheritdoc IModifiersController\n */\n function setFinanceOperator(address _financeOperator) public override onlyGovernance {\n require(_financeOperator != address(0), \"!address(0)\");\n financeOperator = _financeOperator;\n emit TransferFinanceOperator(financeOperator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setRiskOperator(address _riskOperator) public override onlyGovernance {\n require(_riskOperator != address(0), \"!address(0)\");\n riskOperator = _riskOperator;\n emit TransferRiskOperator(riskOperator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setStrategyOperator(address _strategyOperator) public override onlyGovernance {\n require(_strategyOperator != address(0), \"!address(0)\");\n strategyOperator = _strategyOperator;\n emit TransferStrategyOperator(strategyOperator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setOperator(address _operator) public override onlyGovernance {\n require(_operator != address(0), \"!address(0)\");\n operator = _operator;\n emit TransferOperator(operator, msg.sender);\n }\n\n /**\n * @inheritdoc IModifiersController\n */\n function setOPTYDistributor(address _optyDistributor) public override onlyGovernance {\n require(_optyDistributor.isContract(), \"!isContract\");\n optyDistributor = _optyDistributor;\n emit TransferOPTYDistributor(optyDistributor, msg.sender);\n }\n\n /**\n * @notice Modifier to check caller is governance or not\n */\n modifier onlyGovernance() {\n require(msg.sender == governance, \"caller is not having governance\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is financeOperator or not\n */\n modifier onlyFinanceOperator() {\n require(msg.sender == financeOperator, \"caller is not the finance operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is riskOperator or not\n */\n modifier onlyRiskOperator() {\n require(msg.sender == riskOperator, \"caller is not the risk operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is operator or not\n */\n modifier onlyOperator() {\n require(msg.sender == operator, \"caller is not the operator\");\n _;\n }\n\n /**\n * @notice Modifier to check caller is optyDistributor or not\n */\n modifier onlyOptyDistributor() {\n require(msg.sender == optyDistributor, \"caller is not the optyDistributor\");\n _;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/RegistryProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// helper contracts\nimport { RegistryStorage } from \"./RegistryStorage.sol\";\nimport { ModifiersController } from \"./ModifiersController.sol\";\n\n/**\n * @title RegistryProxy Contract\n * @author Opty.fi\n * @dev Storage for the Registry is at this address,\n * while execution is delegated to the `registryImplementation`.\n * Registry should reference this contract as their controller.\n * It defines a fallback function that delegates all calls to the address\n * returned by the abstract _implementation() internal function.\n */\ncontract RegistryProxy is RegistryStorage, ModifiersController {\n /**\n * @notice Emitted when pendingComptrollerImplementation is changed\n * @param oldPendingImplementation Old Registry contract's implementation address which is still pending\n * @param newPendingImplementation New Registry contract's implementation address which is still pending\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is updated\n * @param oldImplementation Old Registry Contract's implementation address\n * @param newImplementation New Registry Contract's implementation address\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingGovernance is changed\n * @param oldPendingGovernance Old Governance's address which is still pending\n * @param newPendingGovernance New Governance's address which is still pending\n */\n event NewPendingGovernance(address oldPendingGovernance, address newPendingGovernance);\n\n /**\n * @notice Emitted when pendingGovernance is accepted, which means governance is updated\n * @param oldGovernance Old Governance's address\n * @param newGovernance New Governance's address\n */\n event NewGovernance(address oldGovernance, address newGovernance);\n\n constructor() public {\n governance = msg.sender;\n setFinanceOperator(msg.sender);\n setRiskOperator(msg.sender);\n setStrategyOperator(msg.sender);\n setOperator(msg.sender);\n }\n\n /* solhint-disable */\n receive() external payable {\n revert();\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev Returns to external caller whatever implementation returns or forwards reverts\n */\n fallback() external payable {\n // delegate all other functions to current implementation\n (bool success, ) = registryImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n\n /* solhint-disable */\n\n /*** Admin Functions ***/\n /**\n * @dev Set the registry contract as pending implementation initally\n * @param newPendingImplementation registry address to act as pending implementation\n */\n function setPendingImplementation(address newPendingImplementation) external onlyOperator {\n address oldPendingImplementation = pendingRegistryImplementation;\n\n pendingRegistryImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingRegistryImplementation);\n }\n\n /**\n * @notice Accepts new implementation of registry\n * @dev Governance function for new implementation to accept it's role as implementation\n */\n function acceptImplementation() external returns (uint256) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n require(\n msg.sender == pendingRegistryImplementation && pendingRegistryImplementation != address(0),\n \"!pendingRegistryImplementation\"\n );\n\n // Save current values for inclusion in log\n address oldImplementation = registryImplementation;\n address oldPendingImplementation = pendingRegistryImplementation;\n\n registryImplementation = pendingRegistryImplementation;\n\n pendingRegistryImplementation = address(0);\n\n emit NewImplementation(oldImplementation, registryImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingRegistryImplementation);\n\n return uint256(0);\n }\n\n /**\n * @notice Transfers the governance rights\n * @dev The newPendingGovernance must call acceptGovernance() to finalize the transfer\n * @param newPendingGovernance New pending governance address\n */\n function setPendingGovernance(address newPendingGovernance) external onlyOperator {\n // Save current value, if any, for inclusion in log\n address oldPendingGovernance = pendingGovernance;\n\n // Store pendingGovernance with value newPendingGovernance\n pendingGovernance = newPendingGovernance;\n\n // Emit NewPendingGovernance(oldPendingGovernance, newPendingGovernance)\n emit NewPendingGovernance(oldPendingGovernance, newPendingGovernance);\n }\n\n /**\n * @notice Accepts transfer of Governance rights\n * @dev Governance function for pending governance to accept role and update Governance\n */\n function acceptGovernance() external returns (uint256) {\n require(msg.sender == pendingGovernance && msg.sender != address(0), \"!pendingGovernance\");\n\n // Save current values for inclusion in log\n address oldGovernance = governance;\n address oldPendingGovernance = pendingGovernance;\n\n // Store admin with value pendingGovernance\n governance = pendingGovernance;\n\n // Clear the pending value\n pendingGovernance = address(0);\n\n emit NewGovernance(oldGovernance, governance);\n emit NewPendingGovernance(oldPendingGovernance, pendingGovernance);\n return uint256(0);\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IVault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for opty.fi's interest bearing vault\n * @author opty.fi\n * @notice Contains mix of permissioned and permissionless vault methods\n */\ninterface IVault {\n /**\n * @notice Set maximum standard deviation of vault value in a single block\n * @dev the maximum vault value jump is in percentage basis points set by governance\n * @param _maxVaultValueJump the standard deviation from a vault value in basis points\n */\n function setMaxVaultValueJump(uint256 _maxVaultValueJump) external;\n\n /**\n * @notice Calculate the value of a vault share in underlying token\n * @dev It should only be called if the current strategy's last step is Curve\n * @return the underlying token worth a vault share is\n */\n function getPricePerFullShareWrite() external returns (uint256);\n\n /**\n * @notice Withdraw the underying asset of vault from previous strategy if any,\n * claims and swaps the reward tokens for the underlying token\n * performs batch minting of shares for users deposited previously without rebalance,\n * deposits the assets into the new strategy if any or holds the same in the vault\n * @dev the vault will be charged to compensate gas fees if operator calls this function\n */\n function rebalance() external;\n\n /**\n * @notice Claim the rewards if any strategy have it and swap for underlying token\n * @param _investStrategyHash vault invest strategy hash\n */\n function harvest(bytes32 _investStrategyHash) external;\n\n /**\n * @notice A cheap function to deposit whole underlying token's balance\n * @dev this function does not rebalance, hence vault shares will be minted on the next rebalance\n */\n function userDepositAll() external;\n\n /**\n * @notice A cheap function to deposit _amount of underlying token to the vault\n * @dev the user will receive vault shares on next rebalance\n * @param _amount the amount of the underlying token to be deposited\n */\n function userDeposit(uint256 _amount) external;\n\n /**\n * @notice Deposit full balance in underlying token of the caller and rebalance\n * @dev the vault shares are minted right away\n */\n function userDepositAllRebalance() external;\n\n /**\n * @notice Deposit amount of underlying token of caller and rebalance\n * @dev the vault shares are minted right away\n * @param _amount the amount of the underlying token\n */\n function userDepositRebalance(uint256 _amount) external;\n\n /**\n * @notice Redeem full balance of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault\n */\n function userWithdrawAllRebalance() external;\n\n /**\n * @notice Redeem the amount of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault\n * @param _redeemAmount the vault shares to redeem\n */\n function userWithdrawRebalance(uint256 _redeemAmount) external;\n\n /**\n * @notice A cheap function to deposit whole underlying token's balance of caller\n * @dev the gas fees are paid in $CHI tokens and vault shares are minted on next rebalance\n */\n function userDepositAllWithCHI() external;\n\n /**\n * @notice A cheap function to deposit amount of underlying token's balance of caller\n * @dev the gas fees are paid in $CHI tokens and vault shares are minted on next rebalance\n * @param _amount the amount of underlying tokens to be deposited\n */\n function userDepositWithCHI(uint256 _amount) external;\n\n /**\n * @notice Deposit full balance in underlying token of the caller and rebalance\n * @dev the vault shares are minted right away and gas fees are paid in $CHI tokens\n */\n function userDepositAllRebalanceWithCHI() external;\n\n /**\n * @notice Deposit amount of underlying token of caller and rebalance\n * @dev the vault shares are minted right away and gas fees are paid in $CHI tokens\n * @param _amount the amount of the underlying token\n */\n function userDepositRebalanceWithCHI(uint256 _amount) external;\n\n /**\n * @notice Redeem full balance of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault and gas fees are paid in $CHI tokens\n */\n function userWithdrawAllRebalanceWithCHI() external;\n\n /**\n * @notice Redeem the amount of vault shares for getting yield optimized underlying tokens\n * @dev this function rebalances the vault and gas fees are paid in $CHI tokens\n * @param _redeemAmount the amount of vault shares\n */\n function userWithdrawRebalanceWithCHI(uint256 _redeemAmount) external;\n\n /**\n * @notice Recall vault investments from current strategy, restricts deposits\n * and allows redemption of the shares\n * @dev this function can be invoked by governance via registry\n */\n function discontinue() external;\n\n /**\n * @notice This function can temporarily restrict user from depositing\n * or withdrawing assets to and from the vault\n * @dev this function can be invoked by governance via registry\n * @param _unpaused for invoking/revoking pause over the vault\n */\n function setUnpaused(bool _unpaused) external;\n\n /**\n * @notice Retrieve underlying token balance in the vault\n * @return The balance of underlying token in the vault\n */\n function balance() external view returns (uint256);\n\n /**\n * @notice Calculate the value of a vault share in underlying token\n * @return The underlying token worth a vault share is\n */\n function getPricePerFullShare() external view returns (uint256);\n\n /**\n * @notice Assign a risk profile name\n * @dev name of the risk profile should be approved by governance\n * @param _riskProfileCode code of the risk profile\n */\n function setRiskProfileCode(uint256 _riskProfileCode) external;\n\n /**\n * @notice Assign the address of the underlying asset of the vault\n * @dev the underlying asset should be approved by the governance\n * @param _underlyingToken the address of the underlying asset\n */\n function setToken(address _underlyingToken) external;\n\n /**\n * @dev A helper function to validate the vault value will not be deviated from max vault value\n * within the same block\n * @param _diff absolute difference between minimum and maximum vault value within a block\n * @param _currentVaultValue the underlying token balance of the vault\n * @return bool returns true if vault value jump is within permissible limits\n */\n function isMaxVaultValueJumpAllowed(uint256 _diff, uint256 _currentVaultValue) external view returns (bool);\n\n /**\n * @notice A function to be called in case vault needs to claim and harvest tokens in case a strategy\n * provides multiple reward tokens\n * @param _codes Array of encoded data in bytes which acts as code to execute\n */\n function adminCall(bytes[] memory _codes) external;\n\n /**\n * @notice A function to get deposit queue\n * @return return queue\n */\n function getDepositQueue() external view returns (DataTypes.UserDepositOperation[] memory);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IContractRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Interface for Contracts deployed with registry contract\n * @author Opty.fi\n * @notice Interface to get registry contract\n */\ninterface IContractRegistry {\n /**\n * @notice Get the address of registry contract\n * @return address of registry contract\n */\n function registryContract() external view returns (address);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/RegistryStorage.sol": { + "content": "/* solhint-disable max-states-count */\n// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"./libraries/types/DataTypes.sol\";\n\n/**\n * @title RegistryAdminStorage Contract\n * @author Opty.fi\n * @dev Contract used to store registry's admin account\n */\ncontract RegistryAdminStorage {\n /**\n * @notice Governance of optyfi's earn protocol\n */\n address public governance;\n\n /**\n * @notice Finance operator of optyfi's earn protocol\n * @dev Handle functions having withdrawal fee, treasury and finance related logic\n */\n address public financeOperator;\n\n /**\n * @notice Risk operator of optyfi's earn protocol\n * @dev Handle functions for maintaining the risk profiles and rating of liquidity/credit pools\n */\n address public riskOperator;\n\n /**\n * @notice Strategy operator of optyfi's earn protocol\n * @dev Handle functions related to strategies/vault strategies to be used\n */\n address public strategyOperator;\n\n /**\n * @notice Operator of optyfi's earn protocol\n */\n address public operator;\n\n /**\n * @notice Treasury of optyfi's earn protocol\n */\n address public treasury;\n\n /**\n * @notice Distributor for OPTY token\n */\n address public optyDistributor;\n\n /**\n * @notice Pending governance for optyfi's earn protocol\n */\n address public pendingGovernance;\n\n /**\n * @notice Active brains of Registry\n */\n address public registryImplementation;\n\n /**\n * @notice Pending brains of Registry\n */\n address public pendingRegistryImplementation;\n\n /**\n * @notice notify when transfer operation of financeOperator occurs\n * @param financeOperator address of Finance operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferFinanceOperator(address indexed financeOperator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of riskOperator occurs\n * @param riskOperator address of Risk operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferRiskOperator(address indexed riskOperator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of strategyOperator occurs\n * @param strategyOperator address of Strategy operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferStrategyOperator(address indexed strategyOperator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of operator occurs\n * @param operator address of Operator of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferOperator(address indexed operator, address indexed caller);\n\n /**\n * @notice notify when transfer operation of treasury occurs\n * @param treasury address of Treasury of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferTreasury(address indexed treasury, address indexed caller);\n\n /**\n * @notice notify when transfer operation of optyDistributor occurs\n * @param optyDistributor address of Opty distributor of optyfi's earn protocol\n * @param caller address of user who has called the respective function to trigger this event\n */\n event TransferOPTYDistributor(address indexed optyDistributor, address indexed caller);\n}\n\n/**\n * @title RegistryStorage Contract\n * @author Opty.fi\n * @dev Contract used to store registry's contract state variables and events\n */\ncontract RegistryStorage is RegistryAdminStorage {\n /**\n * @notice token address status which are approved or not\n */\n mapping(address => bool) public tokens;\n\n /**\n * @notice token data mapped to token/tokens address/addresses hash\n */\n mapping(bytes32 => DataTypes.Token) public tokensHashToTokens;\n\n /**\n * @notice liquidityPool address mapped to its struct having `pool`, `outputToken`, `isBorrow`\n */\n mapping(address => DataTypes.LiquidityPool) public liquidityPools;\n\n /**\n * @notice creaditPool address mapped to its struct having `pool`, `outputToken`, `isBorrow`\n */\n mapping(address => DataTypes.LiquidityPool) public creditPools;\n\n /**\n * @notice liquidityPool address mapped to its adapter\n */\n mapping(address => address) public liquidityPoolToAdapter;\n\n /**\n * @dev riskProfileCode mapped to its struct `RiskProfile`\n */\n mapping(uint256 => DataTypes.RiskProfile) internal riskProfiles;\n\n /**\n * @notice vault contract address mapped to VaultConfiguration\n */\n mapping(address => DataTypes.VaultConfiguration) public vaultToVaultConfiguration;\n\n /**\n * @dev Mapping of users that are allowed to interact with a given vault\n */\n mapping(address => mapping(address => bool)) public whitelistedUsers;\n\n /**\n * @notice withdrawal fee's range\n */\n DataTypes.WithdrawalFeeRange public withdrawalFeeRange;\n\n /**\n * @notice List of all the tokenHashes\n */\n bytes32[] public tokensHashIndexes;\n\n /**\n * @notice List of all the riskProfiles\n */\n uint256[] public riskProfilesArray;\n\n /**\n * @notice strategyProvider contract address\n */\n address public strategyProvider;\n\n /**\n * @notice investStrategyRegistry contract address\n */\n address public investStrategyRegistry;\n\n /**\n * @notice riskManager contract address\n */\n address public riskManager;\n\n /**\n * @notice harvestCodeProvider contract address\n */\n address public harvestCodeProvider;\n\n /**\n * @notice strategyManager contract address\n */\n address public strategyManager;\n\n /**\n * @notice opty contract address\n */\n address public opty;\n\n /**\n * @notice aprOracle contract address\n */\n address public aprOracle;\n\n /**\n * @notice optyStakingRateBalancer contract address\n */\n address public optyStakingRateBalancer;\n\n /**\n * @notice OD vaultBooster contract address\n */\n address public odefiVaultBooster;\n\n /**\n * @notice Emitted when token is approved or revoked\n * @param token Underlying Token's address which is approved or revoked\n * @param enabled Token is approved (true) or revoked (false)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogToken(address indexed token, bool indexed enabled, address indexed caller);\n\n /**\n * @notice Emitted when pool is approved or revoked as liquidity pool\n * @param pool Liquidity Pool's address which is approved or revoked\n * @param enabled Liquidity Pool is approved (true) or revoked (false)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogLiquidityPool(address indexed pool, bool indexed enabled, address indexed caller);\n\n /**\n * @notice Emitted when pool is approved or revoked as credit pool\n * @param pool Credit Pool's address which is approved or revoked\n * @param enabled Credit pool is approved (true) or revoked (false)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogCreditPool(address indexed pool, bool indexed enabled, address indexed caller);\n\n /**\n * @notice Emitted when liquidity pool is rated\n * @param pool Liquidity Pool's address which is rated\n * @param rate Rating of Liquidity Pool set\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRateLiquidityPool(address indexed pool, uint8 indexed rate, address indexed caller);\n\n /**\n * @notice Emitted when credit pool is rated\n * @param pool Credit Pool's address which is rated\n * @param rate Rating of Credit Pool set\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRateCreditPool(address indexed pool, uint8 indexed rate, address indexed caller);\n\n /**\n * @notice Emitted when liquidity pool pool is assigned to adapter\n * @param pool Liquidity Pool's address which is mapped to the adapter\n * @param adapter Address of the respective OptyFi's defi-adapter contract which is mapped to the Liquidity Pool\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogLiquidityPoolToAdapter(address indexed pool, address indexed adapter, address indexed caller);\n\n /**\n * @notice Emitted when tokens are assigned to tokensHash\n * @param tokensHash Hash of the token/list of tokens mapped to the provided token/list of tokens\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogTokensToTokensHash(bytes32 indexed tokensHash, address indexed caller);\n\n /**\n * @dev Emitted when Discontinue over vault is activated\n * @param vault OptyFi's Vault contract address which is discontinued from being operational\n * @param discontinued Discontinue status (true) of OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogDiscontinueVault(address indexed vault, bool indexed discontinued, address indexed caller);\n\n /**\n * @notice Emitted when Pause over vault is activated/deactivated\n * @param vault OptyFi's Vault contract address\n * @param unpaused Unpause status of OptyFi's Vault contract - false (if paused) and true (if unpaused)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogUnpauseVault(address indexed vault, bool indexed unpaused, address indexed caller);\n\n /**\n * @notice Emitted when setLimitStatus is called\n * @param vault OptyFi's Vault contract address\n * @param isLimitedState Limit state of OptyFi's Vault contract - false (if not limited) and true (if limited)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogLimitStateVault(address indexed vault, bool indexed isLimitedState, address indexed caller);\n\n /**\n * @notice Emitted when setLimitStatus is called\n * @param vault OptyFi's Vault contract address\n * @param allowWhitelistedState Whitelisted state of OptyFi's Vault contract - false (if not ) and true (if limited)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogAllowWhitelistedStateVault(\n address indexed vault,\n bool indexed allowWhitelistedState,\n address indexed caller\n );\n\n /**\n * @notice Emitted when setUserDepositCap is called\n * @param vault OptyFi's Vault contract address\n * @param userDepositCap Cap for user deposits in OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogUserDepositCapVault(address indexed vault, uint256 indexed userDepositCap, address indexed caller);\n\n /**\n * @notice Emitted when setMinimumDepositAmount is called\n * @param vault OptyFi's Vault contract address\n * @param minimumDepositAmount Minimum deposit in OptyFi's Vault contract - only for deposits (without rebalance)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMinimumDepositAmountVault(\n address indexed vault,\n uint256 indexed minimumDepositAmount,\n address indexed caller\n );\n\n /**\n * @notice Emitted when setTotalValueLockedLimitInUnderlying is called\n * @param vault OptyFi's Vault contract address\n * @param totalValueLockedLimitInUnderlying Maximum limit for total value locked of OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogVaultTotalValueLockedLimitInUnderlying(\n address indexed vault,\n uint256 indexed totalValueLockedLimitInUnderlying,\n address indexed caller\n );\n\n /**\n * @notice Emitted when setQueueCap is called\n * @param vault OptyFi's Vault contract address\n * @param queueCap Maximum queue length in OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogQueueCapVault(address indexed vault, uint256 indexed queueCap, address indexed caller);\n\n /**\n * @notice Emitted when RiskProfile is added\n * @param index Index of an array at which risk profile is added\n * @param exists Status of risk profile if it exists (true) or not (false)\n * @param canBorrow Borrow is allowed (true) or not (false) for the specified risk profile\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRiskProfile(uint256 indexed index, bool indexed exists, bool indexed canBorrow, address caller);\n\n /**\n * @notice Emitted when Risk profile is added/updated\n * @param index Index of an array at which risk profile is added or updated\n * @param lowerLimit Lower limit of the pool for the specified risk profile\n * @param upperLimit Upper limit of the pool for the specified risk profile\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogRPPoolRatings(uint256 indexed index, uint8 indexed lowerLimit, uint8 indexed upperLimit, address caller);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IModifiersController.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title Interface for ModifiersController Contract\n * @author Opty.fi\n * @notice Interface used to authorize operator and minter accounts\n */\ninterface IModifiersController {\n /**\n * @notice Transfers financeOperator to a new account (`_financeOperator`)\n * @param _financeOperator address of financeOperator's account\n */\n function setFinanceOperator(address _financeOperator) external;\n\n /**\n * @notice Transfers riskOperator to a new account (`_riskOperator`)\n * @param _riskOperator address of riskOperator's account\n */\n function setRiskOperator(address _riskOperator) external;\n\n /**\n * @notice Transfers strategyOperator to a new account (`_strategyOperator`)\n * @param _strategyOperator address of strategyOperator's account\n */\n function setStrategyOperator(address _strategyOperator) external;\n\n /**\n * @notice Transfers operator to a new account (`_operator`)\n * @param _operator address of Operator's account\n */\n function setOperator(address _operator) external;\n\n /**\n * @notice Transfers optyDistributor to a new account (`_optyDistributor`)\n * @param _optyDistributor address of optyDistributor contract\n */\n function setOPTYDistributor(address _optyDistributor) external;\n}\n" + }, + "contracts/mocks/contracts/TestVaultNewImplementation.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { VaultStorage } from \"../../protocol/tokenization/VaultStorage.sol\";\nimport { Modifiers } from \"../../protocol/earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { VersionedInitializable } from \"../../dependencies/openzeppelin/VersionedInitializable.sol\";\nimport { TestStorage } from \"../../protocol/earn-protocol-configuration/contracts/mocks/contracts/TestStorage.sol\";\nimport { IncentivisedERC20 } from \"../../protocol/tokenization/IncentivisedERC20.sol\";\nimport { IRegistry } from \"../../protocol/earn-protocol-configuration/contracts/interfaces/opty/IRegistry.sol\";\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\n\ncontract TestVaultNewImplementation is\n VersionedInitializable,\n IncentivisedERC20,\n Modifiers,\n ReentrancyGuard,\n VaultStorage,\n TestStorage\n{\n /**\n * @dev The version of the Vault business logic\n */\n uint256 public constant opTOKEN_REVISION = 0x3;\n\n /* solhint-disable no-empty-blocks */\n constructor(\n address _registry,\n string memory _name,\n string memory _symbol,\n string memory _riskProfile\n )\n public\n IncentivisedERC20(\n string(abi.encodePacked(\"op \", _name, \" \", _riskProfile, \" vault\")),\n string(abi.encodePacked(\"op\", _symbol, _riskProfile, \"Vault\"))\n )\n Modifiers(_registry)\n {}\n\n /**\n * @dev Initialize the vault\n * @param _registry the address of registry for helping get the protocol configuration\n */\n function initialize(address _registry) external virtual initializer {\n registryContract = IRegistry(_registry);\n }\n\n function isNewContract() external pure returns (bool) {\n return isNewVariable;\n }\n\n function getRevision() internal pure virtual override returns (uint256) {\n return opTOKEN_REVISION;\n }\n}\n" + }, + "contracts/protocol/tokenization/VaultStorage.sol": { + "content": "// solhint-disable max-states-count\n// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n// library\nimport { DataTypes } from \"../../protocol/earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\n\n/**\n * @title Vault state that can change\n * @author opty.fi\n * @dev The storage contract for opty.fi's interest bearing vault token\n */\n\ncontract VaultStorage {\n /**\n * @dev A list to maintain sequence of unprocessed deposits\n */\n DataTypes.UserDepositOperation[] public queue;\n\n /**\n * @dev Mapping of user account who has not received shares against deposited amount\n */\n mapping(address => uint256) public pendingDeposits;\n\n /**\n * @dev Mapping of user account against total deposited amount\n */\n mapping(address => uint256) public totalDeposits;\n\n /**\n * @dev Map the underlying token in vault to the current block for emergency brakes\n */\n mapping(uint256 => DataTypes.BlockVaultValue[]) public blockToBlockVaultValues;\n\n /**\n * @dev Current vault invest strategy\n */\n bytes32 public investStrategyHash;\n\n /**\n * @dev Maximum amount in underlying token allowed to be deposited by user\n */\n uint256 public userDepositCapUT;\n\n /**\n * @dev Minimum deposit value in underlying token required\n */\n uint256 public minimumDepositValueUT;\n\n /**\n * @notice Fee and vaultvalue jump config params of the vault\n * @dev bit 0-15 deposit fee in underlying token without decimals\n * bit 16-31 deposit fee in basis points\n * bit 32-47 withdrawal fee in underlying token without decimals\n * bit 48-63 withdrawal fee in basis points\n * bit 64-79 max vault value jump allowed in basis points (standard deviation allowed for vault value)\n * bit 80-239 vault fee collection address\n * bit 240-247 risk profile code\n * bit 248 emergency shutdown flag\n * bit 249 pause flag (deposit/withdraw is pause when bit is unset, unpause otherwise)\n * bit 250 white list state flag\n */\n uint256 public vaultConfiguration;\n\n /**\n * @dev store the underlying token contract address (for example DAI)\n */\n address public underlyingToken;\n\n /**\n * @notice accounts allowed to interact with vault if whitelisted\n * @dev merkle root hash of whitelisted accounts\n */\n bytes32 public whitelistedAccountsRoot;\n\n /**\n * @dev Maximum TVL in underlying token allowed for the vault\n */\n uint256 public totalValueLockedLimitUT;\n}\n\ncontract VaultStorageV2 is VaultStorage {\n /**\n * @notice smart contracts allowed to interact with vault if whitelisted\n * @dev merkle root hash of the whitelisted smart contract codes\n */\n bytes32 public whitelistedCodesRoot;\n\n /**\n * @notice underlying tokens's hash\n * @dev keccak256 hash of the underlying tokens and chain id\n */\n bytes32 public underlyingTokensHash;\n\n /**@notice current strategy metadata*/\n DataTypes.StrategyStep[] public investStrategySteps;\n\n /**@dev cache strategy metadata*/\n DataTypes.StrategyStep[] internal _cacheNextInvestStrategySteps;\n}\n" + }, + "contracts/dependencies/openzeppelin/VersionedInitializable.sol": { + "content": "// solhint-disable\n// SPDX-License-Identifier: agpl-3.0\npragma solidity ^0.6.12;\n\n/**\n * @title VersionedInitializable\n *\n * @dev Helper contract to implement initializer functions. To use it, replace\n * the constructor with a function that has the `initializer` modifier.\n * WARNING: Unlike constructors, initializer functions must be manually\n * invoked. This applies both to deploying an Initializable contract, as well\n * as extending an Initializable contract via inheritance.\n * WARNING: When used with inheritance, manual care must be taken to not invoke\n * a parent initializer twice, or ensure that all initializers are idempotent,\n * because this is not dealt with automatically as with constructors.\n *\n * @author Aave, inspired by the OpenZeppelin Initializable contract\n */\nabstract contract VersionedInitializable {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n uint256 private lastInitializedRevision = 0;\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 use in the initializer function of a contract.\n */\n modifier initializer() {\n uint256 revision = getRevision();\n require(\n initializing || isConstructor() || revision > lastInitializedRevision,\n \"Contract instance has already been initialized\"\n );\n\n bool isTopLevelCall = !initializing;\n if (isTopLevelCall) {\n initializing = true;\n lastInitializedRevision = revision;\n }\n\n _;\n\n if (isTopLevelCall) {\n initializing = false;\n }\n }\n\n /**\n * @dev returns the revision number of the contract\n * Needs to be defined in the inherited class as a constant.\n **/\n function getRevision() internal pure virtual returns (uint256);\n\n /**\n * @dev Returns true if and only if the function is running in the constructor\n **/\n function isConstructor() private view returns (bool) {\n // extcodesize checks the size of the code stored in an address, and\n // address returns the current address. Since the code is still not\n // deployed when running a constructor, any checks on its code size will\n // yield zero, making it an effective way to detect if a contract is\n // under construction or not.\n uint256 cs;\n //solium-disable-next-line\n assembly {\n cs := extcodesize(address())\n }\n return cs == 0;\n }\n\n // Reserved storage space to allow for layout changes in the future.\n uint256[50] private ______gap;\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/mocks/contracts/TestStorage.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\n/**\n * @title NewImplementationStorage Contract\n * @author Opty.fi\n * @notice Contract to store the state variables of the New Implementation Contract\n */\ncontract TestStorage {\n bool public constant isNewVariable = true;\n}\n" + }, + "contracts/protocol/tokenization/IncentivisedERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { Context } from \"@openzeppelin/contracts/utils/Context.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.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 guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 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 */\nabstract contract IncentivisedERC20 is Context, IERC20 {\n using SafeMath for uint256;\n\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 uint8 private _decimals;\n\n /**\n * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n * a default value of 18.\n *\n * To select a different value for {decimals}, use {_setupDecimals}.\n *\n * All three of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) public {\n _name = name_;\n _symbol = symbol_;\n _decimals = 18;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual 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 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 {_setupDecimals} is\n * called.\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 returns (uint8) {\n return _decimals;\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 * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, 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 * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), 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 * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n _approve(\n sender,\n _msgSender(),\n _allowances[sender][_msgSender()].sub(amount, \"ERC20: transfer amount exceeds allowance\")\n );\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 _approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(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 _approve(\n _msgSender(),\n spender,\n _allowances[_msgSender()][spender].sub(subtractedValue, \"ERC20: decreased allowance below zero\")\n );\n return true;\n }\n\n /**\n * @dev Moves tokens `amount` from `sender` to `recipient`.\n *\n * This is 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 * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n _balances[sender] = _balances[sender].sub(amount, \"ERC20: transfer amount exceeds balance\");\n _balances[recipient] = _balances[recipient].add(amount);\n emit Transfer(sender, recipient, 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 * - `to` 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 = _totalSupply.add(amount);\n _balances[account] = _balances[account].add(amount);\n emit Transfer(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 _balances[account] = _balances[account].sub(amount, \"ERC20: burn amount exceeds balance\");\n _totalSupply = _totalSupply.sub(amount);\n emit Transfer(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 function _setName(string memory newName) internal {\n _name = newName;\n }\n\n function _setSymbol(string memory newSymbol) internal {\n _symbol = newSymbol;\n }\n\n function _setDecimals(uint8 newDecimals) internal {\n _decimals = newDecimals;\n }\n\n /* solhint-disable no-empty-blocks */\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 to 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 /* solhint-disable no-empty-blocks */\n}\n" + }, + "@openzeppelin/contracts/utils/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor () internal {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and make it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n // On the first call to nonReentrant, _notEntered will be true\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n\n _;\n\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n}\n" + }, + "contracts/protocol/tokenization/Vault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// helper contracts\nimport { MultiCall } from \"../../utils/MultiCall.sol\";\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/utils/ReentrancyGuard.sol\";\nimport { VersionedInitializable } from \"../../dependencies/openzeppelin/VersionedInitializable.sol\";\nimport { IncentivisedERC20 } from \"./IncentivisedERC20.sol\";\nimport { Modifiers } from \"../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { VaultStorageV2 } from \"./VaultStorage.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\n\n// libraries\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\nimport { DataTypes } from \"../earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\nimport { Constants } from \"../../utils/Constants.sol\";\nimport { Errors } from \"../../utils/Errors.sol\";\nimport { StrategyManager } from \"../lib/StrategyManager.sol\";\nimport { MerkleProof } from \"@openzeppelin/contracts/cryptography/MerkleProof.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IVault } from \"../../interfaces/opty/IVault.sol\";\nimport { IRegistry } from \"../earn-protocol-configuration/contracts/interfaces/opty/IRegistry.sol\";\nimport { IRiskManager } from \"../earn-protocol-configuration/contracts/interfaces/opty/IRiskManager.sol\";\n\n/**\n * @title Vault contract inspired by AAVE V2's AToken.sol\n * @author opty.fi\n * @notice Implementation of the risk specific interest bearing vault\n */\n\ncontract Vault is\n VersionedInitializable,\n IVault,\n IncentivisedERC20,\n MultiCall,\n Modifiers,\n ReentrancyGuard,\n VaultStorageV2\n{\n using SafeERC20 for IERC20;\n using Address for address;\n using StrategyManager for DataTypes.StrategyStep[];\n\n /**\n * @dev The version of the Vault business logic\n */\n uint256 public constant opTOKEN_REVISION = 0x3;\n\n //===Constructor===//\n\n /* solhint-disable no-empty-blocks */\n constructor(\n address _registry,\n string memory _name,\n string memory _symbol,\n string memory _riskProfileName,\n string memory _riskProfileSymbol\n )\n public\n IncentivisedERC20(\n string(abi.encodePacked(\"op \", _name, \" \", _riskProfileName)),\n string(abi.encodePacked(\"op\", _symbol, _riskProfileSymbol))\n )\n Modifiers(_registry)\n {}\n\n /* solhint-enable no-empty-blocks */\n\n //===External functions===//\n\n /**\n * @dev Initialize the vault\n * @param _registry the address of registry for helping get the protocol configuration\n * @param _underlyingTokensHash The keccak256 hash of the tokens and chain id\n * @param _name The name of the underlying asset\n * @param _symbol The symbol of the underlying asset\n * @param _riskProfileCode Risk profile code of this vault\n */\n function initialize(\n address _registry,\n bytes32 _underlyingTokensHash,\n string memory _name,\n string memory _symbol,\n uint256 _riskProfileCode\n ) external virtual initializer {\n require(bytes(_name).length > 0, Errors.EMPTY_STRING);\n require(bytes(_symbol).length > 0, Errors.EMPTY_STRING);\n registryContract = IRegistry(_registry);\n DataTypes.RiskProfile memory _riskProfile = registryContract.getRiskProfile(_riskProfileCode);\n _setRiskProfileCode(_riskProfileCode, _riskProfile.exists);\n _setUnderlyingTokensHash(_underlyingTokensHash);\n _setName(string(abi.encodePacked(\"op \", _name, \" \", _riskProfile.name)));\n _setSymbol(string(abi.encodePacked(\"op\", _symbol, _riskProfile.symbol)));\n _setDecimals(IncentivisedERC20(underlyingToken).decimals());\n }\n\n /**\n * @inheritdoc IVault\n */\n function setRiskProfileCode(uint256 _riskProfileCode) external override onlyGovernance {\n _setRiskProfileCode(_riskProfileCode, registryContract.getRiskProfile(_riskProfileCode).exists);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setUnderlyingTokensHash(bytes32 _underlyingTokensHash) external override onlyOperator {\n _setUnderlyingTokensHash(_underlyingTokensHash);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setValueControlParams(\n uint256 _userDepositCapUT,\n uint256 _minimumDepositValueUT,\n uint256 _totalValueLockedLimitUT\n ) external override onlyFinanceOperator {\n _setUserDepositCapUT(_userDepositCapUT);\n _setMinimumDepositValueUT(_minimumDepositValueUT);\n _setTotalValueLockedLimitUT(_totalValueLockedLimitUT);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setVaultConfiguration(uint256 _vaultConfiguration) external override onlyGovernance {\n vaultConfiguration = _vaultConfiguration;\n }\n\n /**\n * @inheritdoc IVault\n */\n function setUserDepositCapUT(uint256 _userDepositCapUT) external override onlyFinanceOperator {\n _setUserDepositCapUT(_userDepositCapUT);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setMinimumDepositValueUT(uint256 _minimumDepositValueUT) external override onlyFinanceOperator {\n _setMinimumDepositValueUT(_minimumDepositValueUT);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setTotalValueLockedLimitUT(uint256 _totalValueLockedLimitUT) external override onlyFinanceOperator {\n _setTotalValueLockedLimitUT(_totalValueLockedLimitUT);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setWhitelistedAccountsRoot(bytes32 _whitelistedAccountsRoot) external override onlyGovernance {\n whitelistedAccountsRoot = _whitelistedAccountsRoot;\n }\n\n /**\n * @inheritdoc IVault\n */\n function setWhitelistedCodesRoot(bytes32 _whitelistedCodesRoot) external override onlyGovernance {\n whitelistedCodesRoot = _whitelistedCodesRoot;\n }\n\n /**\n * @inheritdoc IVault\n */\n function setEmergencyShutdown(bool _active) external override onlyGovernance {\n vaultConfiguration = vaultConfiguration & 0xFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;\n if (_active) {\n vaultConfiguration =\n vaultConfiguration |\n 0x0100000000000000000000000000000000000000000000000000000000000000;\n if (investStrategyHash != Constants.ZERO_BYTES32) {\n _vaultWithdrawAllFromStrategy(investStrategySteps);\n investStrategyHash = Constants.ZERO_BYTES32;\n delete investStrategySteps;\n }\n }\n emit LogEmergencyShutdown((vaultConfiguration & (1 << 248)) != 0, msg.sender);\n }\n\n /**\n * @inheritdoc IVault\n */\n function setUnpaused(bool _unpaused) external override onlyGovernance {\n vaultConfiguration = (vaultConfiguration & 0xFDFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n if (!_unpaused) {\n if (investStrategyHash != Constants.ZERO_BYTES32) {\n _vaultWithdrawAllFromStrategy(investStrategySteps);\n investStrategyHash = Constants.ZERO_BYTES32;\n delete investStrategySteps;\n }\n } else {\n vaultConfiguration =\n 0x0200000000000000000000000000000000000000000000000000000000000000 |\n vaultConfiguration;\n }\n emit LogUnpause((vaultConfiguration & (1 << 249)) != 0, msg.sender);\n }\n\n /**\n * @inheritdoc IVault\n */\n function rebalance() external override {\n (bool _vaultDepositPermitted, string memory _vaultDepositPermittedReason) = vaultDepositPermitted();\n require(_vaultDepositPermitted, _vaultDepositPermittedReason);\n (bool _vaultWithdrawPermitted, string memory _vaultWithdrawPermittedReason) = vaultWithdrawPermitted();\n require(_vaultWithdrawPermitted, _vaultWithdrawPermittedReason);\n _setCacheNextInvestStrategySteps(getNextBestInvestStrategy());\n bytes32 _nextBestInvestStrategyHash = computeInvestStrategyHash(_cacheNextInvestStrategySteps);\n if (_nextBestInvestStrategyHash != investStrategyHash) {\n if (investStrategyHash != Constants.ZERO_BYTES32) {\n _vaultWithdrawAllFromStrategy(investStrategySteps);\n }\n // _setInvestStrategySteps\n delete investStrategySteps;\n for (uint256 _i; _i < _cacheNextInvestStrategySteps.length; _i++) {\n investStrategySteps.push(_cacheNextInvestStrategySteps[_i]);\n }\n investStrategyHash = _nextBestInvestStrategyHash;\n }\n uint256 _balanceUT = balanceUT();\n if (investStrategyHash != Constants.ZERO_BYTES32 && _balanceUT > 0) {\n _vaultDepositToStrategy(investStrategySteps, _balanceUT);\n }\n }\n\n /**\n * @inheritdoc IVault\n */\n function userDepositVault(\n uint256 _userDepositUT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external override nonReentrant {\n {\n (bool _vaultDepositPermitted, string memory _vaultDepositPermittedReason) = vaultDepositPermitted();\n require(_vaultDepositPermitted, _vaultDepositPermittedReason);\n }\n _emergencyBrake(_oraStratValueUT());\n // check vault + strategy balance (in UT) before user token transfer\n uint256 _oraVaultAndStratValuePreDepositUT = _oraVaultAndStratValueUT();\n // check vault balance (in UT) before user token transfer\n uint256 _vaultValuePreDepositUT = balanceUT();\n // receive user deposit\n IERC20(underlyingToken).safeTransferFrom(msg.sender, address(this), _userDepositUT);\n // check balance after user token transfer\n uint256 _vaultValuePostDepositUT = balanceUT();\n // only count the actual deposited tokens received into vault\n uint256 _actualDepositAmountUT = _vaultValuePostDepositUT.sub(_vaultValuePreDepositUT);\n // remove deposit fees (if any) but only if deposit is accepted\n // if deposit is not accepted, the entire transaction should revert\n uint256 _depositFeeUT = calcDepositFeeUT(_actualDepositAmountUT);\n uint256 _netUserDepositUT = _actualDepositAmountUT.sub(_depositFeeUT);\n _checkUserDeposit(msg.sender, false, _netUserDepositUT, _depositFeeUT, _accountsProof, _codesProof);\n // add net deposit amount to user's total deposit\n totalDeposits[msg.sender] = totalDeposits[msg.sender].add(_netUserDepositUT);\n // transfer deposit fee to vaultFeeCollector\n if (_depositFeeUT > 0) {\n IERC20(underlyingToken).safeTransfer(address(uint160(vaultConfiguration >> 80)), _depositFeeUT);\n }\n // mint vault tokens\n // if _oraVaultAndStratValuePreDepositUT == 0 or totalSupply == 0, mint vault tokens 1:1 for underlying tokens\n // else, mint vault tokens at constant pre deposit price\n // e.g. if pre deposit price > 1, minted vault tokens < deposited underlying tokens\n // if pre deposit price < 1, minted vault tokens > deposited underlying tokens\n if (_oraVaultAndStratValuePreDepositUT == 0 || totalSupply() == 0) {\n _mint(msg.sender, _netUserDepositUT);\n } else {\n _mint(msg.sender, (_netUserDepositUT.mul(totalSupply())).div(_oraVaultAndStratValuePreDepositUT));\n }\n }\n\n /**\n * @inheritdoc IVault\n */\n function userWithdrawVault(\n uint256 _userWithdrawVT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external override nonReentrant {\n {\n (bool _vaultWithdrawPermitted, string memory _vaultWithdrawPermittedReason) = vaultWithdrawPermitted();\n require(_vaultWithdrawPermitted, _vaultWithdrawPermittedReason);\n }\n _emergencyBrake(_oraStratValueUT());\n _checkUserWithdraw(msg.sender, _userWithdrawVT, _accountsProof, _codesProof);\n // burning should occur at pre userwithdraw price UNLESS there is slippage\n // if there is slippage, the withdrawing user should absorb that cost (see below)\n // i.e. get less underlying tokens than calculated by pre userwithdraw price\n uint256 _oraUserWithdrawUT = _userWithdrawVT.mul(_oraVaultAndStratValueUT()).div(totalSupply());\n _burn(msg.sender, _userWithdrawVT);\n\n uint256 _vaultValuePreStratWithdrawUT = balanceUT();\n\n // if vault does not have sufficient UT, we need to withdraw from strategy\n if (_vaultValuePreStratWithdrawUT < _oraUserWithdrawUT) {\n // withdraw UT shortage from strategy\n uint256 _expectedStratWithdrawUT = _oraUserWithdrawUT.sub(_vaultValuePreStratWithdrawUT);\n\n uint256 _oraAmountLP =\n investStrategySteps.getOraSomeValueLP(\n address(registryContract),\n underlyingToken,\n _expectedStratWithdrawUT\n );\n\n _vaultWithdrawSomeFromStrategy(investStrategySteps, _oraAmountLP);\n\n // Identify Slippage\n // UT requested from strategy withdraw = _expectedStratWithdrawUT\n // UT actually received from strategy withdraw\n // = _receivedStratWithdrawUT\n // = _vaultValuePostStratWithdrawUT.sub(_vaultValuePreStratWithdrawUT)\n // slippage = _expectedStratWithdrawUT - _receivedStratWithdrawUT\n uint256 _vaultValuePostStratWithdrawUT = balanceUT();\n uint256 _receivedStratWithdrawUT = _vaultValuePostStratWithdrawUT.sub(_vaultValuePreStratWithdrawUT); // 440\n\n // If slippage occurs, reduce _oraUserWithdrawUT by slippage amount\n if (_receivedStratWithdrawUT < _expectedStratWithdrawUT) {\n _oraUserWithdrawUT = _oraUserWithdrawUT.sub(_expectedStratWithdrawUT.sub(_receivedStratWithdrawUT));\n }\n }\n uint256 _withdrawFeeUT = calcWithdrawalFeeUT(_oraUserWithdrawUT);\n // transfer withdraw fee to vaultFeeCollector\n if (_withdrawFeeUT > 0) {\n IERC20(underlyingToken).safeTransfer(address(uint160(vaultConfiguration >> 80)), _withdrawFeeUT);\n }\n IERC20(underlyingToken).safeTransfer(msg.sender, _oraUserWithdrawUT.sub(_withdrawFeeUT));\n }\n\n /**\n * @inheritdoc IVault\n */\n function vaultDepositAllToStrategy() external override {\n (bool _vaultDepositPermitted, string memory _vaultDepositPermittedReason) = vaultDepositPermitted();\n require(_vaultDepositPermitted, _vaultDepositPermittedReason);\n if (investStrategyHash != Constants.ZERO_BYTES32) {\n _vaultDepositToStrategy(investStrategySteps, balanceUT());\n }\n }\n\n /**\n * @inheritdoc IVault\n */\n function adminCall(bytes[] memory _codes) external override onlyOperator {\n executeCodes(_codes, Errors.ADMIN_CALL);\n }\n\n //===Public view functions===//\n\n /**\n * @inheritdoc IVault\n */\n function balanceUT() public view override returns (uint256) {\n return IERC20(underlyingToken).balanceOf(address(this));\n }\n\n /**\n * @inheritdoc IVault\n */\n function isMaxVaultValueJumpAllowed(uint256 _diff, uint256 _currentVaultValue) public view override returns (bool) {\n return (_diff.mul(10000)).div(_currentVaultValue) < ((vaultConfiguration >> 64) & 0xFFFF);\n }\n\n /**\n * @inheritdoc IVault\n */\n function getPricePerFullShare() public view override returns (uint256) {\n if (totalSupply() != 0) {\n return _oraVaultAndStratValueUT().mul(Constants.WEI_DECIMAL).div(totalSupply());\n } else {\n return uint256(0);\n }\n }\n\n /**\n * @inheritdoc IVault\n */\n function userDepositPermitted(\n address _user,\n bool _addUserDepositUT,\n uint256 _userDepositUTWithDeductions,\n uint256 _deductions,\n bytes32[] memory _accountsProof,\n bytes32[] memory _codesProof\n ) public view override returns (bool, string memory) {\n if ((vaultConfiguration & (1 << 250)) != 0 && !_verifyWhitelistedAccount(_accountLeaf(_user), _accountsProof)) {\n return (false, Errors.EOA_NOT_WHITELISTED);\n }\n //solhint-disable-next-line avoid-tx-origin\n if (_user != tx.origin && !_noGreyList(_user, _accountsProof, _codesProof)) {\n return (false, Errors.CA_NOT_WHITELISTED);\n }\n if (_userDepositUTWithDeductions < minimumDepositValueUT) {\n return (false, Errors.MINIMUM_USER_DEPOSIT_VALUE_UT);\n }\n uint256 _oraVaultAndStratValueUT = _oraVaultAndStratValueUT();\n if (!_addUserDepositUT && _oraVaultAndStratValueUT.sub(_deductions) > totalValueLockedLimitUT) {\n return (false, Errors.TOTAL_VALUE_LOCKED_LIMIT_UT);\n } else if (_oraVaultAndStratValueUT.add(_userDepositUTWithDeductions) > totalValueLockedLimitUT) {\n return (false, Errors.TOTAL_VALUE_LOCKED_LIMIT_UT);\n }\n if (totalDeposits[_user].add(_userDepositUTWithDeductions) > userDepositCapUT) {\n return (false, Errors.USER_DEPOSIT_CAP_UT);\n }\n return (true, \"\");\n }\n\n /**\n * @inheritdoc IVault\n */\n function vaultDepositPermitted() public view override returns (bool, string memory) {\n if (!((vaultConfiguration & (1 << 249)) != 0)) {\n return (false, Errors.VAULT_PAUSED);\n }\n if ((vaultConfiguration & (1 << 248)) != 0) {\n return (false, Errors.VAULT_EMERGENCY_SHUTDOWN);\n }\n return (true, \"\");\n }\n\n /**\n * @inheritdoc IVault\n */\n function userWithdrawPermitted(\n address _user,\n uint256 _userWithdrawVT,\n bytes32[] memory _accountsProof,\n bytes32[] memory _codesProof\n ) public view override returns (bool, string memory) {\n if ((vaultConfiguration & (1 << 250)) != 0 && !_verifyWhitelistedAccount(_accountLeaf(_user), _accountsProof)) {\n return (false, Errors.EOA_NOT_WHITELISTED);\n }\n //solhint-disable-next-line avoid-tx-origin\n if (_user != tx.origin && !_noGreyList(_user, _accountsProof, _codesProof)) {\n return (false, Errors.CA_NOT_WHITELISTED);\n }\n // require: 0 < withdrawal amount in vault tokens < user's vault token balance\n if (!((vaultConfiguration & (1 << 249)) != 0)) {\n return (false, Errors.VAULT_PAUSED);\n }\n if (!(_userWithdrawVT > 0 && _userWithdrawVT <= balanceOf(_user))) {\n return (false, Errors.USER_WITHDRAW_INSUFFICIENT_VT);\n }\n return (true, \"\");\n }\n\n /**\n * @inheritdoc IVault\n */\n function vaultWithdrawPermitted() public view override returns (bool, string memory) {\n if (!((vaultConfiguration & (1 << 249)) != 0)) {\n return (false, Errors.VAULT_PAUSED);\n }\n return (true, \"\");\n }\n\n /**\n * @inheritdoc IVault\n */\n function calcDepositFeeUT(uint256 _userDepositUT) public view override returns (uint256) {\n return\n ((_userDepositUT.mul((vaultConfiguration >> 16) & 0xFFFF)).div(10000)).add(\n (vaultConfiguration & 0xFFFF) * 10**uint256(decimals())\n );\n }\n\n /**\n * @inheritdoc IVault\n */\n function calcWithdrawalFeeUT(uint256 _userWithdrawUT) public view override returns (uint256) {\n return\n ((_userWithdrawUT.mul((vaultConfiguration >> 48) & 0xFFFF)).div(10000)).add(\n ((vaultConfiguration >> 32) & 0xFFFF) * 10**uint256(decimals())\n );\n }\n\n /**\n * @inheritdoc IVault\n */\n function getNextBestInvestStrategy() public view override returns (DataTypes.StrategyStep[] memory) {\n return\n IRiskManager(registryContract.getRiskManager()).getBestStrategy(\n uint256(uint8(vaultConfiguration >> 240)),\n underlyingTokensHash\n );\n }\n\n /**\n * @inheritdoc IVault\n */\n function getLastStrategyStepBalanceLP(DataTypes.StrategyStep[] memory _investStrategySteps)\n public\n view\n override\n returns (uint256)\n {\n return\n _investStrategySteps.getLastStrategyStepBalanceLP(\n address(registryContract),\n payable(address(this)),\n underlyingToken\n );\n }\n\n /**\n * @inheritdoc IVault\n */\n function getInvestStrategySteps() public view override returns (DataTypes.StrategyStep[] memory) {\n return investStrategySteps;\n }\n\n /**\n * @dev function to compute the keccak256 hash of the strategy steps\n * @param _investStrategySteps metadata for invest strategy\n * @return keccak256 hash of the invest strategy and underlying tokens hash\n */\n function computeInvestStrategyHash(DataTypes.StrategyStep[] memory _investStrategySteps)\n public\n view\n returns (bytes32)\n {\n if (_investStrategySteps.length > 0) {\n bytes32[] memory hashes = new bytes32[](_investStrategySteps.length);\n for (uint256 _i; _i < _investStrategySteps.length; _i++) {\n hashes[_i] = keccak256(\n abi.encodePacked(\n _investStrategySteps[_i].pool,\n _investStrategySteps[_i].outputToken,\n _investStrategySteps[_i].isBorrow\n )\n );\n }\n return keccak256(abi.encodePacked(underlyingTokensHash, hashes));\n }\n return Constants.ZERO_BYTES32;\n }\n\n //===Internal functions===//\n\n /**\n * @dev Internal function to deposit some balance of underlying token from current strategy\n * @param _investStrategySteps array of strategy step tuple\n * @param _depositValueUT amount in underlying token\n */\n function _vaultDepositToStrategy(DataTypes.StrategyStep[] memory _investStrategySteps, uint256 _depositValueUT)\n internal\n {\n uint256 _internalTransactionCount =\n _investStrategySteps.getDepositInternalTransactionCount(address(registryContract));\n for (uint256 _i; _i < _internalTransactionCount; _i++) {\n executeCodes(\n (\n _investStrategySteps.getPoolDepositCodes(\n DataTypes.StrategyConfigurationParams({\n registryContract: address(registryContract),\n vault: payable(address(this)),\n underlyingToken: underlyingToken,\n initialStepInputAmount: _depositValueUT,\n internalTransactionIndex: _i,\n internalTransactionCount: _internalTransactionCount\n })\n )\n ),\n Errors.VAULT_DEPOSIT\n );\n }\n }\n\n /**\n * @dev Internal function to withdraw all investments from current strategy\n * @param _investStrategySteps array of strategy step tuple\n */\n function _vaultWithdrawAllFromStrategy(DataTypes.StrategyStep[] memory _investStrategySteps) internal {\n _vaultWithdrawSomeFromStrategy(_investStrategySteps, getLastStrategyStepBalanceLP(_investStrategySteps));\n }\n\n /**\n * @dev Internal function to withdraw some investments from current strategy\n * @param _investStrategySteps array of strategy step tuple\n * @param _withdrawAmountLP amount in lpToken\n */\n function _vaultWithdrawSomeFromStrategy(\n DataTypes.StrategyStep[] memory _investStrategySteps,\n uint256 _withdrawAmountLP\n ) internal {\n uint256 _internalWithdrawTransactionCount = _investStrategySteps.length;\n for (uint256 _i; _i < _internalWithdrawTransactionCount; _i++) {\n executeCodes(\n _investStrategySteps.getPoolWithdrawCodes(\n DataTypes.StrategyConfigurationParams({\n registryContract: address(registryContract),\n vault: payable(address(this)),\n underlyingToken: underlyingToken,\n initialStepInputAmount: _withdrawAmountLP,\n internalTransactionIndex: _internalWithdrawTransactionCount - 1 - _i,\n internalTransactionCount: _internalWithdrawTransactionCount\n })\n ),\n Errors.VAULT_WITHDRAW\n );\n }\n }\n\n /**\n * @inheritdoc IncentivisedERC20\n */\n function _beforeTokenTransfer(\n address,\n address _to,\n uint256\n ) internal override {\n require(_to != address(this), Errors.TRANSFER_TO_THIS_CONTRACT);\n }\n\n /**\n * @dev Internal function to set the maximum amount in underlying token\n * that a user could deposit in entire life cycle of this vault\n * @param _userDepositCapUT maximum amount in underlying allowed to be deposited by user\n */\n function _setUserDepositCapUT(uint256 _userDepositCapUT) internal {\n userDepositCapUT = _userDepositCapUT;\n emit LogUserDepositCapUT(userDepositCapUT, msg.sender);\n }\n\n /**\n * @dev Internal function to set minimum amount in underlying token required\n * to be deposited by the user\n * @param _minimumDepositValueUT minimum deposit value in underlying token required\n */\n function _setMinimumDepositValueUT(uint256 _minimumDepositValueUT) internal {\n minimumDepositValueUT = _minimumDepositValueUT;\n emit LogMinimumDepositValueUT(minimumDepositValueUT, msg.sender);\n }\n\n /**\n * @dev Internal function to set the total value locked limit in underlying token\n * @param _totalValueLockedLimitUT maximum TVL in underlying allowed for the vault\n */\n function _setTotalValueLockedLimitUT(uint256 _totalValueLockedLimitUT) internal {\n totalValueLockedLimitUT = _totalValueLockedLimitUT;\n emit LogTotalValueLockedLimitUT(totalValueLockedLimitUT, msg.sender);\n }\n\n /**\n * @dev Internal function for caching the next invest strategy metadata\n * @param _investStrategySteps list strategy steps\n */\n function _setCacheNextInvestStrategySteps(DataTypes.StrategyStep[] memory _investStrategySteps) internal {\n delete _cacheNextInvestStrategySteps;\n for (uint256 _i; _i < _investStrategySteps.length; _i++) {\n _cacheNextInvestStrategySteps.push(_investStrategySteps[_i]);\n }\n }\n\n /**\n * @dev Internal function to save risk profile code\n * @param _riskProfileCode risk profile code\n * @param _exists true if risk profile exists\n */\n function _setRiskProfileCode(uint256 _riskProfileCode, bool _exists) internal {\n require(_exists, Errors.RISK_PROFILE_EXISTS);\n vaultConfiguration =\n (_riskProfileCode << 240) |\n (vaultConfiguration & 0xFF00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);\n }\n\n /**\n * @dev Internal function to save underlying tokens hash\n * @param _underlyingTokensHash keccak256 hash of underlying token address and chain id\n */\n function _setUnderlyingTokensHash(bytes32 _underlyingTokensHash) internal {\n address[] memory _tokens = registryContract.getTokensHashToTokenList(_underlyingTokensHash);\n require(_tokens.length == 1, Errors.UNDERLYING_TOKENS_HASH_EXISTS);\n require(registryContract.isApprovedToken(_tokens[0]), Errors.UNDERLYING_TOKEN_APPROVED);\n underlyingTokensHash = _underlyingTokensHash;\n underlyingToken = _tokens[0];\n }\n\n //===Internal view functions===//\n\n /**\n * @dev Computes the vault value in underlying token that includes balance of underlying token\n * in vault and that of investment made in the strategy\n * @return amount in underlying token\n */\n function _oraVaultAndStratValueUT() internal view returns (uint256) {\n return _oraStratValueUT().add(balanceUT());\n }\n\n /**\n * @dev Computes the amount in underlying token for the investment made in strategy\n * @return amount in underlying token\n */\n function _oraStratValueUT() internal view returns (uint256) {\n // totaldebt\n return\n investStrategyHash != Constants.ZERO_BYTES32\n ? investStrategySteps.getOraValueUT(address(registryContract), payable(address(this)), underlyingToken)\n : 0;\n }\n\n /**\n * @dev Internal function to compute the hash of the smart contract code\n * @param _account account address\n * @return _hash bytes32 hash of the smart contract code\n */\n function _getContractHash(address _account) internal view returns (bytes32 _hash) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n _hash := extcodehash(_account)\n }\n }\n\n /**\n * @dev Internal function to compute whether smart contract is grey listed or not\n * @param _account account address\n * @return false if contract account is allowed to interact, true otherwise\n */\n function _noGreyList(\n address _account,\n bytes32[] memory _accountsProof,\n bytes32[] memory _codesProof\n ) internal view returns (bool) {\n return\n _verifyWhitelistedAccount(_accountLeaf(_account), _accountsProof) &&\n _verifyWhitelistedCode(_codeLeaf(_getContractHash(_account)), _codesProof);\n }\n\n function _verifyWhitelistedAccount(bytes32 _leaf, bytes32[] memory _proof) internal view returns (bool) {\n return MerkleProof.verify(_proof, whitelistedAccountsRoot, _leaf);\n }\n\n function _verifyWhitelistedCode(bytes32 _leaf, bytes32[] memory _proof) internal view returns (bool) {\n return MerkleProof.verify(_proof, whitelistedCodesRoot, _leaf);\n }\n\n /**\n * @dev internal function to check whether a user can deposit or not\n * @param _user address of the depositor\n * @param _addUserDepositUT whether to add _userDepositUT while\n * checking for TVL limit reached.\n * @param _userDepositUTWithDeductions actual deposit amount after deducting\n * third party transfer fees and deposit fees if any\n * @param _deductions amount in underlying token to not consider in as a part of\n * user deposit amount\n * @param _accountsProof merkle proof for caller\n * @param _codesProof merkle proof for code hash if caller is smart contract\n */\n function _checkUserDeposit(\n address _user,\n bool _addUserDepositUT,\n uint256 _userDepositUTWithDeductions,\n uint256 _deductions,\n bytes32[] memory _accountsProof,\n bytes32[] memory _codesProof\n ) internal view {\n (bool _userDepositPermitted, string memory _userDepositPermittedReason) =\n userDepositPermitted(\n _user,\n _addUserDepositUT,\n _userDepositUTWithDeductions,\n _deductions,\n _accountsProof,\n _codesProof\n );\n require(_userDepositPermitted, _userDepositPermittedReason);\n }\n\n /**\n * @dev internal function to decide whether user can withdraw or not\n * @param _user account address of the user\n * @param _userWithdrawVT amount of vault tokens to burn\n * @param _accountsProof merkle proof for caller\n * @param _codesProof merkle proof for code hash if caller is smart contract\n */\n function _checkUserWithdraw(\n address _user,\n uint256 _userWithdrawVT,\n bytes32[] memory _accountsProof,\n bytes32[] memory _codesProof\n ) internal view {\n (bool _userWithdrawPermitted, string memory _userWithdrawPermittedReason) =\n userWithdrawPermitted(_user, _userWithdrawVT, _accountsProof, _codesProof);\n require(_userWithdrawPermitted, _userWithdrawPermittedReason);\n }\n\n //===Internal pure functions===//\n\n /**\n * @inheritdoc VersionedInitializable\n */\n function getRevision() internal pure virtual override returns (uint256) {\n return opTOKEN_REVISION;\n }\n\n /**\n * @dev A helper function to calculate the absolute difference\n * @param _a value\n * @param _b value\n * @return _result absolute difference between _a and _b\n */\n function _abs(uint256 _a, uint256 _b) internal pure returns (uint256) {\n return _a > _b ? _a.sub(_b) : _b.sub(_a);\n }\n\n /**\n * @dev internal helper function to return a merkle tree leaf hash for account\n * @param _account account address\n * @return account leaf hash\n */\n function _accountLeaf(address _account) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_account));\n }\n\n /**\n * @dev internal helper function to return a merkle tree leaf hash for codes\n * @param _hash codehash\n * @return code leaf hash\n */\n function _codeLeaf(bytes32 _hash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(_hash));\n }\n\n //===Private functions===//\n\n /**\n * @notice It checks the min/max balance of the first transaction of the current block\n * with the value from the previous block.\n * It is not a protection against flash loan attacks rather just an arbitrary sanity check.\n * @dev Mechanism to restrict the vault value deviating from maxVaultValueJump\n * @param _vaultValue The value of vault in underlying token\n */\n function _emergencyBrake(uint256 _vaultValue) private {\n uint256 _blockTransactions = blockToBlockVaultValues[block.number].length;\n if (_blockTransactions > 0) {\n blockToBlockVaultValues[block.number].push(\n DataTypes.BlockVaultValue({\n actualVaultValue: _vaultValue,\n blockMinVaultValue: _vaultValue <\n blockToBlockVaultValues[block.number][_blockTransactions - 1].blockMinVaultValue\n ? _vaultValue\n : blockToBlockVaultValues[block.number][_blockTransactions - 1].blockMinVaultValue,\n blockMaxVaultValue: _vaultValue >\n blockToBlockVaultValues[block.number][_blockTransactions - 1].blockMaxVaultValue\n ? _vaultValue\n : blockToBlockVaultValues[block.number][_blockTransactions - 1].blockMaxVaultValue\n })\n );\n require(\n isMaxVaultValueJumpAllowed(\n _abs(\n blockToBlockVaultValues[block.number][_blockTransactions].blockMinVaultValue,\n blockToBlockVaultValues[block.number][_blockTransactions].blockMaxVaultValue\n ),\n _vaultValue\n ),\n Errors.EMERGENCY_BRAKE\n );\n } else {\n blockToBlockVaultValues[block.number].push(\n DataTypes.BlockVaultValue({\n actualVaultValue: _vaultValue,\n blockMinVaultValue: _vaultValue,\n blockMaxVaultValue: _vaultValue\n })\n );\n }\n }\n}\n" + }, + "contracts/utils/MultiCall.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n/**\n * @title MultiCall Contract\n * @author Opty.fi\n * @dev Provides functions used commonly for decoding codes and execute\n * the code calls for Opty.fi contracts\n */\nabstract contract MultiCall {\n function executeCode(bytes memory _code, string memory _errorMsg) internal {\n (address _contract, bytes memory _data) = abi.decode(_code, (address, bytes));\n (bool _success, ) = _contract.call(_data); //solhint-disable-line avoid-low-level-calls\n require(_success, _errorMsg);\n }\n\n function executeCodes(bytes[] memory _codes, string memory _errorMsg) internal {\n for (uint256 _j = 0; _j < _codes.length; _j++) {\n executeCode(_codes[_j], _errorMsg);\n }\n }\n}\n" + }, + "contracts/utils/Constants.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.6.12;\n\nlibrary Constants {\n /** @notice Zero value constant of bytes32 datatype */\n bytes32 public constant ZERO_BYTES32 = 0x0000000000000000000000000000000000000000000000000000000000000000;\n\n /** @notice Decimals considered upto 10**18 */\n uint256 public constant WEI_DECIMAL = 10**18;\n}\n" + }, + "contracts/utils/Errors.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nlibrary Errors {\n string public constant USER_WITHDRAW_INSUFFICIENT_VT = \"1\";\n string public constant VAULT_DEPOSIT = \"2\";\n string public constant VAULT_WITHDRAW = \"3\";\n string public constant EMPTY_STRING = \"4\";\n string public constant RISK_PROFILE_EXISTS = \"5\";\n string public constant NOT_A_CONTRACT = \"6\";\n string public constant TOKEN_NOT_APPROVED = \"7\";\n string public constant EOA_NOT_WHITELISTED = \"8\";\n string public constant CA_NOT_WHITELISTED = \"9\";\n string public constant MINIMUM_USER_DEPOSIT_VALUE_UT = \"10\";\n string public constant TOTAL_VALUE_LOCKED_LIMIT_UT = \"11\";\n string public constant USER_DEPOSIT_CAP_UT = \"12\";\n string public constant VAULT_EMERGENCY_SHUTDOWN = \"13\";\n string public constant VAULT_PAUSED = \"14\";\n string public constant ADMIN_CALL = \"15\";\n string public constant EMERGENCY_BRAKE = \"16\";\n string public constant UNDERLYING_TOKENS_HASH_EXISTS = \"17\";\n string public constant TRANSFER_TO_THIS_CONTRACT = \"18\";\n string public constant UNDERLYING_TOKEN_APPROVED = \"19\";\n}\n" + }, + "contracts/protocol/lib/StrategyManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\n\n// interfaces\nimport { IAdapterFull } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterFull.sol\";\nimport { IRegistry } from \"../earn-protocol-configuration/contracts/interfaces/opty/IRegistry.sol\";\nimport {\n IInvestStrategyRegistry\n} from \"../earn-protocol-configuration/contracts/interfaces/opty/IInvestStrategyRegistry.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\n/**\n * @title StrategyBuilder Library\n * @author Opty.fi\n * @notice Central processing unit of the earn protocol\n * @dev Contains the functionality for getting the codes to deposit/withdraw tokens,\n * from the adapters and pass it onto vault contract\n */\nlibrary StrategyManager {\n function getDepositInternalTransactionCount(\n DataTypes.StrategyStep[] memory _strategySteps,\n address _registryContract\n ) internal view returns (uint256) {\n uint256 _strategyStepCount = _strategySteps.length;\n address _lastStepLiquidityPool = _strategySteps[_strategyStepCount - 1].pool;\n if (\n IAdapterFull(IRegistry(_registryContract).getLiquidityPoolToAdapter(_lastStepLiquidityPool)).canStake(\n _lastStepLiquidityPool\n )\n ) {\n return (_strategyStepCount + 1);\n }\n return _strategyStepCount;\n }\n\n function getOraValueUT(\n DataTypes.StrategyStep[] memory _strategySteps,\n address _registryContract,\n address payable _vault,\n address _underlyingToken\n ) internal view returns (uint256 _amountUT) {\n uint256 _nStrategySteps = _strategySteps.length;\n uint256 _outputTokenAmount;\n for (uint256 _i; _i < _nStrategySteps; _i++) {\n uint256 _iterator = _nStrategySteps - 1 - _i;\n address _liquidityPool = _strategySteps[_iterator].pool;\n IAdapterFull _adapter =\n IAdapterFull(IRegistry(_registryContract).getLiquidityPoolToAdapter(_liquidityPool));\n address _inputToken = _underlyingToken;\n if (_iterator != 0) {\n _inputToken = _strategySteps[_iterator - 1].outputToken;\n }\n if (_iterator == (_nStrategySteps - 1)) {\n if (_adapter.canStake(_liquidityPool)) {\n _amountUT = _adapter.getAllAmountInTokenStake(_vault, _inputToken, _liquidityPool);\n } else {\n _amountUT = _adapter.getAllAmountInToken(_vault, _inputToken, _liquidityPool);\n }\n } else {\n _amountUT = _adapter.getSomeAmountInToken(_inputToken, _liquidityPool, _outputTokenAmount);\n }\n _outputTokenAmount = _amountUT;\n }\n }\n\n function getOraSomeValueLP(\n DataTypes.StrategyStep[] memory _strategySteps,\n address _registryContract,\n address _underlyingToken,\n uint256 _wantAmountUT\n ) internal view returns (uint256 _amountLP) {\n uint256 _nStrategySteps = _strategySteps.length;\n for (uint256 _i; _i < _nStrategySteps; _i++) {\n address _liquidityPool = _strategySteps[_i].pool;\n IAdapterFull _adapter =\n IAdapterFull(IRegistry(_registryContract).getLiquidityPoolToAdapter(_liquidityPool));\n address _inputToken = _underlyingToken;\n if (_i != 0) {\n _inputToken = _strategySteps[_i - 1].outputToken;\n }\n _amountLP = _adapter.calculateAmountInLPToken(\n _inputToken,\n _liquidityPool,\n _i == 0 ? _wantAmountUT : _amountLP\n );\n // the _amountLP will be actually _wantAmountUT for _i+1th step\n }\n }\n\n function getPoolDepositCodes(\n DataTypes.StrategyStep[] memory _strategySteps,\n DataTypes.StrategyConfigurationParams memory _strategyConfigurationParams\n ) internal view returns (bytes[] memory _codes) {\n IRegistry _registryContract = IRegistry(_strategyConfigurationParams.registryContract);\n address _underlyingToken = _strategyConfigurationParams.underlyingToken;\n uint256 _depositAmountUT = _strategyConfigurationParams.initialStepInputAmount;\n uint256 _stepCount = _strategySteps.length;\n if (_strategyConfigurationParams.internalTransactionIndex == _stepCount) {\n address _liquidityPool = _strategySteps[_strategyConfigurationParams.internalTransactionIndex - 1].pool;\n IAdapterFull _adapter = IAdapterFull(_registryContract.getLiquidityPoolToAdapter(_liquidityPool));\n _underlyingToken = _strategySteps[_strategyConfigurationParams.internalTransactionIndex - 1].outputToken;\n _depositAmountUT = IERC20(_strategyConfigurationParams.underlyingToken).balanceOf(\n _strategyConfigurationParams.vault\n );\n _codes = _adapter.getStakeAllCodes(\n _strategyConfigurationParams.vault,\n _strategyConfigurationParams.underlyingToken,\n _liquidityPool\n );\n } else {\n address _liquidityPool = _strategySteps[_strategyConfigurationParams.internalTransactionIndex].pool;\n IAdapterFull _adapter = IAdapterFull(_registryContract.getLiquidityPoolToAdapter(_liquidityPool));\n if (_strategyConfigurationParams.internalTransactionIndex != 0) {\n _underlyingToken = _strategySteps[_strategyConfigurationParams.internalTransactionIndex - 1]\n .outputToken;\n _depositAmountUT = IERC20(_underlyingToken).balanceOf(_strategyConfigurationParams.vault);\n }\n _codes = _adapter.getDepositSomeCodes(\n _strategyConfigurationParams.vault,\n _underlyingToken,\n _liquidityPool,\n _depositAmountUT\n );\n }\n }\n\n function getPoolWithdrawCodes(\n DataTypes.StrategyStep[] memory _strategySteps,\n DataTypes.StrategyConfigurationParams memory _strategyConfigurationParams\n ) internal view returns (bytes[] memory _codes) {\n address _liquidityPool = _strategySteps[_strategyConfigurationParams.internalTransactionIndex].pool;\n IRegistry _registryContract = IRegistry(_strategyConfigurationParams.registryContract);\n IAdapterFull _adapter = IAdapterFull(_registryContract.getLiquidityPoolToAdapter(_liquidityPool));\n address _underlyingToken = _strategyConfigurationParams.underlyingToken;\n uint256 _redeemAmountLP = _strategyConfigurationParams.initialStepInputAmount;\n if (_strategyConfigurationParams.internalTransactionIndex != 0) {\n _underlyingToken = _strategySteps[_strategyConfigurationParams.internalTransactionIndex - 1].outputToken;\n }\n if (\n _strategyConfigurationParams.internalTransactionIndex !=\n (_strategyConfigurationParams.internalTransactionCount - 1)\n ) {\n _redeemAmountLP = IERC20(_strategySteps[_strategyConfigurationParams.internalTransactionIndex].outputToken)\n .balanceOf(_strategyConfigurationParams.vault);\n }\n _codes = (_strategyConfigurationParams.internalTransactionIndex ==\n (_strategyConfigurationParams.internalTransactionCount - 1) &&\n _adapter.canStake(_liquidityPool))\n ? _adapter.getUnstakeAndWithdrawSomeCodes(\n _strategyConfigurationParams.vault,\n _underlyingToken,\n _liquidityPool,\n _redeemAmountLP\n )\n : _adapter.getWithdrawSomeCodes(\n _strategyConfigurationParams.vault,\n _underlyingToken,\n _liquidityPool,\n _redeemAmountLP\n );\n }\n\n function getLastStrategyStepBalanceLP(\n DataTypes.StrategyStep[] memory _strategySteps,\n address _registryContract,\n address payable _vault,\n address _underlyingToken\n ) internal view returns (uint256) {\n uint256 _strategyStepsLen = _strategySteps.length;\n address _liquidityPool = _strategySteps[_strategySteps.length - 1].pool;\n IAdapterFull _adapter = IAdapterFull(IRegistry(_registryContract).getLiquidityPoolToAdapter(_liquidityPool));\n if (_strategyStepsLen > 1) {\n // underlying token for last step is previous step's output token\n _underlyingToken = _strategySteps[_strategyStepsLen - 2].outputToken;\n }\n return\n _adapter.canStake(_liquidityPool)\n ? _adapter.getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool)\n : _adapter.getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n }\n}\n" + }, + "@openzeppelin/contracts/cryptography/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev These functions deal with verification of Merkle trees (hash trees),\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) {\n bytes32 computedHash = leaf;\n\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = keccak256(abi.encodePacked(computedHash, proofElement));\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = keccak256(abi.encodePacked(proofElement, computedHash));\n }\n }\n\n // Check if the computed hash (root) is equal to the provided root\n return computedHash == root;\n }\n}\n" + }, + "contracts/interfaces/opty/IVault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../protocol/earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\n\n/**\n * @title Interface for opty.fi's interest bearing vault\n * @author opty.fi\n * @notice Contains mix of permissioned and permissionless vault methods\n */\ninterface IVault {\n /**\n * @notice Assign a risk profile code\n * @dev function to set code of risk profile\n * @param _riskProfileCode code of the risk profile\n */\n function setRiskProfileCode(uint256 _riskProfileCode) external;\n\n /**\n * @notice Assign the address of the underlying asset and its keccak256 hash\n * @dev the underlying asset should be approved by the governance\n * @param _underlyingTokensHash keccak256 hash of underlying token address and chain id\n */\n function setUnderlyingTokensHash(bytes32 _underlyingTokensHash) external;\n\n /**\n * @notice Single function to configure the vault's value control params\n * @param _userDepositCapUT maximum amount in underlying token allowed to be deposited by user\n * @param _minimumDepositValueUT minimum deposit value in underlying token required\n * @param _totalValueLockedLimitUT maximum TVL in underlying token allowed for the vault\n */\n function setValueControlParams(\n uint256 _userDepositCapUT,\n uint256 _minimumDepositValueUT,\n uint256 _totalValueLockedLimitUT\n ) external;\n\n /**\n * @notice Single function to configure the vault's fee params\n * @dev bit 0-15 deposit fee in underlying token without decimals\n * bit 16-31 deposit fee in basis points\n * bit 32-47 withdrawal fee in underlying token without decimals\n * bit 48-63 withdrawal fee in basis points\n * bit 64-79 max vault value jump allowed in basis points (standard deviation allowed for vault value)\n * bit 80-239 vault fee collection address\n * bit 240-247 risk profile code\n * bit 248 emergency shutdown flag\n * bit 249 pause flag (deposit/withdraw is pause when bit is unset, unpause otherwise)\n * bit 250 white list state flag\n * @param _vaultConfiguration bit banging value for vault config\n */\n function setVaultConfiguration(uint256 _vaultConfiguration) external;\n\n /**\n * @notice function to set the maximum amount in underlying token\n * that a user could deposit in entire life cycle of this vault\n * @param _userDepositCapUT maximum amount in underlying token allowed to be deposited by user\n */\n function setUserDepositCapUT(uint256 _userDepositCapUT) external;\n\n /**\n * @notice function to set minimum amount in underlying token required\n * to be deposited by the user\n * @param _minimumDepositValueUT Minimum deposit value in underlying token required\n */\n function setMinimumDepositValueUT(uint256 _minimumDepositValueUT) external;\n\n /**\n * @notice function to set the total value locked limit in underlying token\n * @param _totalValueLockedLimitUT maximum TVL in underlying token allowed for the vault\n */\n function setTotalValueLockedLimitUT(uint256 _totalValueLockedLimitUT) external;\n\n /**\n * @notice function to control the allowance of user interaction\n * only when vault's whitelistedstate is enabled\n * @param _whitelistedAccountsRoot whitelisted accounts root hash\n */\n function setWhitelistedAccountsRoot(bytes32 _whitelistedAccountsRoot) external;\n\n /**\n * @notice function to control the allowance of smart contract interaction\n * with vault\n * @param _whitelistedCodesRoot whitelisted codes root hash\n */\n function setWhitelistedCodesRoot(bytes32 _whitelistedCodesRoot) external;\n\n /**\n * @notice activates or deactives vault mode where\n * all strategies go into full withdrawal. During emergency shutdown\n * - No Users may deposit into the Vault (but may withdraw as usual.)\n * - Only Governance may undo Emergency Shutdown.\n * - No user may transfer vault tokens\n * @dev current strategy will be null\n * @param _active If true, the Vault goes into Emergency Shutdown. If false, the Vault\n * goes back into Normal Operation\n */\n function setEmergencyShutdown(bool _active) external;\n\n /**\n * @notice activates or deactivates vault mode where all strategies\n * go into full withdrawal. During pause\n * - No users may deposit nor withdraw from vault\n * - No user may transfer vault tokens\n * This function can only be invoked by governance\n * @dev current strategy of vault will be null\n * @param _unpaused If true, the vault goes into unpause mode. If false(default), the vault\n * goes into pause mode\n */\n function setUnpaused(bool _unpaused) external;\n\n /**\n * @notice Withdraw the underlying asset of vault from previous strategy if any,\n * claims and swaps the reward tokens for the underlying token\n * performs batch minting of shares for users deposited previously without rebalance,\n * deposits the assets into the new strategy if any or holds the same in the vault\n * @dev the vault will be charged to compensate gas fees if operator calls this function\n */\n function rebalance() external;\n\n /**\n * @notice Deposit underlying tokens to the vault\n * @dev Mint the shares right away as per oracle based price per full share value\n * @param _userDepositUT Amount in underlying token\n * @param _accountsProof merkle proof for caller\n * @param _codesProof merkle proof for code hash if caller is smart contract\n */\n function userDepositVault(\n uint256 _userDepositUT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external;\n\n /**\n * @notice redeems the vault shares and transfers underlying token to the withdrawer\n * @dev Burn the shares right away as per oracle based price per full share value\n * @param _userWithdrawVT amount in vault token\n * @param _accountsProof merkle proof for caller\n * @param _codesProof merkle proof for code hash if caller is smart contract\n */\n function userWithdrawVault(\n uint256 _userWithdrawVT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external;\n\n /**\n * @notice function to deposit whole balance of underlying token to current strategy\n */\n function vaultDepositAllToStrategy() external;\n\n /**\n * @notice A function to be called in case vault needs to claim and harvest tokens in case a strategy\n * provides multiple reward tokens\n * @param _codes Array of encoded data in bytes which acts as code to execute\n */\n function adminCall(bytes[] memory _codes) external;\n\n /**\n * @notice Retrieve underlying token balance in the vault\n * @return The balance of underlying token in the vault\n */\n function balanceUT() external view returns (uint256);\n\n /**\n * @dev A helper function to validate the vault value will not surpass max or min vault value\n * within the same block\n * @param _diff absolute difference between minimum and maximum vault value within a block\n * @param _currentVaultValue the underlying token balance of the vault\n * @return bool returns true if vault value jump is within permissible limits\n */\n function isMaxVaultValueJumpAllowed(uint256 _diff, uint256 _currentVaultValue) external view returns (bool);\n\n /**\n * @notice Calculate the value of a vault share in underlying token\n * read-only function to compute price per share of the vault\n * Note : This function calculates the pricePerFullShare (i.e. the number of underlyingTokens\n * per each vaultToken entitles you to).\n *\n * Please note the following quantities are included in underlyingTokens :\n * - underlyingTokens in vault that are not yet deployed in strategy\n *\n * Please note the following quantities are *NOT* included in underlyingTokens :\n * - unclaimed reward tokens from the current or past strategies\n * - claimed reward tokens that are not yet harvested to underlyingTokens\n * - any tokens other than underlyingTokens of the vault.\n *\n * Please note we rely on the getOraValueUT() function of StrategyBuilder which in turn relies on individual\n * protocol adapters to obtain the current underlying token amount. Thus we are relying on a third party\n * contract (i.e. an oracle). This oracle should be made resilient via best practices.\n * @return The underlying token worth a vault share is\n */\n function getPricePerFullShare() external view returns (uint256);\n\n /**\n * @notice Makes a decision based on vault configuration parameters\n * to allow user deposits\n * @param _user address of the depositor\n * @param _addUserDepositUT whether to add _userDepositUT while\n * checking for TVL limit reached.\n * @param _userDepositUTWithDeductions actual deposit amount after deducting\n * third party transfer fees and deposit fees if any\n * @param _deductions amount in underlying token to not consider in as a part of\n * user deposit amount\n * @param _accountsProof merkle proof for caller\n * @param _codesProof merkle proof for code hash if caller is smart contract\n * @return true if permitted, false otherwise\n * @return reason string if return false, empty otherwise\n */\n function userDepositPermitted(\n address _user,\n bool _addUserDepositUT,\n uint256 _userDepositUTWithDeductions,\n uint256 _deductions,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external view returns (bool, string memory);\n\n /**\n * @notice function to decide whether to allow vault to deposit to the strategy\n * @return true if permitted, false otherwise\n * @return reason string if return false, empty otherwise\n */\n function vaultDepositPermitted() external view returns (bool, string memory);\n\n /**\n * @notice function to decide whether user can withdraw or not\n * @param _user account address of the user\n * @param _userWithdrawVT amount of vault tokens to burn\n * @param _accountsProof merkle proof for caller\n * @param _codesProof merkle proof for code hash if caller is smart contract\n * @return true if permitted, false otherwise\n * @return reason string if return false, empty otherwise\n */\n function userWithdrawPermitted(\n address _user,\n uint256 _userWithdrawVT,\n bytes32[] memory _accountsProof,\n bytes32[] memory _codesProof\n ) external view returns (bool, string memory);\n\n /**\n * @notice function to decide whether vault can withdraw from strategy or not\n * @return true if permitted, false otherwise\n * @return reason string if return false, empty otherwise\n */\n function vaultWithdrawPermitted() external view returns (bool, string memory);\n\n /**\n * @notice Computes deposit fee in underlying token\n * @param _userDepositUT user deposit amount in underlying token\n * @return deposit fee in underlying token\n */\n function calcDepositFeeUT(uint256 _userDepositUT) external view returns (uint256);\n\n /**\n * @notice Computes withdrawal fee in underlying token\n * @param _userWithdrawUT user withdraw amount in underlying token\n * @return _withdrawalFeeUT withdrawal fee in underlying token\n */\n function calcWithdrawalFeeUT(uint256 _userWithdrawUT) external view returns (uint256);\n\n /**\n * @notice Returns next best invest strategy that the vault will execute on next rebalance\n * @return the strategy metadata\n */\n function getNextBestInvestStrategy() external view returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @notice function to compute the balance of lptoken of the vault\n * in the last step of the strategy\n * @param _strategySteps array of strategy step tuple\n * @return balance in lptoken\n */\n function getLastStrategyStepBalanceLP(DataTypes.StrategyStep[] memory _strategySteps)\n external\n view\n returns (uint256);\n\n /**\n * @notice retireves current strategy metadata\n * @return array of strategy steps\n */\n function getInvestStrategySteps() external view returns (DataTypes.StrategyStep[] memory);\n\n /**\n * @dev Emitted when emergency shutdown over vault is changed\n * @param emergencyShutdown true mean vault is in emergency shutdown mode\n * @param caller address of user who has called the respective function to trigger this event\n */\n event LogEmergencyShutdown(bool indexed emergencyShutdown, address indexed caller);\n\n /**\n * @notice Emitted when Pause over vault is activated/deactivated\n * @param unpaused Unpause status of OptyFi's Vault contract - false (if paused) and true (if unpaused)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogUnpause(bool indexed unpaused, address indexed caller);\n\n /**\n * @notice Emitted when setUserDepositCapUT is called\n * @param userDepositCapUT Cap in underlying token for user deposits in OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogUserDepositCapUT(uint256 indexed userDepositCapUT, address indexed caller);\n\n /**\n * @notice Emitted when setMinimumDepositValueUT is called\n * @param minimumDepositValueUT Minimum deposit in OptyFi's Vault contract - only for deposits (without rebalance)\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogMinimumDepositValueUT(uint256 indexed minimumDepositValueUT, address indexed caller);\n\n /**\n * @notice Emitted when setTotalValueLockedLimitUT is called\n * @param totalValueLockedLimitUT Maximum limit for total value locked of OptyFi's Vault contract\n * @param caller Address of user who has called the respective function to trigger this event\n */\n event LogTotalValueLockedLimitUT(uint256 indexed totalValueLockedLimitUT, address indexed caller);\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/interfaces/opty/IInvestStrategyRegistry.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title IInvestStrategyRegistry\n * @author Opty.fi\n * @notice Contains functionality to setting all the strategies for all tokens\n */\ninterface IInvestStrategyRegistry {\n /**\n * @dev Assign strategy in form of _strategySteps to the _tokensHash\n * @param _tokensHash Hash of underlying token address/addresses\n * @param _strategySteps Strategy steps containing [pool, outputToken, isBorrow]\n * @return Returns true indicating successful operation.\n */\n function setStrategy(bytes32 _tokensHash, DataTypes.StrategyStep[] memory _strategySteps) external returns (bool);\n\n /**\n * @dev Assign multiple strategies in form of _strategySteps to the _tokensHash\n * @param _tokensHash List of Hashes of underlying token address/addresses\n * @param _strategySteps List of Strategy steps containing [pool, outputToken, isBorrow]\n * @return Returns true indicating successful operation.\n */\n function setStrategy(bytes32 _tokensHash, DataTypes.StrategyStep[][] memory _strategySteps) external returns (bool);\n\n /**\n * @dev Assign multiple strategies in form of _strategySteps to multiple tokens in form of _tokensHash\n * @param _tokensHash List of Hashes of underlying token address/addresses\n * @param _strategySteps List of Strategy steps containing [pool, outputToken, isBorrow]\n * @return Returns true indicating successful operation.\n */\n function setStrategy(bytes32[] memory _tokensHash, DataTypes.StrategyStep[][] memory _strategySteps)\n external\n returns (bool);\n\n /**\n * @notice Returns the Strategy Steps corresponding to _hash\n * @param _hash Hash of the strategy steps\n * @return _index Index at which strategy is stored\n * @return _strategySteps Returns the Strategy Steps corresponding to _hash provided\n */\n function getStrategy(bytes32 _hash)\n external\n view\n returns (uint256 _index, DataTypes.StrategyStep[] memory _strategySteps);\n\n /**\n * @notice Returns the Strategy Steps corresponding to _tokensHash\n * @param _tokensHash Hash of the underlying token address/addresses\n * @return Returns the List of Strategies corresponding to _tokensHash provided\n */\n function getTokenToStrategies(bytes32 _tokensHash) external view returns (bytes32[] memory);\n}\n" + }, + "contracts/mocks/contracts/TestVault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// helpers\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// interfaces\nimport { IVault } from \"../../interfaces/opty/IVault.sol\";\n\ncontract TestVault {\n using SafeMath for uint256;\n\n function deposit(\n IVault _vault,\n ERC20 _token,\n uint256 _amountUT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external {\n _token.transferFrom(msg.sender, address(this), _amountUT);\n _token.approve(address(_vault), _amountUT);\n _vault.userDepositVault(_amountUT, _accountsProof, _codesProof);\n }\n\n function withdraw(\n IVault _vault,\n uint256 _amountVT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external {\n _vault.userWithdrawVault(_amountVT, _accountsProof, _codesProof);\n }\n\n function withdrawERC20(ERC20 _token, address _recipient) external {\n _token.transfer(_recipient, _token.balanceOf(address(this)));\n }\n\n function withdrawETH(address payable _recipient) external {\n _recipient.transfer(payable(address(this)).balance);\n }\n\n function testUserDepositPermitted(\n IVault _vault,\n uint256 _valueUT,\n bytes32[] calldata _accountsProof,\n bytes32[] calldata _codesProof\n ) external view returns (bool, string memory) {\n uint256 _depositFee = _vault.calcDepositFeeUT(_valueUT);\n return\n _vault.userDepositPermitted(\n address(this),\n true,\n _valueUT.sub(_depositFee),\n _depositFee,\n _accountsProof,\n _codesProof\n );\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/yearn/YearnAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IYearn } from \"@optyfi/defi-legos/ethereum/yearn/contracts/IYearn.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for Yearn protocol\n * @author Opty.fi\n * @dev Abstraction layer to Yearn's pools\n */\ncontract YearnAdapter is IAdapter, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IYearn(_liquidityPool).token();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return\n _depositAmount.mul(10**IYearn(_liquidityPool).decimals()).div(\n IYearn(_liquidityPool).getPricePerFullShare()\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _depositAmount)\n );\n _codes[2] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"deposit(uint256)\", _depositAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable,\n address,\n address _liquidityPool,\n uint256 _shares\n ) public view override returns (bytes[] memory _codes) {\n if (_shares > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"withdraw(uint256)\", _shares));\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return IYearn(_liquidityPool).calcPoolValueInToken();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n return\n getSomeAmountInToken(\n _underlyingToken,\n _liquidityPool,\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool)\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(getLiquidityPoolToken(_underlyingToken, _liquidityPool)).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount\n .mul(IYearn(_liquidityPool).getPricePerFullShare())\n .div(10**IYearn(_liquidityPool).decimals());\n }\n return _liquidityPoolTokenAmount;\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/mocks/contracts/TestDummyTokenTransferFee.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestDummyTokenTransferFee is ERC20 {\n uint256 public constant FEE = uint256(500);\n\n constructor(uint256 initialSupply) public ERC20(\"TestDummyTokenTransferFee\", \"TDTTF\") {\n _mint(msg.sender, initialSupply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n\n function transfer(address recipient, uint256 amount) public override returns (bool) {\n amount = amount.mul(uint256(10000).sub(FEE)).div(10000);\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public virtual override returns (bool) {\n amount = amount.mul(uint256(10000).sub(FEE)).div(10000);\n _transfer(sender, recipient, amount);\n return true;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/mocks/contracts/TestDummyToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestDummyToken is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals,\n uint256 _initialSupply\n ) public ERC20(_name, _symbol) {\n _mint(msg.sender, _initialSupply);\n _setupDecimals(_decimals);\n }\n\n function mint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/mocks/contracts/TestDummyTokenTransferFee.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestDummyTokenTransferFee is ERC20 {\n uint256 public constant FEE = uint256(500);\n\n constructor(uint256 initialSupply) public ERC20(\"TestDummyTokenTransferFee\", \"TDTTF\") {\n _mint(msg.sender, initialSupply);\n }\n\n function mint(address to, uint256 amount) external {\n _mint(to, amount);\n }\n\n function transfer(address recipient, uint256 amount) public override returns (bool) {\n amount = amount.mul(uint256(10000).sub(FEE)).div(10000);\n _transfer(_msgSender(), recipient, amount);\n return true;\n }\n\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public virtual override returns (bool) {\n amount = amount.mul(uint256(10000).sub(FEE)).div(10000);\n _transfer(sender, recipient, amount);\n return true;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/mocks/contracts/TestDummyToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestDummyToken is ERC20 {\n constructor(\n string memory _name,\n string memory _symbol,\n uint8 _decimals,\n uint256 _initialSupply\n ) public ERC20(_name, _symbol) {\n _mint(msg.sender, _initialSupply);\n _setupDecimals(_decimals);\n }\n\n function mint(address _to, uint256 _amount) external {\n _mint(_to, _amount);\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/fulcrum/FulcrumAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IFulcrum } from \"@optyfi/defi-legos/ethereum/fulcrum/contracts/IFulcrum.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for Fulcrum protocol\n * @author Opty.fi\n * @dev Abstraction layer to Fulcrum's pools\n */\ncontract FulcrumAdapter is IAdapter, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, uint256(-1));\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IFulcrum(_liquidityPool).loanTokenAddress();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount.mul(IFulcrum(_liquidityPool).tokenPrice()).div(\n 10**IFulcrum(_liquidityPool).decimals()\n );\n }\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return _depositAmount.mul(10**(IFulcrum(_liquidityPool).decimals())).div(IFulcrum(_liquidityPool).tokenPrice());\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n require(_balanceInToken > 0, \"!balance\");\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _depositAmount)\n );\n _codes[2] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"mint(address,uint256)\", _vault, _depositAmount)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address,\n address _liquidityPool,\n uint256 _burnAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_burnAmount > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"burn(address,uint256)\", _vault, _burnAmount)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return IFulcrum(_liquidityPool).marketLiquidity();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n if (_liquidityPoolTokenBalance > 0) {\n _liquidityPoolTokenBalance = IFulcrum(_liquidityPool).assetBalanceOf(_vault);\n }\n return _liquidityPoolTokenBalance;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(_liquidityPool).balanceOf(_vault);\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/dYdX/dYdXAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n// interfaces\nimport {\n IdYdX,\n AccountInfo,\n AssetAmount,\n AssetDenomination,\n AssetReference,\n ActionArgs,\n AssetReference,\n ActionType\n} from \"@optyfi/defi-legos/ethereum/dydx/contracts/IdYdX.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for dYdX protocol\n * @author Opty.fi\n * @dev Abstraction layer to dYdX's pools\n */\ncontract DyDxAdapter is IAdapter, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n address public constant DYDX_LIQUIIDTY_POOL = address(0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e);\n address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n address public constant SAI = address(0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359);\n address public constant USDC = address(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);\n address public constant DAI = address(0x6B175474E89094C44Da98b954EedeAC495271d0F);\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps underlyingToken address to its market index in dYdX protocol */\n mapping(address => uint256) public marketToIndexes;\n\n /** @notice Maps liquidityPool to the list of underlyingTokens */\n mapping(address => address[]) public liquidityPoolToUnderlyingTokens;\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n address[] memory _dYdXUnderlyingTokens = new address[](4);\n _dYdXUnderlyingTokens[0] = WETH;\n _dYdXUnderlyingTokens[1] = SAI;\n _dYdXUnderlyingTokens[2] = USDC;\n _dYdXUnderlyingTokens[3] = DAI;\n setLiquidityPoolToUnderlyingTokens(DYDX_LIQUIIDTY_POOL, _dYdXUnderlyingTokens);\n addMarket(WETH, 0);\n addMarket(SAI, 1);\n addMarket(USDC, 2);\n addMarket(DAI, 3);\n setMaxDepositProtocolPct(uint256(10000)); // 100% (basis points)\n setMaxDepositProtocolMode(MaxExposure.Pct);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n require(_liquidityPool.isContract(), \"!isContract\");\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n require(_liquidityPool.isContract(), \"!_liquidityPool.isContract()\");\n require(_underlyingToken.isContract(), \"!_underlyingToken.isContract()\");\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @notice Maps the index of market used corresponding to the underlying token\n * @param _underlyingToken token address for which to set the market index\n * @param _marketIndex market index of the given underlying token\n */\n function addMarket(address _underlyingToken, uint256 _marketIndex) public onlyOperator {\n require(_underlyingToken.isContract(), \"!isContract\");\n marketToIndexes[_underlyingToken] = _marketIndex;\n }\n\n /**\n * @notice Maps the liquidity pool to the list of underlyingTokens supported by the given lp\n * @param _liquidityPool liquidity pool address for which to map the underlying tokens supported\n * @param _tokens list of underlying tokens linked to the given liquidity pool\n */\n function setLiquidityPoolToUnderlyingTokens(address _liquidityPool, address[] memory _tokens) public onlyOperator {\n require(_liquidityPool.isContract(), \"!isContract\");\n liquidityPoolToUnderlyingTokens[_liquidityPool] = _tokens;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) public override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) public override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = ERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address) public view override returns (address[] memory) {\n return liquidityPoolToUnderlyingTokens[_liquidityPool];\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n return getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n }\n\n /**\n * @inheritdoc IAdapter\n * @dev Reverting '!empty' message as there is no related functionality for this in dYdX protocol\n */\n function getSomeAmountInToken(\n address,\n address,\n uint256\n ) public view override returns (uint256) {\n revert(\"!empty\");\n }\n\n /**\n * @inheritdoc IAdapter\n * @dev Reverting '!empty' message as there is no related functionality for this in dYdX protocol\n */\n function calculateAmountInLPToken(\n address,\n address,\n uint256\n ) public view override returns (uint256) {\n revert(\"!empty\");\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable,\n address,\n address,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n return _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n uint256 _underlyingTokenIndex = marketToIndexes[_underlyingToken];\n AccountInfo[] memory _accountInfos = new AccountInfo[](1);\n _accountInfos[0] = AccountInfo(_vault, uint256(0));\n AssetAmount memory _amt = AssetAmount(true, AssetDenomination.Wei, AssetReference.Delta, _depositAmount);\n ActionArgs memory _actionArg;\n _actionArg.actionType = ActionType.Deposit;\n _actionArg.accountId = 0;\n _actionArg.amount = _amt;\n _actionArg.primaryMarketId = _underlyingTokenIndex;\n _actionArg.otherAddress = _vault;\n ActionArgs[] memory _actionArgs = new ActionArgs[](1);\n _actionArgs[0] = _actionArg;\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _amount)\n );\n _codes[2] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n // solhint-disable-next-line max-line-length\n \"operate((address,uint256)[],(uint8,uint256,(bool,uint8,uint8,uint256),uint256,uint256,address,uint256,bytes)[])\",\n _accountInfos,\n _actionArgs\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n uint256 _underlyingTokenIndex = marketToIndexes[_underlyingToken];\n AccountInfo[] memory _accountInfos = new AccountInfo[](1);\n _accountInfos[0] = AccountInfo(_vault, uint256(0));\n AssetAmount memory _amt = AssetAmount(false, AssetDenomination.Wei, AssetReference.Delta, _amount);\n ActionArgs memory _actionArg;\n _actionArg.actionType = ActionType.Withdraw;\n _actionArg.accountId = 0;\n _actionArg.amount = _amt;\n _actionArg.primaryMarketId = _underlyingTokenIndex;\n _actionArg.otherAddress = _vault;\n ActionArgs[] memory _actionArgs = new ActionArgs[](1);\n _actionArgs[0] = _actionArg;\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n // solhint-disable-next-line max-line-length\n \"operate((address,uint256)[],(uint8,uint256,(bool,uint8,uint8,uint256),uint256,uint256,address,uint256,bytes)[])\",\n _accountInfos,\n _actionArgs\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address _underlyingToken) public view override returns (uint256) {\n return uint256(IdYdX(_liquidityPool).getMarketTotalPar(marketToIndexes[_underlyingToken]).supply);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n uint256 _underlyingTokenIndex = marketToIndexes[_underlyingToken];\n AccountInfo memory _accountInfo = AccountInfo(_vault, uint256(0));\n (, uint256 value) = IdYdX(_liquidityPool).getAccountWei(_accountInfo, _underlyingTokenIndex);\n return value;\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool, _underlyingToken)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool, address _underlyingToken)\n internal\n view\n returns (uint256)\n {\n uint256 _poolValue = getPoolValue(_liquidityPool, _underlyingToken);\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/curve/CurveDepositPoolAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n// interfaces\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { IAdapterStaking } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol\";\nimport { IAdapterStakingCurve } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStakingCurve.sol\";\nimport { ICurveDeposit } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveDeposit.sol\";\nimport { ICurveGauge } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveGauge.sol\";\nimport {\n ICurveAddressProvider\n} from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveAddressProvider.sol\";\nimport { ICurveSwap } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveSwap.sol\";\nimport { ICurveRegistry } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ICurveRegistry.sol\";\nimport { ITokenMinter } from \"@optyfi/defi-legos/ethereum/curve/contracts/interfacesV0/ITokenMinter.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\n\n/**\n * @title Adapter for Curve Deposit pools\n * @author Opty.fi\n * @dev Abstraction layer to Curve's deposit pools\n * Note 1 : In this adapter, a liquidity pool is defined as a single sided liquidity pool\n * Note 2 : In this adapter, lp token can be redemeed into more than one underlying token\n */\ncontract CurveDepositPoolAdapter is\n IAdapter,\n IAdapterHarvestReward,\n IAdapterStaking,\n IAdapterStakingCurve,\n IAdapterInvestLimit,\n Modifiers\n{\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice Curve Registry Address Provider */\n address public constant ADDRESS_PROVIDER = address(0x0000000022D53366457F9d5E68Ec105046FC4383);\n\n /** @notice HBTC token contract address */\n address public constant HBTC = address(0x0316EB71485b0Ab14103307bf65a021042c6d380);\n\n /** @notice Curve's compound zap deposit contract address */\n address public constant COMPOUND_DEPOSIT_POOL = address(0xeB21209ae4C2c9FF2a86ACA31E123764A3B6Bc06);\n\n /** @notice Curve's usdt zap deposit contract address */\n address public constant USDT_DEPOSIT_POOL = address(0xac795D2c97e60DF6a99ff1c814727302fD747a80);\n\n /** @notice Curve's pax zap deposit contract address */\n address public constant PAX_DEPOSIT_POOL = address(0xA50cCc70b6a011CffDdf45057E39679379187287);\n\n /** @notice Curve's y zap deposit contract address */\n address public constant Y_DEPOSIT_POOL = address(0xbBC81d23Ea2c3ec7e56D39296F0cbB648873a5d3);\n\n /** @notice Curve's busd zap deposit contract address */\n address public constant BUSD_DEPOSIT_POOL = address(0xb6c057591E073249F2D9D88Ba59a46CFC9B59EdB);\n\n /** @notice Curve's susd zap deposit contract address */\n address public constant SUSD_DEPOSIT_POOL = address(0xFCBa3E75865d2d561BE8D220616520c171F12851);\n\n /** @notice Curve's aToken swap contract address */\n address public constant A_SWAP_POOL = address(0xDeBF20617708857ebe4F679508E7b7863a8A8EeE);\n\n /** @notice Curve's saToken swap contract address */\n address public constant SA_SWAP_POOL = address(0xEB16Ae0052ed37f479f7fe63849198Df1765a733);\n\n /** @notice Curve's iron bank swap contract address */\n address public constant Y_SWAP_POOL = address(0x2dded6Da1BF5DBdF597C45fcFaa3194e53EcfeAF);\n\n /** @notice max deposit's default value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @dev deposit addresses that uses old API */\n mapping(address => bool) public isOldDepositZap;\n\n /** @dev swap pool addresses*/\n mapping(address => bool) public isSwapPool;\n\n /** @notice Maps liquidityPool to absolute max deposit values in underlying */\n mapping(address => uint256) public maxDepositAmount;\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct;\n\n /**\n * @dev Configures the CurveDeposit pools according old and new API\n */\n constructor(address _registry) public Modifiers(_registry) {\n isOldDepositZap[COMPOUND_DEPOSIT_POOL] = true; // curve-compound\n isOldDepositZap[USDT_DEPOSIT_POOL] = true; // curve-usdt\n isOldDepositZap[PAX_DEPOSIT_POOL] = true; // curve-pax\n isOldDepositZap[Y_DEPOSIT_POOL] = true; // curve-y\n isOldDepositZap[BUSD_DEPOSIT_POOL] = true; // curve-busd\n isOldDepositZap[SUSD_DEPOSIT_POOL] = true; // curve-susd\n isSwapPool[A_SWAP_POOL] = true; // aToken\n isSwapPool[SA_SWAP_POOL] = true; // saToken\n isSwapPool[Y_SWAP_POOL] = true; // yToken\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n // Note: We are using 18 as decimals for USD and BTC\n maxDepositAmount[_liquidityPool] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function isRedeemableAmountSufficientStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external override returns (bool) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInToken =\n _getAllAmountInTokenStakeWrite(_vault, _underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function getAllAmountInTokenStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) external override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return _getAllAmountInTokenStakeWrite(_vault, _underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function calculateRedeemableLPTokenAmountStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) external override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInToken =\n _getAllAmountInTokenStakeWrite(_vault, _underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapterStakingCurve\n */\n function getUnclaimedRewardTokenAmountWrite(\n address payable _vault,\n address _liquidityPool,\n address\n ) external override returns (uint256) {\n return _getUnclaimedRewardTokenAmountWrite(_vault, _liquidityPool);\n }\n\n /**\n * @dev Maps true to a liquidity pool if it is swap pool\n * @param _liquidityPool swap pool address\n * @param _isSwap set true if the _liquidityPool is a swap pool\n */\n function setIsSwapPool(address _liquidityPool, bool _isSwap) public onlyOperator {\n isSwapPool[_liquidityPool] = _isSwap;\n }\n\n /**\n * @dev Maps true to a liquidity pool if it uses old deposit zap API\n * @param _liquidityPool liquidity pool address\n * @param _isOld set true if the liquidity pool uses old deposit zap's API\n */\n function setIsOldDepositZap(address _liquidityPool, bool _isOld) public onlyOperator {\n isOldDepositZap[_liquidityPool] = _isOld;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n address _swapPool = _getSwapPool(_liquidityPool);\n uint256 _virtualPrice = ICurveSwap(_swapPool).get_virtual_price();\n uint256 _totalSupply = ERC20(getLiquidityPoolToken(address(0), _liquidityPool)).totalSupply();\n // the pool value will be in USD for US dollar stablecoin pools\n // the pool value will be in BTC for BTC pools\n return (_virtualPrice.mul(_totalSupply)).div(10**18);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = ERC20(_underlyingToken).balanceOf(_vault);\n return _getDepositCode(_underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n address _swapPool = _getSwapPool(_liquidityPool);\n address _curveRegistry = _getCurveRegistry();\n address[8] memory _underlyingCoins = _getUnderlyingTokens(_swapPool, _curveRegistry);\n uint256 _nCoins = _getNCoins(_swapPool, _curveRegistry);\n _underlyingTokens = new address[](_nCoins);\n for (uint256 _i = 0; _i < _nCoins; _i++) {\n _underlyingTokens[_i] = _underlyingCoins[_i];\n }\n }\n\n /**\n * @inheritdoc IAdapter\n * @dev Reverting '!empty' message as there is no related functionality for this in CurveDeposit pool\n */\n function calculateAmountInLPToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _underlyingTokenAmount\n ) public view override returns (uint256) {\n if (!isOldDepositZap[_liquidityPool]) {\n if (_underlyingTokenAmount > 0) {\n address _swapPool = _getSwapPool(_liquidityPool);\n uint256 _nCoins = _getNCoins(_swapPool, _getCurveRegistry());\n address[8] memory _underlyingTokens = _getUnderlyingTokens(_swapPool, _getCurveRegistry());\n uint256[] memory _amounts = new uint256[](_nCoins);\n for (uint256 _i; _i < _nCoins; _i++) {\n if (_underlyingTokens[_i] == _underlyingToken) {\n _amounts[_i] = _underlyingTokenAmount;\n }\n }\n if (_nCoins == 2) {\n return ICurveSwap(_liquidityPool).calc_token_amount([_amounts[0], _amounts[1]], true);\n } else if (_nCoins == 3) {\n return ICurveSwap(_liquidityPool).calc_token_amount([_amounts[0], _amounts[1], _amounts[2]], true);\n } else if (_nCoins == 4) {\n return\n ICurveDeposit(_liquidityPool).calc_token_amount(\n [_amounts[0], _amounts[1], _amounts[2], _amounts[3]],\n true\n );\n }\n }\n return uint256(0);\n } else {\n revert(\"!empty\");\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n address _liquidityGauge = _getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry());\n if (_liquidityGauge != address(0)) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _getMinter(_liquidityGauge),\n abi.encodeWithSignature(\"mint(address)\", _liquidityGauge)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _rewardTokenAmount = ERC20(getRewardToken(_liquidityPool)).balanceOf(_vault);\n return getHarvestSomeCodes(_vault, _underlyingToken, _liquidityPool, _rewardTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address _liquidityPool) public view override returns (bool) {\n if (_getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry()) != address(0)) {\n return true;\n }\n return false;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _stakeAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getStakeSomeCodes(_liquidityPool, _stakeAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAllCodes(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory)\n {\n uint256 _unstakeAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeSomeCodes(_liquidityPool, _unstakeAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function calculateRedeemableLPTokenAmountStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n // Note : This function does not take into account unclaimed reward tokens\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInToken = getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function isRedeemableAmountSufficientStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n // Note : This function does not take into account unclaimed reward tokens\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInToken = getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalance);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeAndWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory) {\n return _getDepositCode(_underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n address _swapPool = _getSwapPool(_liquidityPool);\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _liquidityPool);\n\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _amount)\n );\n\n _codes[2] = isSwapPool[_liquidityPool]\n ? abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n \"remove_liquidity_one_coin(uint256,int128,uint256,bool)\",\n _amount,\n _getTokenIndex(_swapPool, _underlyingToken),\n getSomeAmountInToken(_underlyingToken, _liquidityPool, _amount).mul(95).div(100),\n true\n )\n )\n : abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n \"remove_liquidity_one_coin(uint256,int128,uint256)\",\n _amount,\n _getTokenIndex(_swapPool, _underlyingToken),\n getSomeAmountInToken(_underlyingToken, _liquidityPool, _amount).mul(95).div(100)\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return ICurveRegistry(_getCurveRegistry()).get_lp_token(_getSwapPool(_liquidityPool));\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return ERC20(getLiquidityPoolToken(address(0), _liquidityPool)).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n return\n _liquidityPool == Y_SWAP_POOL\n ? ICurveSwap(_liquidityPool).calc_withdraw_one_coin(\n _liquidityPoolTokenAmount,\n _getTokenIndex(_getSwapPool(_liquidityPool), _underlyingToken),\n true\n )\n : ICurveDeposit(_liquidityPool).calc_withdraw_one_coin(\n _liquidityPoolTokenAmount,\n _getTokenIndex(_getSwapPool(_liquidityPool), _underlyingToken)\n );\n }\n return 0;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _liquidityPool) public view override returns (address) {\n address _liquidityGauge = _getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry());\n if (_liquidityGauge != address(0)) {\n return ITokenMinter(_getMinter(_liquidityGauge)).token();\n }\n return address(0);\n }\n\n /* solhint-disable no-empty-blocks */\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable,\n address,\n address\n ) public view override returns (uint256) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /* solhint-disable no-empty-blocks */\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable, address) public view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeSomeCodes(address _liquidityPool, uint256 _stakeAmount)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_stakeAmount > 0) {\n address _liquidityGauge = _getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry());\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _liquidityPool);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityGauge, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityGauge, _stakeAmount)\n );\n _codes[2] = abi.encode(_liquidityGauge, abi.encodeWithSignature(\"deposit(uint256)\", _stakeAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeSomeCodes(address _liquidityPool, uint256 _unstakeAmount)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_unstakeAmount > 0) {\n address _liquidityGauge = _getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry());\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_liquidityGauge, abi.encodeWithSignature(\"withdraw(uint256)\", _unstakeAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getAllAmountInTokenStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n // Note : This function does not take into account unclaimed reward tokens\n uint256 _liquidityPoolTokenBalanceStake = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalanceStake);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getLiquidityPoolTokenBalanceStake(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (uint256)\n {\n return ICurveGauge(_getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry())).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_redeemAmount > 0) {\n _codes = new bytes[](4);\n _codes[0] = getUnstakeSomeCodes(_liquidityPool, _redeemAmount)[0];\n bytes[] memory _withdrawCodes =\n getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n _codes[1] = _withdrawCodes[0];\n _codes[2] = _withdrawCodes[1];\n _codes[3] = _withdrawCodes[2];\n }\n }\n\n /**\n * @notice Returns the balance in underlying for staked liquidityPoolToken balance of holder\n * @dev It should only be implemented in Curve adapters\n * @param _vault Vault contract address\n * @param _underlyingToken Underlying token address for the given liquidity pool\n * @param _liquidityPool Liquidity pool's contract address where the vault has deposited and which is associated\n * to a staking pool where to stake all lpTokens\n * @return Returns the equivalent amount of underlying tokens to the staked amount of liquidityPoolToken\n */\n function _getAllAmountInTokenStakeWrite(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _liquidityPoolTokenBalanceStake\n ) internal returns (uint256) {\n uint256 _b = getSomeAmountInToken(_underlyingToken, _liquidityPool, _liquidityPoolTokenBalanceStake);\n _b = _b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _getUnclaimedRewardTokenAmountWrite(_vault, _liquidityPool)\n )\n );\n return _b;\n }\n\n /*\n * @dev Returns the amount of accrued reward tokens for a specific OptyFi's vault\n * @param _vault Address of the OptyFi's vault contract\n * @param _liquidityPool Address of the pool deposit contract\n * @return Returns the amount of accrued reward tokens\n */\n function _getUnclaimedRewardTokenAmountWrite(address payable _vault, address _liquidityPool)\n internal\n returns (uint256)\n {\n address _liquidityGauge = _getLiquidityGauge(_getSwapPool(_liquidityPool), _getCurveRegistry());\n if (_liquidityGauge != address(0)) {\n return ICurveGauge(_liquidityGauge).claimable_tokens(_vault);\n }\n return uint256(0);\n }\n\n /**\n * @notice Get the Curve Minter's address\n * @param _gauge the liquidity gauge address\n * @return address the address of the minter\n */\n function _getMinter(address _gauge) internal view returns (address) {\n return ICurveGauge(_gauge).minter();\n }\n\n /**\n * @dev This functions returns the token index for a underlying token\n * @param _underlyingToken address of the underlying asset\n * @param _swapPool swap pool address\n * @return _tokenIndex index of coin in swap pool\n */\n function _getTokenIndex(address _swapPool, address _underlyingToken) internal view returns (int128) {\n address[8] memory _underlyingTokens = _getUnderlyingTokens(_swapPool, _getCurveRegistry());\n for (uint256 _i = 0; _i < _underlyingTokens.length; _i++) {\n if (_underlyingTokens[_i] == _underlyingToken) {\n return int128(_i);\n }\n }\n return int128(0);\n }\n\n /**\n * @dev This functions composes the function calls to deposit asset into deposit pool\n * @param _underlyingToken address of the underlying asset\n * @param _liquidityPool liquidity pool address\n * @param _amount the amount in underlying token\n * @return _codes bytes array of function calls to be executed from vault\n * */\n function _getDepositCode(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) internal view returns (bytes[] memory _codes) {\n (\n uint256 _nCoins,\n address[8] memory _underlyingTokens,\n uint256[] memory _amounts,\n uint256 _codeLength,\n uint256 _minAmount\n ) = _getDepositCodeConfig(_underlyingToken, _liquidityPool, _amount);\n if (_codeLength > 1) {\n _codes = new bytes[](_codeLength);\n uint256 _j = 0;\n for (uint256 i = 0; i < _nCoins; i++) {\n if (_amounts[i] > 0) {\n if (_underlyingTokens[i] == HBTC) {\n _codes[_j++] = abi.encode(\n _underlyingTokens[i],\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _amounts[i])\n );\n } else {\n _codes[_j++] = abi.encode(\n _underlyingTokens[i],\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[_j++] = abi.encode(\n _underlyingTokens[i],\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _amounts[i])\n );\n }\n }\n }\n if (_nCoins == uint256(2)) {\n uint256[2] memory _depositAmounts = [_amounts[0], _amounts[1]];\n _codes[_j] = isSwapPool[_liquidityPool]\n ? abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n \"add_liquidity(uint256[2],uint256,bool)\",\n _depositAmounts,\n _minAmount,\n true\n )\n )\n : abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"add_liquidity(uint256[2],uint256)\", _depositAmounts, _minAmount)\n );\n } else if (_nCoins == uint256(3)) {\n uint256[3] memory _depositAmounts = [_amounts[0], _amounts[1], _amounts[2]];\n _codes[_j] = isSwapPool[_liquidityPool]\n ? abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n \"add_liquidity(uint256[3],uint256,bool)\",\n _depositAmounts,\n _minAmount,\n true\n )\n )\n : abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"add_liquidity(uint256[3],uint256)\", _depositAmounts, _minAmount)\n );\n } else if (_nCoins == uint256(4)) {\n uint256[4] memory _depositAmounts = [_amounts[0], _amounts[1], _amounts[2], _amounts[3]];\n _codes[_j] = isSwapPool[_liquidityPool]\n ? abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\n \"add_liquidity(uint256[4],uint256,bool)\",\n _depositAmounts,\n _minAmount,\n true\n )\n )\n : abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"add_liquidity(uint256[4],uint256)\", _depositAmounts, _minAmount)\n );\n }\n }\n }\n\n /**\n * @dev This function composes the configuration required to construct fuction calls\n * @param _underlyingToken address of the underlying asset\n * @param _liquidityPool liquidity pool address\n * @param _amount amount in underlying token\n * @return _nCoins number of underlying tokens in liquidity pool\n * @return _underlyingTokens underlying tokens in a liquidity pool\n * @return _amounts value in an underlying token for each underlying token\n * @return _codeLength number of function call required for deposit\n */\n function _getDepositCodeConfig(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n )\n internal\n view\n returns (\n uint256 _nCoins,\n address[8] memory _underlyingTokens,\n uint256[] memory _amounts,\n uint256 _codeLength,\n uint256 _minAmount\n )\n {\n address _curveRegistry = _getCurveRegistry();\n address _swapPool = _getSwapPool(_liquidityPool);\n _nCoins = _getNCoins(_swapPool, _curveRegistry);\n _underlyingTokens = _getUnderlyingTokens(_swapPool, _curveRegistry);\n _amounts = new uint256[](_nCoins);\n _codeLength = 1;\n for (uint256 _i = 0; _i < _nCoins; _i++) {\n if (_underlyingTokens[_i] == _underlyingToken) {\n _amounts[_i] = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n uint256 _decimals = ERC20(_underlyingToken).decimals();\n if (isOldDepositZap[_liquidityPool]) {\n _minAmount = (_amounts[_i].mul(10**(uint256(36).sub(_decimals))).mul(95)).div(\n ICurveSwap(_swapPool).get_virtual_price().mul(100)\n );\n } else {\n if (_nCoins == 2) {\n _minAmount = ICurveSwap(_liquidityPool)\n .calc_token_amount([_amounts[0], _amounts[1]], true)\n .mul(95)\n .div(100);\n } else if (_nCoins == 3) {\n if (_liquidityPool == Y_SWAP_POOL) {\n _minAmount = (_amounts[_i].mul(10**(uint256(36).sub(_decimals))).mul(95)).div(\n ICurveSwap(_swapPool).get_virtual_price().mul(100)\n );\n } else {\n _minAmount = ICurveSwap(_liquidityPool)\n .calc_token_amount([_amounts[0], _amounts[1], _amounts[2]], true)\n .mul(95)\n .div(100);\n }\n } else if (_nCoins == 4) {\n _minAmount = ICurveDeposit(_liquidityPool)\n .calc_token_amount([_amounts[0], _amounts[1], _amounts[2], _amounts[3]], true)\n .mul(95)\n .div(100);\n }\n }\n\n if (_amounts[_i] > 0) {\n if (_underlyingTokens[_i] == HBTC) {\n _codeLength++;\n } else {\n _codeLength += 2;\n }\n }\n }\n }\n }\n\n /**\n * @dev Get the underlying tokens within a liquidity pool\n * @param _swapPool the swap pool address\n * @param _curveRegistry the address of the Curve registry\n * @return list of underlying token addresses\n */\n function _getUnderlyingTokens(address _swapPool, address _curveRegistry) internal view returns (address[8] memory) {\n return ICurveRegistry(_curveRegistry).get_underlying_coins(_swapPool);\n }\n\n /**\n * @dev Get a liquidity gauge address associated with a liquidity pool\n * @param _swapPool the swap pool address\n * @param _curveRegistry the Curve registry's address\n * @return gauge address\n */\n function _getLiquidityGauge(address _swapPool, address _curveRegistry) internal view returns (address) {\n (address[10] memory _liquidityGauges, ) = ICurveRegistry(_curveRegistry).get_gauges(_swapPool);\n return _liquidityGauges[0];\n }\n\n /**\n * @dev Get the address of swap pool associated with the liquidity pool\n * @param _liquidityPool liquidity pool address\n * @return Address of the swap pool\n */\n function _getSwapPool(address _liquidityPool) internal view returns (address) {\n return\n isSwapPool[_liquidityPool] ? _liquidityPool : isOldDepositZap[_liquidityPool]\n ? ICurveDeposit(_liquidityPool).curve()\n : ICurveDeposit(_liquidityPool).pool();\n }\n\n /**\n * @dev Get the address of the main registry contract\n * @return Address of the main registry contract\n */\n function _getCurveRegistry() internal view returns (address) {\n return ICurveAddressProvider(ADDRESS_PROVIDER).get_registry();\n }\n\n /**\n * @dev Get number of underlying tokens in a liquidity pool\n * @param _swapPool swap pool address associated with liquidity pool\n * @param _curveRegistry address of the main registry contract\n * @return Number of underlying tokens\n */\n function _getNCoins(address _swapPool, address _curveRegistry) internal view returns (uint256) {\n return ICurveRegistry(_curveRegistry).get_n_coins(_swapPool)[1];\n }\n\n /**\n * @dev Get the final value of amount in underlying token to be deposited\n * @param _liquidityPool liquidity pool address\n * @param _underlyingToken underlying token address\n * @param _amount amount in underlying token\n * @return amount in underlying token to be deposited affected by investment limitation\n */\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n return\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountPct(_liquidityPool, _underlyingToken, _amount)\n : _getMaxDepositAmount(_liquidityPool, _underlyingToken, _amount);\n }\n\n /**\n * @dev Gets the maximum amount in underlying token limited by percentage\n * @param _liquidityPool liquidity pool address\n * @param _underlyingToken underlying token address\n * @param _amount amount in underlying token\n * @return amount in underlying token to be deposited affected by\n * investment limit in percentage\n */\n function _getMaxDepositAmountPct(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, _underlyingToken);\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _decimals = ERC20(_underlyingToken).decimals();\n uint256 _actualAmount = _amount.mul(10**(uint256(18).sub(_decimals)));\n uint256 _limit =\n _poolPct == 0 ? _poolValue.mul(maxDepositProtocolPct).div(10000) : _poolValue.mul(_poolPct).div(10000);\n return _actualAmount > _limit ? _limit.div(10**(uint256(18).sub(_decimals))) : _amount;\n }\n\n /**\n * @dev Gets the maximum amount in underlying token affected by investment\n * limit set for liquidity pool in amount\n * @param _liquidityPool liquidity pool address\n * @param _underlyingToken underlying token address\n * @param _amount amount in underlying token\n * @return amount in underlying token to be deposited affected by\n * investment limit set for liquidity pool in amount\n */\n function _getMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _decimals = ERC20(_underlyingToken).decimals();\n uint256 _maxAmount = maxDepositAmount[_liquidityPool].div(10**(uint256(18).sub(_decimals)));\n return _amount > _maxAmount ? _maxAmount : _amount;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/harvest.finance/HarvestV1Adapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IHarvestDeposit } from \"@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestDeposit.sol\";\nimport { IHarvestFarm } from \"@optyfi/defi-legos/ethereum/harvest.finance/contracts/IHarvestFarm.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { IAdapterStaking } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol\";\n\n/**\n * @title Adapter for Harvest.finance protocol\n * @author Opty.fi\n * @dev Abstraction layer to harvest finance's pools\n */\n\ncontract HarvestV1Adapter is IAdapter, IAdapterHarvestReward, IAdapterStaking, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n // deposit pools\n address public constant TBTC_SBTC_CRV_DEPOSIT = address(0x640704D106E79e105FDA424f05467F005418F1B5);\n address public constant THREE_CRV_DEPOSIT = address(0x71B9eC42bB3CB40F017D8AD8011BE8e384a95fa5);\n address public constant Y_CRV_DEPOSIT = address(0x0FE4283e0216F94f5f9750a7a11AC54D3c9C38F3);\n address public constant DAI_DEPOSIT = address(0xab7FA2B2985BCcfC13c6D86b1D5A17486ab1e04C);\n address public constant USDC_DEPOSIT = address(0xf0358e8c3CD5Fa238a29301d0bEa3D63A17bEdBE);\n address public constant USDT_DEPOSIT = address(0x053c80eA73Dc6941F518a68E2FC52Ac45BDE7c9C);\n address public constant TUSD_DEPOSIT = address(0x7674622c63Bee7F46E86a4A5A18976693D54441b);\n address public constant REN_WBTC_CRV_DEPOSIT = address(0x9aA8F427A17d6B0d91B6262989EdC7D45d6aEdf8);\n address public constant WBTC_DEPOSIT = address(0x5d9d25c7C457dD82fc8668FFC6B9746b674d4EcB);\n address public constant RENBTC_DEPOSIT = address(0xC391d1b08c1403313B0c28D47202DFDA015633C4);\n address public constant WETH_DEPOSIT = address(0xFE09e53A81Fe2808bc493ea64319109B5bAa573e);\n address public constant COMPOUND_CRV_DEPOSIT = address(0x998cEb152A42a3EaC1f555B1E911642BeBf00faD);\n address public constant USDN_3CRV_DEPOSIT = address(0x683E683fBE6Cf9b635539712c999f3B3EdCB8664);\n address public constant BUSD_CRV_DEPOSIT = address(0x4b1cBD6F6D8676AcE5E412C78B7a59b4A1bbb68a);\n address public constant HCRV_DEPOSIT = address(0xCC775989e76ab386E9253df5B0c0b473E22102E2);\n address public constant OBTC_SBTC_CRV_DEPOSIT = address(0x966A70A4d3719A6De6a94236532A0167d5246c72);\n address public constant STE_CRV_DEPOSIT = address(0xc27bfE32E0a934a12681C1b35acf0DBA0e7460Ba);\n address public constant UNI_ETH_DPI_DEPOSIT = address(0x2a32dcBB121D48C106F6d94cf2B4714c0b4Dfe48);\n address public constant SUSHI_ETH_SUSHI_DEPOSIT = address(0x5aDe382F38A09A1F8759D06fFE2067992ab5c78e);\n address public constant SUSHI_ETH_DAI_DEPOSIT = address(0x203E97aa6eB65A1A02d9E80083414058303f241E);\n address public constant SUSHI_ETH_USDC_DEPOSIT = address(0x01bd09A1124960d9bE04b638b142Df9DF942b04a);\n address public constant SUSHI_ETH_USDT_DEPOSIT = address(0x64035b583c8c694627A199243E863Bb33be60745);\n address public constant SUSHI_ETH_WBTC_DEPOSIT = address(0x5C0A3F55AAC52AA320Ff5F280E77517cbAF85524);\n address public constant HUSD_3CRV_DEPOSIT = address(0x29780C39164Ebbd62e9DDDE50c151810070140f2);\n address public constant EURS_CRV_DEPOSIT = address(0x6eb941BD065b8a5bd699C5405A928c1f561e2e5a);\n address public constant GUSD_3CRV_DEPOSIT = address(0xB8671E33fcFC7FEA2F7a3Ea4a117F065ec4b009E);\n address public constant UST_3CRV_DEPOSIT = address(0x84A1DfAdd698886A614fD70407936816183C0A02);\n address public constant UNI_UST_MAAPLE_DEPOSIT = address(0x11804D69AcaC6Ae9466798325fA7DE023f63Ab53);\n address public constant UNI_UST_MAMZN_DEPOSIT = address(0x8334A61012A779169725FcC43ADcff1F581350B7);\n address public constant UNI_UST_MGOOGL_DEPOSIT = address(0x07DBe6aA35EF70DaD124f4e2b748fFA6C9E1963a);\n address public constant UNI_UST_MTSLA_DEPOSIT = address(0xC800982d906671637E23E031e907d2e3487291Bc);\n\n // staking vaults\n address public constant TBTC_SBTC_CRV_STAKE = address(0x017eC1772A45d2cf68c429A820eF374f0662C57c);\n address public constant THREE_CRV_STAKE = address(0x27F12d1a08454402175b9F0b53769783578Be7d9);\n address public constant Y_CRV_STAKE = address(0x6D1b6Ea108AA03c6993d8010690264BA96D349A8);\n address public constant DAI_STAKE = address(0x15d3A64B2d5ab9E152F16593Cdebc4bB165B5B4A);\n address public constant USDC_STAKE = address(0x4F7c28cCb0F1Dbd1388209C67eEc234273C878Bd);\n address public constant USDT_STAKE = address(0x6ac4a7AB91E6fD098E13B7d347c6d4d1494994a2);\n address public constant TUSD_STAKE = address(0xeC56a21CF0D7FeB93C25587C12bFfe094aa0eCdA);\n address public constant REN_WBTC_CRV_STAKE = address(0xA3Cf8D1CEe996253FAD1F8e3d68BDCba7B3A3Db5);\n address public constant WBTC_STAKE = address(0x917d6480Ec60cBddd6CbD0C8EA317Bcc709EA77B);\n address public constant RENBTC_STAKE = address(0x7b8Ff8884590f44e10Ea8105730fe637Ce0cb4F6);\n address public constant WETH_STAKE = address(0x3DA9D911301f8144bdF5c3c67886e5373DCdff8e);\n address public constant COMPOUND_CRV_STAKE = address(0xC0f51a979e762202e9BeF0f62b07F600d0697DE1);\n address public constant USDN_3CRV_STAKE = address(0xef4Da1CE3f487DA2Ed0BE23173F76274E0D47579);\n address public constant BUSD_CRV_STAKE = address(0x093C2ae5E6F3D2A897459aa24551289D462449AD);\n address public constant HCRV_STAKE = address(0x01f9CAaD0f9255b0C0Aa2fBD1c1aA06ad8Af7254);\n address public constant OBTC_SBTC_CRV_STAKE = address(0x91B5cD52fDE8dbAC37C95ECafEF0a70bA4c182fC);\n address public constant STE_CRV_STAKE = address(0x2E25800957742C52b4d69b65F9C67aBc5ccbffe6);\n address public constant UNI_ETH_DPI_STAKE = address(0xAd91695b4BeC2798829ac7a4797E226C78f22Abd);\n address public constant SUSHI_ETH_SUSHI_STAKE = address(0x16fBb193f99827C92A4CC22EFe8eD7390465BFa3);\n address public constant SUSHI_ETH_DAI_STAKE = address(0x76Aef359a33C02338902aCA543f37de4b01BA1FA);\n address public constant SUSHI_ETH_USDC_STAKE = address(0x6B4e1E0656Dd38F36c318b077134487B9b0cf7a6);\n address public constant SUSHI_ETH_USDT_STAKE = address(0xA56522BCA0A09f57B85C52c0Cc8Ba1B5eDbc64ef);\n address public constant SUSHI_ETH_WBTC_STAKE = address(0xE2D9FAe95f1e68afca7907dFb36143781f917194);\n address public constant HUSD_3CRV_STAKE = address(0x72C50e6FD8cC5506E166c273b6E814342Aa0a3c1);\n address public constant EURS_CRV_STAKE = address(0xf4d50f60D53a230abc8268c6697972CB255Cd940);\n address public constant GUSD_3CRV_STAKE = address(0x538613A19Eb84D86a4CcfcB63548244A52Ab0B68);\n address public constant UST_3CRV_STAKE = address(0xDdb5D3CCd968Df64Ce48b577776BdC29ebD3120e);\n address public constant UNI_UST_MAAPLE_STAKE = address(0xc02d1Da469d68Adc651Dd135d1A7f6b42F4d1A57);\n address public constant UNI_UST_MAMZN_STAKE = address(0x8Dc427Cbcc75cAe58dD4f386979Eba6662f5C158);\n address public constant UNI_UST_MGOOGL_STAKE = address(0xfE83a00DF3A98dE218c08719FAF7e3741b220D0D);\n address public constant UNI_UST_MTSLA_STAKE = address(0x40C34B0E1bb6984810E17474c6B0Bcc6A6B46614);\n\n /** @notice max deposit's default value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to staking vault */\n mapping(address => address) public liquidityPoolToStakingVault;\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n liquidityPoolToStakingVault[TBTC_SBTC_CRV_DEPOSIT] = TBTC_SBTC_CRV_STAKE;\n liquidityPoolToStakingVault[THREE_CRV_DEPOSIT] = THREE_CRV_STAKE;\n liquidityPoolToStakingVault[Y_CRV_DEPOSIT] = Y_CRV_STAKE;\n liquidityPoolToStakingVault[DAI_DEPOSIT] = DAI_STAKE;\n liquidityPoolToStakingVault[USDC_DEPOSIT] = USDC_STAKE;\n liquidityPoolToStakingVault[USDT_DEPOSIT] = USDT_STAKE;\n liquidityPoolToStakingVault[TUSD_DEPOSIT] = TUSD_STAKE;\n liquidityPoolToStakingVault[REN_WBTC_CRV_DEPOSIT] = REN_WBTC_CRV_STAKE;\n liquidityPoolToStakingVault[WBTC_DEPOSIT] = WBTC_STAKE;\n liquidityPoolToStakingVault[RENBTC_DEPOSIT] = RENBTC_STAKE;\n liquidityPoolToStakingVault[WETH_DEPOSIT] = WETH_STAKE;\n liquidityPoolToStakingVault[COMPOUND_CRV_DEPOSIT] = COMPOUND_CRV_STAKE;\n liquidityPoolToStakingVault[USDN_3CRV_DEPOSIT] = USDN_3CRV_STAKE;\n liquidityPoolToStakingVault[BUSD_CRV_DEPOSIT] = BUSD_CRV_STAKE;\n liquidityPoolToStakingVault[HCRV_DEPOSIT] = HCRV_STAKE;\n liquidityPoolToStakingVault[OBTC_SBTC_CRV_DEPOSIT] = OBTC_SBTC_CRV_STAKE;\n liquidityPoolToStakingVault[STE_CRV_DEPOSIT] = STE_CRV_STAKE;\n liquidityPoolToStakingVault[UNI_ETH_DPI_DEPOSIT] = UNI_ETH_DPI_STAKE;\n liquidityPoolToStakingVault[SUSHI_ETH_SUSHI_DEPOSIT] = SUSHI_ETH_SUSHI_STAKE;\n liquidityPoolToStakingVault[SUSHI_ETH_DAI_DEPOSIT] = SUSHI_ETH_DAI_STAKE;\n liquidityPoolToStakingVault[SUSHI_ETH_USDC_DEPOSIT] = SUSHI_ETH_USDC_STAKE;\n liquidityPoolToStakingVault[SUSHI_ETH_USDT_DEPOSIT] = SUSHI_ETH_USDT_STAKE;\n liquidityPoolToStakingVault[SUSHI_ETH_WBTC_DEPOSIT] = SUSHI_ETH_WBTC_STAKE;\n liquidityPoolToStakingVault[HUSD_3CRV_DEPOSIT] = HUSD_3CRV_STAKE;\n liquidityPoolToStakingVault[EURS_CRV_DEPOSIT] = EURS_CRV_STAKE;\n liquidityPoolToStakingVault[GUSD_3CRV_DEPOSIT] = GUSD_3CRV_STAKE;\n liquidityPoolToStakingVault[UST_3CRV_DEPOSIT] = UST_3CRV_STAKE;\n liquidityPoolToStakingVault[UNI_UST_MAAPLE_DEPOSIT] = UNI_UST_MAAPLE_STAKE;\n liquidityPoolToStakingVault[UNI_UST_MAMZN_DEPOSIT] = UNI_UST_MAMZN_STAKE;\n liquidityPoolToStakingVault[UNI_UST_MGOOGL_DEPOSIT] = UNI_UST_MGOOGL_STAKE;\n liquidityPoolToStakingVault[UNI_UST_MTSLA_DEPOSIT] = UNI_UST_MTSLA_STAKE;\n\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @notice Map the liquidity pool to its Staking vault address\n * @param _liquidityPool liquidity pool address to be mapped with staking vault\n * @param _stakingVault staking vault address to be linked with liquidity pool\n */\n function setLiquidityPoolToStakingVault(address _liquidityPool, address _stakingVault) public onlyOperator {\n liquidityPoolToStakingVault[_liquidityPool] = _stakingVault;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IHarvestDeposit(_liquidityPool).underlying();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return\n _depositAmount.mul(10**IHarvestDeposit(_liquidityPool).decimals()).div(\n IHarvestDeposit(_liquidityPool).getPricePerFullShare()\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_stakingVault, abi.encodeWithSignature(\"getReward()\"));\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _rewardTokenAmount = IERC20(getRewardToken(_liquidityPool)).balanceOf(_vault);\n return getHarvestSomeCodes(_vault, _underlyingToken, _liquidityPool, _rewardTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return true;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _depositAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getStakeSomeCodes(_liquidityPool, _depositAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAllCodes(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory)\n {\n uint256 _redeemAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeSomeCodes(_liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function calculateRedeemableLPTokenAmountStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n uint256 _liquidityPoolTokenBalance = IHarvestFarm(_stakingVault).balanceOf(_vault);\n uint256 _balanceInToken = getAllAmountInTokenStake(_vault, _underlyingToken, _liquidityPool);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function isRedeemableAmountSufficientStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInTokenStake = getAllAmountInTokenStake(_vault, _underlyingToken, _liquidityPool);\n return _balanceInTokenStake >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _unstakeAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeAndWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _unstakeAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _depositAmount)\n );\n _codes[2] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"deposit(uint256)\", _depositAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _shares\n ) public view override returns (bytes[] memory _codes) {\n if (_shares > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n getLiquidityPoolToken(_underlyingToken, _liquidityPool),\n abi.encodeWithSignature(\"withdraw(uint256)\", _shares)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return IHarvestDeposit(_liquidityPool).underlyingBalanceWithInvestment();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n uint256 b =\n getSomeAmountInToken(\n _underlyingToken,\n _liquidityPool,\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool)\n );\n uint256 _unclaimedReward = getUnclaimedRewardTokenAmount(_vault, _liquidityPool, _underlyingToken);\n if (_unclaimedReward > 0) {\n b = b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _unclaimedReward\n )\n );\n }\n return b;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(_liquidityPool).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount\n .mul(IHarvestDeposit(_liquidityPool).getPricePerFullShare())\n .div(10**IHarvestDeposit(_liquidityPool).decimals());\n }\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _liquidityPool) public view override returns (address) {\n return IHarvestFarm(liquidityPoolToStakingVault[_liquidityPool]).rewardToken();\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable _vault,\n address _liquidityPool,\n address\n ) public view override returns (uint256) {\n return IHarvestFarm(liquidityPoolToStakingVault[_liquidityPool]).earned(_vault);\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /* solhint-disable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable, address) public view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeSomeCodes(address _liquidityPool, uint256 _shares)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_shares > 0) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _liquidityPool);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _stakingVault, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _stakingVault, _shares)\n );\n _codes[2] = abi.encode(_stakingVault, abi.encodeWithSignature(\"stake(uint256)\", _shares));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeSomeCodes(address _liquidityPool, uint256 _shares)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_shares > 0) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_stakingVault, abi.encodeWithSignature(\"withdraw(uint256)\", _shares));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getAllAmountInTokenStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n uint256 b = IHarvestFarm(_stakingVault).balanceOf(_vault);\n if (b > 0) {\n b = b.mul(IHarvestDeposit(_liquidityPool).getPricePerFullShare()).div(\n 10**IHarvestDeposit(_liquidityPool).decimals()\n );\n }\n uint256 _unclaimedReward = getUnclaimedRewardTokenAmount(_vault, _liquidityPool, _underlyingToken);\n if (_unclaimedReward > 0) {\n b = b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _unclaimedReward\n )\n );\n }\n return b;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getLiquidityPoolTokenBalanceStake(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (uint256)\n {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n return IHarvestFarm(_stakingVault).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_redeemAmount > 0) {\n _codes = new bytes[](2);\n _codes[0] = getUnstakeSomeCodes(_liquidityPool, _redeemAmount)[0];\n _codes[1] = getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount)[0];\n }\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n\n function _getUnderlyingToken(address _liquidityPoolToken) internal view returns (address) {\n return IHarvestDeposit(_liquidityPoolToken).underlying();\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/dforce/DForceAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IDForceDeposit } from \"@optyfi/defi-legos/ethereum/dforce/contracts/IDForceDeposit.sol\";\nimport { IDForceStake } from \"@optyfi/defi-legos/ethereum/dforce/contracts/IDForceStake.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { IAdapterStaking } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterStaking.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\n\n/**\n * @title Adapter for DForce protocol\n * @author Opty.fi\n * @dev Abstraction layer to DForce's pools\n */\n\ncontract DForceAdapter is IAdapter, IAdapterHarvestReward, IAdapterStaking, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice DForce's reward token address */\n address public rewardToken;\n\n // deposit pools\n address public constant USDT_DEPOSIT_POOL = address(0x868277d475E0e475E38EC5CdA2d9C83B5E1D9fc8);\n address public constant USDC_DEPOSIT_POOL = address(0x16c9cF62d8daC4a38FB50Ae5fa5d51E9170F3179);\n address public constant DAI_DEPOSIT_POOL = address(0x02285AcaafEB533e03A7306C55EC031297df9224);\n\n // staking vaults\n address public constant USDT_STAKING_VAULT = address(0x324EebDAa45829c6A8eE903aFBc7B61AF48538df);\n address public constant USDC_STAKING_VAULT = address(0xB71dEFDd6240c45746EC58314a01dd6D833fD3b5);\n address public constant DAI_STAKING_VAULT = address(0xD2fA07cD6Cd4A5A96aa86BacfA6E50bB3aaDBA8B);\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to staking vault */\n mapping(address => address) public liquidityPoolToStakingVault;\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n liquidityPoolToStakingVault[USDT_DEPOSIT_POOL] = USDT_STAKING_VAULT;\n liquidityPoolToStakingVault[USDC_DEPOSIT_POOL] = USDC_STAKING_VAULT;\n liquidityPoolToStakingVault[DAI_DEPOSIT_POOL] = DAI_STAKING_VAULT;\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @notice Map the liquidity pool to its Staking vault address\n * @param _liquidityPool liquidity pool address to be mapped with staking vault\n * @param _stakingVault staking vault address to be linked with liquidity pool\n */\n function setLiquidityPoolToStakingVault(address _liquidityPool, address _stakingVault) public onlyOperator {\n require(\n liquidityPoolToStakingVault[_liquidityPool] != _stakingVault,\n \"liquidityPoolToStakingVault already set\"\n );\n liquidityPoolToStakingVault[_liquidityPool] = _stakingVault;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IDForceDeposit(_liquidityPool).token();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount\n .mul(IDForceDeposit(_liquidityPool).getExchangeRate())\n .div(10**IDForceDeposit(_liquidityPool).decimals());\n }\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return\n _depositAmount.mul(10**(IDForceDeposit(_liquidityPool).decimals())).div(\n IDForceDeposit(_liquidityPool).getExchangeRate()\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n require(_balanceInToken > 0, \"!balance\");\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_stakingVault, abi.encodeWithSignature(\"getReward()\"));\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _rewardTokenAmount = IERC20(getRewardToken(_liquidityPool)).balanceOf(_vault);\n return getHarvestSomeCodes(_vault, _underlyingToken, _liquidityPool, _rewardTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return true;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _stakeAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getStakeSomeCodes(_liquidityPool, _stakeAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAllCodes(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory)\n {\n uint256 _unstakeAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeSomeCodes(_liquidityPool, _unstakeAmount);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function calculateRedeemableLPTokenAmountStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n uint256 _balanceInTokenStake = getAllAmountInTokenStake(_vault, _underlyingToken, _liquidityPool);\n require(_balanceInTokenStake > 0, \"!balance\");\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInTokenStake).add(1);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function isRedeemableAmountSufficientStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInTokenStake = getAllAmountInTokenStake(_vault, _underlyingToken, _liquidityPool);\n return _balanceInTokenStake >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalanceStake(_vault, _liquidityPool);\n return getUnstakeAndWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _depositAmount)\n );\n _codes[2] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"mint(address,uint256)\", _vault, _depositAmount)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_redeemAmount > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n getLiquidityPoolToken(_underlyingToken, _liquidityPool),\n abi.encodeWithSignature(\"redeem(address,uint256)\", _vault, _redeemAmount)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return IDForceDeposit(_liquidityPool).getLiquidity();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IDForceDeposit(_liquidityPool).getTokenBalance(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(_liquidityPool).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _liquidityPool) public view override returns (address) {\n return IDForceStake(liquidityPoolToStakingVault[_liquidityPool]).df();\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable _vault,\n address _liquidityPool,\n address\n ) public view override returns (uint256) {\n return IDForceStake(liquidityPoolToStakingVault[_liquidityPool]).earned(_vault);\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /* solhint-disable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable, address) public view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getStakeSomeCodes(address _liquidityPool, uint256 _shares)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_shares > 0) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n address _liquidityPoolToken = getLiquidityPoolToken(address(0), _liquidityPool);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _stakingVault, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _stakingVault, _shares)\n );\n _codes[2] = abi.encode(_stakingVault, abi.encodeWithSignature(\"stake(uint256)\", _shares));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeSomeCodes(address _liquidityPool, uint256 _shares)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n if (_shares > 0) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n _codes = new bytes[](1);\n _codes[0] = abi.encode(_stakingVault, abi.encodeWithSignature(\"withdraw(uint256)\", _shares));\n }\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getAllAmountInTokenStake(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n uint256 b = IERC20(_stakingVault).balanceOf(_vault);\n if (b > 0) {\n b = b.mul(IDForceDeposit(getLiquidityPoolToken(_underlyingToken, _liquidityPool)).getExchangeRate()).div(\n 1e18\n );\n }\n uint256 _unclaimedReward = getUnclaimedRewardTokenAmount(_vault, _liquidityPool, _underlyingToken);\n if (_unclaimedReward > 0) {\n b = b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _unclaimedReward\n )\n );\n }\n return b;\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getLiquidityPoolTokenBalanceStake(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (uint256)\n {\n address _stakingVault = liquidityPoolToStakingVault[_liquidityPool];\n return IERC20(_stakingVault).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapterStaking\n */\n function getUnstakeAndWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bytes[] memory _codes) {\n if (_redeemAmount > 0) {\n _codes = new bytes[](2);\n _codes[0] = getUnstakeSomeCodes(_liquidityPool, _redeemAmount)[0];\n _codes[1] = getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount)[0];\n }\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/compound/CompoundETHGateway.sol": { + "content": "// SPDX-License-Identifier:MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IWETH } from \"@optyfi/defi-legos/interfaces/misc/contracts/IWETH.sol\";\nimport { ICompound } from \"@optyfi/defi-legos/ethereum/compound/contracts/ICompound.sol\";\nimport { IETHGateway } from \"@optyfi/defi-legos/interfaces/misc/contracts/IETHGateway.sol\";\n\n/**\n * @title ETH gateway for opty-fi's Compound adapter\n * @author Opty.fi\n * @dev Inspired from Aave WETH gateway\n */\ncontract CompoundETHGateway is IETHGateway, Modifiers {\n // solhint-disable-next-line var-name-mixedcase\n IWETH internal immutable WETH;\n\n // solhint-disable-next-line var-name-mixedcase\n address public immutable CETH;\n\n /**\n * @dev Sets the WETH address.\n * @param weth Address of the Wrapped Ether contract\n **/\n constructor(\n address weth,\n address _registry,\n address _ceth\n ) public Modifiers(_registry) {\n WETH = IWETH(weth);\n CETH = _ceth;\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function depositETH(\n address _vault,\n address _liquidityPool,\n address,\n uint256[2] memory _amounts,\n int128\n ) external override {\n IERC20(address(WETH)).transferFrom(_vault, address(this), _amounts[0]);\n WETH.withdraw(_amounts[0]);\n ICompound(_liquidityPool).mint{ value: address(this).balance }();\n IERC20(_liquidityPool).transfer(_vault, IERC20(_liquidityPool).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function withdrawETH(\n address _vault,\n address _liquidityPool,\n address,\n uint256 _amount,\n int128\n ) external override {\n IERC20(_liquidityPool).transferFrom(_vault, address(this), _amount);\n ICompound(_liquidityPool).redeem(_amount);\n WETH.deposit{ value: address(this).balance }();\n IERC20(address(WETH)).transfer(_vault, IERC20(address(WETH)).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function emergencyTokenTransfer(\n address _token,\n address _to,\n uint256 _amount\n ) external override onlyOperator {\n IERC20(_token).transfer(_to, _amount);\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function emergencyEtherTransfer(address to, uint256 amount) external override onlyOperator {\n _safeTransferETH(to, amount);\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function getWETHAddress() external view override returns (address) {\n return address(WETH);\n }\n\n /**\n * @dev transfer ETH to an address, revert if it fails.\n * @param _to recipient of the transfer\n * @param _value the amount to send\n */\n function _safeTransferETH(address _to, uint256 _value) internal {\n // solhint-disable-next-line avoid-low-level-calls\n (bool _success, ) = _to.call{ value: _value }(new bytes(0));\n require(_success, \"ETH_TRANSFER_FAILED\");\n }\n\n /**\n * @dev Only WETH and CETH contracts are allowed to transfer ETH here. Prevent other addresses\n * to send Ether to this contract.\n */\n receive() external payable {\n require(msg.sender == address(WETH) || msg.sender == address(CETH), \"Receive not allowed\");\n }\n\n /**\n * @dev Revert fallback calls\n */\n fallback() external payable {\n revert(\"Fallback not allowed\");\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/compound/CompoundAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { CompoundETHGateway } from \"./CompoundETHGateway.sol\";\n\n// interfaces\nimport { ICompound } from \"@optyfi/defi-legos/ethereum/compound/contracts/ICompound.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for Compound protocol\n * @author Opty.fi\n * @dev Abstraction layer to Compound's pools\n */\n\ncontract CompoundAdapter is IAdapter, IAdapterHarvestReward, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @dev ETH gateway contract for compound adapter */\n address public immutable compoundETHGatewayContract;\n\n /**\n * @notice Compound's ETH liquidity pool contract address\n * @dev It is required to cover edge case of depositing\n * ETH to Compound's ETH liquidity pool contract\n */\n address public constant CETH = address(0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5);\n\n /** WETH ERC20 token address */\n address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n compoundETHGatewayContract = address(new CompoundETHGateway(WETH, _registry, CETH));\n setMaxDepositProtocolPct(uint256(10000)); // 100% (basis points)\n setMaxDepositProtocolMode(MaxExposure.Pct);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n require(_liquidityPool.isContract(), \"!isContract\");\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n require(_liquidityPool.isContract(), \"!_liquidityPool.isContract()\");\n require(_underlyingToken.isContract(), \"!_underlyingToken.isContract()\");\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) public override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) public override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = _liquidityPool == CETH ? address(WETH) : ICompound(_liquidityPool).underlying();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return\n _depositAmount.mul(1e18).div(\n ICompound(getLiquidityPoolToken(_underlyingToken, _liquidityPool)).exchangeRateStored()\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n ICompound(_liquidityPool).comptroller(),\n abi.encodeWithSignature(\"claimComp(address)\", _vault)\n );\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _rewardTokenAmount = IERC20(getRewardToken(_liquidityPool)).balanceOf(_vault);\n return getHarvestSomeCodes(_vault, _underlyingToken, _liquidityPool, _rewardTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n address _lendingPool = _liquidityPool == CETH ? compoundETHGatewayContract : _liquidityPool;\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _depositAmount)\n );\n if (_liquidityPool == CETH) {\n _codes[2] = abi.encode(\n compoundETHGatewayContract,\n abi.encodeWithSignature(\n \"depositETH(address,address,address,uint256[2],int128)\",\n _vault,\n _liquidityPool,\n _liquidityPool,\n [uint256(_depositAmount), uint256(0)],\n int128(0)\n )\n );\n } else {\n _codes[2] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"mint(uint256)\", _depositAmount));\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n if (_liquidityPool == CETH) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"approve(address,uint256)\", compoundETHGatewayContract, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPool,\n abi.encodeWithSignature(\"approve(address,uint256)\", compoundETHGatewayContract, uint256(_amount))\n );\n _codes[2] = abi.encode(\n compoundETHGatewayContract,\n abi.encodeWithSignature(\n \"withdrawETH(address,address,address,uint256,int128)\",\n _vault,\n _liquidityPool,\n _liquidityPool,\n uint256(_amount),\n int128(0)\n )\n );\n } else {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n getLiquidityPoolToken(_underlyingToken, _liquidityPool),\n abi.encodeWithSignature(\"redeem(uint256)\", uint256(_amount))\n );\n }\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return ICompound(_liquidityPool).getCash();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n // Mantisa 1e18 to decimals\n uint256 b =\n getSomeAmountInToken(\n _underlyingToken,\n _liquidityPool,\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool)\n );\n uint256 _unclaimedReward = getUnclaimedRewardTokenAmount(_vault, _liquidityPool, _underlyingToken);\n if (_unclaimedReward > 0) {\n b = b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _unclaimedReward\n )\n );\n }\n return b;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(_liquidityPool).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount\n .mul(ICompound(_liquidityPool).exchangeRateStored())\n .div(1e18);\n }\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _liquidityPool) public view override returns (address) {\n return ICompound(ICompound(_liquidityPool).comptroller()).getCompAddress();\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable,\n address,\n address\n ) public view override returns (uint256) {\n // Requires write call to get unclaimed COMP tokens\n return uint256(0);\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /* solhint-disable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable, address) public view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/aave/AaveV1ETHGateway.sol": { + "content": "// SPDX-License-Identifier:MIT\npragma solidity 0.6.12;\npragma experimental ABIEncoderV2;\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IWETH } from \"@optyfi/defi-legos/interfaces/misc/contracts/IWETH.sol\";\nimport { ILendingPool } from \"@optyfi/defi-legos/ethereum/aave/contracts/ILendingPool.sol\";\nimport { IAaveV1Token } from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1Token.sol\";\nimport { IETHGateway } from \"@optyfi/defi-legos/interfaces/misc/contracts/IETHGateway.sol\";\nimport {\n IAaveV1LendingPoolAddressesProvider\n} from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1LendingPoolAddressesProvider.sol\";\n\n/**\n * @title ETH gateway for opty-fi's AaveV1 adapter\n * @author Opty.fi\n * @dev Inspired from Aave WETH gateway\n */\ncontract AaveV1ETHGateway is IETHGateway, Modifiers {\n // solhint-disable-next-line var-name-mixedcase\n IWETH internal immutable WETH;\n\n // solhint-disable-next-line var-name-mixedcase\n address public immutable AETH;\n\n // solhint-disable-next-line var-name-mixedcase\n address public constant ETH = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\n\n // solhint-disable-next-line var-name-mixedcase\n address public AaveV1LendingPool;\n\n // solhint-disable-next-line var-name-mixedcase\n address public AaveV1LendingPoolCore;\n\n /**\n * @dev Sets the WETH and AETH (AaveV1 Eth pool) addresses along with registry.\n * @param weth Address of the Wrapped Ether contract\n * @param _registry Registry contract address\n * @param _aeth Address of the aETH liquidity pool\n **/\n constructor(\n address weth,\n address _registry,\n address _aeth\n ) public Modifiers(_registry) {\n WETH = IWETH(weth);\n AETH = _aeth;\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function depositETH(\n address _vault,\n address _liquidityPoolAddressProvider,\n address _liquidityPool,\n uint256[2] memory _amounts,\n int128\n ) external override {\n // Setting AaveV1LendingPool and AaveV1LendingPoolCore as these are used in receive ETH function\n AaveV1LendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n AaveV1LendingPoolCore = _getLendingPoolCore(_liquidityPoolAddressProvider);\n IERC20(address(WETH)).transferFrom(_vault, address(this), _amounts[0]);\n WETH.withdraw(_amounts[0]);\n ILendingPool(AaveV1LendingPool).deposit{ value: address(this).balance }(ETH, _amounts[0], uint16(0));\n IERC20(_liquidityPool).transfer(_vault, IERC20(_liquidityPool).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function withdrawETH(\n address _vault,\n address _liquidityPoolAddressProvider,\n address _liquidityPool,\n uint256 _amount,\n int128\n ) external override {\n // Setting AaveV1LendingPool and AaveV1LendingPoolCore as these are used in receive ETH function\n AaveV1LendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n AaveV1LendingPoolCore = _getLendingPoolCore(_liquidityPoolAddressProvider);\n IERC20(_liquidityPool).transferFrom(_vault, address(this), _amount);\n IAaveV1Token(_liquidityPool).redeem(_amount);\n WETH.deposit{ value: address(this).balance }();\n IERC20(address(WETH)).transfer(_vault, IERC20(address(WETH)).balanceOf(address(this)));\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function emergencyTokenTransfer(\n address _token,\n address _to,\n uint256 _amount\n ) external override onlyOperator {\n IERC20(_token).transfer(_to, _amount);\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function emergencyEtherTransfer(address to, uint256 amount) external override onlyOperator {\n _safeTransferETH(to, amount);\n }\n\n /**\n * @inheritdoc IETHGateway\n */\n function getWETHAddress() external view override returns (address) {\n return address(WETH);\n }\n\n /**\n * @dev transfer ETH to an address, revert if it fails.\n * @param _to recipient of the transfer\n * @param _value the amount to send\n */\n function _safeTransferETH(address _to, uint256 _value) internal {\n // solhint-disable-next-line avoid-low-level-calls\n (bool _success, ) = _to.call{ value: _value }(new bytes(0));\n require(_success, \"ETH_TRANSFER_FAILED\");\n }\n\n /**\n * @dev Function to get the AaveV1's Lending Pool's address\n * @param _lendingPoolAddressProvider AaveV1's Lending pool address provider contract's address\n */\n function _getLendingPool(address _lendingPoolAddressProvider) internal view returns (address) {\n return IAaveV1LendingPoolAddressesProvider(_lendingPoolAddressProvider).getLendingPool();\n }\n\n /**\n * @dev Function to get the AaveV1's Lending Pool Core's address\n * @param _lendingPoolAddressProvider AaveV1's Lending pool address provider contract's address\n */\n function _getLendingPoolCore(address _lendingPoolAddressProvider) internal view returns (address) {\n return IAaveV1LendingPoolAddressesProvider(_lendingPoolAddressProvider).getLendingPoolCore();\n }\n\n /**\n * @dev Only WETH and AETH contracts are allowed to transfer ETH here. Prevent other addresses\n * to send Ether to this contract.\n */\n receive() external payable {\n require(\n msg.sender == address(WETH) ||\n msg.sender == address(AETH) ||\n msg.sender == AaveV1LendingPool ||\n msg.sender == AaveV1LendingPoolCore,\n \"Receive not allowed\"\n );\n }\n\n /**\n * @dev Revert fallback calls\n */\n fallback() external payable {\n revert(\"Fallback not allowed\");\n }\n}\n" + }, + "@optyfi/defi-legos/ethereum/aave/contracts/ILendingPool.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <=0.9.0;\n\ninterface ILendingPool {\n function addressesProvider() external view returns (address);\n\n function deposit(\n address _reserve,\n uint256 _amount,\n uint16 _referralCode\n ) external payable;\n\n function redeemUnderlying(\n address _reserve,\n address _user,\n uint256 _amount\n ) external;\n\n function borrow(\n address _reserve,\n uint256 _amount,\n uint256 _interestRateMode,\n uint16 _referralCode\n ) external;\n\n function repay(\n address _reserve,\n uint256 _amount,\n address _onBehalfOf\n ) external payable;\n\n function swapBorrowRateMode(address _reserve) external;\n\n function rebalanceFixedBorrowRate(address _reserve, address _user) external;\n\n function setUserUseReserveAsCollateral(address _reserve, bool _useAsCollateral) external;\n\n function liquidationCall(\n address _collateral,\n address _reserve,\n address _user,\n uint256 _purchaseAmount,\n bool _receiveAToken\n ) external payable;\n\n function flashLoan(\n address _receiver,\n address _reserve,\n uint256 _amount,\n bytes calldata _params\n ) external;\n\n function getReserveConfigurationData(address _reserve)\n external\n view\n returns (\n uint256 ltv,\n uint256 liquidationThreshold,\n uint256 liquidationDiscount,\n address interestRateStrategyAddress,\n bool usageAsCollateralEnabled,\n bool borrowingEnabled,\n bool fixedBorrowRateEnabled,\n bool isActive\n );\n\n function getReserveData(address _reserve)\n external\n view\n returns (\n uint256 totalLiquidity,\n uint256 availableLiquidity,\n uint256 totalBorrowsFixed,\n uint256 totalBorrowsVariable,\n uint256 liquidityRate,\n uint256 variableBorrowRate,\n uint256 fixedBorrowRate,\n uint256 averageFixedBorrowRate,\n uint256 utilizationRate,\n uint256 liquidityIndex,\n uint256 variableBorrowIndex,\n address aTokenAddress,\n uint40 lastUpdateTimestamp\n );\n\n function getUserAccountData(address _user)\n external\n view\n returns (\n uint256 totalLiquidityETH,\n uint256 totalCollateralETH,\n uint256 totalBorrowsETH,\n uint256 availableBorrowsETH,\n uint256 currentLiquidationThreshold,\n uint256 ltv,\n uint256 healthFactor\n );\n\n function getUserReserveData(address _reserve, address _user)\n external\n view\n returns (\n uint256 currentATokenBalance,\n uint256 currentUnderlyingBalance,\n uint256 currentBorrowBalance,\n uint256 principalBorrowBalance,\n uint256 borrowRateMode,\n uint256 borrowRate,\n uint256 liquidityRate,\n uint256 originationFee,\n uint256 variableBorrowIndex,\n uint256 lastUpdateTimestamp,\n bool usageAsCollateralEnabled\n );\n\n function getReserves() external view;\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/aave/AaveV1Adapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\n// interfaces\nimport { IAaveV1PriceOracle } from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1PriceOracle.sol\";\nimport {\n IAaveV1LendingPoolAddressesProvider\n} from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1LendingPoolAddressesProvider.sol\";\nimport {\n IAaveV1,\n UserReserveData,\n ReserveConfigurationData,\n ReserveDataV1,\n UserAccountData\n} from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1.sol\";\nimport { IAaveV1Token } from \"@optyfi/defi-legos/ethereum/aave/contracts/IAaveV1Token.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterBorrow } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterBorrow.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\nimport { AaveV1ETHGateway } from \"./AaveV1ETHGateway.sol\";\n\n/**\n * @title Adapter for AaveV1 protocol\n * @author Opty.fi\n\n * @dev Abstraction layer to AaveV1's pools\n */\ncontract AaveV1Adapter is IAdapter, IAdapterBorrow, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /**\n * @notice numeric representation of the safety of vault's deposited assets against the borrowed assets\n * and its underlying value\n */\n uint256 public healthFactor = 2;\n\n /**\n * @notice Percentage of the value in USD of the collateral we can borrow\n * @dev ltv defines as loan-to-value\n */\n uint256 public ltv = 65;\n\n /** @notice Max percentage value i.e. 100% */\n uint256 public max = 100;\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n /**\n * @notice Aave's ETH liquidity pool contract address\n * @dev It is required to cover edge case of depositing\n * ETH to Aave's ETH liquidity pool contract\n */\n address public constant AETH = address(0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04);\n\n /** WETH ERC20 token address */\n address public constant WETH = address(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);\n\n // solhint-disable-next-line var-name-mixedcase\n address public constant ETH = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\n\n /** @dev ETH gateway contract for aavev1 adapter */\n address public immutable aaveV1ETHGatewayContract;\n\n constructor(address _registry) public Modifiers(_registry) {\n aaveV1ETHGatewayContract = address(new AaveV1ETHGateway(WETH, _registry, AETH));\n setMaxDepositProtocolPct(uint256(10000)); // 100% (basis points)\n setMaxDepositProtocolMode(MaxExposure.Pct);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n require(_liquidityPool.isContract(), \"!isContract\");\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n require(_liquidityPool.isContract(), \"!_liquidityPool.isContract()\");\n require(_underlyingToken.isContract(), \"!_underlyingToken.isContract()\");\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) public override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) public override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider\n ) public view override returns (bytes[] memory) {\n uint256 _amount = ERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPoolAddressProvider, _amount);\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getBorrowAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n address _outputToken\n ) public view override returns (bytes[] memory _codes) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n ReserveConfigurationData memory _inputTokenReserveConfigurationData =\n IAaveV1(_lendingPool).getReserveConfigurationData(_underlyingToken);\n ReserveConfigurationData memory _outputTokenReserveConfigurationData =\n IAaveV1(_lendingPool).getReserveConfigurationData(_outputToken);\n require(\n _inputTokenReserveConfigurationData.isActive &&\n _inputTokenReserveConfigurationData.usageAsCollateralEnabled &&\n _outputTokenReserveConfigurationData.isActive &&\n _outputTokenReserveConfigurationData.borrowingEnabled,\n \"!borrow\"\n );\n uint256 _borrow = _availableToBorrowReserve(_vault, _liquidityPoolAddressProvider, _outputToken);\n if (_borrow > 0) {\n bool _isUserCollateralEnabled = IAaveV1(_lendingPool).getUserReserveData(_underlyingToken, _vault).enabled;\n uint256 _interestRateMode =\n _outputTokenReserveConfigurationData.stableBorrowRateEnabled ? uint256(1) : uint256(2);\n if (_isUserCollateralEnabled) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"borrow(address,uint256,uint256,uint16)\",\n _outputToken,\n _borrow,\n _interestRateMode,\n uint16(0)\n )\n );\n } else {\n _codes = new bytes[](2);\n _codes[0] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"setUserUseReserveAsCollateral(address,bool)\", _underlyingToken, true)\n );\n _codes[1] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"borrow(address,uint256,uint256,uint16)\",\n _outputToken,\n _borrow,\n _interestRateMode,\n uint16(0)\n )\n );\n }\n }\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getRepayAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n address _outputToken\n ) public view override returns (bytes[] memory _codes) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n address _lendingPoolCore = _getLendingPoolCore(_liquidityPoolAddressProvider);\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n uint256 _liquidityPoolTokenBalance =\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProvider);\n\n // borrow token amount\n uint256 _borrowAmount = ERC20(_outputToken).balanceOf(_vault);\n\n uint256 _aTokenAmount =\n _maxWithdrawal(_vault, _lendingPool, _liquidityPoolTokenBalance, _outputToken, _borrowAmount);\n\n uint256 _outputTokenRepayable =\n _over(_vault, _underlyingToken, _liquidityPoolAddressProvider, _outputToken, _aTokenAmount);\n\n if (_outputTokenRepayable > 0) {\n if (_outputTokenRepayable > _borrowAmount) {\n _outputTokenRepayable = _borrowAmount;\n }\n if (_outputTokenRepayable > 0) {\n _codes = new bytes[](4);\n _codes[0] = abi.encode(\n _outputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPoolCore, uint256(0))\n );\n _codes[1] = abi.encode(\n _outputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPoolCore, _borrowAmount)\n );\n _codes[2] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"repay(address,uint256,address)\", _outputToken, _borrowAmount, _vault)\n );\n _codes[3] = abi.encode(\n getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProvider),\n abi.encodeWithSignature(\"redeem(uint256)\", uint256(-1))\n );\n }\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider\n ) public view override returns (bytes[] memory _codes) {\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPoolAddressProvider, uint256(-1));\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address, address _liquidityPoolToken)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IAaveV1Token(_liquidityPoolToken).underlyingAssetAddress();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getAllAmountInTokenBorrow(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n address _borrowToken,\n uint256 _borrowAmount\n ) public view override returns (uint256) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n uint256 _liquidityPoolTokenBalance =\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProvider);\n return\n getSomeAmountInTokenBorrow(\n _vault,\n _underlyingToken,\n _liquidityPoolAddressProvider,\n _liquidityPoolTokenBalance,\n _borrowToken,\n _borrowAmount\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address,\n uint256 _underlyingTokenAmount\n ) public view override returns (uint256) {\n return _underlyingTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable,\n address,\n address,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n return _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPoolAddressProvider, address _underlyingToken)\n public\n view\n override\n returns (uint256)\n {\n return\n IAaveV1(_getLendingPool(_liquidityPoolAddressProvider))\n .getReserveData(_getToggledUnderlyingToken(_underlyingToken))\n .availableLiquidity;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n uint256 _depositAmount = _getDepositAmount(_liquidityPoolAddressProvider, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n ReserveConfigurationData memory _inputTokenReserveConfigurationData =\n IAaveV1(_lendingPool).getReserveConfigurationData(_underlyingToken);\n require(_inputTokenReserveConfigurationData.isActive, \"!isActive\");\n address _lendingPoolCore = _getLendingPoolCore(_liquidityPoolAddressProvider);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n address(_underlyingToken) == ETH ? WETH : _underlyingToken,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(_underlyingToken) == ETH ? aaveV1ETHGatewayContract : _lendingPoolCore,\n uint256(0)\n )\n );\n _codes[1] = abi.encode(\n address(_underlyingToken) == ETH ? WETH : _underlyingToken,\n abi.encodeWithSignature(\n \"approve(address,uint256)\",\n address(_underlyingToken) == ETH ? aaveV1ETHGatewayContract : _lendingPoolCore,\n _depositAmount\n )\n );\n\n if (address(_underlyingToken) == ETH) {\n _codes[2] = abi.encode(\n aaveV1ETHGatewayContract,\n abi.encodeWithSignature(\n \"depositETH(address,address,address,uint256[2],int128)\",\n _vault,\n _liquidityPoolAddressProvider,\n AETH,\n [uint256(_depositAmount), uint256(0)],\n int128(0)\n )\n );\n } else {\n _codes[2] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"deposit(address,uint256,uint16)\",\n _underlyingToken,\n _depositAmount,\n uint16(0)\n )\n );\n }\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n uint256 _vaultBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProvider);\n if (_amount > 0 && _vaultBalance != uint256(0)) {\n if (_underlyingToken == ETH) {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n AETH,\n abi.encodeWithSignature(\"approve(address,uint256)\", aaveV1ETHGatewayContract, uint256(0))\n );\n _codes[1] = abi.encode(\n AETH,\n abi.encodeWithSignature(\"approve(address,uint256)\", aaveV1ETHGatewayContract, _vaultBalance)\n );\n _codes[2] = abi.encode(\n aaveV1ETHGatewayContract,\n abi.encodeWithSignature(\n \"withdrawETH(address,address,address,uint256,int128)\",\n _vault,\n _liquidityPoolAddressProvider,\n AETH,\n _vaultBalance,\n int128(0)\n )\n );\n } else {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProvider),\n abi.encodeWithSignature(\"redeem(uint256)\", _amount)\n );\n }\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address _underlyingToken, address _liquidityPoolAddressProvider)\n public\n view\n override\n returns (address)\n {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n ReserveDataV1 memory _reserveData =\n IAaveV1(_lendingPool).getReserveData(_getToggledUnderlyingToken(_underlyingToken));\n return _reserveData.aTokenAddress;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider\n ) public view override returns (uint256) {\n return getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProvider);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider\n ) public view override returns (uint256) {\n return\n ERC20(getLiquidityPoolToken(_getToggledUnderlyingToken(_underlyingToken), _liquidityPoolAddressProvider))\n .balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getSomeAmountInTokenBorrow(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n uint256 _liquidityPoolTokenBalance,\n address _borrowToken,\n uint256 _borrowAmount\n ) public view override returns (uint256) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProvider);\n uint256 _aTokenAmount =\n _maxWithdrawal(_vault, _lendingPool, _liquidityPoolTokenBalance, _borrowToken, _borrowAmount);\n uint256 _outputTokenRepayable =\n _over(_vault, _underlyingToken, _liquidityPoolAddressProvider, _borrowToken, _aTokenAmount);\n if (_outputTokenRepayable > _borrowAmount) {\n return _aTokenAmount;\n } else {\n return\n _aTokenAmount.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getOptimalTokenAmount(\n _borrowToken,\n _underlyingToken,\n _borrowAmount.sub(_outputTokenRepayable)\n )\n );\n }\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool, _underlyingToken)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool, address _underlyingToken)\n internal\n view\n returns (uint256)\n {\n uint256 _poolValue = getPoolValue(_liquidityPool, _underlyingToken);\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n\n function _getLendingPool(address _lendingPoolAddressProvider) internal view returns (address) {\n return IAaveV1LendingPoolAddressesProvider(_lendingPoolAddressProvider).getLendingPool();\n }\n\n function _getLendingPoolCore(address _lendingPoolAddressProvider) internal view returns (address) {\n return IAaveV1LendingPoolAddressesProvider(_lendingPoolAddressProvider).getLendingPoolCore();\n }\n\n function _getPriceOracle(address _lendingPoolAddressProvider) internal view returns (address) {\n return IAaveV1LendingPoolAddressesProvider(_lendingPoolAddressProvider).getPriceOracle();\n }\n\n function _maxSafeETH(address _vault, address _liquidityPoolAddressProvider)\n internal\n view\n returns (\n uint256 maxBorrowsETH,\n uint256 totalBorrowsETH,\n uint256 availableBorrowsETH\n )\n {\n UserAccountData memory _userAccountData =\n IAaveV1(_getLendingPool(_liquidityPoolAddressProvider)).getUserAccountData(_vault);\n uint256 _totalBorrowsETH = _userAccountData.totalBorrowsETH;\n uint256 _availableBorrowsETH = _userAccountData.availableBorrowsETH;\n uint256 _maxBorrowETH = (_totalBorrowsETH.add(_availableBorrowsETH));\n return (_maxBorrowETH.div(healthFactor), _totalBorrowsETH, _availableBorrowsETH);\n }\n\n function _availableToBorrowETH(address _vault, address _liquidityPoolAddressProvider)\n internal\n view\n returns (uint256)\n {\n (uint256 _maxSafeETH_, uint256 _totalBorrowsETH, uint256 _availableBorrowsETH) =\n _maxSafeETH(_vault, _liquidityPoolAddressProvider);\n _maxSafeETH_ = _maxSafeETH_.mul(95).div(100); // 5% buffer so we don't go into a earn/rebalance loop\n if (_maxSafeETH_ > _totalBorrowsETH) {\n return _availableBorrowsETH.mul(_maxSafeETH_.sub(_totalBorrowsETH)).div(_availableBorrowsETH);\n } else {\n return 0;\n }\n }\n\n function _getReservePrice(address _liquidityPoolAddressProvider, address _token) internal view returns (uint256) {\n return _getReservePriceETH(_liquidityPoolAddressProvider, _token);\n }\n\n function _getReservePriceETH(address _liquidityPoolAddressProvider, address _token)\n internal\n view\n returns (uint256)\n {\n return\n IAaveV1PriceOracle(_getPriceOracle(_liquidityPoolAddressProvider)).getAssetPrice(\n _getToggledUnderlyingToken(_token)\n );\n }\n\n function _availableToBorrowReserve(\n address _vault,\n address _liquidityPoolAddressProvider,\n address _outputToken\n ) internal view returns (uint256) {\n uint256 _available = _availableToBorrowETH(_vault, _liquidityPoolAddressProvider);\n if (_available > 0) {\n return\n _available.mul(uint256(10)**ERC20(_outputToken).decimals()).div(\n _getReservePrice(_liquidityPoolAddressProvider, _outputToken)\n );\n } else {\n return 0;\n }\n }\n\n function _getUnderlyingPrice(address _liquidityPoolAddressProvider, address _underlyingToken)\n internal\n view\n returns (uint256)\n {\n return _getReservePriceETH(_liquidityPoolAddressProvider, _underlyingToken);\n }\n\n function _getUnderlyingPriceETH(\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n uint256 _amount\n ) internal view returns (uint256) {\n _underlyingToken = _getToggledUnderlyingToken(_underlyingToken);\n address _liquidityPoolToken = getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProvider);\n _amount = _amount.mul(_getUnderlyingPrice(_liquidityPoolAddressProvider, _underlyingToken)).div(\n uint256(10)**ERC20(address(_liquidityPoolToken)).decimals()\n ); // Calculate the amount we are withdrawing in ETH\n return _amount.mul(ltv).div(max).div(healthFactor);\n }\n\n function _over(\n address _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProvider,\n address _outputToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _eth = _getUnderlyingPriceETH(_underlyingToken, _liquidityPoolAddressProvider, _amount);\n (uint256 _maxSafeETH_, uint256 _totalBorrowsETH, ) = _maxSafeETH(_vault, _liquidityPoolAddressProvider);\n _maxSafeETH_ = _maxSafeETH_.mul(105).div(100); // 5% buffer so we don't go into a earn/rebalance loop\n if (_eth > _maxSafeETH_) {\n _maxSafeETH_ = 0;\n } else {\n _maxSafeETH_ = _maxSafeETH_.sub(_eth); // Add the ETH we are withdrawing\n }\n if (_maxSafeETH_ < _totalBorrowsETH) {\n uint256 _over_ = _totalBorrowsETH.mul(_totalBorrowsETH.sub(_maxSafeETH_)).div(_totalBorrowsETH);\n _over_ = _over_.mul(uint256(10)**ERC20(_outputToken).decimals()).div(\n _getReservePrice(_liquidityPoolAddressProvider, _outputToken)\n );\n return _over_;\n } else {\n return 0;\n }\n }\n\n function _getUserReserveData(\n address _lendingPool,\n address _underlyingToken,\n address _vault\n ) internal view returns (UserReserveData memory) {\n return IAaveV1(_lendingPool).getUserReserveData(_getToggledUnderlyingToken(_underlyingToken), _vault);\n }\n\n function _debt(\n address _vault,\n address _lendingPool,\n address _outputToken\n ) internal view returns (uint256) {\n return IAaveV1(_lendingPool).getUserReserveData(_outputToken, _vault).currentBorrowBalance;\n }\n\n // % of tokens locked and cannot be withdrawn per user\n // this is impermanent locked, unless the debt out accrues the strategy\n function _locked(\n address _vault,\n address _lendingPool,\n address _borrowToken,\n uint256 _borrowAmount\n ) internal view returns (uint256) {\n return _borrowAmount.mul(1e18).div(_debt(_vault, _lendingPool, _borrowToken));\n }\n\n // Calculates in impermanent lock due to debt\n function _maxWithdrawal(\n address _vault,\n address _lendingPool,\n uint256 _aTokenAmount,\n address _borrowToken,\n uint256 _borrowAmount\n ) internal view returns (uint256) {\n uint256 _safeWithdraw = _aTokenAmount.mul(_locked(_vault, _lendingPool, _borrowToken, _borrowAmount)).div(1e18);\n if (_safeWithdraw > _aTokenAmount) {\n return _aTokenAmount;\n } else {\n uint256 _diff = _aTokenAmount.sub(_safeWithdraw);\n return _aTokenAmount.sub(_diff.mul(healthFactor)); // technically 150%, not 200%, but adding buffer\n }\n }\n\n function _getToggledUnderlyingToken(address _underlyingToken) internal pure returns (address) {\n return _underlyingToken == WETH ? ETH : _underlyingToken;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/aave/AaveV2Adapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// interfaces\nimport { IAaveV2PriceOracle } from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2PriceOracle.sol\";\nimport {\n IAaveV2LendingPoolAddressesProvider\n} from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2LendingPoolAddressesProvider.sol\";\nimport {\n IAaveV2LendingPoolAddressProviderRegistry\n} from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2LendingPoolAddressProviderRegistry.sol\";\nimport { IAaveV2, ReserveDataV2, UserAccountData } from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2.sol\";\nimport { IAaveV2Token } from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2Token.sol\";\nimport {\n IAaveV2ProtocolDataProvider,\n UserReserveData,\n ReserveDataProtocol,\n ReserveConfigurationData\n} from \"@optyfi/defi-legos/ethereum/aavev2/contracts/IAaveV2ProtocolDataProvider.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterBorrow } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterBorrow.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for AaveV2 protocol\n * @author Opty.fi\n * @dev Abstraction layer to AaveV2's pools\n */\ncontract AaveV2Adapter is IAdapter, IAdapterBorrow, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /**\n * @notice numeric representation of the safety of vault's deposited assets against the borrowed assets\n * and its underlying value\n */\n uint256 public healthFactor = 2;\n\n /**\n * @notice Percentage of the value in USD of the collateral we can borrow\n * @dev ltv defines as loan-to-value\n */\n uint256 public ltv = 65;\n\n /** @notice Max percentage value i.e. 100% */\n uint256 public max = 100;\n\n /** @notice AaveV2's Data provider id */\n bytes32 public constant PROTOCOL_DATA_PROVIDER_ID =\n 0x0100000000000000000000000000000000000000000000000000000000000000;\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n setMaxDepositProtocolPct(uint256(10000)); // 100% (basis points)\n setMaxDepositProtocolMode(MaxExposure.Pct);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n require(_liquidityPool.isContract(), \"!isContract\");\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n require(_liquidityPool.isContract(), \"!_liquidityPool.isContract()\");\n require(_underlyingToken.isContract(), \"!_underlyingToken.isContract()\");\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) public override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) public override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry\n ) public view override returns (bytes[] memory) {\n uint256 _amount = ERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry, _amount);\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getBorrowAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n address _outputToken\n ) public view override returns (bytes[] memory _codes) {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProviderRegistry);\n ReserveConfigurationData memory _reserveConfigurationData =\n IAaveV2ProtocolDataProvider(_getProtocolDataProvider(_liquidityPoolAddressProviderRegistry))\n .getReserveConfigurationData(_underlyingToken);\n if (\n _reserveConfigurationData.usageAsCollateralEnabled &&\n _reserveConfigurationData.stableBorrowRateEnabled &&\n _reserveConfigurationData.borrowingEnabled &&\n _reserveConfigurationData.isActive &&\n !_reserveConfigurationData.isFrozen\n ) {\n uint256 _borrow = _availableToBorrowReserve(_vault, _liquidityPoolAddressProviderRegistry, _outputToken);\n if (_borrow > 0) {\n bool _isUserCollateralEnabled =\n _getUserReserveData(_liquidityPoolAddressProviderRegistry, _underlyingToken, _vault)\n .usageAsCollateralEnabled;\n if (_isUserCollateralEnabled) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"borrow(address,uint256,uint256,uint16,address)\",\n _outputToken,\n _borrow,\n uint256(1),\n uint16(0),\n _vault\n )\n );\n } else {\n _codes = new bytes[](2);\n _codes[0] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"setUserUseReserveAsCollateral(address,bool)\", _underlyingToken, true)\n );\n _codes[1] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"borrow(address,uint256,uint256,uint16,address)\",\n _outputToken,\n _borrow,\n uint256(1),\n uint16(0),\n _vault\n )\n );\n }\n }\n } else {\n revert(\"!borrow\");\n }\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getRepayAndWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n address _outputToken\n ) public view override returns (bytes[] memory _codes) {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProviderRegistry);\n uint256 _liquidityPoolTokenBalance =\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry);\n\n // borrow token amount\n uint256 _borrowAmount = ERC20(_outputToken).balanceOf(_vault);\n\n uint256 _aTokenAmount =\n _maxWithdrawal(\n _vault,\n _liquidityPoolAddressProviderRegistry,\n _liquidityPoolTokenBalance,\n _outputToken,\n _borrowAmount\n );\n\n uint256 _outputTokenRepayable =\n _over(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry, _outputToken, _aTokenAmount);\n\n if (_outputTokenRepayable > 0) {\n if (_outputTokenRepayable > _borrowAmount) {\n _outputTokenRepayable = _borrowAmount;\n }\n if (_outputTokenRepayable > 0) {\n address _liquidityPoolToken =\n getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProviderRegistry);\n _codes = new bytes[](6);\n _codes[0] = abi.encode(\n _outputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _outputToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _borrowAmount)\n );\n _codes[2] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"repay(address,uint256,uint256,address)\",\n _outputToken,\n _borrowAmount,\n uint256(1),\n _vault\n )\n );\n _codes[3] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[4] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _aTokenAmount)\n );\n _codes[5] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"withdraw(address,uint256,address)\",\n _underlyingToken,\n _aTokenAmount,\n _vault\n )\n );\n }\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount =\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address, address _liquidityPoolToken)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = IAaveV2Token(_liquidityPoolToken).UNDERLYING_ASSET_ADDRESS();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getAllAmountInTokenBorrow(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n address _borrowToken,\n uint256 _borrowAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance =\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry);\n return\n getSomeAmountInTokenBorrow(\n _vault,\n _underlyingToken,\n _liquidityPoolAddressProviderRegistry,\n _liquidityPoolTokenBalance,\n _borrowToken,\n _borrowAmount\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address,\n address,\n uint256 _underlyingTokenAmount\n ) public view override returns (uint256) {\n return _underlyingTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable,\n address,\n address,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n return _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address) public view override returns (address) {\n return address(0);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address _underlyingToken, address _liquidityPoolAddressProviderRegistry)\n public\n view\n override\n returns (address)\n {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProviderRegistry);\n ReserveDataV2 memory _reserveData = IAaveV2(_lendingPool).getReserveData(_underlyingToken);\n return _reserveData.aTokenAddress;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry\n ) public view override returns (uint256) {\n return getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry\n ) public view override returns (uint256) {\n return ERC20(getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProviderRegistry)).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapterBorrow\n */\n function getSomeAmountInTokenBorrow(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n uint256 _liquidityPoolTokenBalance,\n address _borrowToken,\n uint256 _borrowAmount\n ) public view override returns (uint256) {\n uint256 _aTokenAmount =\n _maxWithdrawal(\n _vault,\n _liquidityPoolAddressProviderRegistry,\n _liquidityPoolTokenBalance,\n _borrowToken,\n _borrowAmount\n );\n uint256 _outputTokenRepayable =\n _over(_vault, _underlyingToken, _liquidityPoolAddressProviderRegistry, _borrowToken, _aTokenAmount);\n if (_outputTokenRepayable > _borrowAmount) {\n return _aTokenAmount;\n } else {\n return\n _aTokenAmount.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getOptimalTokenAmount(\n _borrowToken,\n _underlyingToken,\n _borrowAmount.sub(_outputTokenRepayable)\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPoolAddressProviderRegistry, address _underlyingToken)\n public\n view\n override\n returns (uint256)\n {\n return _getReserveData(_liquidityPoolAddressProviderRegistry, _underlyingToken).availableLiquidity;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPoolAddressProviderRegistry, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProviderRegistry);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _depositAmount)\n );\n _codes[2] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\n \"deposit(address,uint256,address,uint16)\",\n _underlyingToken,\n _depositAmount,\n _vault,\n uint16(0)\n )\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n address _lendingPool = _getLendingPool(_liquidityPoolAddressProviderRegistry);\n address _liquidityPoolToken =\n getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProviderRegistry);\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _liquidityPoolToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _lendingPool, _amount)\n );\n _codes[2] = abi.encode(\n _lendingPool,\n abi.encodeWithSignature(\"withdraw(address,uint256,address)\", _underlyingToken, _amount, _vault)\n );\n }\n }\n\n function _getLendingPool(address _lendingPoolAddressProviderRegistry) internal view returns (address) {\n return\n IAaveV2LendingPoolAddressesProvider(_getLendingPoolAddressProvider(_lendingPoolAddressProviderRegistry))\n .getLendingPool();\n }\n\n function _getPriceOracle(address _lendingPoolAddressProviderRegistry) internal view returns (address) {\n return\n IAaveV2LendingPoolAddressesProvider(_getLendingPoolAddressProvider(_lendingPoolAddressProviderRegistry))\n .getPriceOracle();\n }\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool, _underlyingToken)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool, address _underlyingToken)\n internal\n view\n returns (uint256)\n {\n uint256 _poolValue = getPoolValue(_liquidityPool, _underlyingToken);\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n\n function _maxSafeETH(address _vault, address _liquidityPoolAddressProviderRegistry)\n internal\n view\n returns (\n uint256 maxBorrowsETH,\n uint256 totalBorrowsETH,\n uint256 availableBorrowsETH\n )\n {\n UserAccountData memory _userAccountData =\n IAaveV2(_getLendingPool(_liquidityPoolAddressProviderRegistry)).getUserAccountData(_vault);\n uint256 _totalBorrowsETH = _userAccountData.totalDebtETH;\n uint256 _availableBorrowsETH = _userAccountData.availableBorrowsETH;\n uint256 _maxBorrowETH = (_totalBorrowsETH.add(_availableBorrowsETH));\n return (_maxBorrowETH.div(healthFactor), _totalBorrowsETH, _availableBorrowsETH);\n }\n\n function _availableToBorrowETH(address _vault, address _liquidityPoolAddressProviderRegistry)\n internal\n view\n returns (uint256)\n {\n (uint256 _maxSafeETH_, uint256 _totalBorrowsETH, uint256 _availableBorrowsETH) =\n _maxSafeETH(_vault, _liquidityPoolAddressProviderRegistry);\n _maxSafeETH_ = _maxSafeETH_.mul(95).div(100); // 5% buffer so we don't go into a earn/rebalance loop\n if (_maxSafeETH_ > _totalBorrowsETH) {\n return _availableBorrowsETH.mul(_maxSafeETH_.sub(_totalBorrowsETH)).div(_availableBorrowsETH);\n } else {\n return 0;\n }\n }\n\n function _getReservePrice(address _liquidityPoolAddressProviderRegistry, address _token)\n internal\n view\n returns (uint256)\n {\n return _getReservePriceETH(_liquidityPoolAddressProviderRegistry, _token);\n }\n\n function _getReservePriceETH(address _liquidityPoolAddressProviderRegistry, address _token)\n internal\n view\n returns (uint256)\n {\n return IAaveV2PriceOracle(_getPriceOracle(_liquidityPoolAddressProviderRegistry)).getAssetPrice(_token);\n }\n\n function _availableToBorrowReserve(\n address _vault,\n address _liquidityPoolAddressProvider,\n address _outputToken\n ) internal view returns (uint256) {\n uint256 _available = _availableToBorrowETH(_vault, _liquidityPoolAddressProvider);\n if (_available > 0) {\n return\n _available.mul(uint256(10)**ERC20(_outputToken).decimals()).div(\n _getReservePrice(_liquidityPoolAddressProvider, _outputToken)\n );\n } else {\n return 0;\n }\n }\n\n function _getUnderlyingPrice(address _liquidityPoolAddressProviderRegistry, address _underlyingToken)\n internal\n view\n returns (uint256)\n {\n return _getReservePriceETH(_liquidityPoolAddressProviderRegistry, _underlyingToken);\n }\n\n function _getUnderlyingPriceETH(\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n uint256 _amount\n ) internal view returns (uint256) {\n address _liquidityPoolToken = getLiquidityPoolToken(_underlyingToken, _liquidityPoolAddressProviderRegistry);\n _amount = _amount.mul(_getUnderlyingPrice(_liquidityPoolAddressProviderRegistry, _underlyingToken)).div(\n uint256(10)**ERC20(address(_liquidityPoolToken)).decimals()\n ); // Calculate the amount we are withdrawing in ETH\n return _amount.mul(ltv).div(max).div(healthFactor);\n }\n\n function _over(\n address _vault,\n address _underlyingToken,\n address _liquidityPoolAddressProviderRegistry,\n address _outputToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _eth = _getUnderlyingPriceETH(_underlyingToken, _liquidityPoolAddressProviderRegistry, _amount);\n (uint256 _maxSafeETH_, uint256 _totalBorrowsETH, ) = _maxSafeETH(_vault, _liquidityPoolAddressProviderRegistry);\n _maxSafeETH_ = _maxSafeETH_.mul(105).div(100); // 5% buffer so we don't go into a earn/rebalance loop\n if (_eth > _maxSafeETH_) {\n _maxSafeETH_ = 0;\n } else {\n _maxSafeETH_ = _maxSafeETH_.sub(_eth); // Add the ETH we are withdrawing\n }\n if (_maxSafeETH_ < _totalBorrowsETH) {\n uint256 _over_ = _totalBorrowsETH.mul(_totalBorrowsETH.sub(_maxSafeETH_)).div(_totalBorrowsETH);\n _over_ = _over_.mul(uint256(10)**ERC20(_outputToken).decimals()).div(\n _getReservePrice(_liquidityPoolAddressProviderRegistry, _outputToken)\n );\n return _over_;\n } else {\n return 0;\n }\n }\n\n function _getUserReserveData(\n address _liquidityPoolAddressProviderRegistry,\n address _underlyingToken,\n address _vault\n ) internal view returns (UserReserveData memory) {\n return\n IAaveV2ProtocolDataProvider(_getProtocolDataProvider(_liquidityPoolAddressProviderRegistry))\n .getUserReserveData(_underlyingToken, _vault);\n }\n\n function _getReserveData(address _liquidityPoolAddressProviderRegistry, address _underlyingToken)\n internal\n view\n returns (ReserveDataProtocol memory)\n {\n return\n IAaveV2ProtocolDataProvider(_getProtocolDataProvider(_liquidityPoolAddressProviderRegistry)).getReserveData(\n _underlyingToken\n );\n }\n\n function _debt(\n address _vault,\n address _liquidityPoolAddressProviderRegistry,\n address _outputToken\n ) internal view returns (uint256) {\n return\n IAaveV2ProtocolDataProvider(_getProtocolDataProvider(_liquidityPoolAddressProviderRegistry))\n .getUserReserveData(_outputToken, _vault)\n .currentStableDebt;\n }\n\n // % of tokens locked and cannot be withdrawn per user\n // this is impermanent locked, unless the debt out accrues the strategy\n function _locked(\n address _vault,\n address _liquidityPoolAddressProviderRegistry,\n address _borrowToken,\n uint256 _borrowAmount\n ) internal view returns (uint256) {\n return _borrowAmount.mul(1e18).div(_debt(_vault, _liquidityPoolAddressProviderRegistry, _borrowToken));\n }\n\n // Calculates in impermanent lock due to debt\n function _maxWithdrawal(\n address _vault,\n address _liquidityPoolAddressProviderRegistry,\n uint256 _aTokenAmount,\n address _borrowToken,\n uint256 _borrowAmount\n ) internal view returns (uint256) {\n uint256 _safeWithdraw =\n _aTokenAmount.mul(_locked(_vault, _liquidityPoolAddressProviderRegistry, _borrowToken, _borrowAmount)).div(\n 1e18\n );\n if (_safeWithdraw > _aTokenAmount) {\n return _aTokenAmount;\n } else {\n uint256 _diff = _aTokenAmount.sub(_safeWithdraw);\n return _aTokenAmount.sub(_diff.mul(healthFactor)); // technically 150%, not 200%, but adding buffer\n }\n }\n\n function _getLendingPoolAddressProvider(address _liquidityPoolAddressProviderRegistry)\n internal\n view\n returns (address)\n {\n return\n IAaveV2LendingPoolAddressProviderRegistry(_liquidityPoolAddressProviderRegistry)\n .getAddressesProvidersList()[0];\n }\n\n function _getProtocolDataProvider(address _liquidityPoolAddressProviderRegistry) internal view returns (address) {\n return\n IAaveV2LendingPoolAddressesProvider(_getLendingPoolAddressProvider(_liquidityPoolAddressProviderRegistry))\n .getAddress(PROTOCOL_DATA_PROVIDER_ID);\n }\n}\n" + }, + "contracts/protocol/adapters/defi-adapters/contracts/mock/TestDeFiAdapter.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { IAdapterFull } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterFull.sol\";\nimport { MultiCall } from \"../utils/MultiCall.sol\";\n\n///////////////////////////////////////\n/// THIS CONTRACTS MOCKS AS A VAULT ///\n///////////////////////////////////////\n\n////////////////////////////////\n/// DO NOT USE IN PRODUCTION ///\n////////////////////////////////\n\ncontract TestDeFiAdapter is MultiCall {\n function testGetDepositAllCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getDepositAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"depositAll\"\n );\n }\n\n function testGetDepositSomeCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter,\n uint256 _amount\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getDepositSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _amount\n ),\n \"depositSome\"\n );\n }\n\n function testGetBorrowAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _outputToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getBorrowAllCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _outputToken\n ),\n \"borrowAll\"\n );\n }\n\n function testGetStakeAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getStakeAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"stakeAll!\"\n );\n }\n\n function testGetStakeSomeCodes(\n address _liquidityPool,\n uint256 _stakeAmount,\n address _adapter\n ) external {\n executeCodes(IAdapterFull(_adapter).getStakeSomeCodes(_liquidityPool, _stakeAmount), \"stakeSome!\");\n }\n\n function testClaimRewardTokenCode(address _liquidityPool, address _adapter) external {\n executeCodes(\n IAdapterFull(_adapter).getClaimRewardTokenCode(payable(address(this)), _liquidityPool),\n \"claimReward\"\n );\n }\n\n function testGetHarvestAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getHarvestAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"harvestAll\"\n );\n }\n\n function testGetHarvestSomeCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter,\n uint256 _rewardTokenAmount\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getHarvestSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _rewardTokenAmount\n ),\n \"harvestSome\"\n );\n }\n\n function testGetUnstakeAllCodes(address _liquidityPool, address _adapter) external {\n executeCodes(IAdapterFull(_adapter).getUnstakeAllCodes(payable(address(this)), _liquidityPool), \"unstakeAll\");\n }\n\n function testGetUnstakeSomeCodes(\n address _liquidityPool,\n uint256 _stakeAmount,\n address _adapter\n ) external {\n executeCodes(IAdapterFull(_adapter).getUnstakeSomeCodes(_liquidityPool, _stakeAmount), \"unstakeAll\");\n }\n\n function testGetWithdrawAllCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getWithdrawAllCodes(payable(address(this)), _underlyingToken, _liquidityPool),\n \"withdrawAll\"\n );\n }\n\n function testGetWithdrawSomeCodes(\n address _underlyingToken,\n address _liquidityPool,\n address _adapter,\n uint256 _amount\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getWithdrawSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _amount\n ),\n \"withdrawSome\"\n );\n }\n\n function testGetRepayAndWithdrawAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _outputToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getRepayAndWithdrawAllCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _outputToken\n ),\n \"repayAndWithdrawAll\"\n );\n }\n\n function testGetUnstakeAndWithdrawAllCodes(\n address _liquidityPool,\n address _underlyingToken,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getUnstakeAndWithdrawAllCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool\n ),\n \"unstakeAndWithdrawAll\"\n );\n }\n\n function testGetUnstakeAndWithdrawSomeCodes(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _redeemAmount,\n address _adapter\n ) external {\n executeCodes(\n IAdapterFull(_adapter).getUnstakeAndWithdrawSomeCodes(\n payable(address(this)),\n _underlyingToken,\n _liquidityPool,\n _redeemAmount\n ),\n \"unstakeAndWithdrawSome\"\n );\n }\n\n function getERC20TokenBalance(address _token, address _account) external view returns (uint256) {\n return ERC20(_token).balanceOf(_account);\n }\n}\n" + }, + "contracts/protocol/adapters/defi-adapters/contracts/utils/MultiCall.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity >0.6.0;\npragma experimental ABIEncoderV2;\n\n/////////////////////////////////////////////////////\n/// PLEASE DO NOT USE THIS CONTRACT IN PRODUCTION ///\n/////////////////////////////////////////////////////\n\n/**\n * @title MultiCall Contract\n * @author Opty.fi\n * @dev Provides functions used commonly for decoding codes and execute\n * the code calls for Opty.fi contracts\n */\nabstract contract MultiCall {\n /**\n * @notice Executes any functionality and check if it is working or not\n * @dev Execute the code and revert with error message if code provided is incorrect\n * @param _code Encoded data in bytes which acts as code to execute\n * @param _errorMsg Error message to throw when code execution call fails\n */\n function executeCode(bytes memory _code, string memory _errorMsg) internal {\n (address _contract, bytes memory _data) = abi.decode(_code, (address, bytes));\n (bool _success, ) = _contract.call(_data); //solhint-disable-line avoid-low-level-calls\n require(_success, _errorMsg);\n }\n\n /**\n * @notice Executes bunch of functionalities and check if they are working or not\n * @dev Execute the codes array and revert with error message if code provided is incorrect\n * @param _codes Array of encoded data in bytes which acts as code to execute\n * @param _errorMsg Error message to throw when code execution call fails\n */\n function executeCodes(bytes[] memory _codes, string memory _errorMsg) internal {\n for (uint256 _j = 0; _j < _codes.length; _j++) {\n executeCode(_codes[_j], _errorMsg);\n }\n }\n}\n" + }, + "contracts/mocks/contracts/TestOpenDefiVault.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { SafeERC20, IERC20, Address } from \"@openzeppelin/contracts/token/ERC20/SafeERC20.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ODEFIVaultBooster } from \"../../protocol/partnership/ODEFIVaultBooster.sol\";\nimport { IncentivisedERC20 } from \"../../protocol/tokenization/IncentivisedERC20.sol\";\n\ncontract TestOpenDefiVault is IncentivisedERC20 {\n using SafeERC20 for IERC20;\n using Address for address;\n\n uint256 public constant opTOKEN_REVISION = 0x1;\n address public underlyingToken; // store the underlying token contract address (for example DAI)\n ODEFIVaultBooster public odefiVaultBoosterContract;\n\n /* solhint-disable no-empty-blocks */\n constructor(address _underlyingToken)\n public\n IncentivisedERC20(\n string(abi.encodePacked(\"op \", ERC20(_underlyingToken).name(), \" Open\", \" Vault\")),\n string(abi.encodePacked(\"op\", ERC20(_underlyingToken).symbol(), \"OpenVault\"))\n )\n {}\n\n /* solhint-disable no-empty-blocks */\n\n function initialize(address _underlyingToken, address _odefiVaultBoosterContract) external virtual {\n setToken(_underlyingToken); // underlying token contract address (for example DAI)\n _setName(string(abi.encodePacked(\"op \", ERC20(_underlyingToken).name(), \" Open\", \" Vault\")));\n _setSymbol(string(abi.encodePacked(\"op\", ERC20(_underlyingToken).symbol(), \"OpenVault\")));\n _setDecimals(ERC20(_underlyingToken).decimals());\n odefiVaultBoosterContract = ODEFIVaultBooster(_odefiVaultBoosterContract);\n }\n\n function userDeposit(uint256 _amount) external returns (bool) {\n require(_amount > 0, \"!(_amount>0)\");\n uint256 _tokenBalance = balance();\n uint256 shares = 0;\n\n if (_tokenBalance == 0 || totalSupply() == 0) {\n shares = _amount;\n } else {\n shares = (_amount.mul(totalSupply())).div((_tokenBalance));\n }\n IERC20(underlyingToken).safeTransferFrom(msg.sender, address(this), _amount);\n odefiVaultBoosterContract.updateUserRewards(address(this), msg.sender);\n _mint(msg.sender, shares);\n odefiVaultBoosterContract.updateOdefiVaultRatePerSecondAndVaultToken(address(this));\n odefiVaultBoosterContract.updateOdefiVaultIndex(address(this));\n odefiVaultBoosterContract.updateUserStateInVault(address(this), msg.sender);\n return true;\n }\n\n function setToken(address _underlyingToken) public returns (bool) {\n require(_underlyingToken.isContract(), \"!_underlyingToken.isContract\");\n underlyingToken = _underlyingToken;\n return true;\n }\n\n /**\n * @dev Function to get the underlying token balance of OptyVault Contract\n */\n function balance() public view returns (uint256) {\n return IERC20(underlyingToken).balanceOf(address(this));\n }\n\n function getRevision() internal pure virtual returns (uint256) {\n return opTOKEN_REVISION;\n }\n}\n" + }, + "contracts/mocks/contracts/TestEmergencyBrake.sol": { + "content": "// solhint-disable\n// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\n\nimport { Vault } from \"../../protocol/tokenization/Vault.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestEmergencyBrake {\n ERC20 tokenAddr;\n Vault vaultAddr;\n\n constructor(Vault _vault, ERC20 _erc20) public {\n vaultAddr = _vault;\n tokenAddr = _erc20;\n }\n\n function runUserDepositVault(\n uint256 _userDepositUT,\n bytes32[] calldata _accountProofs,\n bytes32[] calldata _codeProofs\n ) external {\n tokenAddr.approve(address(vaultAddr), _userDepositUT);\n vaultAddr.userDepositVault(_userDepositUT, _accountProofs, _codeProofs);\n }\n\n function runUserWithdrawVault(\n uint256 _userWithdrawVT,\n bytes32[] calldata _accountProofs,\n bytes32[] calldata _codeProofs\n ) external {\n vaultAddr.userWithdrawVault(_userWithdrawVT, _accountProofs, _codeProofs);\n }\n\n function runTwoTxnUserDepositVault(\n uint256 _minAmountUT,\n uint256 _maxAmountUT,\n bytes32[] calldata _accountProofs,\n bytes32[] calldata _codeProofs\n ) external {\n tokenAddr.approve(address(vaultAddr), (_minAmountUT + _maxAmountUT));\n vaultAddr.userDepositVault(_maxAmountUT, _accountProofs, _codeProofs);\n vaultAddr.userDepositVault(_minAmountUT, _accountProofs, _codeProofs);\n }\n\n function runTwoTxnUserWithdrawVault(\n uint256 _minAmount,\n uint256 _maxAmount,\n bytes32[] calldata _accountProofs,\n bytes32[] calldata _codeProofs\n ) external {\n tokenAddr.approve(address(vaultAddr), (_minAmount + _maxAmount));\n tokenAddr.transfer(address(vaultAddr), _maxAmount);\n vaultAddr.userWithdrawVault(_maxAmount, _accountProofs, _codeProofs);\n tokenAddr.transfer(address(vaultAddr), _minAmount);\n vaultAddr.userWithdrawVault(_minAmount, _accountProofs, _codeProofs);\n }\n\n function runTwoTxnUserWithdrawVaultNoDeposit(\n uint256 _minAmountVT,\n uint256 _maxAmountVT,\n bytes32[] calldata _accountProofs,\n bytes32[] calldata _codeProofs\n ) external {\n tokenAddr.approve(address(vaultAddr), (_minAmountVT + _maxAmountVT));\n tokenAddr.transfer(address(vaultAddr), _maxAmountVT);\n vaultAddr.userWithdrawVault(_maxAmountVT, _accountProofs, _codeProofs);\n tokenAddr.transfer(address(vaultAddr), _minAmountVT);\n vaultAddr.userWithdrawVault(_minAmountVT, _accountProofs, _codeProofs);\n }\n\n function runTwoTxnWithdrawAndDepositRebalance(\n uint256 _minAmount,\n uint256 _maxAmount,\n bytes32[] calldata _accountProofs,\n bytes32[] calldata _codeProofs\n ) external {\n tokenAddr.approve(address(vaultAddr), _maxAmount);\n vaultAddr.userDepositVault(_maxAmount, _accountProofs, _codeProofs);\n tokenAddr.transfer(address(vaultAddr), _minAmount);\n vaultAddr.userWithdrawVault(_minAmount, _accountProofs, _codeProofs);\n }\n\n function getBalance() external view returns (uint256) {\n uint256 balance = vaultAddr.balanceUT();\n return balance;\n }\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/1_ethereum/cream/CreamAdapter.sol": { + "content": "// solhint-disable no-unused-vars\n// SPDX-License-Identifier:MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { SafeMath } from \"@openzeppelin/contracts/math/SafeMath.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n// helper contracts\nimport { Modifiers } from \"../../earn-protocol-configuration/contracts/Modifiers.sol\";\n\n// interfaces\nimport { ICream } from \"@optyfi/defi-legos/ethereum/cream/contracts/ICream.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IHarvestCodeProvider } from \"../interfaces/IHarvestCodeProvider.sol\";\nimport { IAdapter } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapter.sol\";\nimport { IAdapterHarvestReward } from \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterHarvestReward.sol\";\nimport \"@optyfi/defi-legos/interfaces/defiAdapters/contracts/IAdapterInvestLimit.sol\";\n\n/**\n * @title Adapter for Cream protocol\n * @author Opty.fi\n * @dev Abstraction layer to Cream's pools\n */\ncontract CreamAdapter is IAdapter, IAdapterHarvestReward, IAdapterInvestLimit, Modifiers {\n using SafeMath for uint256;\n using Address for address;\n\n /** @notice max deposit value datatypes */\n MaxExposure public maxDepositProtocolMode;\n\n /** @notice HBTC token contract address */\n address public constant HBTC = address(0x0316EB71485b0Ab14103307bf65a021042c6d380);\n\n /** @notice HFIL token contract address */\n address public constant HFIL = address(0x9AFb950948c2370975fb91a441F36FDC02737cD4);\n\n /** @notice max deposit's protocol value in percentage */\n uint256 public maxDepositProtocolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in percentage */\n mapping(address => uint256) public maxDepositPoolPct; // basis points\n\n /** @notice Maps liquidityPool to max deposit value in absolute value for a specific token */\n mapping(address => mapping(address => uint256)) public maxDepositAmount;\n\n constructor(address _registry) public Modifiers(_registry) {\n maxDepositProtocolPct = uint256(10000); // 100% (basis points)\n maxDepositProtocolMode = MaxExposure.Pct;\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositPoolPct(address _liquidityPool, uint256 _maxDepositPoolPct)\n external\n override\n onlyRiskOperator\n {\n maxDepositPoolPct[_liquidityPool] = _maxDepositPoolPct;\n emit LogMaxDepositPoolPct(maxDepositPoolPct[_liquidityPool], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _maxDepositAmount\n ) external override onlyRiskOperator {\n maxDepositAmount[_liquidityPool][_underlyingToken] = _maxDepositAmount;\n emit LogMaxDepositAmount(maxDepositAmount[_liquidityPool][_underlyingToken], msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolMode(MaxExposure _mode) external override onlyRiskOperator {\n maxDepositProtocolMode = _mode;\n emit LogMaxDepositProtocolMode(maxDepositProtocolMode, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapterInvestLimit\n */\n function setMaxDepositProtocolPct(uint256 _maxDepositProtocolPct) external override onlyRiskOperator {\n maxDepositProtocolPct = _maxDepositProtocolPct;\n emit LogMaxDepositProtocolPct(maxDepositProtocolPct, msg.sender);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _amount = IERC20(_underlyingToken).balanceOf(_vault);\n return getDepositSomeCodes(_vault, _underlyingToken, _liquidityPool, _amount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _redeemAmount = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n return getWithdrawSomeCodes(_vault, _underlyingToken, _liquidityPool, _redeemAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getUnderlyingTokens(address _liquidityPool, address)\n public\n view\n override\n returns (address[] memory _underlyingTokens)\n {\n _underlyingTokens = new address[](1);\n _underlyingTokens[0] = ICream(_liquidityPool).underlying();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateAmountInLPToken(\n address _underlyingToken,\n address _liquidityPool,\n uint256 _depositAmount\n ) public view override returns (uint256) {\n return\n _depositAmount.mul(1e18).div(\n ICream(getLiquidityPoolToken(_underlyingToken, _liquidityPool)).exchangeRateStored()\n );\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function calculateRedeemableLPTokenAmount(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (uint256) {\n uint256 _liquidityPoolTokenBalance = getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool);\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n require(_balanceInToken > 0, \"!balance\");\n // can have unintentional rounding errors\n return (_liquidityPoolTokenBalance.mul(_redeemAmount)).div(_balanceInToken).add(1);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function isRedeemableAmountSufficient(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _redeemAmount\n ) public view override returns (bool) {\n uint256 _balanceInToken = getAllAmountInToken(_vault, _underlyingToken, _liquidityPool);\n return _balanceInToken >= _redeemAmount;\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getClaimRewardTokenCode(address payable _vault, address _liquidityPool)\n public\n view\n override\n returns (bytes[] memory _codes)\n {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n ICream(_liquidityPool).comptroller(),\n abi.encodeWithSignature(\"claimComp(address)\", _vault)\n );\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestAllCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (bytes[] memory) {\n uint256 _rewardTokenAmount = IERC20(getRewardToken(_liquidityPool)).balanceOf(_vault);\n return getHarvestSomeCodes(_vault, _underlyingToken, _liquidityPool, _rewardTokenAmount);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function canStake(address) public view override returns (bool) {\n return false;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getDepositSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n uint256 _depositAmount = _getDepositAmount(_liquidityPool, _underlyingToken, _amount);\n if (_depositAmount > 0) {\n if (_underlyingToken == HBTC || _underlyingToken == HFIL) {\n _codes = new bytes[](2);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _amount)\n );\n _codes[1] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"mint(uint256)\", _depositAmount));\n } else {\n _codes = new bytes[](3);\n _codes[0] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, uint256(0))\n );\n _codes[1] = abi.encode(\n _underlyingToken,\n abi.encodeWithSignature(\"approve(address,uint256)\", _liquidityPool, _depositAmount)\n );\n _codes[2] = abi.encode(_liquidityPool, abi.encodeWithSignature(\"mint(uint256)\", _depositAmount));\n }\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getWithdrawSomeCodes(\n address payable,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _amount\n ) public view override returns (bytes[] memory _codes) {\n if (_amount > 0) {\n _codes = new bytes[](1);\n _codes[0] = abi.encode(\n getLiquidityPoolToken(_underlyingToken, _liquidityPool),\n abi.encodeWithSignature(\"redeem(uint256)\", _amount)\n );\n }\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getPoolValue(address _liquidityPool, address) public view override returns (uint256) {\n return ICream(_liquidityPool).getCash();\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolToken(address, address _liquidityPool) public view override returns (address) {\n return _liquidityPool;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getAllAmountInToken(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n // Mantisa 1e18 to decimals\n uint256 b =\n getSomeAmountInToken(\n _underlyingToken,\n _liquidityPool,\n getLiquidityPoolTokenBalance(_vault, _underlyingToken, _liquidityPool)\n );\n uint256 _unclaimedReward = getUnclaimedRewardTokenAmount(_vault, _liquidityPool, _underlyingToken);\n if (_unclaimedReward > 0) {\n b = b.add(\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).rewardBalanceInUnderlyingTokens(\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _unclaimedReward\n )\n );\n }\n return b;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getLiquidityPoolTokenBalance(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool\n ) public view override returns (uint256) {\n return IERC20(getLiquidityPoolToken(_underlyingToken, _liquidityPool)).balanceOf(_vault);\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getSomeAmountInToken(\n address,\n address _liquidityPool,\n uint256 _liquidityPoolTokenAmount\n ) public view override returns (uint256) {\n if (_liquidityPoolTokenAmount > 0) {\n _liquidityPoolTokenAmount = _liquidityPoolTokenAmount.mul(ICream(_liquidityPool).exchangeRateStored()).div(\n 1e18\n );\n }\n return _liquidityPoolTokenAmount;\n }\n\n /**\n * @inheritdoc IAdapter\n */\n function getRewardToken(address _liquidityPool) public view override returns (address) {\n return ICream(ICream(_liquidityPool).comptroller()).getCompAddress();\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getUnclaimedRewardTokenAmount(\n address payable _vault,\n address _liquidityPool,\n address\n ) public view override returns (uint256) {\n return ICream(ICream(_liquidityPool).comptroller()).compAccrued(_vault);\n }\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getHarvestSomeCodes(\n address payable _vault,\n address _underlyingToken,\n address _liquidityPool,\n uint256 _rewardTokenAmount\n ) public view override returns (bytes[] memory) {\n return\n IHarvestCodeProvider(registryContract.getHarvestCodeProvider()).getHarvestCodes(\n _vault,\n getRewardToken(_liquidityPool),\n _underlyingToken,\n _rewardTokenAmount\n );\n }\n\n /* solhint-disable no-empty-blocks */\n\n /**\n * @inheritdoc IAdapterHarvestReward\n */\n function getAddLiquidityCodes(address payable, address) public view override returns (bytes[] memory) {}\n\n /* solhint-enable no-empty-blocks */\n\n function _getDepositAmount(\n address _liquidityPool,\n address _underlyingToken,\n uint256 _amount\n ) internal view returns (uint256) {\n uint256 _limit =\n maxDepositProtocolMode == MaxExposure.Pct\n ? _getMaxDepositAmountByPct(_liquidityPool)\n : maxDepositAmount[_liquidityPool][_underlyingToken];\n return _amount > _limit ? _limit : _amount;\n }\n\n function _getMaxDepositAmountByPct(address _liquidityPool) internal view returns (uint256) {\n uint256 _poolValue = getPoolValue(_liquidityPool, address(0));\n uint256 _poolPct = maxDepositPoolPct[_liquidityPool];\n uint256 _limit =\n _poolPct == 0\n ? _poolValue.mul(maxDepositProtocolPct).div(uint256(10000))\n : _poolValue.mul(_poolPct).div(uint256(10000));\n return _limit;\n }\n}\n" + }, + "contracts/mocks/contracts/TestStrategyManager.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { MultiCall } from \"../../utils/MultiCall.sol\";\nimport { StrategyManager } from \"../../protocol/lib/StrategyManager.sol\";\nimport { DataTypes } from \"../../protocol/earn-protocol-configuration/contracts/libraries/types/DataTypes.sol\";\n\ncontract TestStrategyManager is MultiCall {\n using StrategyManager for DataTypes.StrategyStep[];\n\n function testGetDepositInternalTransactionCount(\n DataTypes.StrategyStep[] calldata _strategySteps,\n address _registryContract,\n uint256 _expectedValue\n ) external view returns (bool) {\n return _expectedValue == _strategySteps.getDepositInternalTransactionCount(_registryContract);\n }\n\n function testOraValueUT(\n DataTypes.StrategyStep[] calldata _strategySteps,\n address _registryContract,\n address payable _vault,\n address _underlyingToken,\n uint256 _expectedAmountUT\n ) external view returns (bool) {\n return _expectedAmountUT == _strategySteps.getOraValueUT(_registryContract, _vault, _underlyingToken);\n }\n\n function testOraSomeValueLP(\n DataTypes.StrategyStep[] calldata _strategySteps,\n address _registryContract,\n address _underlyingToken,\n uint256 _wantAmountUT,\n uint256 _expectedAmountLP\n ) external view returns (bool) {\n return\n _expectedAmountLP == _strategySteps.getOraSomeValueLP(_registryContract, _underlyingToken, _wantAmountUT);\n }\n\n function testGetPoolDepositCodes(\n DataTypes.StrategyStep[] calldata _strategySteps,\n DataTypes.StrategyConfigurationParams memory _strategyConfigurationParams\n ) external {\n executeCodes(_strategySteps.getPoolDepositCodes(_strategyConfigurationParams), \"!deposit\");\n }\n\n function testGetPoolWithdrawCodes(\n DataTypes.StrategyStep[] calldata _strategySteps,\n DataTypes.StrategyConfigurationParams memory _strategyConfigurationParams\n ) external {\n executeCodes(_strategySteps.getPoolWithdrawCodes(_strategyConfigurationParams), \"!withdraw\");\n }\n\n function testGetLastStrategyStepBalanceLP(\n DataTypes.StrategyStep[] memory _strategySteps,\n address _registryContract,\n address payable _vault,\n address _underlyingToken,\n uint256 _expectedBalanceLP\n ) external view returns (bool) {\n return\n _expectedBalanceLP ==\n _strategySteps.getLastStrategyStepBalanceLP(_registryContract, _vault, _underlyingToken);\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/mocks/contracts/TestRiskManagerNewImplementation.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { RiskManagerStorage } from \"../../RiskManagerStorage.sol\";\nimport { RiskManagerProxy } from \"../../RiskManagerProxy.sol\";\nimport { Modifiers } from \"../../Modifiers.sol\";\nimport { TestStorage } from \"./TestStorage.sol\";\n\ncontract TestRiskManagerNewImplementation is RiskManagerStorage, TestStorage, Modifiers {\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n\n /**\n * @dev Set TestRiskManagerNewImplementation to act as RiskManager\n * @param _riskManagerProxy RiskManagerProxy contract address to act as RiskManager\n */\n function become(RiskManagerProxy _riskManagerProxy) external onlyGovernance {\n require(_riskManagerProxy.acceptImplementation() == 0, \"!unauthorized\");\n }\n\n function isNewContract() external pure returns (bool) {\n return isNewVariable;\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/mocks/contracts/TestRegistryNewImplementation.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { ModifiersController } from \"../../ModifiersController.sol\";\nimport { RegistryProxy } from \"../../RegistryProxy.sol\";\nimport { RegistryStorage } from \"../../RegistryStorage.sol\";\nimport { TestStorage } from \"./TestStorage.sol\";\n\ncontract TestRegistryNewImplementation is RegistryStorage, TestStorage, ModifiersController {\n /**\n * @dev Set TestRegistryNewImplementation to act as Registry\n * @param _registryProxy RegistryProxy Contract address to act as Registry\n */\n function become(RegistryProxy _registryProxy) external {\n require(msg.sender == _registryProxy.governance(), \"!governance\");\n require(_registryProxy.acceptImplementation() == 0, \"!unauthorized\");\n }\n\n function isNewContract() external pure returns (bool) {\n return isNewVariable;\n }\n\n function getTokensHashToTokenList(bytes32 _tokensHash) public view returns (address[] memory) {\n return tokensHashToTokens[_tokensHash].tokens;\n }\n\n function getTokensHashByIndex(uint256 _index) public view returns (bytes32) {\n return tokensHashIndexes[_index];\n }\n}\n" + }, + "contracts/protocol/earn-protocol-configuration/contracts/mocks/contracts/TestDummyEmptyContractWithRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\nimport { Modifiers } from \"../../Modifiers.sol\";\n\ncontract TestDummyEmptyContractWithRegistry is Modifiers {\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/interfaces/opty/IInvestStrategyRegistry.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\n// libraries\nimport { DataTypes } from \"../../libraries/types/DataTypes.sol\";\n\n/**\n * @title IInvestStrategyRegistry\n * @author Opty.fi\n * @notice Contains functionality to setting all the strategies for all tokens\n */\ninterface IInvestStrategyRegistry {\n /**\n * @dev Assign strategy in form of _strategySteps to the _tokensHash\n * @param _tokensHash Hash of underlying token address/addresses\n * @param _strategySteps Strategy steps containing [pool, outputToken, isBorrow]\n * @return Returns true indicating successful operation.\n */\n function setStrategy(bytes32 _tokensHash, DataTypes.StrategyStep[] memory _strategySteps) external returns (bool);\n\n /**\n * @dev Assign multiple strategies in form of _strategySteps to the _tokensHash\n * @param _tokensHash List of Hashes of underlying token address/addresses\n * @param _strategySteps List of Strategy steps containing [pool, outputToken, isBorrow]\n * @return Returns true indicating successful operation.\n */\n function setStrategy(bytes32 _tokensHash, DataTypes.StrategyStep[][] memory _strategySteps) external returns (bool);\n\n /**\n * @dev Assign multiple strategies in form of _strategySteps to multiple tokens in form of _tokensHash\n * @param _tokensHash List of Hashes of underlying token address/addresses\n * @param _strategySteps List of Strategy steps containing [pool, outputToken, isBorrow]\n * @return Returns true indicating successful operation.\n */\n function setStrategy(bytes32[] memory _tokensHash, DataTypes.StrategyStep[][] memory _strategySteps)\n external\n returns (bool);\n\n /**\n * @notice Returns the Strategy Steps corresponding to _hash\n * @param _hash Hash of the strategy steps\n * @return _index Index at which strategy is stored\n * @return _strategySteps Returns the Strategy Steps corresponding to _hash provided\n */\n function getStrategy(bytes32 _hash)\n external\n view\n returns (uint256 _index, DataTypes.StrategyStep[] memory _strategySteps);\n\n /**\n * @notice Returns the Strategy Steps corresponding to _tokensHash\n * @param _tokensHash Hash of the underlying token address/addresses\n * @return Returns the List of Strategies corresponding to _tokensHash provided\n */\n function getTokenToStrategies(bytes32 _tokensHash) external view returns (bytes32[] memory);\n}\n" + }, + "contracts/protocol/adapters/ethereum/team-defi-adapters/contracts/earn-protocol-configuration/contracts/mocks/contracts/TestDummyEmptyContractWithRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.6.12;\nimport { Modifiers } from \"../../Modifiers.sol\";\n\ncontract TestDummyEmptyContractWithRegistry is Modifiers {\n /* solhint-disable no-empty-blocks */\n constructor(address _registry) public Modifiers(_registry) {}\n}\n" + }, + "contracts/protocol/adapters/defi-adapters/contracts/mock/Imports.sol": { + "content": "// SPDX-License-Identifier: agpl-3.0\n\npragma solidity ^0.6.12;\npragma experimental ABIEncoderV2;\n\nimport { IUniswapV2Pair } from \"@uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol\";\n" + } + }, + "settings": { + "metadata": { + "bytecodeHash": "none", + "useLiteralContent": true + }, + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates", + "devdoc", + "userdoc" + ], + "": ["ast"] + } + } + } +} diff --git a/helper-hardhat-config.ts b/helper-hardhat-config.ts index 8bf4385f4..dad182243 100644 --- a/helper-hardhat-config.ts +++ b/helper-hardhat-config.ts @@ -90,7 +90,7 @@ export const NETWORKS_DEFAULT_GAS: iEVMParamsPerNetwork = { }; export const BLOCK_TO_FORK: iEVMParamsPerNetwork = { - [eEVMNetwork.mainnet]: 14892305, + [eEVMNetwork.mainnet]: 14969244, [eEVMNetwork.kovan]: 29962003, [eEVMNetwork.ropsten]: undefined, [eEVMNetwork.hardhat]: undefined, diff --git a/tasks/actions/print-tokens-hash.ts b/tasks/actions/print-tokens-hash.ts new file mode 100644 index 000000000..7d71d3929 --- /dev/null +++ b/tasks/actions/print-tokens-hash.ts @@ -0,0 +1,23 @@ +import { task, types } from "hardhat/config"; +import { getAddress } from "ethers/lib/utils"; +import { isAddress, generateTokenHashV2 } from "../../helpers/helpers"; +import TASKS from "../task-names"; + +import { NETWORKS_CHAIN_ID_TO_HEX } from "../../helper-hardhat-config"; + +task(TASKS.ACTION_TASKS.PRINT_TOKENS_HASH.NAME, TASKS.ACTION_TASKS.PRINT_TOKENS_HASH.DESCRIPTION) + .addParam("token", "the address of token", "", types.string) + .setAction(async ({ token }, hre) => { + if (token === "") { + throw new Error("token cannot be empty"); + } + + if (!isAddress(token)) { + throw new Error("token address is invalid"); + } + + console.log( + "TokensHash : ", + generateTokenHashV2([getAddress(token)], NETWORKS_CHAIN_ID_TO_HEX[await hre.getChainId()]), + ); + }); diff --git a/tasks/task-names.ts b/tasks/task-names.ts index 9b25b01c9..98d139ab5 100644 --- a/tasks/task-names.ts +++ b/tasks/task-names.ts @@ -36,6 +36,7 @@ export default { }, SET_BEST_STRATEGY: { NAME: "set-best-strategy", DESCRIPTION: "Set the best strategy for a specific token" }, PRINT_STRATEGY_HASH: { NAME: "print-strategy-hash", DESCRIPTION: "Print the strategy" }, + PRINT_TOKENS_HASH: { NAME: "print-tokens-hash", DESCRIPTION: "Print tokens hash" }, UNPAUSE_VAULT: { NAME: "unpause-vault", DESCRIPTION: "Set pause state for a specific vault" }, VAULT_ACTIONS: { NAME: "vault-actions", diff --git a/whitelist/eoa-ethereum.json b/whitelist/eoa-ethereum.json index 4116416a9..8a2cdc5a7 100644 --- a/whitelist/eoa-ethereum.json +++ b/whitelist/eoa-ethereum.json @@ -24034,6 +24034,143 @@ ] } ] + }, + "opAAVEaggr": { + "opAAVEaggr_proxy": "0xd610c0CcE9792321BfEd3c2f31dceA6784c84F19", + "merkle_root_service": "", + "root_hash": "0x1f241a0f2460742481da49475eb1683fb84eb69cf3da43519a8b701f3309f783", + "addresses": [ + "0x25b972807a54bbbce0a206a76ea68f3c556c1a8b", + "0xDd704A44866AE9C387CfC687fa642a222b84f0D3", + "0x5fAd091BBa2731937087aa471d0BaCCFaD4157c4", + "0x65786B3dEe53D4C61E2fd0bd0F7049C2613b376a", + "0x46bB1A2549F36423227158c7AC7aE6BeaE1bFfb4", + "0x6e6976bB88285b4Ca5E928e1c1720550D570Ac69", + "0xD26Ec7401C198ADAc340d3A4Cb8B52b845F3A542", + "0x6bd60f089B6E8BA75c409a54CDea34AA511277f6", + "0xaAa9AaB67BB37b75d9F5db1F456348Ef1584E896", + "0xC89F54E7dee2D45Ec11fca623cf7f772c6F34a19", + "0x9f4DEc4A424394e93f36D2497f2dF970F9C2975a", + "0xaE2304daA840D45ef2Af30f02CF0f48e4974f595", + "0x66488AC3727Fc0e3F58022F0001e5Db827BC0022" + ], + "merkle_proofs": [ + { + "account": "0x25b972807a54bbbce0a206a76ea68f3c556c1a8b", + "proofs": [ + "0xf29f8e7dbbaeeb3725b8d387e5a4a5e57a41af88ad2a913eff1082f82a0cecab", + "0x48df329d7b302f9a040da0637cf572c7f3b90a66d0f58d8c4e1e064a7491db9e", + "0x68083a09cd5acffbdd3c0e2608279df648921159d6c3d286af2075231a227172", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0xDd704A44866AE9C387CfC687fa642a222b84f0D3", + "proofs": [ + "0xfa894935d1e6ce07360daccac94d7272903decf0e835df7b3a8fbfd5816a1b18", + "0x48df329d7b302f9a040da0637cf572c7f3b90a66d0f58d8c4e1e064a7491db9e", + "0x68083a09cd5acffbdd3c0e2608279df648921159d6c3d286af2075231a227172", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0x5fAd091BBa2731937087aa471d0BaCCFaD4157c4", + "proofs": [ + "0x11a178bf8e6496ea5f690ace392d1b4fa72d58cbb2394b51711ff373cf3ce367", + "0xd892315bdd6fa3d023cd0f71f600c36b8ec678891e7a65d960af28bfe5482fb5", + "0x68083a09cd5acffbdd3c0e2608279df648921159d6c3d286af2075231a227172", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0x65786B3dEe53D4C61E2fd0bd0F7049C2613b376a", + "proofs": [ + "0x8aa455d813b229fe05013c62038e400f890590c7c31c8cd3c4447cf063d2aad6", + "0xd892315bdd6fa3d023cd0f71f600c36b8ec678891e7a65d960af28bfe5482fb5", + "0x68083a09cd5acffbdd3c0e2608279df648921159d6c3d286af2075231a227172", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0x46bB1A2549F36423227158c7AC7aE6BeaE1bFfb4", + "proofs": [ + "0xe9b9e71f1d30a78e0d60c2ebf454b6db475ed12927cfe931cafffc9858b746ba", + "0x8d1b192e3b9e5636e84a81f457e6c92fd5770e861420a410c66aa0d80a7dcf6b", + "0xcfe08611b21fa3ad70db1af5a3b1e99f574cdbadba21d03c17319799efe2479a", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0x6e6976bB88285b4Ca5E928e1c1720550D570Ac69", + "proofs": [ + "0x180be9857a4f8f4ab678d1c4606d343db9de63b6d50767b4fb5cab9c3a927d47", + "0x8d1b192e3b9e5636e84a81f457e6c92fd5770e861420a410c66aa0d80a7dcf6b", + "0xcfe08611b21fa3ad70db1af5a3b1e99f574cdbadba21d03c17319799efe2479a", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0xD26Ec7401C198ADAc340d3A4Cb8B52b845F3A542", + "proofs": [ + "0xa16f465289d778c504df9c2839207dfcb20c1a216e26fd52782c2098ea51b1c3", + "0x800a067776a0f60252f9d4b821235edebada9004e6f9bc41150346a4cbdf681a", + "0xcfe08611b21fa3ad70db1af5a3b1e99f574cdbadba21d03c17319799efe2479a", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0x6bd60f089B6E8BA75c409a54CDea34AA511277f6", + "proofs": [ + "0x5a1811fbc236cf35939f76fa4d17221c34199e0c9f77f720306dfad6e6181a4d", + "0x800a067776a0f60252f9d4b821235edebada9004e6f9bc41150346a4cbdf681a", + "0xcfe08611b21fa3ad70db1af5a3b1e99f574cdbadba21d03c17319799efe2479a", + "0x961114393dddb8eba887623b7b7302fd0ff9ae9d5cc380335f1b0eda5c1ab378" + ] + }, + { + "account": "0xaAa9AaB67BB37b75d9F5db1F456348Ef1584E896", + "proofs": [ + "0xa30586646d1d4d6f311d079093a411665abb7b821592e9e0d9854bfd498932db", + "0x48f63b6fb85e15e46285b82d8f27007367f4d1e9f7bde809947d9e4ba42a157a", + "0x6f01c7faf165bc97e65bec2b9df13fd3c2c2768ce4e4d6d26bb45c39de1cc7cd", + "0xbdd3bd59318322a607ac1168be16a493d60d3660a1ce3f796727b7e33b04a5f3" + ] + }, + { + "account": "0xC89F54E7dee2D45Ec11fca623cf7f772c6F34a19", + "proofs": [ + "0xfe20939bb7688ec2096aade3718ff030b05a70524a3a9aa0483b34f734ff12fd", + "0x48f63b6fb85e15e46285b82d8f27007367f4d1e9f7bde809947d9e4ba42a157a", + "0x6f01c7faf165bc97e65bec2b9df13fd3c2c2768ce4e4d6d26bb45c39de1cc7cd", + "0xbdd3bd59318322a607ac1168be16a493d60d3660a1ce3f796727b7e33b04a5f3" + ] + }, + { + "account": "0x9f4DEc4A424394e93f36D2497f2dF970F9C2975a", + "proofs": [ + "0x3b8a7644b5ec56cd0239772ff7e13e8603388ab4bc313ccff71f3cb95199033b", + "0x74aac03dec70d534b8aab60700011ca52c4f0874f177bf82e75974f67a7512f9", + "0x6f01c7faf165bc97e65bec2b9df13fd3c2c2768ce4e4d6d26bb45c39de1cc7cd", + "0xbdd3bd59318322a607ac1168be16a493d60d3660a1ce3f796727b7e33b04a5f3" + ] + }, + { + "account": "0xaE2304daA840D45ef2Af30f02CF0f48e4974f595", + "proofs": [ + "0x7d039cf73a6ec0c4ce8d69523d68d46dc24ef831f7ba568841892e219ba40fb8", + "0x74aac03dec70d534b8aab60700011ca52c4f0874f177bf82e75974f67a7512f9", + "0x6f01c7faf165bc97e65bec2b9df13fd3c2c2768ce4e4d6d26bb45c39de1cc7cd", + "0xbdd3bd59318322a607ac1168be16a493d60d3660a1ce3f796727b7e33b04a5f3" + ] + }, + { + "account": "0x66488AC3727Fc0e3F58022F0001e5Db827BC0022", + "proofs": [ + "0x3372c435af48eef9e0d69fec447e455286b2376e8c85a9106e1c9ec8f061e07b", + "0xbdd3bd59318322a607ac1168be16a493d60d3660a1ce3f796727b7e33b04a5f3" + ] + } + ] } } }