diff --git a/contracts/deploy/mainnet/179_upgrade_ousd_morpho_v2_strategy.js b/contracts/deploy/mainnet/179_upgrade_ousd_morpho_v2_strategy.js index f0245f60dd..93650e0970 100644 --- a/contracts/deploy/mainnet/179_upgrade_ousd_morpho_v2_strategy.js +++ b/contracts/deploy/mainnet/179_upgrade_ousd_morpho_v2_strategy.js @@ -7,7 +7,7 @@ module.exports = deploymentWithGovernanceProposal( forceDeploy: false, reduceQueueTime: true, deployerIsProposer: false, - proposalId: "", + proposalId: "38234265178409078333598297388552567945868201345097914935151040432111128029390", }, async ({ deployWithConfirmation }) => { const cVaultProxy = await ethers.getContract("VaultProxy"); diff --git a/contracts/deployments/mainnet/.migrations.json b/contracts/deployments/mainnet/.migrations.json index a583e15cb3..03c6eafa15 100644 --- a/contracts/deployments/mainnet/.migrations.json +++ b/contracts/deployments/mainnet/.migrations.json @@ -66,5 +66,6 @@ "173_improve_curve_pb_module": 1770818413, "175_deploy_pool_booster_merkl_factory": 1772620839, "177_change_crosschain_strategy_operator": 1771489463, - "178_ousd_auto_withdrawal_module": 1771922160 + "178_ousd_auto_withdrawal_module": 1771922160, + "179_upgrade_ousd_morpho_v2_strategy": 1772658143 } \ No newline at end of file diff --git a/contracts/deployments/mainnet/MorphoV2Strategy.json b/contracts/deployments/mainnet/MorphoV2Strategy.json new file mode 100644 index 0000000000..63dde67a11 --- /dev/null +++ b/contracts/deployments/mainnet/MorphoV2Strategy.json @@ -0,0 +1,1007 @@ +{ + "address": "0x34E28A257dF02fb3cEA12f0836fb8730B77ef9Cd", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "platformAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "vaultAddress", + "type": "address" + } + ], + "internalType": "struct InitializableAbstractStrategy.BaseStrategyConfig", + "name": "_baseConfig", + "type": "tuple" + }, + { + "internalType": "address", + "name": "_assetToken", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "adapter", + "type": "address" + } + ], + "name": "IncompatibleAdapter", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ClaimedRewards", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_pToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "GovernorshipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "_oldHarvesterAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_newHarvesterAddress", + "type": "address" + } + ], + "name": "HarvesterAddressesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_pToken", + "type": "address" + } + ], + "name": "PTokenAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_pToken", + "type": "address" + } + ], + "name": "PTokenRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousGovernor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newGovernor", + "type": "address" + } + ], + "name": "PendingGovernorshipTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "_oldAddresses", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "_newAddresses", + "type": "address[]" + } + ], + "name": "RewardTokenAddressesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "_pToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "Withdrawal", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "assetToPToken", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "assetToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "checkBalance", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "claimGovernance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "collectRewardTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "depositAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getRewardTokenAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "governor", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "harvesterAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isGovernor", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxWithdraw", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes32[]", + "name": "proof", + "type": "bytes32[]" + } + ], + "name": "merkleClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "merkleDistributor", + "outputs": [ + { + "internalType": "contract IDistributor", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "platformAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "removePToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "rewardTokenAddresses", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "safeApproveAllTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_harvesterAddress", + "type": "address" + } + ], + "name": "setHarvesterAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "setPTokenAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "_rewardTokenAddresses", + "type": "address[]" + } + ], + "name": "setRewardTokenAddresses", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shareToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + } + ], + "name": "supportsAsset", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newGovernor", + "type": "address" + } + ], + "name": "transferGovernance", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "transferToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_recipient", + "type": "address" + }, + { + "internalType": "address", + "name": "_asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x3a881965d4bb084c06191ac62c2bd1021d69e6f8874cf838c9c438f0050d4890", + "receipt": { + "to": null, + "from": "0xDba474FeF81bc7475f70e28DFC12410f032A83Db", + "contractAddress": "0x34E28A257dF02fb3cEA12f0836fb8730B77ef9Cd", + "transactionIndex": 177, + "gasUsed": "2275645", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd7f37b8e36072babd1beea7367c661ba185d760f64f63003ec83ec38b8efa123", + "transactionHash": "0x3a881965d4bb084c06191ac62c2bd1021d69e6f8874cf838c9c438f0050d4890", + "logs": [], + "blockNumber": 24586624, + "cumulativeGasUsed": "27513746", + "status": 1, + "byzantium": true + }, + "args": [ + [ + "0xFB154c729A16802c4ad1E8f7FF539a8b9f49c960", + "0xE75D77B1865Ae93c7eaa3040B038D7aA7BC02F70" + ], + "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" + ], + "numDeployments": 1, + "solcInputHash": "ca5c08626bc4341b9af4973050a80d7d", + "metadata": "{\"compiler\":{\"version\":\"0.8.28+commit.7893614a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"platformAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vaultAddress\",\"type\":\"address\"}],\"internalType\":\"struct InitializableAbstractStrategy.BaseStrategyConfig\",\"name\":\"_baseConfig\",\"type\":\"tuple\"},{\"internalType\":\"address\",\"name\":\"_assetToken\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"adapter\",\"type\":\"address\"}],\"name\":\"IncompatibleAdapter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ClaimedRewards\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_pToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"GovernorshipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_oldHarvesterAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_newHarvesterAddress\",\"type\":\"address\"}],\"name\":\"HarvesterAddressesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_pToken\",\"type\":\"address\"}],\"name\":\"PTokenAdded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_pToken\",\"type\":\"address\"}],\"name\":\"PTokenRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousGovernor\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newGovernor\",\"type\":\"address\"}],\"name\":\"PendingGovernorshipTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"_oldAddresses\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"_newAddresses\",\"type\":\"address[]\"}],\"name\":\"RewardTokenAddressesUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"rewardToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"RewardTokenCollected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"_pToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"assetToPToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"assetToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"balance\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"claimGovernance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"collectRewardTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"deposit\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"depositAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getRewardTokenAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"governor\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"harvesterAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxWithdraw\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes32[]\",\"name\":\"proof\",\"type\":\"bytes32[]\"}],\"name\":\"merkleClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"merkleDistributor\",\"outputs\":[{\"internalType\":\"contract IDistributor\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"platformAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"removePToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"rewardTokenAddresses\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"safeApproveAllTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_harvesterAddress\",\"type\":\"address\"}],\"name\":\"setHarvesterAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"setPTokenAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"_rewardTokenAddresses\",\"type\":\"address[]\"}],\"name\":\"setRewardTokenAddresses\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shareToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"supportsAsset\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newGovernor\",\"type\":\"address\"}],\"name\":\"transferGovernance\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"transferToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"}],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawAll\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"checkBalance(address)\":{\"params\":{\"_asset\":\"Address of the asset\"},\"returns\":{\"balance\":\" Total value of the asset in the platform\"}},\"constructor\":{\"params\":{\"_assetToken\":\"Address of the ERC-4626 asset token. e.g. USDC\",\"_baseConfig\":\"Base strategy config with Morpho V2 Vault and vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy\"}},\"deposit(address,uint256)\":{\"details\":\"Deposit assets by converting them to shares\",\"params\":{\"_amount\":\"Amount of asset to deposit\",\"_asset\":\"Address of asset to deposit\"}},\"depositAll()\":{\"details\":\"Deposit the entire balance of assetToken to gain shareToken\"},\"getRewardTokenAddresses()\":{\"returns\":{\"_0\":\"address[] the reward token addresses.\"}},\"merkleClaim(address,uint256,bytes32[])\":{\"params\":{\"amount\":\"The amount of tokens to claim.\",\"proof\":\"The Merkle proof to validate the claim.\",\"token\":\"The address of the token to claim.\"}},\"removePToken(uint256)\":{\"details\":\"If the ERC-4626 Tokenized Vault needed to be changed, a new contract would need to be deployed and the proxy updated.\"},\"setHarvesterAddress(address)\":{\"params\":{\"_harvesterAddress\":\"Address of the harvester contract.\"}},\"setPTokenAddress(address,address)\":{\"details\":\"If the ERC-4626 Tokenized Vault needed to be changed, a new contract would need to be deployed and the proxy updated.\"},\"setRewardTokenAddresses(address[])\":{\"params\":{\"_rewardTokenAddresses\":\"Array of reward token addresses\"}},\"supportsAsset(address)\":{\"details\":\"Returns bool indicating whether asset is supported by strategy\",\"params\":{\"_asset\":\"Address of the asset\"}},\"transferGovernance(address)\":{\"params\":{\"_newGovernor\":\"Address of the new Governor\"}},\"transferToken(address,uint256)\":{\"params\":{\"_amount\":\"Amount of the asset to transfer\",\"_asset\":\"Address for the asset\"}},\"withdraw(address,address,uint256)\":{\"details\":\"Withdraw asset by burning shares\",\"params\":{\"_amount\":\"Amount of asset to withdraw\",\"_asset\":\"Address of asset to withdraw\",\"_recipient\":\"Address to receive withdrawn asset\"}},\"withdrawAll()\":{\"details\":\"Remove all the liquidity that is available in the Morpho V2 vault The particular behaviour of the Morpho V2 vault is that it can hold multiple Morpho V1 vaults as adapters but only one liquidity adapter. The immediate available funds on the Morpho V2 vault are therfore any liquid assets residing on the Vault V2 contract and the maxWithdraw amount that the Morpho V1 contract can supply.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"assetToPToken(address)\":{\"notice\":\"asset => pToken (Platform Specific Token Address)\"},\"checkBalance(address)\":{\"notice\":\"Get the total asset value held in the platform\"},\"claimGovernance()\":{\"notice\":\"Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor.\"},\"collectRewardTokens()\":{\"notice\":\"Collect accumulated reward token and send to Vault.\"},\"getRewardTokenAddresses()\":{\"notice\":\"Get the reward token addresses.\"},\"governor()\":{\"notice\":\"Returns the address of the current Governor.\"},\"harvesterAddress()\":{\"notice\":\"Address of the Harvester contract allowed to collect reward tokens\"},\"isGovernor()\":{\"notice\":\"Returns true if the caller is the current Governor.\"},\"merkleClaim(address,uint256,bytes32[])\":{\"notice\":\"Claim tokens from the Merkle Distributor\"},\"merkleDistributor()\":{\"notice\":\"The address of the Merkle Distributor contract.\"},\"platformAddress()\":{\"notice\":\"Address of the underlying platform\"},\"removePToken(uint256)\":{\"notice\":\"is not supported for this strategy as the asset and ERC-4626 Tokenized Vault are set at deploy time.\"},\"rewardTokenAddresses(uint256)\":{\"notice\":\"Address of the reward tokens. eg CRV, BAL, CVX, AURA\"},\"safeApproveAllTokens()\":{\"notice\":\"Governor approves the ERC-4626 Tokenized Vault to spend the asset.\"},\"setHarvesterAddress(address)\":{\"notice\":\"Set the Harvester contract that can collect rewards.\"},\"setPTokenAddress(address,address)\":{\"notice\":\"is not supported for this strategy as the asset and ERC-4626 Tokenized Vault are set at deploy time.\"},\"setRewardTokenAddresses(address[])\":{\"notice\":\"Set the reward token addresses. Any old addresses will be overwritten.\"},\"transferGovernance(address)\":{\"notice\":\"Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete\"},\"transferToken(address,uint256)\":{\"notice\":\"Transfer token to governor. Intended for recovering tokens stuck in strategy contracts, i.e. mistaken sends.\"},\"vaultAddress()\":{\"notice\":\"Address of the OToken vault\"},\"withdrawAll()\":{\"notice\":\"Remove all the liquidity that is available in the Morpho V2 vault. Which might not be all of the liquidity owned by the strategy.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/strategies/MorphoV2Strategy.sol\":\"MorphoV2Strategy\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `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(\\n address sender,\\n address recipient,\\n uint256 amount\\n ) external returns (bool);\\n\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n}\\n\",\"keccak256\":\"0x61437cb513a887a1bbad006e7b1c8b414478427d33de47c5600af3c748f108da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0xc3d946432c0ddbb1f846a0d3985be71299df331b91d06732152117f62f0be2b5\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)\\n\\npragma solidity ^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 assembly {\\n size := extcodesize(account)\\n }\\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 (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCall(target, data, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n require(isContract(target), \\\"Address: static call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(isContract(target), \\\"Address: delegate call to non-contract\\\");\\n\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResult(success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x51b758a8815ecc9596c66c37d56b1d33883a444631a3f916b9fe65cb863ef7c4\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a >= b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a / b + (a % b == 0 ? 0 : 1);\\n }\\n}\\n\",\"keccak256\":\"0xfaad496c1c944b6259b7dc70b4865eb1775d6402bc0c81b38a0b24d9f525ae37\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeCast.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\\n * checks.\\n *\\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\\n * easily result in undesired exploitation or bugs, since developers usually\\n * assume that overflows raise errors. `SafeCast` restores this intuition by\\n * reverting the transaction when such an operation overflows.\\n *\\n * Using this library instead of the unchecked operations eliminates an entire\\n * class of bugs, so it's recommended to use it always.\\n *\\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\\n * all math on `uint256` and `int256` and then downcasting.\\n */\\nlibrary SafeCast {\\n /**\\n * @dev Returns the downcasted uint224 from uint256, reverting on\\n * overflow (when the input is greater than largest uint224).\\n *\\n * Counterpart to Solidity's `uint224` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 224 bits\\n */\\n function toUint224(uint256 value) internal pure returns (uint224) {\\n require(value <= type(uint224).max, \\\"SafeCast: value doesn't fit in 224 bits\\\");\\n return uint224(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint128 from uint256, reverting on\\n * overflow (when the input is greater than largest uint128).\\n *\\n * Counterpart to Solidity's `uint128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n */\\n function toUint128(uint256 value) internal pure returns (uint128) {\\n require(value <= type(uint128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return uint128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint96 from uint256, reverting on\\n * overflow (when the input is greater than largest uint96).\\n *\\n * Counterpart to Solidity's `uint96` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 96 bits\\n */\\n function toUint96(uint256 value) internal pure returns (uint96) {\\n require(value <= type(uint96).max, \\\"SafeCast: value doesn't fit in 96 bits\\\");\\n return uint96(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint64 from uint256, reverting on\\n * overflow (when the input is greater than largest uint64).\\n *\\n * Counterpart to Solidity's `uint64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n */\\n function toUint64(uint256 value) internal pure returns (uint64) {\\n require(value <= type(uint64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return uint64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint32 from uint256, reverting on\\n * overflow (when the input is greater than largest uint32).\\n *\\n * Counterpart to Solidity's `uint32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n */\\n function toUint32(uint256 value) internal pure returns (uint32) {\\n require(value <= type(uint32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return uint32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint16 from uint256, reverting on\\n * overflow (when the input is greater than largest uint16).\\n *\\n * Counterpart to Solidity's `uint16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n */\\n function toUint16(uint256 value) internal pure returns (uint16) {\\n require(value <= type(uint16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return uint16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted uint8 from uint256, reverting on\\n * overflow (when the input is greater than largest uint8).\\n *\\n * Counterpart to Solidity's `uint8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n */\\n function toUint8(uint256 value) internal pure returns (uint8) {\\n require(value <= type(uint8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return uint8(value);\\n }\\n\\n /**\\n * @dev Converts a signed int256 into an unsigned uint256.\\n *\\n * Requirements:\\n *\\n * - input must be greater than or equal to 0.\\n */\\n function toUint256(int256 value) internal pure returns (uint256) {\\n require(value >= 0, \\\"SafeCast: value must be positive\\\");\\n return uint256(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int128 from int256, reverting on\\n * overflow (when the input is less than smallest int128 or\\n * greater than largest int128).\\n *\\n * Counterpart to Solidity's `int128` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 128 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt128(int256 value) internal pure returns (int128) {\\n require(value >= type(int128).min && value <= type(int128).max, \\\"SafeCast: value doesn't fit in 128 bits\\\");\\n return int128(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int64 from int256, reverting on\\n * overflow (when the input is less than smallest int64 or\\n * greater than largest int64).\\n *\\n * Counterpart to Solidity's `int64` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 64 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt64(int256 value) internal pure returns (int64) {\\n require(value >= type(int64).min && value <= type(int64).max, \\\"SafeCast: value doesn't fit in 64 bits\\\");\\n return int64(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int32 from int256, reverting on\\n * overflow (when the input is less than smallest int32 or\\n * greater than largest int32).\\n *\\n * Counterpart to Solidity's `int32` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 32 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt32(int256 value) internal pure returns (int32) {\\n require(value >= type(int32).min && value <= type(int32).max, \\\"SafeCast: value doesn't fit in 32 bits\\\");\\n return int32(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int16 from int256, reverting on\\n * overflow (when the input is less than smallest int16 or\\n * greater than largest int16).\\n *\\n * Counterpart to Solidity's `int16` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 16 bits\\n *\\n * _Available since v3.1._\\n */\\n function toInt16(int256 value) internal pure returns (int16) {\\n require(value >= type(int16).min && value <= type(int16).max, \\\"SafeCast: value doesn't fit in 16 bits\\\");\\n return int16(value);\\n }\\n\\n /**\\n * @dev Returns the downcasted int8 from int256, reverting on\\n * overflow (when the input is less than smallest int8 or\\n * greater than largest int8).\\n *\\n * Counterpart to Solidity's `int8` operator.\\n *\\n * Requirements:\\n *\\n * - input must fit into 8 bits.\\n *\\n * _Available since v3.1._\\n */\\n function toInt8(int256 value) internal pure returns (int8) {\\n require(value >= type(int8).min && value <= type(int8).max, \\\"SafeCast: value doesn't fit in 8 bits\\\");\\n return int8(value);\\n }\\n\\n /**\\n * @dev Converts an unsigned uint256 into a signed int256.\\n *\\n * Requirements:\\n *\\n * - input must be less than or equal to maxInt256.\\n */\\n function toInt256(uint256 value) internal pure returns (int256) {\\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\\n require(value <= uint256(type(int256).max), \\\"SafeCast: value doesn't fit in an int256\\\");\\n return int256(value);\\n }\\n}\\n\",\"keccak256\":\"0x5c6caab697d302ad7eb59c234a4d2dbc965c1bae87709bd2850060b7695b28c7\",\"license\":\"MIT\"},\"contracts/governance/Governable.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Base for contracts that are managed by the Origin Protocol's Governor.\\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\\n * from owner to governor and renounce methods removed. Does not use\\n * Context.sol like Ownable.sol does for simplification.\\n * @author Origin Protocol Inc\\n */\\nabstract contract Governable {\\n // Storage position of the owner and pendingOwner of the contract\\n // keccak256(\\\"OUSD.governor\\\");\\n bytes32 private constant governorPosition =\\n 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\\n\\n // keccak256(\\\"OUSD.pending.governor\\\");\\n bytes32 private constant pendingGovernorPosition =\\n 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\\n\\n // keccak256(\\\"OUSD.reentry.status\\\");\\n bytes32 private constant reentryStatusPosition =\\n 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\\n\\n // See OpenZeppelin ReentrancyGuard implementation\\n uint256 constant _NOT_ENTERED = 1;\\n uint256 constant _ENTERED = 2;\\n\\n event PendingGovernorshipTransfer(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n event GovernorshipTransferred(\\n address indexed previousGovernor,\\n address indexed newGovernor\\n );\\n\\n /**\\n * @notice Returns the address of the current Governor.\\n */\\n function governor() public view returns (address) {\\n return _governor();\\n }\\n\\n /**\\n * @dev Returns the address of the current Governor.\\n */\\n function _governor() internal view returns (address governorOut) {\\n bytes32 position = governorPosition;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n governorOut := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Returns the address of the pending Governor.\\n */\\n function _pendingGovernor()\\n internal\\n view\\n returns (address pendingGovernor)\\n {\\n bytes32 position = pendingGovernorPosition;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n pendingGovernor := sload(position)\\n }\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the Governor.\\n */\\n modifier onlyGovernor() {\\n require(isGovernor(), \\\"Caller is not the Governor\\\");\\n _;\\n }\\n\\n /**\\n * @notice Returns true if the caller is the current Governor.\\n */\\n function isGovernor() public view returns (bool) {\\n return msg.sender == _governor();\\n }\\n\\n function _setGovernor(address newGovernor) internal {\\n emit GovernorshipTransferred(_governor(), newGovernor);\\n\\n bytes32 position = governorPosition;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(position, newGovernor)\\n }\\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 bytes32 position = reentryStatusPosition;\\n uint256 _reentry_status;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n _reentry_status := sload(position)\\n }\\n\\n // On the first call to nonReentrant, _notEntered will be true\\n require(_reentry_status != _ENTERED, \\\"Reentrant call\\\");\\n\\n // Any calls to nonReentrant after this point will fail\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(position, _ENTERED)\\n }\\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 // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(position, _NOT_ENTERED)\\n }\\n }\\n\\n function _setPendingGovernor(address newGovernor) internal {\\n bytes32 position = pendingGovernorPosition;\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n sstore(position, newGovernor)\\n }\\n }\\n\\n /**\\n * @notice Transfers Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the current Governor. Must be claimed for this to complete\\n * @param _newGovernor Address of the new Governor\\n */\\n function transferGovernance(address _newGovernor) external onlyGovernor {\\n _setPendingGovernor(_newGovernor);\\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\\n }\\n\\n /**\\n * @notice Claim Governance of the contract to a new account (`newGovernor`).\\n * Can only be called by the new Governor.\\n */\\n function claimGovernance() external {\\n require(\\n msg.sender == _pendingGovernor(),\\n \\\"Only the pending Governor can complete the claim\\\"\\n );\\n _changeGovernor(msg.sender);\\n }\\n\\n /**\\n * @dev Change Governance of the contract to a new account (`newGovernor`).\\n * @param _newGovernor Address of the new Governor\\n */\\n function _changeGovernor(address _newGovernor) internal {\\n require(_newGovernor != address(0), \\\"New Governor is address(0)\\\");\\n _setGovernor(_newGovernor);\\n }\\n}\\n\",\"keccak256\":\"0xf32f873c8bfbacf2e5f01d0cf37bc7f54fbd5aa656e95c8a599114229946f107\",\"license\":\"BUSL-1.1\"},\"contracts/interfaces/IBasicToken.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\ninterface IBasicToken {\\n function symbol() external view returns (string memory);\\n\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0xa562062698aa12572123b36dfd2072f1a39e44fed2031cc19c2c9fd522f96ec2\",\"license\":\"MIT\"},\"contracts/interfaces/IMerkl.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\ninterface IDistributor {\\n event Claimed(address indexed user, address indexed token, uint256 amount);\\n\\n function claim(\\n address[] calldata users,\\n address[] calldata tokens,\\n uint256[] calldata amounts,\\n bytes32[][] calldata proofs\\n ) external;\\n}\\n\",\"keccak256\":\"0xdf9acbbc3e7c00135f5428b8a2cc8a5a31e3d095bb27cd93a58c546a0b606697\",\"license\":\"BUSL-1.1\"},\"contracts/interfaces/IStrategy.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\\n */\\ninterface IStrategy {\\n /**\\n * @dev Deposit the given asset to platform\\n * @param _asset asset address\\n * @param _amount Amount to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external;\\n\\n /**\\n * @dev Deposit the entire balance of all supported assets in the Strategy\\n * to the platform\\n */\\n function depositAll() external;\\n\\n /**\\n * @dev Withdraw given asset from Lending platform\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external;\\n\\n /**\\n * @dev Liquidate all assets in strategy and return them to Vault.\\n */\\n function withdrawAll() external;\\n\\n /**\\n * @dev Returns the current balance of the given asset.\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n returns (uint256 balance);\\n\\n /**\\n * @dev Returns bool indicating whether strategy supports asset.\\n */\\n function supportsAsset(address _asset) external view returns (bool);\\n\\n /**\\n * @dev Collect reward tokens from the Strategy.\\n */\\n function collectRewardTokens() external;\\n\\n /**\\n * @dev The address array of the reward tokens for the Strategy.\\n */\\n function getRewardTokenAddresses() external view returns (address[] memory);\\n\\n function harvesterAddress() external view returns (address);\\n\\n function transferToken(address token, uint256 amount) external;\\n\\n function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses)\\n external;\\n}\\n\",\"keccak256\":\"0x79ca47defb3b5a56bba13f14c440838152fd1c1aa640476154516a16da4da8ba\",\"license\":\"BUSL-1.1\"},\"contracts/interfaces/IVault.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport { VaultStorage } from \\\"../vault/VaultStorage.sol\\\";\\n\\ninterface IVault {\\n // slither-disable-start constable-states\\n\\n event AssetAllocated(address _asset, address _strategy, uint256 _amount);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event DefaultStrategyUpdated(address _strategy);\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n event StrategyAddedToMintWhitelist(address indexed strategy);\\n event StrategyRemovedFromMintWhitelist(address indexed strategy);\\n event RebasePerSecondMaxChanged(uint256 rebaseRatePerSecond);\\n event DripDurationChanged(uint256 dripDuration);\\n event WithdrawalRequested(\\n address indexed _withdrawer,\\n uint256 indexed _requestId,\\n uint256 _amount,\\n uint256 _queued\\n );\\n event WithdrawalClaimed(\\n address indexed _withdrawer,\\n uint256 indexed _requestId,\\n uint256 _amount\\n );\\n event WithdrawalClaimable(uint256 _claimable, uint256 _newClaimable);\\n event WithdrawalClaimDelayUpdated(uint256 _newDelay);\\n\\n // Governable.sol\\n function transferGovernance(address _newGovernor) external;\\n\\n function claimGovernance() external;\\n\\n function governor() external view returns (address);\\n\\n // VaultAdmin.sol\\n function setVaultBuffer(uint256 _vaultBuffer) external;\\n\\n function vaultBuffer() external view returns (uint256);\\n\\n function setAutoAllocateThreshold(uint256 _threshold) external;\\n\\n function autoAllocateThreshold() external view returns (uint256);\\n\\n function setRebaseThreshold(uint256 _threshold) external;\\n\\n function rebaseThreshold() external view returns (uint256);\\n\\n function setStrategistAddr(address _address) external;\\n\\n function strategistAddr() external view returns (address);\\n\\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\\n\\n function maxSupplyDiff() external view returns (uint256);\\n\\n function setTrusteeAddress(address _address) external;\\n\\n function trusteeAddress() external view returns (address);\\n\\n function setTrusteeFeeBps(uint256 _basis) external;\\n\\n function trusteeFeeBps() external view returns (uint256);\\n\\n function approveStrategy(address _addr) external;\\n\\n function removeStrategy(address _addr) external;\\n\\n function setDefaultStrategy(address _strategy) external;\\n\\n function defaultStrategy() external view returns (address);\\n\\n function pauseRebase() external;\\n\\n function unpauseRebase() external;\\n\\n function rebasePaused() external view returns (bool);\\n\\n function pauseCapital() external;\\n\\n function unpauseCapital() external;\\n\\n function capitalPaused() external view returns (bool);\\n\\n function transferToken(address _asset, uint256 _amount) external;\\n\\n function withdrawAllFromStrategy(address _strategyAddr) external;\\n\\n function withdrawAllFromStrategies() external;\\n\\n function withdrawFromStrategy(\\n address _strategyFromAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external;\\n\\n function depositToStrategy(\\n address _strategyToAddress,\\n address[] calldata _assets,\\n uint256[] calldata _amounts\\n ) external;\\n\\n // VaultCore.sol\\n function mint(uint256 _amount) external;\\n\\n function mintForStrategy(uint256 _amount) external;\\n\\n function burnForStrategy(uint256 _amount) external;\\n\\n function allocate() external;\\n\\n function rebase() external;\\n\\n function totalValue() external view returns (uint256 value);\\n\\n function checkBalance(address _asset) external view returns (uint256);\\n\\n function getAssetCount() external view returns (uint256);\\n\\n function getAllAssets() external view returns (address[] memory);\\n\\n function getStrategyCount() external view returns (uint256);\\n\\n function getAllStrategies() external view returns (address[] memory);\\n\\n /// @notice Deprecated.\\n function isSupportedAsset(address _asset) external view returns (bool);\\n\\n function asset() external view returns (address);\\n\\n function initialize(address) external;\\n\\n function addWithdrawalQueueLiquidity() external;\\n\\n function requestWithdrawal(uint256 _amount)\\n external\\n returns (uint256 requestId, uint256 queued);\\n\\n function claimWithdrawal(uint256 requestId)\\n external\\n returns (uint256 amount);\\n\\n function claimWithdrawals(uint256[] memory requestIds)\\n external\\n returns (uint256[] memory amounts, uint256 totalAmount);\\n\\n function withdrawalQueueMetadata()\\n external\\n view\\n returns (VaultStorage.WithdrawalQueueMetadata memory);\\n\\n function withdrawalRequests(uint256 requestId)\\n external\\n view\\n returns (VaultStorage.WithdrawalRequest memory);\\n\\n function addStrategyToMintWhitelist(address strategyAddr) external;\\n\\n function removeStrategyFromMintWhitelist(address strategyAddr) external;\\n\\n function isMintWhitelistedStrategy(address strategyAddr)\\n external\\n view\\n returns (bool);\\n\\n function withdrawalClaimDelay() external view returns (uint256);\\n\\n function setWithdrawalClaimDelay(uint256 newDelay) external;\\n\\n function lastRebase() external view returns (uint64);\\n\\n function dripDuration() external view returns (uint64);\\n\\n function setDripDuration(uint256 _dripDuration) external;\\n\\n function rebasePerSecondMax() external view returns (uint64);\\n\\n function setRebaseRateMax(uint256 yearlyApr) external;\\n\\n function rebasePerSecondTarget() external view returns (uint64);\\n\\n function previewYield() external view returns (uint256 yield);\\n\\n // slither-disable-end constable-states\\n}\\n\",\"keccak256\":\"0x5d42df4e6bf7c750a61ba0fba5e49c3b601205ff1f5bfd5b33de63febad89d70\",\"license\":\"BUSL-1.1\"},\"contracts/interfaces/morpho/IMorphoV2Adapter.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\ninterface IMorphoV2Adapter {\\n // address of the underlying vault\\n function morphoVaultV1() external view returns (address);\\n\\n // address of the parent Morpho V2 vault\\n function parentVault() external view returns (address);\\n}\\n\",\"keccak256\":\"0x3628a0b75bfa214ff590bfea368578c6de25f8dee99e932971b591ca0143bee2\",\"license\":\"BUSL-1.1\"},\"contracts/interfaces/morpho/IVaultV2.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport { IERC4626 } from \\\"../../../lib/openzeppelin/interfaces/IERC4626.sol\\\";\\n\\ninterface IVaultV2 is IERC4626 {\\n function liquidityAdapter() external view returns (address);\\n}\\n\",\"keccak256\":\"0xd6f2233a5df417b6517cde90ec380109d96cc666fcbb9dc354475a52aeeca4c8\",\"license\":\"BUSL-1.1\"},\"contracts/strategies/Generalized4626Strategy.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Generalized 4626 Strategy\\n * @notice Investment strategy for ERC-4626 Tokenized Vaults\\n * @dev This strategy should not be used for the Morpho V2 Vaults as those are not\\n * completley ERC-4626 compliant - they don't implement the maxWithdraw() and \\n * maxRedeem() functions and rather return 0 when any of them is called.\\n * @author Origin Protocol Inc\\n */\\nimport { IERC4626 } from \\\"../../lib/openzeppelin/interfaces/IERC4626.sol\\\";\\nimport { IERC20, InitializableAbstractStrategy } from \\\"../utils/InitializableAbstractStrategy.sol\\\";\\nimport { IDistributor } from \\\"../interfaces/IMerkl.sol\\\";\\n\\ncontract Generalized4626Strategy is InitializableAbstractStrategy {\\n /// @notice The address of the Merkle Distributor contract.\\n IDistributor public constant merkleDistributor =\\n IDistributor(0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae);\\n\\n /// @dev Replaced with an immutable variable\\n // slither-disable-next-line constable-states\\n address private _deprecate_shareToken;\\n /// @dev Replaced with an immutable variable\\n // slither-disable-next-line constable-states\\n address private _deprecate_assetToken;\\n\\n IERC20 public immutable shareToken;\\n IERC20 public immutable assetToken;\\n\\n // For future use\\n uint256[50] private __gap;\\n\\n event ClaimedRewards(address indexed token, uint256 amount);\\n\\n /**\\n * @param _baseConfig Base strategy config with platformAddress (ERC-4626 Vault contract), eg sfrxETH or sDAI,\\n * and vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy\\n * @param _assetToken Address of the ERC-4626 asset token. eg frxETH or DAI\\n */\\n constructor(BaseStrategyConfig memory _baseConfig, address _assetToken)\\n InitializableAbstractStrategy(_baseConfig)\\n {\\n shareToken = IERC20(_baseConfig.platformAddress);\\n assetToken = IERC20(_assetToken);\\n }\\n\\n function initialize() external virtual onlyGovernor initializer {\\n address[] memory rewardTokens = new address[](0);\\n address[] memory assets = new address[](1);\\n address[] memory pTokens = new address[](1);\\n\\n assets[0] = address(assetToken);\\n pTokens[0] = address(platformAddress);\\n\\n InitializableAbstractStrategy._initialize(\\n rewardTokens,\\n assets,\\n pTokens\\n );\\n }\\n\\n /**\\n * @dev Deposit assets by converting them to shares\\n * @param _asset Address of asset to deposit\\n * @param _amount Amount of asset to deposit\\n */\\n function deposit(address _asset, uint256 _amount)\\n external\\n virtual\\n override\\n onlyVault\\n nonReentrant\\n {\\n _deposit(_asset, _amount);\\n }\\n\\n /**\\n * @dev Deposit assets by converting them to shares\\n * @param _asset Address of asset to deposit\\n * @param _amount Amount of asset to deposit\\n */\\n function _deposit(address _asset, uint256 _amount) internal virtual {\\n require(_amount > 0, \\\"Must deposit something\\\");\\n require(_asset == address(assetToken), \\\"Unexpected asset address\\\");\\n\\n // slither-disable-next-line unused-return\\n IERC4626(platformAddress).deposit(_amount, address(this));\\n emit Deposit(_asset, address(shareToken), _amount);\\n }\\n\\n /**\\n * @dev Deposit the entire balance of assetToken to gain shareToken\\n */\\n function depositAll() external virtual override onlyVault nonReentrant {\\n uint256 balance = assetToken.balanceOf(address(this));\\n if (balance > 0) {\\n _deposit(address(assetToken), balance);\\n }\\n }\\n\\n /**\\n * @dev Withdraw asset by burning shares\\n * @param _recipient Address to receive withdrawn asset\\n * @param _asset Address of asset to withdraw\\n * @param _amount Amount of asset to withdraw\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external virtual override onlyVault nonReentrant {\\n _withdraw(_recipient, _asset, _amount);\\n }\\n\\n function _withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) internal virtual {\\n require(_amount > 0, \\\"Must withdraw something\\\");\\n require(_recipient != address(0), \\\"Must specify recipient\\\");\\n require(_asset == address(assetToken), \\\"Unexpected asset address\\\");\\n\\n // slither-disable-next-line unused-return\\n IERC4626(platformAddress).withdraw(_amount, _recipient, address(this));\\n emit Withdrawal(_asset, address(shareToken), _amount);\\n }\\n\\n /**\\n * @dev Internal method to respond to the addition of new asset / share tokens\\n */\\n function _abstractSetPToken(address, address) internal virtual override {\\n _approveBase();\\n }\\n\\n /**\\n * @dev Remove all assets from platform and send them to Vault contract.\\n */\\n function withdrawAll()\\n external\\n virtual\\n override\\n onlyVaultOrGovernor\\n nonReentrant\\n {\\n // @dev Don't use for Morpho V2 Vaults as below line will return 0\\n uint256 sharesToRedeem = IERC4626(platformAddress).maxRedeem(address(this));\\n\\n uint256 assetAmount = 0;\\n if (sharesToRedeem > 0) {\\n assetAmount = IERC4626(platformAddress).redeem(\\n sharesToRedeem,\\n vaultAddress,\\n address(this)\\n );\\n emit Withdrawal(\\n address(assetToken),\\n address(shareToken),\\n assetAmount\\n );\\n }\\n }\\n\\n /**\\n * @notice Get the total asset value held in the platform\\n * @param _asset Address of the asset\\n * @return balance Total value of the asset in the platform\\n */\\n function checkBalance(address _asset)\\n public\\n view\\n virtual\\n override\\n returns (uint256 balance)\\n {\\n require(_asset == address(assetToken), \\\"Unexpected asset address\\\");\\n /* We are intentionally not counting the amount of assetToken parked on the\\n * contract toward the checkBalance. The deposit and withdraw functions\\n * should not result in assetToken being unused and owned by this strategy\\n * contract.\\n */\\n IERC4626 platform = IERC4626(platformAddress);\\n return platform.previewRedeem(platform.balanceOf(address(this)));\\n }\\n\\n /**\\n * @notice Governor approves the ERC-4626 Tokenized Vault to spend the asset.\\n */\\n function safeApproveAllTokens() external override onlyGovernor {\\n _approveBase();\\n }\\n\\n function _approveBase() internal virtual {\\n // Approval the asset to be transferred to the ERC-4626 Tokenized Vault.\\n // Used by the ERC-4626 deposit() and mint() functions\\n // slither-disable-next-line unused-return\\n assetToken.approve(platformAddress, type(uint256).max);\\n }\\n\\n /**\\n * @dev Returns bool indicating whether asset is supported by strategy\\n * @param _asset Address of the asset\\n */\\n function supportsAsset(address _asset)\\n public\\n view\\n virtual\\n override\\n returns (bool)\\n {\\n return _asset == address(assetToken);\\n }\\n\\n /**\\n * @notice is not supported for this strategy as the asset and\\n * ERC-4626 Tokenized Vault are set at deploy time.\\n * @dev If the ERC-4626 Tokenized Vault needed to be changed, a new\\n * contract would need to be deployed and the proxy updated.\\n */\\n function setPTokenAddress(address, address) external override onlyGovernor {\\n revert(\\\"unsupported function\\\");\\n }\\n\\n /**\\n * @notice is not supported for this strategy as the asset and\\n * ERC-4626 Tokenized Vault are set at deploy time.\\n * @dev If the ERC-4626 Tokenized Vault needed to be changed, a new\\n * contract would need to be deployed and the proxy updated.\\n */\\n function removePToken(uint256) external override onlyGovernor {\\n revert(\\\"unsupported function\\\");\\n }\\n\\n /// @notice Claim tokens from the Merkle Distributor\\n /// @param token The address of the token to claim.\\n /// @param amount The amount of tokens to claim.\\n /// @param proof The Merkle proof to validate the claim.\\n function merkleClaim(\\n address token,\\n uint256 amount,\\n bytes32[] calldata proof\\n ) external {\\n address[] memory users = new address[](1);\\n users[0] = address(this);\\n\\n address[] memory tokens = new address[](1);\\n tokens[0] = token;\\n\\n uint256[] memory amounts = new uint256[](1);\\n amounts[0] = amount;\\n\\n bytes32[][] memory proofs = new bytes32[][](1);\\n proofs[0] = proof;\\n\\n merkleDistributor.claim(users, tokens, amounts, proofs);\\n\\n emit ClaimedRewards(token, amount);\\n }\\n}\\n\",\"keccak256\":\"0x167e83a029d817a18074c15d0371c59e45c8f1fbeba52da26b2cf55e82f29b58\",\"license\":\"BUSL-1.1\"},\"contracts/strategies/MorphoV2Strategy.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Generalized 4626 Strategy when the underlying platform is Morpho V2\\n * @notice Investment strategy for ERC-4626 Tokenized Vaults for the Morpho V2 platform.\\n * @author Origin Protocol Inc\\n */\\nimport { Generalized4626Strategy } from \\\"./Generalized4626Strategy.sol\\\";\\nimport { MorphoV2VaultUtils } from \\\"./MorphoV2VaultUtils.sol\\\";\\nimport { IVaultV2 } from \\\"../interfaces/morpho/IVaultV2.sol\\\";\\nimport { Math } from \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\n\\ncontract MorphoV2Strategy is Generalized4626Strategy {\\n\\n /**\\n * @param _baseConfig Base strategy config with Morpho V2 Vault and\\n * vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy\\n * @param _assetToken Address of the ERC-4626 asset token. e.g. USDC\\n */\\n constructor(BaseStrategyConfig memory _baseConfig, address _assetToken)\\n Generalized4626Strategy(_baseConfig, _assetToken)\\n {}\\n\\n /**\\n * @notice Remove all the liquidity that is available in the Morpho V2 vault.\\n * Which might not be all of the liquidity owned by the strategy.\\n * @dev Remove all the liquidity that is available in the Morpho V2 vault\\n * The particular behaviour of the Morpho V2 vault is that it can hold\\n * multiple Morpho V1 vaults as adapters but only one liquidity adapter.\\n * The immediate available funds on the Morpho V2 vault are therfore any\\n * liquid assets residing on the Vault V2 contract and the maxWithdraw\\n * amount that the Morpho V1 contract can supply.\\n */\\n function withdrawAll()\\n external\\n virtual\\n override\\n onlyVaultOrGovernor\\n nonReentrant\\n {\\n uint256 availableMorphoVault = _maxWithdraw();\\n uint256 balanceToWithdraw = Math.min(\\n availableMorphoVault,\\n checkBalance(address(assetToken))\\n );\\n\\n if (balanceToWithdraw > 0) {\\n // slither-disable-next-line unused-return\\n IVaultV2(platformAddress).withdraw(\\n balanceToWithdraw,\\n vaultAddress,\\n address(this)\\n );\\n }\\n\\n emit Withdrawal(\\n address(assetToken),\\n address(shareToken),\\n balanceToWithdraw\\n );\\n }\\n\\n function maxWithdraw() external view returns (uint256) {\\n return _maxWithdraw();\\n }\\n\\n function _maxWithdraw()\\n internal\\n view\\n returns (uint256 availableAssetLiquidity)\\n {\\n availableAssetLiquidity = MorphoV2VaultUtils.maxWithdrawableAssets(\\n platformAddress,\\n address(assetToken)\\n );\\n }\\n}\\n\",\"keccak256\":\"0x3f42b1341f3c94ec4c806464eec5adf37b982af4898a764d13b7f6db97a02640\",\"license\":\"BUSL-1.1\"},\"contracts/strategies/MorphoV2VaultUtils.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport { IERC20 } from \\\"../utils/InitializableAbstractStrategy.sol\\\";\\nimport { IERC4626 } from \\\"../../lib/openzeppelin/interfaces/IERC4626.sol\\\";\\nimport { IVaultV2 } from \\\"../interfaces/morpho/IVaultV2.sol\\\";\\nimport { IMorphoV2Adapter } from \\\"../interfaces/morpho/IMorphoV2Adapter.sol\\\";\\n\\nlibrary MorphoV2VaultUtils {\\n error IncompatibleAdapter(address adapter);\\n\\n /**\\n * @notice Return maximum amount that can be safely withdrawn from a Morpho V2 vault.\\n * @dev Available liquidity is:\\n * 1) asset balance parked on Morpho V2 vault contract\\n * 2) additional liquidity from the active adapter if it resolves to a Morpho V1 vault\\n * and, when provided, matches the expected adapter\\n */\\n function maxWithdrawableAssets(\\n address platformAddress,\\n address assetToken\\n ) internal view returns (uint256 availableAssetLiquidity) {\\n availableAssetLiquidity = IERC20(assetToken).balanceOf(platformAddress);\\n\\n address liquidityAdapter = IVaultV2(platformAddress).liquidityAdapter();\\n // this is a sufficient check to ensure the adapter is Morpho V1\\n try IMorphoV2Adapter(liquidityAdapter).morphoVaultV1() returns (\\n address underlyingVault\\n ) {\\n availableAssetLiquidity += IERC4626(underlyingVault).maxWithdraw(\\n liquidityAdapter\\n );\\n } catch {\\n revert IncompatibleAdapter(liquidityAdapter);\\n }\\n }\\n\\n}\\n\",\"keccak256\":\"0x38c73e0553df1b59c6564e26e5b1668416d2727fca41af35c6c39592a03287d8\",\"license\":\"BUSL-1.1\"},\"contracts/token/OUSD.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title OUSD Token Contract\\n * @dev ERC20 compatible contract for OUSD\\n * @dev Implements an elastic supply\\n * @author Origin Protocol Inc\\n */\\nimport { IVault } from \\\"../interfaces/IVault.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { SafeCast } from \\\"@openzeppelin/contracts/utils/math/SafeCast.sol\\\";\\n\\ncontract OUSD is Governable {\\n using SafeCast for int256;\\n using SafeCast for uint256;\\n\\n /// @dev Event triggered when the supply changes\\n /// @param totalSupply Updated token total supply\\n /// @param rebasingCredits Updated token rebasing credits\\n /// @param rebasingCreditsPerToken Updated token rebasing credits per token\\n event TotalSupplyUpdatedHighres(\\n uint256 totalSupply,\\n uint256 rebasingCredits,\\n uint256 rebasingCreditsPerToken\\n );\\n /// @dev Event triggered when an account opts in for rebasing\\n /// @param account Address of the account\\n event AccountRebasingEnabled(address account);\\n /// @dev Event triggered when an account opts out of rebasing\\n /// @param account Address of the account\\n event AccountRebasingDisabled(address account);\\n /// @dev Emitted when `value` tokens are moved from one account `from` to\\n /// another `to`.\\n /// @param from Address of the account tokens are moved from\\n /// @param to Address of the account tokens are moved to\\n /// @param value Amount of tokens transferred\\n event Transfer(address indexed from, address indexed to, uint256 value);\\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 /// @param owner Address of the owner approving allowance\\n /// @param spender Address of the spender allowance is granted to\\n /// @param value Amount of tokens spender can transfer\\n event Approval(\\n address indexed owner,\\n address indexed spender,\\n uint256 value\\n );\\n /// @dev Yield resulting from {changeSupply} that a `source` account would\\n /// receive is directed to `target` account.\\n /// @param source Address of the source forwarding the yield\\n /// @param target Address of the target receiving the yield\\n event YieldDelegated(address source, address target);\\n /// @dev Yield delegation from `source` account to the `target` account is\\n /// suspended.\\n /// @param source Address of the source suspending yield forwarding\\n /// @param target Address of the target no longer receiving yield from `source`\\n /// account\\n event YieldUndelegated(address source, address target);\\n\\n enum RebaseOptions {\\n NotSet,\\n StdNonRebasing,\\n StdRebasing,\\n YieldDelegationSource,\\n YieldDelegationTarget\\n }\\n\\n uint256[154] private _gap; // Slots to align with deployed contract\\n uint256 private constant MAX_SUPPLY = type(uint128).max;\\n /// @dev The amount of tokens in existence\\n uint256 public totalSupply;\\n mapping(address => mapping(address => uint256)) private allowances;\\n /// @dev The vault with privileges to execute {mint}, {burn}\\n /// and {changeSupply}\\n address public vaultAddress;\\n mapping(address => uint256) internal creditBalances;\\n // the 2 storage variables below need trailing underscores to not name collide with public functions\\n uint256 private rebasingCredits_; // Sum of all rebasing credits (creditBalances for rebasing accounts)\\n uint256 private rebasingCreditsPerToken_;\\n /// @dev The amount of tokens that are not rebasing - receiving yield\\n uint256 public nonRebasingSupply;\\n mapping(address => uint256) internal alternativeCreditsPerToken;\\n /// @dev A map of all addresses and their respective RebaseOptions\\n mapping(address => RebaseOptions) public rebaseState;\\n mapping(address => uint256) private __deprecated_isUpgraded;\\n /// @dev A map of addresses that have yields forwarded to. This is an\\n /// inverse mapping of {yieldFrom}\\n /// Key Account forwarding yield\\n /// Value Account receiving yield\\n mapping(address => address) public yieldTo;\\n /// @dev A map of addresses that are receiving the yield. This is an\\n /// inverse mapping of {yieldTo}\\n /// Key Account receiving yield\\n /// Value Account forwarding yield\\n mapping(address => address) public yieldFrom;\\n\\n uint256 private constant RESOLUTION_INCREASE = 1e9;\\n uint256[34] private __gap; // including below gap totals up to 200\\n\\n /// @dev Verifies that the caller is the Governor or Strategist.\\n modifier onlyGovernorOrStrategist() {\\n require(\\n isGovernor() || msg.sender == IVault(vaultAddress).strategistAddr(),\\n \\\"Caller is not the Strategist or Governor\\\"\\n );\\n _;\\n }\\n\\n /// @dev Initializes the contract and sets necessary variables.\\n /// @param _vaultAddress Address of the vault contract\\n /// @param _initialCreditsPerToken The starting rebasing credits per token.\\n function initialize(address _vaultAddress, uint256 _initialCreditsPerToken)\\n external\\n onlyGovernor\\n {\\n require(_vaultAddress != address(0), \\\"Zero vault address\\\");\\n require(vaultAddress == address(0), \\\"Already initialized\\\");\\n\\n rebasingCreditsPerToken_ = _initialCreditsPerToken;\\n vaultAddress = _vaultAddress;\\n }\\n\\n /// @dev Returns the symbol of the token, a shorter version\\n /// of the name.\\n function symbol() external pure virtual returns (string memory) {\\n return \\\"OUSD\\\";\\n }\\n\\n /// @dev Returns the name of the token.\\n function name() external pure virtual returns (string memory) {\\n return \\\"Origin Dollar\\\";\\n }\\n\\n /// @dev Returns the number of decimals used to get its user representation.\\n function decimals() external pure virtual returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Vault contract\\n */\\n modifier onlyVault() {\\n require(vaultAddress == msg.sender, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @return High resolution rebasingCreditsPerToken\\n */\\n function rebasingCreditsPerTokenHighres() external view returns (uint256) {\\n return rebasingCreditsPerToken_;\\n }\\n\\n /**\\n * @return Low resolution rebasingCreditsPerToken\\n */\\n function rebasingCreditsPerToken() external view returns (uint256) {\\n return rebasingCreditsPerToken_ / RESOLUTION_INCREASE;\\n }\\n\\n /**\\n * @return High resolution total number of rebasing credits\\n */\\n function rebasingCreditsHighres() external view returns (uint256) {\\n return rebasingCredits_;\\n }\\n\\n /**\\n * @return Low resolution total number of rebasing credits\\n */\\n function rebasingCredits() external view returns (uint256) {\\n return rebasingCredits_ / RESOLUTION_INCREASE;\\n }\\n\\n /**\\n * @notice Gets the balance of the specified address.\\n * @param _account Address to query the balance of.\\n * @return A uint256 representing the amount of base units owned by the\\n * specified address.\\n */\\n function balanceOf(address _account) public view returns (uint256) {\\n RebaseOptions state = rebaseState[_account];\\n if (state == RebaseOptions.YieldDelegationSource) {\\n // Saves a slot read when transferring to or from a yield delegating source\\n // since we know creditBalances equals the balance.\\n return creditBalances[_account];\\n }\\n uint256 baseBalance = (creditBalances[_account] * 1e18) /\\n _creditsPerToken(_account);\\n if (state == RebaseOptions.YieldDelegationTarget) {\\n // creditBalances of yieldFrom accounts equals token balances\\n return baseBalance - creditBalances[yieldFrom[_account]];\\n }\\n return baseBalance;\\n }\\n\\n /**\\n * @notice Gets the credits balance of the specified address.\\n * @dev Backwards compatible with old low res credits per token.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256) Credit balance and credits per token of the\\n * address\\n */\\n function creditsBalanceOf(address _account)\\n external\\n view\\n returns (uint256, uint256)\\n {\\n uint256 cpt = _creditsPerToken(_account);\\n if (cpt == 1e27) {\\n // For a period before the resolution upgrade, we created all new\\n // contract accounts at high resolution. Since they are not changing\\n // as a result of this upgrade, we will return their true values\\n return (creditBalances[_account], cpt);\\n } else {\\n return (\\n creditBalances[_account] / RESOLUTION_INCREASE,\\n cpt / RESOLUTION_INCREASE\\n );\\n }\\n }\\n\\n /**\\n * @notice Gets the credits balance of the specified address.\\n * @param _account The address to query the balance of.\\n * @return (uint256, uint256, bool) Credit balance, credits per token of the\\n * address, and isUpgraded\\n */\\n function creditsBalanceOfHighres(address _account)\\n external\\n view\\n returns (\\n uint256,\\n uint256,\\n bool\\n )\\n {\\n return (\\n creditBalances[_account],\\n _creditsPerToken(_account),\\n true // all accounts have their resolution \\\"upgraded\\\"\\n );\\n }\\n\\n // Backwards compatible view\\n function nonRebasingCreditsPerToken(address _account)\\n external\\n view\\n returns (uint256)\\n {\\n return alternativeCreditsPerToken[_account];\\n }\\n\\n /**\\n * @notice Transfer tokens to a specified address.\\n * @param _to the address to transfer to.\\n * @param _value the amount to be transferred.\\n * @return true on success.\\n */\\n function transfer(address _to, uint256 _value) external returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n\\n _executeTransfer(msg.sender, _to, _value);\\n\\n emit Transfer(msg.sender, _to, _value);\\n return true;\\n }\\n\\n /**\\n * @notice Transfer tokens from one address to another.\\n * @param _from The address you want to send tokens from.\\n * @param _to The address you want to transfer to.\\n * @param _value The amount of tokens to be transferred.\\n * @return true on success.\\n */\\n function transferFrom(\\n address _from,\\n address _to,\\n uint256 _value\\n ) external returns (bool) {\\n require(_to != address(0), \\\"Transfer to zero address\\\");\\n uint256 userAllowance = allowances[_from][msg.sender];\\n require(_value <= userAllowance, \\\"Allowance exceeded\\\");\\n\\n unchecked {\\n allowances[_from][msg.sender] = userAllowance - _value;\\n }\\n\\n _executeTransfer(_from, _to, _value);\\n\\n emit Transfer(_from, _to, _value);\\n return true;\\n }\\n\\n function _executeTransfer(\\n address _from,\\n address _to,\\n uint256 _value\\n ) internal {\\n (\\n int256 fromRebasingCreditsDiff,\\n int256 fromNonRebasingSupplyDiff\\n ) = _adjustAccount(_from, -_value.toInt256());\\n (\\n int256 toRebasingCreditsDiff,\\n int256 toNonRebasingSupplyDiff\\n ) = _adjustAccount(_to, _value.toInt256());\\n\\n _adjustGlobals(\\n fromRebasingCreditsDiff + toRebasingCreditsDiff,\\n fromNonRebasingSupplyDiff + toNonRebasingSupplyDiff\\n );\\n }\\n\\n function _adjustAccount(address _account, int256 _balanceChange)\\n internal\\n returns (int256 rebasingCreditsDiff, int256 nonRebasingSupplyDiff)\\n {\\n RebaseOptions state = rebaseState[_account];\\n int256 currentBalance = balanceOf(_account).toInt256();\\n if (currentBalance + _balanceChange < 0) {\\n revert(\\\"Transfer amount exceeds balance\\\");\\n }\\n uint256 newBalance = (currentBalance + _balanceChange).toUint256();\\n\\n if (state == RebaseOptions.YieldDelegationSource) {\\n address target = yieldTo[_account];\\n uint256 targetOldBalance = balanceOf(target);\\n uint256 targetNewCredits = _balanceToRebasingCredits(\\n targetOldBalance + newBalance\\n );\\n rebasingCreditsDiff =\\n targetNewCredits.toInt256() -\\n creditBalances[target].toInt256();\\n\\n creditBalances[_account] = newBalance;\\n creditBalances[target] = targetNewCredits;\\n } else if (state == RebaseOptions.YieldDelegationTarget) {\\n uint256 newCredits = _balanceToRebasingCredits(\\n newBalance + creditBalances[yieldFrom[_account]]\\n );\\n rebasingCreditsDiff =\\n newCredits.toInt256() -\\n creditBalances[_account].toInt256();\\n creditBalances[_account] = newCredits;\\n } else {\\n _autoMigrate(_account);\\n uint256 alternativeCreditsPerTokenMem = alternativeCreditsPerToken[\\n _account\\n ];\\n if (alternativeCreditsPerTokenMem > 0) {\\n nonRebasingSupplyDiff = _balanceChange;\\n if (alternativeCreditsPerTokenMem != 1e18) {\\n alternativeCreditsPerToken[_account] = 1e18;\\n }\\n creditBalances[_account] = newBalance;\\n } else {\\n uint256 newCredits = _balanceToRebasingCredits(newBalance);\\n rebasingCreditsDiff =\\n newCredits.toInt256() -\\n creditBalances[_account].toInt256();\\n creditBalances[_account] = newCredits;\\n }\\n }\\n }\\n\\n function _adjustGlobals(\\n int256 _rebasingCreditsDiff,\\n int256 _nonRebasingSupplyDiff\\n ) internal {\\n if (_rebasingCreditsDiff != 0) {\\n rebasingCredits_ = (rebasingCredits_.toInt256() +\\n _rebasingCreditsDiff).toUint256();\\n }\\n if (_nonRebasingSupplyDiff != 0) {\\n nonRebasingSupply = (nonRebasingSupply.toInt256() +\\n _nonRebasingSupplyDiff).toUint256();\\n }\\n }\\n\\n /**\\n * @notice Function to check the amount of tokens that _owner has allowed\\n * to `_spender`.\\n * @param _owner The address which owns the funds.\\n * @param _spender The address which will spend the funds.\\n * @return The number of tokens still available for the _spender.\\n */\\n function allowance(address _owner, address _spender)\\n external\\n view\\n returns (uint256)\\n {\\n return allowances[_owner][_spender];\\n }\\n\\n /**\\n * @notice Approve the passed address to spend the specified amount of\\n * tokens on behalf of msg.sender.\\n * @param _spender The address which will spend the funds.\\n * @param _value The amount of tokens to be spent.\\n * @return true on success.\\n */\\n function approve(address _spender, uint256 _value) external returns (bool) {\\n allowances[msg.sender][_spender] = _value;\\n emit Approval(msg.sender, _spender, _value);\\n return true;\\n }\\n\\n /**\\n * @notice Creates `_amount` tokens and assigns them to `_account`,\\n * increasing the total supply.\\n */\\n function mint(address _account, uint256 _amount) external onlyVault {\\n require(_account != address(0), \\\"Mint to the zero address\\\");\\n\\n // Account\\n (\\n int256 toRebasingCreditsDiff,\\n int256 toNonRebasingSupplyDiff\\n ) = _adjustAccount(_account, _amount.toInt256());\\n // Globals\\n _adjustGlobals(toRebasingCreditsDiff, toNonRebasingSupplyDiff);\\n totalSupply = totalSupply + _amount;\\n\\n require(totalSupply < MAX_SUPPLY, \\\"Max supply\\\");\\n emit Transfer(address(0), _account, _amount);\\n }\\n\\n /**\\n * @notice Destroys `_amount` tokens from `_account`,\\n * reducing the total supply.\\n */\\n function burn(address _account, uint256 _amount) external onlyVault {\\n require(_account != address(0), \\\"Burn from the zero address\\\");\\n if (_amount == 0) {\\n return;\\n }\\n\\n // Account\\n (\\n int256 toRebasingCreditsDiff,\\n int256 toNonRebasingSupplyDiff\\n ) = _adjustAccount(_account, -_amount.toInt256());\\n // Globals\\n _adjustGlobals(toRebasingCreditsDiff, toNonRebasingSupplyDiff);\\n totalSupply = totalSupply - _amount;\\n\\n emit Transfer(_account, address(0), _amount);\\n }\\n\\n /**\\n * @dev Get the credits per token for an account. Returns a fixed amount\\n * if the account is non-rebasing.\\n * @param _account Address of the account.\\n */\\n function _creditsPerToken(address _account)\\n internal\\n view\\n returns (uint256)\\n {\\n uint256 alternativeCreditsPerTokenMem = alternativeCreditsPerToken[\\n _account\\n ];\\n if (alternativeCreditsPerTokenMem != 0) {\\n return alternativeCreditsPerTokenMem;\\n } else {\\n return rebasingCreditsPerToken_;\\n }\\n }\\n\\n /**\\n * @dev Auto migrate contracts to be non rebasing,\\n * unless they have opted into yield.\\n * @param _account Address of the account.\\n */\\n function _autoMigrate(address _account) internal {\\n uint256 codeLen = _account.code.length;\\n bool isEOA = (codeLen == 0) ||\\n (codeLen == 23 && bytes3(_account.code) == 0xef0100);\\n // In previous code versions, contracts would not have had their\\n // rebaseState[_account] set to RebaseOptions.NonRebasing when migrated\\n // therefore we check the actual accounting used on the account as well.\\n if (\\n (!isEOA) &&\\n rebaseState[_account] == RebaseOptions.NotSet &&\\n alternativeCreditsPerToken[_account] == 0\\n ) {\\n _rebaseOptOut(_account);\\n }\\n }\\n\\n /**\\n * @dev Calculates credits from contract's global rebasingCreditsPerToken_, and\\n * also balance that corresponds to those credits. The latter is important\\n * when adjusting the contract's global nonRebasingSupply to circumvent any\\n * possible rounding errors.\\n *\\n * @param _balance Balance of the account.\\n */\\n function _balanceToRebasingCredits(uint256 _balance)\\n internal\\n view\\n returns (uint256 rebasingCredits)\\n {\\n // Rounds up, because we need to ensure that accounts always have\\n // at least the balance that they should have.\\n // Note this should always be used on an absolute account value,\\n // not on a possibly negative diff, because then the rounding would be wrong.\\n return ((_balance) * rebasingCreditsPerToken_ + 1e18 - 1) / 1e18;\\n }\\n\\n /**\\n * @notice The calling account will start receiving yield after a successful call.\\n * @param _account Address of the account.\\n */\\n function governanceRebaseOptIn(address _account) external onlyGovernor {\\n require(_account != address(0), \\\"Zero address not allowed\\\");\\n _rebaseOptIn(_account);\\n }\\n\\n /**\\n * @notice The calling account will start receiving yield after a successful call.\\n */\\n function rebaseOptIn() external {\\n _rebaseOptIn(msg.sender);\\n }\\n\\n function _rebaseOptIn(address _account) internal {\\n uint256 balance = balanceOf(_account);\\n\\n // prettier-ignore\\n require(\\n alternativeCreditsPerToken[_account] > 0 ||\\n // Accounts may explicitly `rebaseOptIn` regardless of\\n // accounting if they have a 0 balance.\\n creditBalances[_account] == 0\\n ,\\n \\\"Account must be non-rebasing\\\"\\n );\\n RebaseOptions state = rebaseState[_account];\\n // prettier-ignore\\n require(\\n state == RebaseOptions.StdNonRebasing ||\\n state == RebaseOptions.NotSet,\\n \\\"Only standard non-rebasing accounts can opt in\\\"\\n );\\n\\n uint256 newCredits = _balanceToRebasingCredits(balance);\\n\\n // Account\\n rebaseState[_account] = RebaseOptions.StdRebasing;\\n alternativeCreditsPerToken[_account] = 0;\\n creditBalances[_account] = newCredits;\\n // Globals\\n _adjustGlobals(newCredits.toInt256(), -balance.toInt256());\\n\\n emit AccountRebasingEnabled(_account);\\n }\\n\\n /**\\n * @notice The calling account will no longer receive yield\\n */\\n function rebaseOptOut() external {\\n _rebaseOptOut(msg.sender);\\n }\\n\\n function _rebaseOptOut(address _account) internal {\\n require(\\n alternativeCreditsPerToken[_account] == 0,\\n \\\"Account must be rebasing\\\"\\n );\\n RebaseOptions state = rebaseState[_account];\\n require(\\n state == RebaseOptions.StdRebasing || state == RebaseOptions.NotSet,\\n \\\"Only standard rebasing accounts can opt out\\\"\\n );\\n\\n uint256 oldCredits = creditBalances[_account];\\n uint256 balance = balanceOf(_account);\\n\\n // Account\\n rebaseState[_account] = RebaseOptions.StdNonRebasing;\\n alternativeCreditsPerToken[_account] = 1e18;\\n creditBalances[_account] = balance;\\n // Globals\\n _adjustGlobals(-oldCredits.toInt256(), balance.toInt256());\\n\\n emit AccountRebasingDisabled(_account);\\n }\\n\\n /**\\n * @notice Distribute yield to users. This changes the exchange rate\\n * between \\\"credits\\\" and OUSD tokens to change rebasing user's balances.\\n * @param _newTotalSupply New total supply of OUSD.\\n */\\n function changeSupply(uint256 _newTotalSupply) external onlyVault {\\n require(totalSupply > 0, \\\"Cannot increase 0 supply\\\");\\n\\n if (totalSupply == _newTotalSupply) {\\n emit TotalSupplyUpdatedHighres(\\n totalSupply,\\n rebasingCredits_,\\n rebasingCreditsPerToken_\\n );\\n return;\\n }\\n\\n totalSupply = _newTotalSupply > MAX_SUPPLY\\n ? MAX_SUPPLY\\n : _newTotalSupply;\\n\\n uint256 rebasingSupply = totalSupply - nonRebasingSupply;\\n // round up in the favour of the protocol\\n rebasingCreditsPerToken_ =\\n (rebasingCredits_ * 1e18 + rebasingSupply - 1) /\\n rebasingSupply;\\n\\n require(rebasingCreditsPerToken_ > 0, \\\"Invalid change in supply\\\");\\n\\n emit TotalSupplyUpdatedHighres(\\n totalSupply,\\n rebasingCredits_,\\n rebasingCreditsPerToken_\\n );\\n }\\n\\n /*\\n * @notice Send the yield from one account to another account.\\n * Each account keeps its own balances.\\n */\\n function delegateYield(address _from, address _to)\\n external\\n onlyGovernorOrStrategist\\n {\\n require(_from != address(0), \\\"Zero from address not allowed\\\");\\n require(_to != address(0), \\\"Zero to address not allowed\\\");\\n\\n require(_from != _to, \\\"Cannot delegate to self\\\");\\n require(\\n yieldFrom[_to] == address(0) &&\\n yieldTo[_to] == address(0) &&\\n yieldFrom[_from] == address(0) &&\\n yieldTo[_from] == address(0),\\n \\\"Blocked by existing yield delegation\\\"\\n );\\n RebaseOptions stateFrom = rebaseState[_from];\\n RebaseOptions stateTo = rebaseState[_to];\\n\\n require(\\n stateFrom == RebaseOptions.NotSet ||\\n stateFrom == RebaseOptions.StdNonRebasing ||\\n stateFrom == RebaseOptions.StdRebasing,\\n \\\"Invalid rebaseState from\\\"\\n );\\n\\n require(\\n stateTo == RebaseOptions.NotSet ||\\n stateTo == RebaseOptions.StdNonRebasing ||\\n stateTo == RebaseOptions.StdRebasing,\\n \\\"Invalid rebaseState to\\\"\\n );\\n\\n if (alternativeCreditsPerToken[_from] == 0) {\\n _rebaseOptOut(_from);\\n }\\n if (alternativeCreditsPerToken[_to] > 0) {\\n _rebaseOptIn(_to);\\n }\\n\\n uint256 fromBalance = balanceOf(_from);\\n uint256 toBalance = balanceOf(_to);\\n uint256 oldToCredits = creditBalances[_to];\\n uint256 newToCredits = _balanceToRebasingCredits(\\n fromBalance + toBalance\\n );\\n\\n // Set up the bidirectional links\\n yieldTo[_from] = _to;\\n yieldFrom[_to] = _from;\\n\\n // Local\\n rebaseState[_from] = RebaseOptions.YieldDelegationSource;\\n alternativeCreditsPerToken[_from] = 1e18;\\n creditBalances[_from] = fromBalance;\\n rebaseState[_to] = RebaseOptions.YieldDelegationTarget;\\n creditBalances[_to] = newToCredits;\\n\\n // Global\\n int256 creditsChange = newToCredits.toInt256() -\\n oldToCredits.toInt256();\\n _adjustGlobals(creditsChange, -(fromBalance).toInt256());\\n emit YieldDelegated(_from, _to);\\n }\\n\\n /*\\n * @notice Stop sending the yield from one account to another account.\\n */\\n function undelegateYield(address _from) external onlyGovernorOrStrategist {\\n // Require a delegation, which will also ensure a valid delegation\\n require(yieldTo[_from] != address(0), \\\"Zero address not allowed\\\");\\n\\n address to = yieldTo[_from];\\n uint256 fromBalance = balanceOf(_from);\\n uint256 toBalance = balanceOf(to);\\n uint256 oldToCredits = creditBalances[to];\\n uint256 newToCredits = _balanceToRebasingCredits(toBalance);\\n\\n // Remove the bidirectional links\\n yieldFrom[to] = address(0);\\n yieldTo[_from] = address(0);\\n\\n // Local\\n rebaseState[_from] = RebaseOptions.StdNonRebasing;\\n // alternativeCreditsPerToken[from] already 1e18 from `delegateYield()`\\n creditBalances[_from] = fromBalance;\\n rebaseState[to] = RebaseOptions.StdRebasing;\\n // alternativeCreditsPerToken[to] already 0 from `delegateYield()`\\n creditBalances[to] = newToCredits;\\n\\n // Global\\n int256 creditsChange = newToCredits.toInt256() -\\n oldToCredits.toInt256();\\n _adjustGlobals(creditsChange, fromBalance.toInt256());\\n emit YieldUndelegated(_from, to);\\n }\\n}\\n\",\"keccak256\":\"0x73439bef6569f5adf6f5ce2cb54a5f0d3109d4819457532236e172a7091980a9\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Helpers.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\nimport { IBasicToken } from \\\"../interfaces/IBasicToken.sol\\\";\\n\\nlibrary Helpers {\\n /**\\n * @notice Fetch the `symbol()` from an ERC20 token\\n * @dev Grabs the `symbol()` from a contract\\n * @param _token Address of the ERC20 token\\n * @return string Symbol of the ERC20 token\\n */\\n function getSymbol(address _token) internal view returns (string memory) {\\n string memory symbol = IBasicToken(_token).symbol();\\n return symbol;\\n }\\n\\n /**\\n * @notice Fetch the `decimals()` from an ERC20 token\\n * @dev Grabs the `decimals()` from a contract and fails if\\n * the decimal value does not live within a certain range\\n * @param _token Address of the ERC20 token\\n * @return uint256 Decimals of the ERC20 token\\n */\\n function getDecimals(address _token) internal view returns (uint256) {\\n uint256 decimals = IBasicToken(_token).decimals();\\n require(\\n decimals >= 4 && decimals <= 18,\\n \\\"Token must have sufficient decimal places\\\"\\n );\\n\\n return decimals;\\n }\\n}\\n\",\"keccak256\":\"0x4366f8d90b34c1eef8bbaaf369b1e5cd59f04027bb3c111f208eaee65bbc0346\",\"license\":\"BUSL-1.1\"},\"contracts/utils/Initializable.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Base contract any contracts that need to initialize state after deployment.\\n * @author Origin Protocol Inc\\n */\\nabstract contract Initializable {\\n /**\\n * @dev Indicates that the contract has been initialized.\\n */\\n bool private initialized;\\n\\n /**\\n * @dev Indicates that the contract is in the process of being initialized.\\n */\\n bool private initializing;\\n\\n /**\\n * @dev Modifier to protect an initializer function from being invoked twice.\\n */\\n modifier initializer() {\\n require(\\n initializing || !initialized,\\n \\\"Initializable: contract is already initialized\\\"\\n );\\n\\n bool isTopLevelCall = !initializing;\\n if (isTopLevelCall) {\\n initializing = true;\\n initialized = true;\\n }\\n\\n _;\\n\\n if (isTopLevelCall) {\\n initializing = false;\\n }\\n }\\n\\n uint256[50] private ______gap;\\n}\\n\",\"keccak256\":\"0x50d39ebf38a3d3111f2b77a6c75ece1d4ae731552fec4697ab16fcf6c0d4d5e8\",\"license\":\"BUSL-1.1\"},\"contracts/utils/InitializableAbstractStrategy.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title Base contract for vault strategies.\\n * @author Origin Protocol Inc\\n */\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport { Initializable } from \\\"../utils/Initializable.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { IVault } from \\\"../interfaces/IVault.sol\\\";\\n\\nabstract contract InitializableAbstractStrategy is Initializable, Governable {\\n using SafeERC20 for IERC20;\\n\\n event PTokenAdded(address indexed _asset, address _pToken);\\n event PTokenRemoved(address indexed _asset, address _pToken);\\n event Deposit(address indexed _asset, address _pToken, uint256 _amount);\\n event Withdrawal(address indexed _asset, address _pToken, uint256 _amount);\\n event RewardTokenCollected(\\n address recipient,\\n address rewardToken,\\n uint256 amount\\n );\\n event RewardTokenAddressesUpdated(\\n address[] _oldAddresses,\\n address[] _newAddresses\\n );\\n event HarvesterAddressesUpdated(\\n address _oldHarvesterAddress,\\n address _newHarvesterAddress\\n );\\n\\n /// @notice Address of the underlying platform\\n address public immutable platformAddress;\\n /// @notice Address of the OToken vault\\n address public immutable vaultAddress;\\n\\n /// @dev Replaced with an immutable variable\\n // slither-disable-next-line constable-states\\n address private _deprecated_platformAddress;\\n\\n /// @dev Replaced with an immutable\\n // slither-disable-next-line constable-states\\n address private _deprecated_vaultAddress;\\n\\n /// @notice asset => pToken (Platform Specific Token Address)\\n mapping(address => address) public assetToPToken;\\n\\n /// @notice Full list of all assets supported by the strategy\\n address[] internal assetsMapped;\\n\\n // Deprecated: Reward token address\\n // slither-disable-next-line constable-states\\n address private _deprecated_rewardTokenAddress;\\n\\n // Deprecated: now resides in Harvester's rewardTokenConfigs\\n // slither-disable-next-line constable-states\\n uint256 private _deprecated_rewardLiquidationThreshold;\\n\\n /// @notice Address of the Harvester contract allowed to collect reward tokens\\n address public harvesterAddress;\\n\\n /// @notice Address of the reward tokens. eg CRV, BAL, CVX, AURA\\n address[] public rewardTokenAddresses;\\n\\n /* Reserved for future expansion. Used to be 100 storage slots\\n * and has decreased to accommodate:\\n * - harvesterAddress\\n * - rewardTokenAddresses\\n */\\n int256[98] private _reserved;\\n\\n struct BaseStrategyConfig {\\n address platformAddress; // Address of the underlying platform\\n address vaultAddress; // Address of the OToken's Vault\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Governor or Strategist.\\n */\\n modifier onlyGovernorOrStrategist() virtual {\\n require(\\n isGovernor() || msg.sender == IVault(vaultAddress).strategistAddr(),\\n \\\"Caller is not the Strategist or Governor\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @param _config The platform and OToken vault addresses\\n */\\n constructor(BaseStrategyConfig memory _config) {\\n platformAddress = _config.platformAddress;\\n vaultAddress = _config.vaultAddress;\\n }\\n\\n /**\\n * @dev Internal initialize function, to set up initial internal state\\n * @param _rewardTokenAddresses Address of reward token for platform\\n * @param _assets Addresses of initial supported assets\\n * @param _pTokens Platform Token corresponding addresses\\n */\\n function _initialize(\\n address[] memory _rewardTokenAddresses,\\n address[] memory _assets,\\n address[] memory _pTokens\\n ) internal {\\n rewardTokenAddresses = _rewardTokenAddresses;\\n\\n uint256 assetCount = _assets.length;\\n require(assetCount == _pTokens.length, \\\"Invalid input arrays\\\");\\n for (uint256 i = 0; i < assetCount; ++i) {\\n _setPTokenAddress(_assets[i], _pTokens[i]);\\n }\\n }\\n\\n /**\\n * @notice Collect accumulated reward token and send to Vault.\\n */\\n function collectRewardTokens() external virtual onlyHarvester nonReentrant {\\n _collectRewardTokens();\\n }\\n\\n /**\\n * @dev Default implementation that transfers reward tokens to the Harvester\\n * Implementing strategies need to add custom logic to collect the rewards.\\n */\\n function _collectRewardTokens() internal virtual {\\n uint256 rewardTokenCount = rewardTokenAddresses.length;\\n for (uint256 i = 0; i < rewardTokenCount; ++i) {\\n IERC20 rewardToken = IERC20(rewardTokenAddresses[i]);\\n uint256 balance = rewardToken.balanceOf(address(this));\\n if (balance > 0) {\\n emit RewardTokenCollected(\\n harvesterAddress,\\n address(rewardToken),\\n balance\\n );\\n rewardToken.safeTransfer(harvesterAddress, balance);\\n }\\n }\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Vault.\\n */\\n modifier onlyVault() {\\n require(msg.sender == vaultAddress, \\\"Caller is not the Vault\\\");\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Harvester.\\n */\\n modifier onlyHarvester() {\\n require(msg.sender == harvesterAddress, \\\"Caller is not the Harvester\\\");\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Vault or Governor.\\n */\\n modifier onlyVaultOrGovernor() {\\n require(\\n msg.sender == vaultAddress || msg.sender == governor(),\\n \\\"Caller is not the Vault or Governor\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\\n */\\n modifier onlyVaultOrGovernorOrStrategist() {\\n require(\\n msg.sender == vaultAddress ||\\n msg.sender == governor() ||\\n msg.sender == IVault(vaultAddress).strategistAddr(),\\n \\\"Caller is not the Vault, Governor, or Strategist\\\"\\n );\\n _;\\n }\\n\\n /**\\n * @notice Set the reward token addresses. Any old addresses will be overwritten.\\n * @param _rewardTokenAddresses Array of reward token addresses\\n */\\n function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses)\\n external\\n onlyGovernor\\n {\\n uint256 rewardTokenCount = _rewardTokenAddresses.length;\\n for (uint256 i = 0; i < rewardTokenCount; ++i) {\\n require(\\n _rewardTokenAddresses[i] != address(0),\\n \\\"Can not set an empty address as a reward token\\\"\\n );\\n }\\n\\n emit RewardTokenAddressesUpdated(\\n rewardTokenAddresses,\\n _rewardTokenAddresses\\n );\\n rewardTokenAddresses = _rewardTokenAddresses;\\n }\\n\\n /**\\n * @notice Get the reward token addresses.\\n * @return address[] the reward token addresses.\\n */\\n function getRewardTokenAddresses()\\n external\\n view\\n returns (address[] memory)\\n {\\n return rewardTokenAddresses;\\n }\\n\\n /**\\n * @notice Provide support for asset by passing its pToken address.\\n * This method can only be called by the system Governor\\n * @param _asset Address for the asset\\n * @param _pToken Address for the corresponding platform token\\n */\\n function setPTokenAddress(address _asset, address _pToken)\\n external\\n virtual\\n onlyGovernor\\n {\\n _setPTokenAddress(_asset, _pToken);\\n }\\n\\n /**\\n * @notice Remove a supported asset by passing its index.\\n * This method can only be called by the system Governor\\n * @param _assetIndex Index of the asset to be removed\\n */\\n function removePToken(uint256 _assetIndex) external virtual onlyGovernor {\\n require(_assetIndex < assetsMapped.length, \\\"Invalid index\\\");\\n address asset = assetsMapped[_assetIndex];\\n address pToken = assetToPToken[asset];\\n\\n if (_assetIndex < assetsMapped.length - 1) {\\n assetsMapped[_assetIndex] = assetsMapped[assetsMapped.length - 1];\\n }\\n assetsMapped.pop();\\n assetToPToken[asset] = address(0);\\n\\n emit PTokenRemoved(asset, pToken);\\n }\\n\\n /**\\n * @notice Provide support for asset by passing its pToken address.\\n * Add to internal mappings and execute the platform specific,\\n * abstract method `_abstractSetPToken`\\n * @param _asset Address for the asset\\n * @param _pToken Address for the corresponding platform token\\n */\\n function _setPTokenAddress(address _asset, address _pToken) internal {\\n require(assetToPToken[_asset] == address(0), \\\"pToken already set\\\");\\n require(\\n _asset != address(0) && _pToken != address(0),\\n \\\"Invalid addresses\\\"\\n );\\n\\n assetToPToken[_asset] = _pToken;\\n assetsMapped.push(_asset);\\n\\n emit PTokenAdded(_asset, _pToken);\\n\\n _abstractSetPToken(_asset, _pToken);\\n }\\n\\n /**\\n * @notice Transfer token to governor. Intended for recovering tokens stuck in\\n * strategy contracts, i.e. mistaken sends.\\n * @param _asset Address for the asset\\n * @param _amount Amount of the asset to transfer\\n */\\n function transferToken(address _asset, uint256 _amount)\\n public\\n virtual\\n onlyGovernor\\n {\\n require(!supportsAsset(_asset), \\\"Cannot transfer supported asset\\\");\\n IERC20(_asset).safeTransfer(governor(), _amount);\\n }\\n\\n /**\\n * @notice Set the Harvester contract that can collect rewards.\\n * @param _harvesterAddress Address of the harvester contract.\\n */\\n function setHarvesterAddress(address _harvesterAddress)\\n external\\n onlyGovernor\\n {\\n emit HarvesterAddressesUpdated(harvesterAddress, _harvesterAddress);\\n harvesterAddress = _harvesterAddress;\\n }\\n\\n /***************************************\\n Abstract\\n ****************************************/\\n\\n function _abstractSetPToken(address _asset, address _pToken)\\n internal\\n virtual;\\n\\n function safeApproveAllTokens() external virtual;\\n\\n /**\\n * @notice Deposit an amount of assets into the platform\\n * @param _asset Address for the asset\\n * @param _amount Units of asset to deposit\\n */\\n function deposit(address _asset, uint256 _amount) external virtual;\\n\\n /**\\n * @notice Deposit all supported assets in this strategy contract to the platform\\n */\\n function depositAll() external virtual;\\n\\n /**\\n * @notice Withdraw an `amount` of assets from the platform and\\n * send to the `_recipient`.\\n * @param _recipient Address to which the asset should be sent\\n * @param _asset Address of the asset\\n * @param _amount Units of asset to withdraw\\n */\\n function withdraw(\\n address _recipient,\\n address _asset,\\n uint256 _amount\\n ) external virtual;\\n\\n /**\\n * @notice Withdraw all supported assets from platform and\\n * sends to the OToken's Vault.\\n */\\n function withdrawAll() external virtual;\\n\\n /**\\n * @notice Get the total asset value held in the platform.\\n * This includes any interest that was generated since depositing.\\n * @param _asset Address of the asset\\n * @return balance Total value of the asset in the platform\\n */\\n function checkBalance(address _asset)\\n external\\n view\\n virtual\\n returns (uint256 balance);\\n\\n /**\\n * @notice Check if an asset is supported.\\n * @param _asset Address of the asset\\n * @return bool Whether asset is supported\\n */\\n function supportsAsset(address _asset) public view virtual returns (bool);\\n}\\n\",\"keccak256\":\"0x6e99dee31bac1365445ef297fead7e055eb7993cebce078e36b09474b2e0c035\",\"license\":\"BUSL-1.1\"},\"contracts/vault/VaultStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BUSL-1.1\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title OToken VaultStorage contract\\n * @notice The VaultStorage contract defines the storage for the Vault contracts\\n * @author Origin Protocol Inc\\n */\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { Address } from \\\"@openzeppelin/contracts/utils/Address.sol\\\";\\n\\nimport { IStrategy } from \\\"../interfaces/IStrategy.sol\\\";\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { Governable } from \\\"../governance/Governable.sol\\\";\\nimport { OUSD } from \\\"../token/OUSD.sol\\\";\\nimport { Initializable } from \\\"../utils/Initializable.sol\\\";\\nimport \\\"../utils/Helpers.sol\\\";\\n\\nabstract contract VaultStorage is Initializable, Governable {\\n using SafeERC20 for IERC20;\\n\\n event AssetAllocated(address _asset, address _strategy, uint256 _amount);\\n event StrategyApproved(address _addr);\\n event StrategyRemoved(address _addr);\\n event Mint(address _addr, uint256 _value);\\n event Redeem(address _addr, uint256 _value);\\n event CapitalPaused();\\n event CapitalUnpaused();\\n event DefaultStrategyUpdated(address _strategy);\\n event RebasePaused();\\n event RebaseUnpaused();\\n event VaultBufferUpdated(uint256 _vaultBuffer);\\n event AllocateThresholdUpdated(uint256 _threshold);\\n event RebaseThresholdUpdated(uint256 _threshold);\\n event StrategistUpdated(address _address);\\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\\n event TrusteeFeeBpsChanged(uint256 _basis);\\n event TrusteeAddressChanged(address _address);\\n event StrategyAddedToMintWhitelist(address indexed strategy);\\n event StrategyRemovedFromMintWhitelist(address indexed strategy);\\n event RebasePerSecondMaxChanged(uint256 rebaseRatePerSecond);\\n event DripDurationChanged(uint256 dripDuration);\\n event WithdrawalRequested(\\n address indexed _withdrawer,\\n uint256 indexed _requestId,\\n uint256 _amount,\\n uint256 _queued\\n );\\n event WithdrawalClaimed(\\n address indexed _withdrawer,\\n uint256 indexed _requestId,\\n uint256 _amount\\n );\\n event WithdrawalClaimable(uint256 _claimable, uint256 _newClaimable);\\n event WithdrawalClaimDelayUpdated(uint256 _newDelay);\\n\\n // Since we are proxy, all state should be uninitalized.\\n // Since this storage contract does not have logic directly on it\\n // we should not be checking for to see if these variables can be constant.\\n // slither-disable-start uninitialized-state\\n // slither-disable-start constable-states\\n\\n /// @dev mapping of supported vault assets to their configuration\\n uint256 private _deprecated_assets;\\n /// @dev list of all assets supported by the vault.\\n address[] private _deprecated_allAssets;\\n\\n // Strategies approved for use by the Vault\\n struct Strategy {\\n bool isSupported;\\n uint256 _deprecated; // Deprecated storage slot\\n }\\n /// @dev mapping of strategy contracts to their configuration\\n mapping(address => Strategy) public strategies;\\n /// @dev list of all vault strategies\\n address[] internal allStrategies;\\n\\n /// @notice Address of the Oracle price provider contract\\n address private _deprecated_priceProvider;\\n /// @notice pause rebasing if true\\n bool public rebasePaused;\\n /// @notice pause operations that change the OToken supply.\\n /// eg mint, redeem, allocate, mint/burn for strategy\\n bool public capitalPaused;\\n /// @notice Redemption fee in basis points. eg 50 = 0.5%\\n uint256 private _deprecated_redeemFeeBps;\\n /// @notice Percentage of assets to keep in Vault to handle (most) withdrawals. 100% = 1e18.\\n uint256 public vaultBuffer;\\n /// @notice OToken mints over this amount automatically allocate funds. 18 decimals.\\n uint256 public autoAllocateThreshold;\\n /// @notice OToken mints over this amount automatically rebase. 18 decimals.\\n uint256 public rebaseThreshold;\\n\\n /// @dev Address of the OToken token. eg OUSD or OETH.\\n OUSD public oToken;\\n\\n /// @dev Address of the contract responsible for post rebase syncs with AMMs\\n address private _deprecated_rebaseHooksAddr = address(0);\\n\\n /// @dev Deprecated: Address of Uniswap\\n address private _deprecated_uniswapAddr = address(0);\\n\\n /// @notice Address of the Strategist\\n address public strategistAddr = address(0);\\n\\n /// @notice Mapping of asset address to the Strategy that they should automatically\\n // be allocated to\\n uint256 private _deprecated_assetDefaultStrategies;\\n\\n /// @notice Max difference between total supply and total value of assets. 18 decimals.\\n uint256 public maxSupplyDiff;\\n\\n /// @notice Trustee contract that can collect a percentage of yield\\n address public trusteeAddress;\\n\\n /// @notice Amount of yield collected in basis points. eg 2000 = 20%\\n uint256 public trusteeFeeBps;\\n\\n /// @dev Deprecated: Tokens that should be swapped for stablecoins\\n address[] private _deprecated_swapTokens;\\n\\n /// @notice Metapool strategy that is allowed to mint/burn OTokens without changing collateral\\n\\n address private _deprecated_ousdMetaStrategy;\\n\\n /// @notice How much OTokens are currently minted by the strategy\\n int256 private _deprecated_netOusdMintedForStrategy;\\n\\n /// @notice How much net total OTokens are allowed to be minted by all strategies\\n uint256 private _deprecated_netOusdMintForStrategyThreshold;\\n\\n uint256 private _deprecated_swapConfig;\\n\\n // List of strategies that can mint oTokens directly\\n // Used in OETHBaseVaultCore\\n mapping(address => bool) public isMintWhitelistedStrategy;\\n\\n /// @notice Address of the Dripper contract that streams harvested rewards to the Vault\\n /// @dev The vault is proxied so needs to be set with setDripper against the proxy contract.\\n address private _deprecated_dripper;\\n\\n /// Withdrawal Queue Storage /////\\n\\n struct WithdrawalQueueMetadata {\\n // cumulative total of all withdrawal requests included the ones that have already been claimed\\n uint128 queued;\\n // cumulative total of all the requests that can be claimed including the ones that have already been claimed\\n uint128 claimable;\\n // total of all the requests that have been claimed\\n uint128 claimed;\\n // index of the next withdrawal request starting at 0\\n uint128 nextWithdrawalIndex;\\n }\\n\\n /// @notice Global metadata for the withdrawal queue including:\\n /// queued - cumulative total of all withdrawal requests included the ones that have already been claimed\\n /// claimable - cumulative total of all the requests that can be claimed including the ones already claimed\\n /// claimed - total of all the requests that have been claimed\\n /// nextWithdrawalIndex - index of the next withdrawal request starting at 0\\n WithdrawalQueueMetadata public withdrawalQueueMetadata;\\n\\n struct WithdrawalRequest {\\n address withdrawer;\\n bool claimed;\\n uint40 timestamp; // timestamp of the withdrawal request\\n // Amount of oTokens to redeem. eg OETH\\n uint128 amount;\\n // cumulative total of all withdrawal requests including this one.\\n // this request can be claimed when this queued amount is less than or equal to the queue's claimable amount.\\n uint128 queued;\\n }\\n\\n /// @notice Mapping of withdrawal request indices to the user withdrawal request data\\n mapping(uint256 => WithdrawalRequest) public withdrawalRequests;\\n\\n /// @notice Sets a minimum delay that is required to elapse between\\n /// requesting async withdrawals and claiming the request.\\n /// When set to 0 async withdrawals are disabled.\\n uint256 public withdrawalClaimDelay;\\n\\n /// @notice Time in seconds that the vault last rebased yield.\\n uint64 public lastRebase;\\n\\n /// @notice Automatic rebase yield calculations. In seconds. Set to 0 or 1 to disable.\\n uint64 public dripDuration;\\n\\n /// @notice max rebase percentage per second\\n /// Can be used to set maximum yield of the protocol,\\n /// spreading out yield over time\\n uint64 public rebasePerSecondMax;\\n\\n /// @notice target rebase rate limit, based on past rates and funds available.\\n uint64 public rebasePerSecondTarget;\\n\\n uint256 internal constant MAX_REBASE = 0.02 ether;\\n uint256 internal constant MAX_REBASE_PER_SECOND =\\n uint256(0.05 ether) / 1 days;\\n\\n /// @notice Default strategy for asset\\n address public defaultStrategy;\\n\\n // For future use\\n uint256[42] private __gap;\\n\\n /// @notice Index of WETH asset in allAssets array\\n /// Legacy OETHVaultCore code, relocated here for vault consistency.\\n uint256 private _deprecated_wethAssetIndex;\\n\\n /// @dev Address of the asset (eg. WETH or USDC)\\n address public immutable asset;\\n uint8 internal immutable assetDecimals;\\n\\n // slither-disable-end constable-states\\n // slither-disable-end uninitialized-state\\n\\n constructor(address _asset) {\\n uint8 _decimals = IERC20Metadata(_asset).decimals();\\n require(_decimals <= 18, \\\"invalid asset decimals\\\");\\n asset = _asset;\\n assetDecimals = _decimals;\\n }\\n\\n /// @notice Deprecated: use `oToken()` instead.\\n function oUSD() external view returns (OUSD) {\\n return oToken;\\n }\\n}\\n\",\"keccak256\":\"0xcca0e0ebbbbda50b23fba7aea96a1e34f6a9d58c8f2e86e84b0911d4a9e5d418\",\"license\":\"BUSL-1.1\"},\"lib/openzeppelin/interfaces/IERC4626.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n\\npragma solidity ^0.8.0;\\n\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IERC4626 is IERC20, IERC20Metadata {\\n event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);\\n\\n event Withdraw(\\n address indexed caller,\\n address indexed receiver,\\n address indexed owner,\\n uint256 assets,\\n uint256 shares\\n );\\n\\n /**\\n * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\\n *\\n * - MUST be an ERC-20 token contract.\\n * - MUST NOT revert.\\n */\\n function asset() external view returns (address assetTokenAddress);\\n\\n /**\\n * @dev Returns the total amount of the underlying asset that is \\u201cmanaged\\u201d by Vault.\\n *\\n * - SHOULD include any compounding that occurs from yield.\\n * - MUST be inclusive of any fees that are charged against assets in the Vault.\\n * - MUST NOT revert.\\n */\\n function totalAssets() external view returns (uint256 totalManagedAssets);\\n\\n /**\\n * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\\n * scenario where all the conditions are met.\\n *\\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\\n * - MUST NOT show any variations depending on the caller.\\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\\n * - MUST NOT revert.\\n *\\n * NOTE: This calculation MAY NOT reflect the \\u201cper-user\\u201d price-per-share, and instead should reflect the\\n * \\u201caverage-user\\u2019s\\u201d price-per-share, meaning what the average user should expect to see when exchanging to and\\n * from.\\n */\\n function convertToShares(uint256 assets) external view returns (uint256 shares);\\n\\n /**\\n * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\\n * scenario where all the conditions are met.\\n *\\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\\n * - MUST NOT show any variations depending on the caller.\\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\\n * - MUST NOT revert.\\n *\\n * NOTE: This calculation MAY NOT reflect the \\u201cper-user\\u201d price-per-share, and instead should reflect the\\n * \\u201caverage-user\\u2019s\\u201d price-per-share, meaning what the average user should expect to see when exchanging to and\\n * from.\\n */\\n function convertToAssets(uint256 shares) external view returns (uint256 assets);\\n\\n /**\\n * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\\n * through a deposit call.\\n *\\n * - MUST return a limited value if receiver is subject to some deposit limit.\\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\\n * - MUST NOT revert.\\n */\\n function maxDeposit(address receiver) external view returns (uint256 maxAssets);\\n\\n /**\\n * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\\n * current on-chain conditions.\\n *\\n * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\\n * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\\n * in the same transaction.\\n * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\\n * deposit would be accepted, regardless if the user has enough tokens approved, etc.\\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\\n * - MUST NOT revert.\\n *\\n * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\\n */\\n function previewDeposit(uint256 assets) external view returns (uint256 shares);\\n\\n /**\\n * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\\n *\\n * - MUST emit the Deposit event.\\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\\n * deposit execution, and are accounted for during deposit.\\n * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\\n * approving enough underlying tokens to the Vault contract, etc).\\n *\\n * NOTE: most implementations will require pre-approval of the Vault with the Vault\\u2019s underlying asset token.\\n */\\n function deposit(uint256 assets, address receiver) external returns (uint256 shares);\\n\\n /**\\n * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\\n * - MUST return a limited value if receiver is subject to some mint limit.\\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\\n * - MUST NOT revert.\\n */\\n function maxMint(address receiver) external view returns (uint256 maxShares);\\n\\n /**\\n * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\\n * current on-chain conditions.\\n *\\n * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\\n * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\\n * same transaction.\\n * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\\n * would be accepted, regardless if the user has enough tokens approved, etc.\\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\\n * - MUST NOT revert.\\n *\\n * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\\n * share price or some other type of condition, meaning the depositor will lose assets by minting.\\n */\\n function previewMint(uint256 shares) external view returns (uint256 assets);\\n\\n /**\\n * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\\n *\\n * - MUST emit the Deposit event.\\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\\n * execution, and are accounted for during mint.\\n * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\\n * approving enough underlying tokens to the Vault contract, etc).\\n *\\n * NOTE: most implementations will require pre-approval of the Vault with the Vault\\u2019s underlying asset token.\\n */\\n function mint(uint256 shares, address receiver) external returns (uint256 assets);\\n\\n /**\\n * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\\n * Vault, through a withdraw call.\\n *\\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\\n * - MUST NOT revert.\\n */\\n function maxWithdraw(address owner) external view returns (uint256 maxAssets);\\n\\n /**\\n * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\\n * given current on-chain conditions.\\n *\\n * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\\n * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\\n * called\\n * in the same transaction.\\n * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\\n * the withdrawal would be accepted, regardless if the user has enough shares, etc.\\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\\n * - MUST NOT revert.\\n *\\n * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\\n */\\n function previewWithdraw(uint256 assets) external view returns (uint256 shares);\\n\\n /**\\n * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\\n *\\n * - MUST emit the Withdraw event.\\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\\n * withdraw execution, and are accounted for during withdraw.\\n * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\\n * not having enough shares, etc).\\n *\\n * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\\n * Those methods should be performed separately.\\n */\\n function withdraw(\\n uint256 assets,\\n address receiver,\\n address owner\\n ) external returns (uint256 shares);\\n\\n /**\\n * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\\n * through a redeem call.\\n *\\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\\n * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\\n * - MUST NOT revert.\\n */\\n function maxRedeem(address owner) external view returns (uint256 maxShares);\\n\\n /**\\n * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\\n * given current on-chain conditions.\\n *\\n * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\\n * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\\n * same transaction.\\n * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\\n * redemption would be accepted, regardless if the user has enough shares, etc.\\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\\n * - MUST NOT revert.\\n *\\n * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\\n * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\\n */\\n function previewRedeem(uint256 shares) external view returns (uint256 assets);\\n\\n /**\\n * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\\n *\\n * - MUST emit the Withdraw event.\\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\\n * redeem execution, and are accounted for during redeem.\\n * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\\n * not having enough shares, etc).\\n *\\n * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\\n * Those methods should be performed separately.\\n */\\n function redeem(\\n uint256 shares,\\n address receiver,\\n address owner\\n ) external returns (uint256 assets);\\n}\",\"keccak256\":\"0xd1abd028496aacc3eef98e585a744e1a449dcf9b2e818c59d15d5c0091c3f293\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x61010060405234801561001157600080fd5b50604051612a2f380380612a2f83398101604081905261003091610076565b81516001600160a01b039081166080526020830151811660a0529151821660c0521660e0526100ff565b80516001600160a01b038116811461007157600080fd5b919050565b600080828403606081121561008a57600080fd5b604081121561009857600080fd5b50604080519081016001600160401b03811182821017156100c957634e487b7160e01b600052604160045260246000fd5b6040526100d58461005a565b81526100e36020850161005a565b602082015291506100f66040840161005a565b90509250929050565b60805160a05160c05160e05161283a6101f56000396000818161024f0152818161037d01528181610524015281816109ae01528181610c3101528181610dee01528181610f1401528181611348015281816113c8015281816114f901528181611892015281816119170152611a2501526000818161030701528181610ee8015281816115e80152611b1c015260008181610289015281816107df01528181610d0501528181610e3d0152818161122a01526112bd01526000818161041301528181610a1201528181610c8501528181610e6b0152818161156401528181611871015281816118e70152611aa0015261283a6000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c80638129fc1c11610104578063c2e1e3f4116100a2578063dbe55e5611610071578063dbe55e561461040e578063de5f626814610435578063f4537f781461043d578063f6ca71b01461045857600080fd5b8063c2e1e3f4146103cd578063c7af3352146103e0578063d38bfff4146103e8578063d9caed12146103fb57600080fd5b806396d538bb116100de57806396d538bb1461035a578063aa388af61461036d578063ac7a1b5b146103bd578063ad1728cb146103c557600080fd5b80638129fc1c1461033c578063853828b6146103445780639136616a1461034c57600080fd5b806347e7ef24116101715780635f5152261161014b5780635f515226146102ce57806367c7066c146102ef5780636c9fa59e146103025780637b2d9b2c1461032957600080fd5b806347e7ef24146102ab5780635a063f63146102be5780635d36b190146102c657600080fd5b80631072cbea116101ad5780631072cbea146102375780631083f7611461024a578063237839f014610271578063430bf08a1461028457600080fd5b80630c340a24146101d45780630ed57b3a146101f95780630fc3b4c41461020e575b600080fd5b6101dc61046d565b6040516001600160a01b0390911681526020015b60405180910390f35b61020c61020736600461224e565b61048a565b005b6101dc61021c366004612287565b6035602052600090815260409020546001600160a01b031681565b61020c6102453660046122a4565b6104f6565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b61020c61027f36600461231c565b6105b5565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b61020c6102b93660046122a4565b6107d4565b61020c610865565b61020c610904565b6102e16102dc366004612287565b6109aa565b6040519081526020016101f0565b6039546101dc906001600160a01b031681565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b6101dc610337366004612378565b610af5565b61020c610b1f565b61020c610cfa565b61020c610207366004612378565b61020c610368366004612391565b610f6a565b6103ad61037b366004612287565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b60405190151581526020016101f0565b6102e1611087565b61020c611091565b61020c6103db366004612287565b6110bd565b6103ad61114a565b61020c6103f6366004612287565b61117b565b61020c6104093660046123d3565b61121f565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b61020c6112b2565b6101dc733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b6104606113f5565b6040516101f09190612459565b60006104856000805160206127e58339815191525490565b905090565b61049261114a565b6104b75760405162461bcd60e51b81526004016104ae9061246c565b60405180910390fd5b60405162461bcd60e51b81526020600482015260146024820152733ab739bab83837b93a32b210333ab731ba34b7b760611b60448201526064016104ae565b6104fe61114a565b61051a5760405162461bcd60e51b81526004016104ae9061246c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036105955760405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220737570706f727465642061737365740060448201526064016104ae565b6105b16105a061046d565b6001600160a01b0384169083611457565b5050565b6040805160018082528183019092526000916020808301908036833701905050905030816000815181106105eb576105eb6124a3565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050858160008151811061063c5761063c6124a3565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050858160008151811061068d5761068d6124a3565b6020908102919091010152604080516001808252818301909252600091816020015b60608152602001906001900390816106af579050509050858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525085518694509092501515905061070d5761070d6124a3565b60209081029190910101526040516301c7ba5760e61b8152733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae906371ee95c0906107559087908790879087906004016124b9565b600060405180830381600087803b15801561076f57600080fd5b505af1158015610783573d6000803e3d6000fd5b50505050876001600160a01b03167f2d5429efdeca7741a8cd94067b18d988bc4e5f1d5b8272c37b7bfc31e9bfa32c886040516107c291815260200190565b60405180910390a25050505050505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461081c5760405162461bcd60e51b81526004016104ae906125a7565b6000805160206127c58339815191528054600119810161084e5760405162461bcd60e51b81526004016104ae906125de565b6002825561085c84846114ae565b50600190555050565b6039546001600160a01b031633146108bf5760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206973206e6f742074686520486172766573746572000000000060448201526064016104ae565b6000805160206127c5833981519152805460011981016108f15760405162461bcd60e51b81526004016104ae906125de565b600282556108fd611644565b5060019055565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b03161461099f5760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b60648201526084016104ae565b6109a833611758565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146109fd5760405162461bcd60e51b81526004016104ae90612606565b6040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03821690634cdad5069082906370a0823190602401602060405180830381865afa158015610a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8f919061263d565b6040518263ffffffff1660e01b8152600401610aad91815260200190565b602060405180830381865afa158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee919061263d565b9392505050565b603a8181548110610b0557600080fd5b6000918252602090912001546001600160a01b0316905081565b610b2761114a565b610b435760405162461bcd60e51b81526004016104ae9061246c565b600054610100900460ff1680610b5c575060005460ff16155b610bbf5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104ae565b600054610100900460ff16158015610be1576000805461ffff19166101011790555b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000082600081518110610c6357610c636124a3565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600081518110610cb757610cb76124a3565b60200260200101906001600160a01b031690816001600160a01b031681525050610ce28383836117b7565b5050508015610cf7576000805461ff00191690555b50565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610d495750610d3461046d565b6001600160a01b0316336001600160a01b0316145b610da15760405162461bcd60e51b815260206004820152602360248201527f43616c6c6572206973206e6f7420746865205661756c74206f7220476f7665726044820152623737b960e91b60648201526084016104ae565b6000805160206127c583398151915280546001198101610dd35760405162461bcd60e51b81526004016104ae906125de565b600282556000610de161186a565b90506000610e1782610e127f00000000000000000000000000000000000000000000000000000000000000006109aa565b6118b6565b90508015610eda57604051632d182be560e21b8152600481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301523060448301527f0000000000000000000000000000000000000000000000000000000000000000169063b460af94906064016020604051808303816000875af1158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed8919061263d565b505b604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490527f000000000000000000000000000000000000000000000000000000000000000016917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a25050600182555050565b610f7261114a565b610f8e5760405162461bcd60e51b81526004016104ae9061246c565b8060005b81811015611038576000848483818110610fae57610fae6124a3565b9050602002016020810190610fc39190612287565b6001600160a01b0316036110305760405162461bcd60e51b815260206004820152602e60248201527f43616e206e6f742073657420616e20656d70747920616464726573732061732060448201526d30903932bbb0b932103a37b5b2b760911b60648201526084016104ae565b600101610f92565b507f04c0b9649497d316554306e53678d5f5f5dbc3a06f97dec13ff4cfe98b986bbc603a848460405161106d93929190612656565b60405180910390a1611081603a848461216c565b50505050565b600061048561186a565b61109961114a565b6110b55760405162461bcd60e51b81526004016104ae9061246c565b6109a86118d0565b6110c561114a565b6110e15760405162461bcd60e51b81526004016104ae9061246c565b603954604080516001600160a01b03928316815291831660208301527fe48386b84419f4d36e0f96c10cc3510b6fb1a33795620c5098b22472bbe90796910160405180910390a1603980546001600160a01b0319166001600160a01b0392909216919091179055565b60006111626000805160206127e58339815191525490565b6001600160a01b0316336001600160a01b031614905090565b61118361114a565b61119f5760405162461bcd60e51b81526004016104ae9061246c565b6111c7817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b03166111e76000805160206127e58339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112675760405162461bcd60e51b81526004016104ae906125a7565b6000805160206127c5833981519152805460011981016112995760405162461bcd60e51b81526004016104ae906125de565b600282556112a8858585611984565b5060019055505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112fa5760405162461bcd60e51b81526004016104ae906125a7565b6000805160206127c58339815191528054600119810161132c5760405162461bcd60e51b81526004016104ae906125de565b600282556040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bb919061263d565b905080156113ed576113ed7f0000000000000000000000000000000000000000000000000000000000000000826114ae565b505060019055565b6060603a80548060200260200160405190810160405280929190818152602001828054801561144d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161142f575b5050505050905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114a9908490611b79565b505050565b600081116114f75760405162461bcd60e51b81526020600482015260166024820152754d757374206465706f73697420736f6d657468696e6760501b60448201526064016104ae565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146115485760405162461bcd60e51b81526004016104ae90612606565b604051636e553f6560e01b8152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303816000875af11580156115b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d9919061263d565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b603a5460005b818110156105b1576000603a8281548110611667576116676124a3565b60009182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156116ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116de919061263d565b9050801561174e57603954604080516001600160a01b039283168152918416602083015281018290527ff6c07a063ed4e63808eb8da7112d46dbcd38de2b40a73dbcc9353c5a94c723539060600160405180910390a160395461174e906001600160a01b03848116911683611457565b505060010161164a565b6001600160a01b0381166117ae5760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f72206973206164647265737328302900000000000060448201526064016104ae565b610cf781611c4b565b82516117ca90603a9060208601906121cf565b508151815181146118145760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420696e7075742061727261797360601b60448201526064016104ae565b60005b818110156118635761185b848281518110611834576118346124a3565b602002602001015184838151811061184e5761184e6124a3565b6020026020010151611cb2565b600101611817565b5050505050565b60006104857f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e17565b60008183106118c557816118c7565b825b90505b92915050565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015611960573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf791906126f1565b600081116119d45760405162461bcd60e51b815260206004820152601760248201527f4d75737420776974686472617720736f6d657468696e6700000000000000000060448201526064016104ae565b6001600160a01b038316611a235760405162461bcd60e51b8152602060048201526016602482015275135d5cdd081cdc1958da599e481c9958da5c1a595b9d60521b60448201526064016104ae565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614611a745760405162461bcd60e51b81526004016104ae90612606565b604051632d182be560e21b8152600481018290526001600160a01b0384811660248301523060448301527f0000000000000000000000000000000000000000000000000000000000000000169063b460af94906064016020604051808303816000875af1158015611ae9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0d919061263d565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a2505050565b6000611bce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fec9092919063ffffffff16565b8051909150156114a95780806020019051810190611bec91906126f1565b6114a95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104ae565b806001600160a01b0316611c6b6000805160206127e58339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36000805160206127e583398151915255565b6001600160a01b038281166000908152603560205260409020541615611d0f5760405162461bcd60e51b81526020600482015260126024820152711c151bdad95b88185b1c9958591e481cd95d60721b60448201526064016104ae565b6001600160a01b03821615801590611d2f57506001600160a01b03811615155b611d6f5760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b60448201526064016104ae565b6001600160a01b03828116600081815260356020908152604080832080549587166001600160a01b031996871681179091556036805460018101825594527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890930180549095168417909455925190815290917fef6485b84315f9b1483beffa32aae9a0596890395e3d7521f1c5fbb51790e765910160405180910390a26105b18282612003565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908316906370a0823190602401602060405180830381865afa158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e85919061263d565b90506000836001600160a01b031663ad468d116040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190612713565b9050806001600160a01b031663e4baaddf6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611f47575060408051601f3d908101601f19168201909252611f4491810190612713565b60015b611f6f57604051630a10bc7f60e41b81526001600160a01b03821660048201526024016104ae565b60405163ce96cb7760e01b81526001600160a01b03838116600483015282169063ce96cb7790602401602060405180830381865afa158015611fb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd9919061263d565b611fe39084612730565b95945050505050565b6060611ffb848460008561200b565b949350505050565b6105b16118d0565b60608247101561206c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104ae565b843b6120ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104ae565b600080866001600160a01b031685876040516120d69190612775565b60006040518083038185875af1925050503d8060008114612113576040519150601f19603f3d011682016040523d82523d6000602084013e612118565b606091505b5091509150612128828286612133565b979650505050505050565b60608315612142575081610aee565b8251156121525782518084602001fd5b8160405162461bcd60e51b81526004016104ae9190612791565b8280548282559060005260206000209081019282156121bf579160200282015b828111156121bf5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019061218c565b506121cb929150612224565b5090565b8280548282559060005260206000209081019282156121bf579160200282015b828111156121bf57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906121ef565b5b808211156121cb5760008155600101612225565b6001600160a01b0381168114610cf757600080fd5b6000806040838503121561226157600080fd5b823561226c81612239565b9150602083013561227c81612239565b809150509250929050565b60006020828403121561229957600080fd5b8135610aee81612239565b600080604083850312156122b757600080fd5b82356122c281612239565b946020939093013593505050565b60008083601f8401126122e257600080fd5b50813567ffffffffffffffff8111156122fa57600080fd5b6020830191508360208260051b850101111561231557600080fd5b9250929050565b6000806000806060858703121561233257600080fd5b843561233d81612239565b935060208501359250604085013567ffffffffffffffff81111561236057600080fd5b61236c878288016122d0565b95989497509550505050565b60006020828403121561238a57600080fd5b5035919050565b600080602083850312156123a457600080fd5b823567ffffffffffffffff8111156123bb57600080fd5b6123c7858286016122d0565b90969095509350505050565b6000806000606084860312156123e857600080fd5b83356123f381612239565b9250602084013561240381612239565b929592945050506040919091013590565b600081518084526020840193506020830160005b8281101561244f5781516001600160a01b0316865260209586019590910190600101612428565b5093949350505050565b6020815260006118c76020830184612414565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6080815260006124cc6080830187612414565b82810360208401526124de8187612414565b83810360408501528551808252602080880193509091019060005b818110156125175783518352602093840193909201916001016124f9565b50508381036060850152845180825260208083019350600582901b8301810190870160005b8381101561259757848303601f190186528151805180855260209182019185019060005b8181101561257e578351835260209384019390920191600101612560565b505060209788019790945092909201915060010161253c565b50909a9950505050505050505050565b60208082526017908201527f43616c6c6572206973206e6f7420746865205661756c74000000000000000000604082015260600190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60208082526018908201527f556e657870656374656420617373657420616464726573730000000000000000604082015260600190565b60006020828403121561264f57600080fd5b5051919050565b6040808252845490820181905260008581526020812090916060840190835b8181101561269c5783546001600160a01b0316835260019384019360209093019201612675565b50508381036020808601919091528582520190508460005b858110156126e55781356126c781612239565b6001600160a01b0316835260209283019291909101906001016126b4565b50909695505050505050565b60006020828403121561270357600080fd5b81518015158114610aee57600080fd5b60006020828403121561272557600080fd5b8151610aee81612239565b808201808211156118ca57634e487b7160e01b600052601160045260246000fd5b60005b8381101561276c578181015183820152602001612754565b50506000910152565b60008251612787818460208701612751565b9190910192915050565b60208152600082518060208401526127b0816040850160208701612751565b601f01601f1916919091016040019291505056fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45357bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa264697066735822122002188f6f4d67849445727f634a22761f8d0bac3e25b3657ee983787791113b0f64736f6c634300081c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101cf5760003560e01c80638129fc1c11610104578063c2e1e3f4116100a2578063dbe55e5611610071578063dbe55e561461040e578063de5f626814610435578063f4537f781461043d578063f6ca71b01461045857600080fd5b8063c2e1e3f4146103cd578063c7af3352146103e0578063d38bfff4146103e8578063d9caed12146103fb57600080fd5b806396d538bb116100de57806396d538bb1461035a578063aa388af61461036d578063ac7a1b5b146103bd578063ad1728cb146103c557600080fd5b80638129fc1c1461033c578063853828b6146103445780639136616a1461034c57600080fd5b806347e7ef24116101715780635f5152261161014b5780635f515226146102ce57806367c7066c146102ef5780636c9fa59e146103025780637b2d9b2c1461032957600080fd5b806347e7ef24146102ab5780635a063f63146102be5780635d36b190146102c657600080fd5b80631072cbea116101ad5780631072cbea146102375780631083f7611461024a578063237839f014610271578063430bf08a1461028457600080fd5b80630c340a24146101d45780630ed57b3a146101f95780630fc3b4c41461020e575b600080fd5b6101dc61046d565b6040516001600160a01b0390911681526020015b60405180910390f35b61020c61020736600461224e565b61048a565b005b6101dc61021c366004612287565b6035602052600090815260409020546001600160a01b031681565b61020c6102453660046122a4565b6104f6565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b61020c61027f36600461231c565b6105b5565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b61020c6102b93660046122a4565b6107d4565b61020c610865565b61020c610904565b6102e16102dc366004612287565b6109aa565b6040519081526020016101f0565b6039546101dc906001600160a01b031681565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b6101dc610337366004612378565b610af5565b61020c610b1f565b61020c610cfa565b61020c610207366004612378565b61020c610368366004612391565b610f6a565b6103ad61037b366004612287565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b60405190151581526020016101f0565b6102e1611087565b61020c611091565b61020c6103db366004612287565b6110bd565b6103ad61114a565b61020c6103f6366004612287565b61117b565b61020c6104093660046123d3565b61121f565b6101dc7f000000000000000000000000000000000000000000000000000000000000000081565b61020c6112b2565b6101dc733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b6104606113f5565b6040516101f09190612459565b60006104856000805160206127e58339815191525490565b905090565b61049261114a565b6104b75760405162461bcd60e51b81526004016104ae9061246c565b60405180910390fd5b60405162461bcd60e51b81526020600482015260146024820152733ab739bab83837b93a32b210333ab731ba34b7b760611b60448201526064016104ae565b6104fe61114a565b61051a5760405162461bcd60e51b81526004016104ae9061246c565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116908316036105955760405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220737570706f727465642061737365740060448201526064016104ae565b6105b16105a061046d565b6001600160a01b0384169083611457565b5050565b6040805160018082528183019092526000916020808301908036833701905050905030816000815181106105eb576105eb6124a3565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050858160008151811061063c5761063c6124a3565b6001600160a01b039290921660209283029190910190910152604080516001808252818301909252600091816020016020820280368337019050509050858160008151811061068d5761068d6124a3565b6020908102919091010152604080516001808252818301909252600091816020015b60608152602001906001900390816106af579050509050858580806020026020016040519081016040528093929190818152602001838360200280828437600092018290525085518694509092501515905061070d5761070d6124a3565b60209081029190910101526040516301c7ba5760e61b8152733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae906371ee95c0906107559087908790879087906004016124b9565b600060405180830381600087803b15801561076f57600080fd5b505af1158015610783573d6000803e3d6000fd5b50505050876001600160a01b03167f2d5429efdeca7741a8cd94067b18d988bc4e5f1d5b8272c37b7bfc31e9bfa32c886040516107c291815260200190565b60405180910390a25050505050505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461081c5760405162461bcd60e51b81526004016104ae906125a7565b6000805160206127c58339815191528054600119810161084e5760405162461bcd60e51b81526004016104ae906125de565b6002825561085c84846114ae565b50600190555050565b6039546001600160a01b031633146108bf5760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206973206e6f742074686520486172766573746572000000000060448201526064016104ae565b6000805160206127c5833981519152805460011981016108f15760405162461bcd60e51b81526004016104ae906125de565b600282556108fd611644565b5060019055565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b03161461099f5760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b60648201526084016104ae565b6109a833611758565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146109fd5760405162461bcd60e51b81526004016104ae90612606565b6040516370a0823160e01b81523060048201527f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03821690634cdad5069082906370a0823190602401602060405180830381865afa158015610a6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a8f919061263d565b6040518263ffffffff1660e01b8152600401610aad91815260200190565b602060405180830381865afa158015610aca573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610aee919061263d565b9392505050565b603a8181548110610b0557600080fd5b6000918252602090912001546001600160a01b0316905081565b610b2761114a565b610b435760405162461bcd60e51b81526004016104ae9061246c565b600054610100900460ff1680610b5c575060005460ff16155b610bbf5760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b60648201526084016104ae565b600054610100900460ff16158015610be1576000805461ffff19166101011790555b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f000000000000000000000000000000000000000000000000000000000000000082600081518110610c6357610c636124a3565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600081518110610cb757610cb76124a3565b60200260200101906001600160a01b031690816001600160a01b031681525050610ce28383836117b7565b5050508015610cf7576000805461ff00191690555b50565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480610d495750610d3461046d565b6001600160a01b0316336001600160a01b0316145b610da15760405162461bcd60e51b815260206004820152602360248201527f43616c6c6572206973206e6f7420746865205661756c74206f7220476f7665726044820152623737b960e91b60648201526084016104ae565b6000805160206127c583398151915280546001198101610dd35760405162461bcd60e51b81526004016104ae906125de565b600282556000610de161186a565b90506000610e1782610e127f00000000000000000000000000000000000000000000000000000000000000006109aa565b6118b6565b90508015610eda57604051632d182be560e21b8152600481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301523060448301527f0000000000000000000000000000000000000000000000000000000000000000169063b460af94906064016020604051808303816000875af1158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed8919061263d565b505b604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490527f000000000000000000000000000000000000000000000000000000000000000016917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a25050600182555050565b610f7261114a565b610f8e5760405162461bcd60e51b81526004016104ae9061246c565b8060005b81811015611038576000848483818110610fae57610fae6124a3565b9050602002016020810190610fc39190612287565b6001600160a01b0316036110305760405162461bcd60e51b815260206004820152602e60248201527f43616e206e6f742073657420616e20656d70747920616464726573732061732060448201526d30903932bbb0b932103a37b5b2b760911b60648201526084016104ae565b600101610f92565b507f04c0b9649497d316554306e53678d5f5f5dbc3a06f97dec13ff4cfe98b986bbc603a848460405161106d93929190612656565b60405180910390a1611081603a848461216c565b50505050565b600061048561186a565b61109961114a565b6110b55760405162461bcd60e51b81526004016104ae9061246c565b6109a86118d0565b6110c561114a565b6110e15760405162461bcd60e51b81526004016104ae9061246c565b603954604080516001600160a01b03928316815291831660208301527fe48386b84419f4d36e0f96c10cc3510b6fb1a33795620c5098b22472bbe90796910160405180910390a1603980546001600160a01b0319166001600160a01b0392909216919091179055565b60006111626000805160206127e58339815191525490565b6001600160a01b0316336001600160a01b031614905090565b61118361114a565b61119f5760405162461bcd60e51b81526004016104ae9061246c565b6111c7817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b03166111e76000805160206127e58339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112675760405162461bcd60e51b81526004016104ae906125a7565b6000805160206127c5833981519152805460011981016112995760405162461bcd60e51b81526004016104ae906125de565b600282556112a8858585611984565b5060019055505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112fa5760405162461bcd60e51b81526004016104ae906125a7565b6000805160206127c58339815191528054600119810161132c5760405162461bcd60e51b81526004016104ae906125de565b600282556040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611397573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bb919061263d565b905080156113ed576113ed7f0000000000000000000000000000000000000000000000000000000000000000826114ae565b505060019055565b6060603a80548060200260200160405190810160405280929190818152602001828054801561144d57602002820191906000526020600020905b81546001600160a01b0316815260019091019060200180831161142f575b5050505050905090565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526114a9908490611b79565b505050565b600081116114f75760405162461bcd60e51b81526020600482015260166024820152754d757374206465706f73697420736f6d657468696e6760501b60448201526064016104ae565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146115485760405162461bcd60e51b81526004016104ae90612606565b604051636e553f6560e01b8152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303816000875af11580156115b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115d9919061263d565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b603a5460005b818110156105b1576000603a8281548110611667576116676124a3565b60009182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa1580156116ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116de919061263d565b9050801561174e57603954604080516001600160a01b039283168152918416602083015281018290527ff6c07a063ed4e63808eb8da7112d46dbcd38de2b40a73dbcc9353c5a94c723539060600160405180910390a160395461174e906001600160a01b03848116911683611457565b505060010161164a565b6001600160a01b0381166117ae5760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f72206973206164647265737328302900000000000060448201526064016104ae565b610cf781611c4b565b82516117ca90603a9060208601906121cf565b508151815181146118145760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420696e7075742061727261797360601b60448201526064016104ae565b60005b818110156118635761185b848281518110611834576118346124a3565b602002602001015184838151811061184e5761184e6124a3565b6020026020010151611cb2565b600101611817565b5050505050565b60006104857f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000611e17565b60008183106118c557816118c7565b825b90505b92915050565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015611960573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf791906126f1565b600081116119d45760405162461bcd60e51b815260206004820152601760248201527f4d75737420776974686472617720736f6d657468696e6700000000000000000060448201526064016104ae565b6001600160a01b038316611a235760405162461bcd60e51b8152602060048201526016602482015275135d5cdd081cdc1958da599e481c9958da5c1a595b9d60521b60448201526064016104ae565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614611a745760405162461bcd60e51b81526004016104ae90612606565b604051632d182be560e21b8152600481018290526001600160a01b0384811660248301523060448301527f0000000000000000000000000000000000000000000000000000000000000000169063b460af94906064016020604051808303816000875af1158015611ae9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b0d919061263d565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a2505050565b6000611bce826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611fec9092919063ffffffff16565b8051909150156114a95780806020019051810190611bec91906126f1565b6114a95760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016104ae565b806001600160a01b0316611c6b6000805160206127e58339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a36000805160206127e583398151915255565b6001600160a01b038281166000908152603560205260409020541615611d0f5760405162461bcd60e51b81526020600482015260126024820152711c151bdad95b88185b1c9958591e481cd95d60721b60448201526064016104ae565b6001600160a01b03821615801590611d2f57506001600160a01b03811615155b611d6f5760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b60448201526064016104ae565b6001600160a01b03828116600081815260356020908152604080832080549587166001600160a01b031996871681179091556036805460018101825594527f4a11f94e20a93c79f6ec743a1954ec4fc2c08429ae2122118bf234b2185c81b890930180549095168417909455925190815290917fef6485b84315f9b1483beffa32aae9a0596890395e3d7521f1c5fbb51790e765910160405180910390a26105b18282612003565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908316906370a0823190602401602060405180830381865afa158015611e61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e85919061263d565b90506000836001600160a01b031663ad468d116040518163ffffffff1660e01b8152600401602060405180830381865afa158015611ec7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eeb9190612713565b9050806001600160a01b031663e4baaddf6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611f47575060408051601f3d908101601f19168201909252611f4491810190612713565b60015b611f6f57604051630a10bc7f60e41b81526001600160a01b03821660048201526024016104ae565b60405163ce96cb7760e01b81526001600160a01b03838116600483015282169063ce96cb7790602401602060405180830381865afa158015611fb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fd9919061263d565b611fe39084612730565b95945050505050565b6060611ffb848460008561200b565b949350505050565b6105b16118d0565b60608247101561206c5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016104ae565b843b6120ba5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016104ae565b600080866001600160a01b031685876040516120d69190612775565b60006040518083038185875af1925050503d8060008114612113576040519150601f19603f3d011682016040523d82523d6000602084013e612118565b606091505b5091509150612128828286612133565b979650505050505050565b60608315612142575081610aee565b8251156121525782518084602001fd5b8160405162461bcd60e51b81526004016104ae9190612791565b8280548282559060005260206000209081019282156121bf579160200282015b828111156121bf5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019061218c565b506121cb929150612224565b5090565b8280548282559060005260206000209081019282156121bf579160200282015b828111156121bf57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906121ef565b5b808211156121cb5760008155600101612225565b6001600160a01b0381168114610cf757600080fd5b6000806040838503121561226157600080fd5b823561226c81612239565b9150602083013561227c81612239565b809150509250929050565b60006020828403121561229957600080fd5b8135610aee81612239565b600080604083850312156122b757600080fd5b82356122c281612239565b946020939093013593505050565b60008083601f8401126122e257600080fd5b50813567ffffffffffffffff8111156122fa57600080fd5b6020830191508360208260051b850101111561231557600080fd5b9250929050565b6000806000806060858703121561233257600080fd5b843561233d81612239565b935060208501359250604085013567ffffffffffffffff81111561236057600080fd5b61236c878288016122d0565b95989497509550505050565b60006020828403121561238a57600080fd5b5035919050565b600080602083850312156123a457600080fd5b823567ffffffffffffffff8111156123bb57600080fd5b6123c7858286016122d0565b90969095509350505050565b6000806000606084860312156123e857600080fd5b83356123f381612239565b9250602084013561240381612239565b929592945050506040919091013590565b600081518084526020840193506020830160005b8281101561244f5781516001600160a01b0316865260209586019590910190600101612428565b5093949350505050565b6020815260006118c76020830184612414565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b6080815260006124cc6080830187612414565b82810360208401526124de8187612414565b83810360408501528551808252602080880193509091019060005b818110156125175783518352602093840193909201916001016124f9565b50508381036060850152845180825260208083019350600582901b8301810190870160005b8381101561259757848303601f190186528151805180855260209182019185019060005b8181101561257e578351835260209384019390920191600101612560565b505060209788019790945092909201915060010161253c565b50909a9950505050505050505050565b60208082526017908201527f43616c6c6572206973206e6f7420746865205661756c74000000000000000000604082015260600190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60208082526018908201527f556e657870656374656420617373657420616464726573730000000000000000604082015260600190565b60006020828403121561264f57600080fd5b5051919050565b6040808252845490820181905260008581526020812090916060840190835b8181101561269c5783546001600160a01b0316835260019384019360209093019201612675565b50508381036020808601919091528582520190508460005b858110156126e55781356126c781612239565b6001600160a01b0316835260209283019291909101906001016126b4565b50909695505050505050565b60006020828403121561270357600080fd5b81518015158114610aee57600080fd5b60006020828403121561272557600080fd5b8151610aee81612239565b808201808211156118ca57634e487b7160e01b600052601160045260246000fd5b60005b8381101561276c578181015183820152602001612754565b50506000910152565b60008251612787818460208701612751565b9190910192915050565b60208152600082518060208401526127b0816040850160208701612751565b601f01601f1916919091016040019291505056fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45357bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa264697066735822122002188f6f4d67849445727f634a22761f8d0bac3e25b3657ee983787791113b0f64736f6c634300081c0033", + "libraries": {}, + "devdoc": { + "kind": "dev", + "methods": { + "checkBalance(address)": { + "params": { + "_asset": "Address of the asset" + }, + "returns": { + "balance": " Total value of the asset in the platform" + } + }, + "constructor": { + "params": { + "_assetToken": "Address of the ERC-4626 asset token. e.g. USDC", + "_baseConfig": "Base strategy config with Morpho V2 Vault and vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy" + } + }, + "deposit(address,uint256)": { + "details": "Deposit assets by converting them to shares", + "params": { + "_amount": "Amount of asset to deposit", + "_asset": "Address of asset to deposit" + } + }, + "depositAll()": { + "details": "Deposit the entire balance of assetToken to gain shareToken" + }, + "getRewardTokenAddresses()": { + "returns": { + "_0": "address[] the reward token addresses." + } + }, + "merkleClaim(address,uint256,bytes32[])": { + "params": { + "amount": "The amount of tokens to claim.", + "proof": "The Merkle proof to validate the claim.", + "token": "The address of the token to claim." + } + }, + "removePToken(uint256)": { + "details": "If the ERC-4626 Tokenized Vault needed to be changed, a new contract would need to be deployed and the proxy updated." + }, + "setHarvesterAddress(address)": { + "params": { + "_harvesterAddress": "Address of the harvester contract." + } + }, + "setPTokenAddress(address,address)": { + "details": "If the ERC-4626 Tokenized Vault needed to be changed, a new contract would need to be deployed and the proxy updated." + }, + "setRewardTokenAddresses(address[])": { + "params": { + "_rewardTokenAddresses": "Array of reward token addresses" + } + }, + "supportsAsset(address)": { + "details": "Returns bool indicating whether asset is supported by strategy", + "params": { + "_asset": "Address of the asset" + } + }, + "transferGovernance(address)": { + "params": { + "_newGovernor": "Address of the new Governor" + } + }, + "transferToken(address,uint256)": { + "params": { + "_amount": "Amount of the asset to transfer", + "_asset": "Address for the asset" + } + }, + "withdraw(address,address,uint256)": { + "details": "Withdraw asset by burning shares", + "params": { + "_amount": "Amount of asset to withdraw", + "_asset": "Address of asset to withdraw", + "_recipient": "Address to receive withdrawn asset" + } + }, + "withdrawAll()": { + "details": "Remove all the liquidity that is available in the Morpho V2 vault The particular behaviour of the Morpho V2 vault is that it can hold multiple Morpho V1 vaults as adapters but only one liquidity adapter. The immediate available funds on the Morpho V2 vault are therfore any liquid assets residing on the Vault V2 contract and the maxWithdraw amount that the Morpho V1 contract can supply." + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "assetToPToken(address)": { + "notice": "asset => pToken (Platform Specific Token Address)" + }, + "checkBalance(address)": { + "notice": "Get the total asset value held in the platform" + }, + "claimGovernance()": { + "notice": "Claim Governance of the contract to a new account (`newGovernor`). Can only be called by the new Governor." + }, + "collectRewardTokens()": { + "notice": "Collect accumulated reward token and send to Vault." + }, + "getRewardTokenAddresses()": { + "notice": "Get the reward token addresses." + }, + "governor()": { + "notice": "Returns the address of the current Governor." + }, + "harvesterAddress()": { + "notice": "Address of the Harvester contract allowed to collect reward tokens" + }, + "isGovernor()": { + "notice": "Returns true if the caller is the current Governor." + }, + "merkleClaim(address,uint256,bytes32[])": { + "notice": "Claim tokens from the Merkle Distributor" + }, + "merkleDistributor()": { + "notice": "The address of the Merkle Distributor contract." + }, + "platformAddress()": { + "notice": "Address of the underlying platform" + }, + "removePToken(uint256)": { + "notice": "is not supported for this strategy as the asset and ERC-4626 Tokenized Vault are set at deploy time." + }, + "rewardTokenAddresses(uint256)": { + "notice": "Address of the reward tokens. eg CRV, BAL, CVX, AURA" + }, + "safeApproveAllTokens()": { + "notice": "Governor approves the ERC-4626 Tokenized Vault to spend the asset." + }, + "setHarvesterAddress(address)": { + "notice": "Set the Harvester contract that can collect rewards." + }, + "setPTokenAddress(address,address)": { + "notice": "is not supported for this strategy as the asset and ERC-4626 Tokenized Vault are set at deploy time." + }, + "setRewardTokenAddresses(address[])": { + "notice": "Set the reward token addresses. Any old addresses will be overwritten." + }, + "transferGovernance(address)": { + "notice": "Transfers Governance of the contract to a new account (`newGovernor`). Can only be called by the current Governor. Must be claimed for this to complete" + }, + "transferToken(address,uint256)": { + "notice": "Transfer token to governor. Intended for recovering tokens stuck in strategy contracts, i.e. mistaken sends." + }, + "vaultAddress()": { + "notice": "Address of the OToken vault" + }, + "withdrawAll()": { + "notice": "Remove all the liquidity that is available in the Morpho V2 vault. Which might not be all of the liquidity owned by the strategy." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 8060, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "initialized", + "offset": 0, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 8063, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "initializing", + "offset": 1, + "slot": "0", + "type": "t_bool" + }, + { + "astId": 8103, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "______gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage" + }, + { + "astId": 8183, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_deprecated_platformAddress", + "offset": 0, + "slot": "51", + "type": "t_address" + }, + { + "astId": 8186, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_deprecated_vaultAddress", + "offset": 0, + "slot": "52", + "type": "t_address" + }, + { + "astId": 8191, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "assetToPToken", + "offset": 0, + "slot": "53", + "type": "t_mapping(t_address,t_address)" + }, + { + "astId": 8195, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "assetsMapped", + "offset": 0, + "slot": "54", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 8197, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_deprecated_rewardTokenAddress", + "offset": 0, + "slot": "55", + "type": "t_address" + }, + { + "astId": 8199, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_deprecated_rewardLiquidationThreshold", + "offset": 0, + "slot": "56", + "type": "t_uint256" + }, + { + "astId": 8202, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "harvesterAddress", + "offset": 0, + "slot": "57", + "type": "t_address" + }, + { + "astId": 8206, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "rewardTokenAddresses", + "offset": 0, + "slot": "58", + "type": "t_array(t_address)dyn_storage" + }, + { + "astId": 8210, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_reserved", + "offset": 0, + "slot": "59", + "type": "t_array(t_int256)98_storage" + }, + { + "astId": 3130, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_deprecate_shareToken", + "offset": 0, + "slot": "157", + "type": "t_address" + }, + { + "astId": 3133, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "_deprecate_assetToken", + "offset": 0, + "slot": "158", + "type": "t_address" + }, + { + "astId": 3143, + "contract": "contracts/strategies/MorphoV2Strategy.sol:MorphoV2Strategy", + "label": "__gap", + "offset": 0, + "slot": "159", + "type": "t_array(t_uint256)50_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "base": "t_address", + "encoding": "dynamic_array", + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_int256)98_storage": { + "base": "t_int256", + "encoding": "inplace", + "label": "int256[98]", + "numberOfBytes": "3136" + }, + "t_array(t_uint256)50_storage": { + "base": "t_uint256", + "encoding": "inplace", + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_int256": { + "encoding": "inplace", + "label": "int256", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_address)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address)", + "numberOfBytes": "32", + "value": "t_address" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/contracts/deployments/mainnet/solcInputs/ca5c08626bc4341b9af4973050a80d7d.json b/contracts/deployments/mainnet/solcInputs/ca5c08626bc4341b9af4973050a80d7d.json new file mode 100644 index 0000000000..3a376760b5 --- /dev/null +++ b/contracts/deployments/mainnet/solcInputs/ca5c08626bc4341b9af4973050a80d7d.json @@ -0,0 +1,132 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `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\n uint256 currentAllowance = _allowances[sender][_msgSender()];\n require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n unchecked {\n _approve(sender, _msgSender(), currentAllowance - amount);\n }\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] + 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 uint256 currentAllowance = _allowances[_msgSender()][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `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 uint256 senderBalance = _balances[sender];\n require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[sender] = senderBalance - amount;\n }\n _balances[recipient] += amount;\n\n emit Transfer(sender, recipient, amount);\n\n _afterTokenTransfer(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 * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `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(\n address sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Address.sol)\n\npragma solidity ^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 assembly {\n size := extcodesize(account)\n }\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 (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a / b + (a % b == 0 ? 0 : 1);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128) {\n require(value >= type(int128).min && value <= type(int128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return int128(value);\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64) {\n require(value >= type(int64).min && value <= type(int64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return int64(value);\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32) {\n require(value >= type(int32).min && value <= type(int32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return int32(value);\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16) {\n require(value >= type(int16).min && value <= type(int16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return int16(value);\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits.\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8) {\n require(value >= type(int8).min && value <= type(int8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return int8(value);\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "contracts/governance/Governable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title Base for contracts that are managed by the Origin Protocol's Governor.\n * @dev Copy of the openzeppelin Ownable.sol contract with nomenclature change\n * from owner to governor and renounce methods removed. Does not use\n * Context.sol like Ownable.sol does for simplification.\n * @author Origin Protocol Inc\n */\nabstract contract Governable {\n // Storage position of the owner and pendingOwner of the contract\n // keccak256(\"OUSD.governor\");\n bytes32 private constant governorPosition =\n 0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;\n\n // keccak256(\"OUSD.pending.governor\");\n bytes32 private constant pendingGovernorPosition =\n 0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;\n\n // keccak256(\"OUSD.reentry.status\");\n bytes32 private constant reentryStatusPosition =\n 0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;\n\n // See OpenZeppelin ReentrancyGuard implementation\n uint256 constant _NOT_ENTERED = 1;\n uint256 constant _ENTERED = 2;\n\n event PendingGovernorshipTransfer(\n address indexed previousGovernor,\n address indexed newGovernor\n );\n\n event GovernorshipTransferred(\n address indexed previousGovernor,\n address indexed newGovernor\n );\n\n /**\n * @notice Returns the address of the current Governor.\n */\n function governor() public view returns (address) {\n return _governor();\n }\n\n /**\n * @dev Returns the address of the current Governor.\n */\n function _governor() internal view returns (address governorOut) {\n bytes32 position = governorPosition;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n governorOut := sload(position)\n }\n }\n\n /**\n * @dev Returns the address of the pending Governor.\n */\n function _pendingGovernor()\n internal\n view\n returns (address pendingGovernor)\n {\n bytes32 position = pendingGovernorPosition;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n pendingGovernor := sload(position)\n }\n }\n\n /**\n * @dev Throws if called by any account other than the Governor.\n */\n modifier onlyGovernor() {\n require(isGovernor(), \"Caller is not the Governor\");\n _;\n }\n\n /**\n * @notice Returns true if the caller is the current Governor.\n */\n function isGovernor() public view returns (bool) {\n return msg.sender == _governor();\n }\n\n function _setGovernor(address newGovernor) internal {\n emit GovernorshipTransferred(_governor(), newGovernor);\n\n bytes32 position = governorPosition;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(position, newGovernor)\n }\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 bytes32 position = reentryStatusPosition;\n uint256 _reentry_status;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n _reentry_status := sload(position)\n }\n\n // On the first call to nonReentrant, _notEntered will be true\n require(_reentry_status != _ENTERED, \"Reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(position, _ENTERED)\n }\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 // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(position, _NOT_ENTERED)\n }\n }\n\n function _setPendingGovernor(address newGovernor) internal {\n bytes32 position = pendingGovernorPosition;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(position, newGovernor)\n }\n }\n\n /**\n * @notice Transfers Governance of the contract to a new account (`newGovernor`).\n * Can only be called by the current Governor. Must be claimed for this to complete\n * @param _newGovernor Address of the new Governor\n */\n function transferGovernance(address _newGovernor) external onlyGovernor {\n _setPendingGovernor(_newGovernor);\n emit PendingGovernorshipTransfer(_governor(), _newGovernor);\n }\n\n /**\n * @notice Claim Governance of the contract to a new account (`newGovernor`).\n * Can only be called by the new Governor.\n */\n function claimGovernance() external {\n require(\n msg.sender == _pendingGovernor(),\n \"Only the pending Governor can complete the claim\"\n );\n _changeGovernor(msg.sender);\n }\n\n /**\n * @dev Change Governance of the contract to a new account (`newGovernor`).\n * @param _newGovernor Address of the new Governor\n */\n function _changeGovernor(address _newGovernor) internal {\n require(_newGovernor != address(0), \"New Governor is address(0)\");\n _setGovernor(_newGovernor);\n }\n}\n" + }, + "contracts/governance/Strategizable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { Governable } from \"./Governable.sol\";\n\ncontract Strategizable is Governable {\n event StrategistUpdated(address _address);\n\n // Address of strategist\n address public strategistAddr;\n\n // For future use\n uint256[50] private __gap;\n\n /**\n * @dev Verifies that the caller is either Governor or Strategist.\n */\n modifier onlyGovernorOrStrategist() virtual {\n require(\n msg.sender == strategistAddr || isGovernor(),\n \"Caller is not the Strategist or Governor\"\n );\n _;\n }\n\n /**\n * @dev Set address of Strategist\n * @param _address Address of Strategist\n */\n function setStrategistAddr(address _address) external onlyGovernor {\n _setStrategistAddr(_address);\n }\n\n /**\n * @dev Set address of Strategist\n * @param _address Address of Strategist\n */\n function _setStrategistAddr(address _address) internal {\n strategistAddr = _address;\n emit StrategistUpdated(_address);\n }\n}\n" + }, + "contracts/interfaces/cctp/ICCTP.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\ninterface ICCTPTokenMessenger {\n function depositForBurn(\n uint256 amount,\n uint32 destinationDomain,\n bytes32 mintRecipient,\n address burnToken,\n bytes32 destinationCaller,\n uint256 maxFee,\n uint32 minFinalityThreshold\n ) external;\n\n function depositForBurnWithHook(\n uint256 amount,\n uint32 destinationDomain,\n bytes32 mintRecipient,\n address burnToken,\n bytes32 destinationCaller,\n uint256 maxFee,\n uint32 minFinalityThreshold,\n bytes memory hookData\n ) external;\n\n function getMinFeeAmount(uint256 amount) external view returns (uint256);\n}\n\ninterface ICCTPMessageTransmitter {\n function sendMessage(\n uint32 destinationDomain,\n bytes32 recipient,\n bytes32 destinationCaller,\n uint32 minFinalityThreshold,\n bytes memory messageBody\n ) external;\n\n function receiveMessage(bytes calldata message, bytes calldata attestation)\n external\n returns (bool);\n}\n\ninterface IMessageHandlerV2 {\n /**\n * @notice Handles an incoming finalized message from an IReceiverV2\n * @dev Finalized messages have finality threshold values greater than or equal to 2000\n * @param sourceDomain The source domain of the message\n * @param sender The sender of the message\n * @param finalityThresholdExecuted the finality threshold at which the message was attested to\n * @param messageBody The raw bytes of the message body\n * @return success True, if successful; false, if not.\n */\n function handleReceiveFinalizedMessage(\n uint32 sourceDomain,\n bytes32 sender,\n uint32 finalityThresholdExecuted,\n bytes calldata messageBody\n ) external returns (bool);\n\n /**\n * @notice Handles an incoming unfinalized message from an IReceiverV2\n * @dev Unfinalized messages have finality threshold values less than 2000\n * @param sourceDomain The source domain of the message\n * @param sender The sender of the message\n * @param finalityThresholdExecuted The finality threshold at which the message was attested to\n * @param messageBody The raw bytes of the message body\n * @return success True, if successful; false, if not.\n */\n function handleReceiveUnfinalizedMessage(\n uint32 sourceDomain,\n bytes32 sender,\n uint32 finalityThresholdExecuted,\n bytes calldata messageBody\n ) external returns (bool);\n}\n" + }, + "contracts/interfaces/IBasicToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IBasicToken {\n function symbol() external view returns (string memory);\n\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/interfaces/IMerkl.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\ninterface IDistributor {\n event Claimed(address indexed user, address indexed token, uint256 amount);\n\n function claim(\n address[] calldata users,\n address[] calldata tokens,\n uint256[] calldata amounts,\n bytes32[][] calldata proofs\n ) external;\n}\n" + }, + "contracts/interfaces/IStrategy.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title Platform interface to integrate with lending platform like Compound, AAVE etc.\n */\ninterface IStrategy {\n /**\n * @dev Deposit the given asset to platform\n * @param _asset asset address\n * @param _amount Amount to deposit\n */\n function deposit(address _asset, uint256 _amount) external;\n\n /**\n * @dev Deposit the entire balance of all supported assets in the Strategy\n * to the platform\n */\n function depositAll() external;\n\n /**\n * @dev Withdraw given asset from Lending platform\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external;\n\n /**\n * @dev Liquidate all assets in strategy and return them to Vault.\n */\n function withdrawAll() external;\n\n /**\n * @dev Returns the current balance of the given asset.\n */\n function checkBalance(address _asset)\n external\n view\n returns (uint256 balance);\n\n /**\n * @dev Returns bool indicating whether strategy supports asset.\n */\n function supportsAsset(address _asset) external view returns (bool);\n\n /**\n * @dev Collect reward tokens from the Strategy.\n */\n function collectRewardTokens() external;\n\n /**\n * @dev The address array of the reward tokens for the Strategy.\n */\n function getRewardTokenAddresses() external view returns (address[] memory);\n\n function harvesterAddress() external view returns (address);\n\n function transferToken(address token, uint256 amount) external;\n\n function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses)\n external;\n}\n" + }, + "contracts/interfaces/IVault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { VaultStorage } from \"../vault/VaultStorage.sol\";\n\ninterface IVault {\n // slither-disable-start constable-states\n\n event AssetAllocated(address _asset, address _strategy, uint256 _amount);\n event StrategyApproved(address _addr);\n event StrategyRemoved(address _addr);\n event Mint(address _addr, uint256 _value);\n event Redeem(address _addr, uint256 _value);\n event CapitalPaused();\n event CapitalUnpaused();\n event DefaultStrategyUpdated(address _strategy);\n event RebasePaused();\n event RebaseUnpaused();\n event VaultBufferUpdated(uint256 _vaultBuffer);\n event AllocateThresholdUpdated(uint256 _threshold);\n event RebaseThresholdUpdated(uint256 _threshold);\n event StrategistUpdated(address _address);\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\n event TrusteeFeeBpsChanged(uint256 _basis);\n event TrusteeAddressChanged(address _address);\n event StrategyAddedToMintWhitelist(address indexed strategy);\n event StrategyRemovedFromMintWhitelist(address indexed strategy);\n event RebasePerSecondMaxChanged(uint256 rebaseRatePerSecond);\n event DripDurationChanged(uint256 dripDuration);\n event WithdrawalRequested(\n address indexed _withdrawer,\n uint256 indexed _requestId,\n uint256 _amount,\n uint256 _queued\n );\n event WithdrawalClaimed(\n address indexed _withdrawer,\n uint256 indexed _requestId,\n uint256 _amount\n );\n event WithdrawalClaimable(uint256 _claimable, uint256 _newClaimable);\n event WithdrawalClaimDelayUpdated(uint256 _newDelay);\n\n // Governable.sol\n function transferGovernance(address _newGovernor) external;\n\n function claimGovernance() external;\n\n function governor() external view returns (address);\n\n // VaultAdmin.sol\n function setVaultBuffer(uint256 _vaultBuffer) external;\n\n function vaultBuffer() external view returns (uint256);\n\n function setAutoAllocateThreshold(uint256 _threshold) external;\n\n function autoAllocateThreshold() external view returns (uint256);\n\n function setRebaseThreshold(uint256 _threshold) external;\n\n function rebaseThreshold() external view returns (uint256);\n\n function setStrategistAddr(address _address) external;\n\n function strategistAddr() external view returns (address);\n\n function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;\n\n function maxSupplyDiff() external view returns (uint256);\n\n function setTrusteeAddress(address _address) external;\n\n function trusteeAddress() external view returns (address);\n\n function setTrusteeFeeBps(uint256 _basis) external;\n\n function trusteeFeeBps() external view returns (uint256);\n\n function approveStrategy(address _addr) external;\n\n function removeStrategy(address _addr) external;\n\n function setDefaultStrategy(address _strategy) external;\n\n function defaultStrategy() external view returns (address);\n\n function pauseRebase() external;\n\n function unpauseRebase() external;\n\n function rebasePaused() external view returns (bool);\n\n function pauseCapital() external;\n\n function unpauseCapital() external;\n\n function capitalPaused() external view returns (bool);\n\n function transferToken(address _asset, uint256 _amount) external;\n\n function withdrawAllFromStrategy(address _strategyAddr) external;\n\n function withdrawAllFromStrategies() external;\n\n function withdrawFromStrategy(\n address _strategyFromAddress,\n address[] calldata _assets,\n uint256[] calldata _amounts\n ) external;\n\n function depositToStrategy(\n address _strategyToAddress,\n address[] calldata _assets,\n uint256[] calldata _amounts\n ) external;\n\n // VaultCore.sol\n function mint(uint256 _amount) external;\n\n function mintForStrategy(uint256 _amount) external;\n\n function burnForStrategy(uint256 _amount) external;\n\n function allocate() external;\n\n function rebase() external;\n\n function totalValue() external view returns (uint256 value);\n\n function checkBalance(address _asset) external view returns (uint256);\n\n function getAssetCount() external view returns (uint256);\n\n function getAllAssets() external view returns (address[] memory);\n\n function getStrategyCount() external view returns (uint256);\n\n function getAllStrategies() external view returns (address[] memory);\n\n /// @notice Deprecated.\n function isSupportedAsset(address _asset) external view returns (bool);\n\n function asset() external view returns (address);\n\n function initialize(address) external;\n\n function addWithdrawalQueueLiquidity() external;\n\n function requestWithdrawal(uint256 _amount)\n external\n returns (uint256 requestId, uint256 queued);\n\n function claimWithdrawal(uint256 requestId)\n external\n returns (uint256 amount);\n\n function claimWithdrawals(uint256[] memory requestIds)\n external\n returns (uint256[] memory amounts, uint256 totalAmount);\n\n function withdrawalQueueMetadata()\n external\n view\n returns (VaultStorage.WithdrawalQueueMetadata memory);\n\n function withdrawalRequests(uint256 requestId)\n external\n view\n returns (VaultStorage.WithdrawalRequest memory);\n\n function addStrategyToMintWhitelist(address strategyAddr) external;\n\n function removeStrategyFromMintWhitelist(address strategyAddr) external;\n\n function isMintWhitelistedStrategy(address strategyAddr)\n external\n view\n returns (bool);\n\n function withdrawalClaimDelay() external view returns (uint256);\n\n function setWithdrawalClaimDelay(uint256 newDelay) external;\n\n function lastRebase() external view returns (uint64);\n\n function dripDuration() external view returns (uint64);\n\n function setDripDuration(uint256 _dripDuration) external;\n\n function rebasePerSecondMax() external view returns (uint64);\n\n function setRebaseRateMax(uint256 yearlyApr) external;\n\n function rebasePerSecondTarget() external view returns (uint64);\n\n function previewYield() external view returns (uint256 yield);\n\n // slither-disable-end constable-states\n}\n" + }, + "contracts/interfaces/morpho/IMorphoV2Adapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\ninterface IMorphoV2Adapter {\n // address of the underlying vault\n function morphoVaultV1() external view returns (address);\n\n // address of the parent Morpho V2 vault\n function parentVault() external view returns (address);\n}\n" + }, + "contracts/interfaces/morpho/IVaultV2.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { IERC4626 } from \"../../../lib/openzeppelin/interfaces/IERC4626.sol\";\n\ninterface IVaultV2 is IERC4626 {\n function liquidityAdapter() external view returns (address);\n}\n" + }, + "contracts/mocks/MockERC4626Vault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { IERC4626 } from \"../../lib/openzeppelin/interfaces/IERC4626.sol\";\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\ncontract MockERC4626Vault is IERC4626, ERC20 {\n using SafeERC20 for IERC20;\n\n address public asset;\n uint8 public constant DECIMALS = 18;\n\n constructor(address _asset) ERC20(\"Mock Vault Share\", \"MVS\") {\n asset = _asset;\n }\n\n // ERC20 totalSupply is inherited\n\n // ERC20 balanceOf is inherited\n\n function deposit(uint256 assets, address receiver)\n public\n override\n returns (uint256 shares)\n {\n shares = previewDeposit(assets);\n IERC20(asset).safeTransferFrom(msg.sender, address(this), assets);\n _mint(receiver, shares);\n return shares;\n }\n\n function mint(uint256 shares, address receiver)\n public\n override\n returns (uint256 assets)\n {\n assets = previewMint(shares);\n IERC20(asset).safeTransferFrom(msg.sender, address(this), assets);\n _mint(receiver, shares);\n return assets;\n }\n\n function withdraw(\n uint256 assets,\n address receiver,\n address owner\n ) public override returns (uint256 shares) {\n shares = previewWithdraw(assets);\n if (msg.sender != owner) {\n // No approval check for mock\n }\n _burn(owner, shares);\n IERC20(asset).safeTransfer(receiver, assets);\n return shares;\n }\n\n function redeem(\n uint256 shares,\n address receiver,\n address owner\n ) public override returns (uint256 assets) {\n assets = previewRedeem(shares);\n if (msg.sender != owner) {\n // No approval check for mock\n }\n _burn(owner, shares);\n IERC20(asset).safeTransfer(receiver, assets);\n return assets;\n }\n\n function totalAssets() public view override returns (uint256) {\n return IERC20(asset).balanceOf(address(this));\n }\n\n function convertToShares(uint256 assets)\n public\n view\n override\n returns (uint256 shares)\n {\n uint256 supply = totalSupply(); // Use ERC20 totalSupply\n return\n supply == 0 || assets == 0\n ? assets\n : (assets * supply) / totalAssets();\n }\n\n function convertToAssets(uint256 shares)\n public\n view\n override\n returns (uint256 assets)\n {\n uint256 supply = totalSupply(); // Use ERC20 totalSupply\n return supply == 0 ? shares : (shares * totalAssets()) / supply;\n }\n\n function maxDeposit(address receiver)\n public\n view\n override\n returns (uint256)\n {\n return type(uint256).max;\n }\n\n function maxMint(address receiver) public view override returns (uint256) {\n return type(uint256).max;\n }\n\n function maxWithdraw(address owner) public view override returns (uint256) {\n return convertToAssets(balanceOf(owner));\n }\n\n function maxRedeem(address owner) public view override returns (uint256) {\n return balanceOf(owner);\n }\n\n function previewDeposit(uint256 assets)\n public\n view\n override\n returns (uint256 shares)\n {\n return convertToShares(assets);\n }\n\n function previewMint(uint256 shares)\n public\n view\n override\n returns (uint256 assets)\n {\n return convertToAssets(shares);\n }\n\n function previewWithdraw(uint256 assets)\n public\n view\n override\n returns (uint256 shares)\n {\n return convertToShares(assets);\n }\n\n function previewRedeem(uint256 shares)\n public\n view\n override\n returns (uint256 assets)\n {\n return convertToAssets(shares);\n }\n\n function _mint(address account, uint256 amount) internal override {\n super._mint(account, amount);\n }\n\n function _burn(address account, uint256 amount) internal override {\n super._burn(account, amount);\n }\n\n // Inherited from ERC20\n}\n" + }, + "contracts/mocks/MockMorphoV1Vault.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { MockERC4626Vault } from \"./MockERC4626Vault.sol\";\n\ncontract MockMorphoV1Vault is MockERC4626Vault {\n address public liquidityAdapter;\n\n constructor(address _asset) MockERC4626Vault(_asset) {}\n\n function setLiquidityAdapter(address _liquidityAdapter) external {\n liquidityAdapter = _liquidityAdapter;\n }\n}\n" + }, + "contracts/mocks/MockMorphoV1VaultLiquidityAdapter.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { IMorphoV2Adapter } from \"../interfaces/morpho/IMorphoV2Adapter.sol\";\n\ncontract MockMorphoV1VaultLiquidityAdapter is IMorphoV2Adapter {\n address public mockMorphoVault;\n\n function setMockMorphoVault(address _mockMorphoVault) external {\n mockMorphoVault = _mockMorphoVault;\n }\n\n function morphoVaultV1() external view override returns (address) {\n return mockMorphoVault;\n }\n\n function parentVault() external view override returns (address) {\n return mockMorphoVault;\n }\n}\n" + }, + "contracts/strategies/crosschain/AbstractCCTPIntegrator.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title AbstractCCTPIntegrator\n * @author Origin Protocol Inc\n *\n * @dev Abstract contract that contains all the logic used to integrate with CCTP.\n */\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"../../utils/InitializableAbstractStrategy.sol\";\n\nimport { ICCTPTokenMessenger, ICCTPMessageTransmitter, IMessageHandlerV2 } from \"../../interfaces/cctp/ICCTP.sol\";\n\nimport { CrossChainStrategyHelper } from \"./CrossChainStrategyHelper.sol\";\nimport { Governable } from \"../../governance/Governable.sol\";\nimport { BytesHelper } from \"../../utils/BytesHelper.sol\";\nimport \"../../utils/Helpers.sol\";\n\nabstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 {\n using SafeERC20 for IERC20;\n\n using BytesHelper for bytes;\n using CrossChainStrategyHelper for bytes;\n\n event LastTransferNonceUpdated(uint64 lastTransferNonce);\n event NonceProcessed(uint64 nonce);\n\n event CCTPMinFinalityThresholdSet(uint16 minFinalityThreshold);\n event CCTPFeePremiumBpsSet(uint16 feePremiumBps);\n event OperatorChanged(address operator);\n event TokensBridged(\n uint32 destinationDomain,\n address peerStrategy,\n address tokenAddress,\n uint256 tokenAmount,\n uint256 maxFee,\n uint32 minFinalityThreshold,\n bytes hookData\n );\n event MessageTransmitted(\n uint32 destinationDomain,\n address peerStrategy,\n uint32 minFinalityThreshold,\n bytes message\n );\n\n // Message body V2 fields\n // Ref: https://developers.circle.com/cctp/technical-guide#message-body\n // Ref: https://github.com/circlefin/evm-cctp-contracts/blob/master/src/messages/v2/BurnMessageV2.sol\n uint8 private constant BURN_MESSAGE_V2_VERSION_INDEX = 0;\n uint8 private constant BURN_MESSAGE_V2_BURN_TOKEN_INDEX = 4;\n uint8 private constant BURN_MESSAGE_V2_RECIPIENT_INDEX = 36;\n uint8 private constant BURN_MESSAGE_V2_AMOUNT_INDEX = 68;\n uint8 private constant BURN_MESSAGE_V2_MESSAGE_SENDER_INDEX = 100;\n uint8 private constant BURN_MESSAGE_V2_FEE_EXECUTED_INDEX = 164;\n uint8 private constant BURN_MESSAGE_V2_HOOK_DATA_INDEX = 228;\n\n /**\n * @notice Max transfer threshold imposed by the CCTP\n * Ref: https://developers.circle.com/cctp/evm-smart-contracts#depositforburn\n * @dev 10M USDC limit applies to both standard and fast transfer modes. The fast transfer mode has\n * an additional limitation that is not present on-chain and Circle may alter that amount off-chain\n * at their preference. The amount available for fast transfer can be queried here:\n * https://iris-api.circle.com/v2/fastBurn/USDC/allowance .\n * If a fast transfer token transaction has been issued and there is not enough allowance for it\n * the off-chain Iris component will re-attempt the transaction and if it fails it will fallback\n * to a standard transfer. Reference section 4.3 in the whitepaper:\n * https://6778953.fs1.hubspotusercontent-na1.net/hubfs/6778953/PDFs/Whitepapers/CCTPV2_White_Paper.pdf\n */\n uint256 public constant MAX_TRANSFER_AMOUNT = 10_000_000 * 10**6; // 10M USDC\n\n /// @notice Minimum transfer amount to avoid zero or dust transfers\n uint256 public constant MIN_TRANSFER_AMOUNT = 10**6;\n\n // CCTP contracts\n // This implementation assumes that remote and local chains have these contracts\n // deployed on the same addresses.\n /// @notice CCTP message transmitter contract\n ICCTPMessageTransmitter public immutable cctpMessageTransmitter;\n /// @notice CCTP token messenger contract\n ICCTPTokenMessenger public immutable cctpTokenMessenger;\n\n /// @notice USDC address on local chain\n address public immutable usdcToken;\n\n /// @notice USDC address on remote chain\n address public immutable peerUsdcToken;\n\n /// @notice Domain ID of the chain from which messages are accepted\n uint32 public immutable peerDomainID;\n\n /// @notice Strategy address on other chain\n address public immutable peerStrategy;\n\n /**\n * @notice Minimum finality threshold\n * Can be 1000 (safe, after 1 epoch) or 2000 (finalized, after 2 epochs).\n * Ref: https://developers.circle.com/cctp/technical-guide#finality-thresholds\n * @dev When configuring the contract for fast transfer we should check the available\n * allowance of USDC that can be bridged using fast mode:\n * wget https://iris-api.circle.com/v2/fastBurn/USDC/allowance\n */\n uint16 public minFinalityThreshold;\n\n /// @notice Fee premium in basis points\n uint16 public feePremiumBps;\n\n /// @notice Nonce of the last known deposit or withdrawal\n uint64 public lastTransferNonce;\n\n /// @notice Operator address: Can relay CCTP messages\n address public operator;\n\n /// @notice Mapping of processed nonces\n mapping(uint64 => bool) private nonceProcessed;\n\n // For future use\n uint256[48] private __gap;\n\n modifier onlyCCTPMessageTransmitter() {\n require(\n msg.sender == address(cctpMessageTransmitter),\n \"Caller is not CCTP transmitter\"\n );\n _;\n }\n\n modifier onlyOperator() {\n require(msg.sender == operator, \"Caller is not the Operator\");\n _;\n }\n\n /**\n * @notice Configuration for CCTP integration\n * @param cctpTokenMessenger Address of the CCTP token messenger contract\n * @param cctpMessageTransmitter Address of the CCTP message transmitter contract\n * @param peerDomainID Domain ID of the chain from which messages are accepted.\n * 0 for Ethereum, 6 for Base, etc.\n * Ref: https://developers.circle.com/cctp/cctp-supported-blockchains\n * @param peerStrategy Address of the master or remote strategy on the other chain\n * @param usdcToken USDC address on local chain\n */\n struct CCTPIntegrationConfig {\n address cctpTokenMessenger;\n address cctpMessageTransmitter;\n uint32 peerDomainID;\n address peerStrategy;\n address usdcToken;\n address peerUsdcToken;\n }\n\n constructor(CCTPIntegrationConfig memory _config) {\n require(_config.usdcToken != address(0), \"Invalid USDC address\");\n require(\n _config.peerUsdcToken != address(0),\n \"Invalid peer USDC address\"\n );\n require(\n _config.cctpTokenMessenger != address(0),\n \"Invalid CCTP config\"\n );\n require(\n _config.cctpMessageTransmitter != address(0),\n \"Invalid CCTP config\"\n );\n require(\n _config.peerStrategy != address(0),\n \"Invalid peer strategy address\"\n );\n\n cctpMessageTransmitter = ICCTPMessageTransmitter(\n _config.cctpMessageTransmitter\n );\n cctpTokenMessenger = ICCTPTokenMessenger(_config.cctpTokenMessenger);\n\n // Domain ID of the chain from which messages are accepted\n peerDomainID = _config.peerDomainID;\n\n // Strategy address on other chain, should\n // always be same as the proxy of this strategy\n peerStrategy = _config.peerStrategy;\n\n // USDC address on local chain\n usdcToken = _config.usdcToken;\n\n // Just a sanity check to ensure the base token is USDC\n uint256 _usdcTokenDecimals = Helpers.getDecimals(_config.usdcToken);\n string memory _usdcTokenSymbol = Helpers.getSymbol(_config.usdcToken);\n require(_usdcTokenDecimals == 6, \"Base token decimals must be 6\");\n require(\n keccak256(abi.encodePacked(_usdcTokenSymbol)) ==\n keccak256(abi.encodePacked(\"USDC\")),\n \"Token symbol must be USDC\"\n );\n\n // USDC address on remote chain\n peerUsdcToken = _config.peerUsdcToken;\n }\n\n /**\n * @dev Initialize the implementation contract\n * @param _operator Operator address\n * @param _minFinalityThreshold Minimum finality threshold\n * @param _feePremiumBps Fee premium in basis points\n */\n function _initialize(\n address _operator,\n uint16 _minFinalityThreshold,\n uint16 _feePremiumBps\n ) internal {\n _setOperator(_operator);\n _setMinFinalityThreshold(_minFinalityThreshold);\n _setFeePremiumBps(_feePremiumBps);\n\n // Nonce starts at 1, so assume nonce 0 as processed.\n // NOTE: This will cause the deposit/withdraw to fail if the\n // strategy is not initialized properly (which is expected).\n nonceProcessed[0] = true;\n }\n\n /***************************************\n Settings\n ****************************************/\n /**\n * @dev Set the operator address\n * @param _operator Operator address\n */\n function setOperator(address _operator) external onlyGovernor {\n _setOperator(_operator);\n }\n\n /**\n * @dev Set the operator address\n * @param _operator Operator address\n */\n function _setOperator(address _operator) internal {\n operator = _operator;\n emit OperatorChanged(_operator);\n }\n\n /**\n * @dev Set the minimum finality threshold at which\n * the message is considered to be finalized to relay.\n * Only accepts a value of 1000 (Safe, after 1 epoch) or\n * 2000 (Finalized, after 2 epochs).\n * @param _minFinalityThreshold Minimum finality threshold\n */\n function setMinFinalityThreshold(uint16 _minFinalityThreshold)\n external\n onlyGovernor\n {\n _setMinFinalityThreshold(_minFinalityThreshold);\n }\n\n /**\n * @dev Set the minimum finality threshold\n * @param _minFinalityThreshold Minimum finality threshold\n */\n function _setMinFinalityThreshold(uint16 _minFinalityThreshold) internal {\n // 1000 for fast transfer and 2000 for standard transfer\n require(\n _minFinalityThreshold == 1000 || _minFinalityThreshold == 2000,\n \"Invalid threshold\"\n );\n\n minFinalityThreshold = _minFinalityThreshold;\n emit CCTPMinFinalityThresholdSet(_minFinalityThreshold);\n }\n\n /**\n * @dev Set the fee premium in basis points.\n * Cannot be higher than 30% (3000 basis points).\n * @param _feePremiumBps Fee premium in basis points\n */\n function setFeePremiumBps(uint16 _feePremiumBps) external onlyGovernor {\n _setFeePremiumBps(_feePremiumBps);\n }\n\n /**\n * @dev Set the fee premium in basis points\n * Cannot be higher than 30% (3000 basis points).\n * Ref: https://developers.circle.com/cctp/technical-guide#fees\n * @param _feePremiumBps Fee premium in basis points\n */\n function _setFeePremiumBps(uint16 _feePremiumBps) internal {\n require(_feePremiumBps <= 3000, \"Fee premium too high\"); // 30%\n\n feePremiumBps = _feePremiumBps;\n emit CCTPFeePremiumBpsSet(_feePremiumBps);\n }\n\n /***************************************\n CCTP message handling\n ****************************************/\n\n /**\n * @dev Handles a finalized CCTP message\n * @param sourceDomain Source domain of the message\n * @param sender Sender of the message\n * @param finalityThresholdExecuted Fidelity threshold executed\n * @param messageBody Message body\n */\n function handleReceiveFinalizedMessage(\n uint32 sourceDomain,\n bytes32 sender,\n uint32 finalityThresholdExecuted,\n bytes memory messageBody\n ) external override onlyCCTPMessageTransmitter returns (bool) {\n // Make sure the finality threshold at execution is at least 2000\n require(\n finalityThresholdExecuted >= 2000,\n \"Finality threshold too low\"\n );\n\n return _handleReceivedMessage(sourceDomain, sender, messageBody);\n }\n\n /**\n * @dev Handles an unfinalized but safe CCTP message\n * @param sourceDomain Source domain of the message\n * @param sender Sender of the message\n * @param finalityThresholdExecuted Fidelity threshold executed\n * @param messageBody Message body\n */\n function handleReceiveUnfinalizedMessage(\n uint32 sourceDomain,\n bytes32 sender,\n uint32 finalityThresholdExecuted,\n bytes memory messageBody\n ) external override onlyCCTPMessageTransmitter returns (bool) {\n // Make sure the contract is configured to handle unfinalized messages\n require(\n minFinalityThreshold == 1000,\n \"Unfinalized messages are not supported\"\n );\n // Make sure the finality threshold at execution is at least 1000\n require(\n finalityThresholdExecuted >= 1000,\n \"Finality threshold too low\"\n );\n\n return _handleReceivedMessage(sourceDomain, sender, messageBody);\n }\n\n /**\n * @dev Handles a CCTP message\n * @param sourceDomain Source domain of the message\n * @param sender Sender of the message\n * @param messageBody Message body\n */\n function _handleReceivedMessage(\n uint32 sourceDomain,\n bytes32 sender,\n bytes memory messageBody\n ) internal returns (bool) {\n require(sourceDomain == peerDomainID, \"Unknown Source Domain\");\n\n // Extract address from bytes32 (CCTP stores addresses as right-padded bytes32)\n address senderAddress = address(uint160(uint256(sender)));\n require(senderAddress == peerStrategy, \"Unknown Sender\");\n\n _onMessageReceived(messageBody);\n\n return true;\n }\n\n /**\n * @dev Sends tokens to the peer strategy using CCTP Token Messenger\n * @param tokenAmount Amount of tokens to send\n * @param hookData Hook data\n */\n function _sendTokens(uint256 tokenAmount, bytes memory hookData)\n internal\n virtual\n {\n // CCTP has a maximum transfer amount of 10M USDC per tx\n require(tokenAmount <= MAX_TRANSFER_AMOUNT, \"Token amount too high\");\n\n // Approve only what needs to be transferred\n IERC20(usdcToken).safeApprove(address(cctpTokenMessenger), tokenAmount);\n\n // Compute the max fee to be paid.\n // Ref: https://developers.circle.com/cctp/evm-smart-contracts#getminfeeamount\n // The right way to compute fees would be to use CCTP's getMinFeeAmount function.\n // The issue is that the getMinFeeAmount is not present on v2.0 contracts, but is on\n // v2.1. Some of CCTP's deployed contracts are v2.0, some are v2.1.\n // We will only be using standard transfers and fee on those is 0 for now. If they\n // ever start implementing fee for standard transfers or if we decide to use fast\n // trasnfer, we can use feePremiumBps as a workaround.\n uint256 maxFee = feePremiumBps > 0\n ? (tokenAmount * feePremiumBps) / 10000\n : 0;\n\n // Send tokens to the peer strategy using CCTP Token Messenger\n cctpTokenMessenger.depositForBurnWithHook(\n tokenAmount,\n peerDomainID,\n bytes32(uint256(uint160(peerStrategy))),\n address(usdcToken),\n bytes32(uint256(uint160(peerStrategy))),\n maxFee,\n uint32(minFinalityThreshold),\n hookData\n );\n\n emit TokensBridged(\n peerDomainID,\n peerStrategy,\n usdcToken,\n tokenAmount,\n maxFee,\n uint32(minFinalityThreshold),\n hookData\n );\n }\n\n /**\n * @dev Sends a message to the peer strategy using CCTP Message Transmitter\n * @param message Payload of the message to send\n */\n function _sendMessage(bytes memory message) internal virtual {\n cctpMessageTransmitter.sendMessage(\n peerDomainID,\n bytes32(uint256(uint160(peerStrategy))),\n bytes32(uint256(uint160(peerStrategy))),\n uint32(minFinalityThreshold),\n message\n );\n\n emit MessageTransmitted(\n peerDomainID,\n peerStrategy,\n uint32(minFinalityThreshold),\n message\n );\n }\n\n /**\n * @dev Receives a message from the peer strategy on the other chain,\n * does some basic checks and relays it to the local MessageTransmitterV2.\n * If the message is a burn message, it will also handle the hook data\n * and call the _onTokenReceived function.\n * @param message Payload of the message to send\n * @param attestation Attestation of the message\n */\n function relay(bytes memory message, bytes memory attestation)\n external\n onlyOperator\n {\n (\n uint32 version,\n uint32 sourceDomainID,\n address sender,\n address recipient,\n bytes memory messageBody\n ) = message.decodeMessageHeader();\n\n // Ensure that it's a CCTP message\n require(\n version == CrossChainStrategyHelper.CCTP_MESSAGE_VERSION,\n \"Invalid CCTP message version\"\n );\n\n // Ensure that the source domain is the peer domain\n require(sourceDomainID == peerDomainID, \"Unknown Source Domain\");\n\n // Ensure message body version\n version = messageBody.extractUint32(BURN_MESSAGE_V2_VERSION_INDEX);\n\n // NOTE: There's a possibility that the CCTP Token Messenger might\n // send other types of messages in future, not just the burn message.\n // If it ever comes to that, this shouldn't cause us any problems\n // because it has to still go through the followign checks:\n // - version check\n // - message body length check\n // - sender and recipient (which should be in the same slots and same as address(this))\n // - hook data handling (which will revert even if all the above checks pass)\n bool isBurnMessageV1 = sender == address(cctpTokenMessenger);\n\n if (isBurnMessageV1) {\n // Handle burn message\n require(\n version == 1 &&\n messageBody.length >= BURN_MESSAGE_V2_HOOK_DATA_INDEX,\n \"Invalid burn message\"\n );\n\n // Ensure the burn token is USDC\n address burnToken = messageBody.extractAddress(\n BURN_MESSAGE_V2_BURN_TOKEN_INDEX\n );\n require(burnToken == peerUsdcToken, \"Invalid burn token\");\n\n // Address of caller of depositForBurn (or depositForBurnWithCaller) on source domain\n sender = messageBody.extractAddress(\n BURN_MESSAGE_V2_MESSAGE_SENDER_INDEX\n );\n\n recipient = messageBody.extractAddress(\n BURN_MESSAGE_V2_RECIPIENT_INDEX\n );\n } else {\n // We handle only Burn message or our custom messagee\n require(\n version == CrossChainStrategyHelper.ORIGIN_MESSAGE_VERSION,\n \"Unsupported message version\"\n );\n }\n\n // Ensure the recipient is this contract\n // Both sender and recipient should be deployed to same address on both chains.\n require(address(this) == recipient, \"Unexpected recipient address\");\n require(sender == peerStrategy, \"Incorrect sender/recipient address\");\n\n // Relay the message\n // This step also mints USDC and transfers it to the recipient wallet\n bool relaySuccess = cctpMessageTransmitter.receiveMessage(\n message,\n attestation\n );\n require(relaySuccess, \"Receive message failed\");\n\n if (isBurnMessageV1) {\n // Extract the hook data from the message body\n bytes memory hookData = messageBody.extractSlice(\n BURN_MESSAGE_V2_HOOK_DATA_INDEX,\n messageBody.length\n );\n\n // Extract the token amount from the message body\n uint256 tokenAmount = messageBody.extractUint256(\n BURN_MESSAGE_V2_AMOUNT_INDEX\n );\n\n // Extract the fee executed from the message body\n uint256 feeExecuted = messageBody.extractUint256(\n BURN_MESSAGE_V2_FEE_EXECUTED_INDEX\n );\n\n // Call the _onTokenReceived function\n _onTokenReceived(tokenAmount - feeExecuted, feeExecuted, hookData);\n }\n }\n\n /***************************************\n Message utils\n ****************************************/\n\n /***************************************\n Nonce Handling\n ****************************************/\n /**\n * @dev Checks if the last known transfer is pending.\n * Nonce starts at 1, so 0 is disregarded.\n * @return True if a transfer is pending, false otherwise\n */\n function isTransferPending() public view returns (bool) {\n return !nonceProcessed[lastTransferNonce];\n }\n\n /**\n * @dev Checks if a given nonce is processed.\n * Nonce starts at 1, so 0 is disregarded.\n * @param nonce Nonce to check\n * @return True if the nonce is processed, false otherwise\n */\n function isNonceProcessed(uint64 nonce) public view returns (bool) {\n return nonceProcessed[nonce];\n }\n\n /**\n * @dev Marks a given nonce as processed.\n * Can only mark nonce as processed once. New nonce should\n * always be greater than the last known nonce. Also updates\n * the last known nonce.\n * @param nonce Nonce to mark as processed\n */\n function _markNonceAsProcessed(uint64 nonce) internal {\n uint64 lastNonce = lastTransferNonce;\n\n // Can only mark latest nonce as processed\n // Master strategy when receiving a message from the remote strategy\n // will have lastNone == nonce, as the nonce is increase at the start\n // of deposit / withdrawal flow.\n // Remote strategy will have lastNonce < nonce, as a new nonce initiated\n // from master will be greater than the last one.\n require(nonce >= lastNonce, \"Nonce too low\");\n // Can only mark nonce as processed once\n require(!nonceProcessed[nonce], \"Nonce already processed\");\n\n nonceProcessed[nonce] = true;\n emit NonceProcessed(nonce);\n\n if (nonce != lastNonce) {\n // Update last known nonce\n lastTransferNonce = nonce;\n emit LastTransferNonceUpdated(nonce);\n }\n }\n\n /**\n * @dev Gets the next nonce to use.\n * Nonce starts at 1, so 0 is disregarded.\n * Reverts if last nonce hasn't been processed yet.\n * @return Next nonce\n */\n function _getNextNonce() internal returns (uint64) {\n uint64 nonce = lastTransferNonce;\n\n require(nonceProcessed[nonce], \"Pending token transfer\");\n\n nonce = nonce + 1;\n lastTransferNonce = nonce;\n emit LastTransferNonceUpdated(nonce);\n\n return nonce;\n }\n\n /***************************************\n Inheritence overrides\n ****************************************/\n\n /**\n * @dev Called when the USDC is received from the CCTP\n * @param tokenAmount The actual amount of USDC received (amount sent - fee executed)\n * @param feeExecuted The fee executed\n * @param payload The payload of the message (hook data)\n */\n function _onTokenReceived(\n uint256 tokenAmount,\n uint256 feeExecuted,\n bytes memory payload\n ) internal virtual;\n\n /**\n * @dev Called when the message is received\n * @param payload The payload of the message\n */\n function _onMessageReceived(bytes memory payload) internal virtual;\n}\n" + }, + "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title CrossChainRemoteStrategy\n * @author Origin Protocol Inc\n *\n * @dev Part of the cross-chain strategy that lives on the remote chain.\n * Handles deposits and withdrawals from the master strategy on peer chain\n * and locally deposits the funds to a 4626 compatible vault.\n */\n\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport { IERC20 } from \"../../utils/InitializableAbstractStrategy.sol\";\nimport { IERC4626 } from \"../../../lib/openzeppelin/interfaces/IERC4626.sol\";\nimport { IVaultV2 } from \"../../interfaces/morpho/IVaultV2.sol\";\nimport { Generalized4626Strategy } from \"../Generalized4626Strategy.sol\";\nimport { AbstractCCTPIntegrator } from \"./AbstractCCTPIntegrator.sol\";\nimport { CrossChainStrategyHelper } from \"./CrossChainStrategyHelper.sol\";\nimport { InitializableAbstractStrategy } from \"../../utils/InitializableAbstractStrategy.sol\";\nimport { Strategizable } from \"../../governance/Strategizable.sol\";\nimport { MorphoV2VaultUtils } from \"../MorphoV2VaultUtils.sol\";\n\ncontract CrossChainRemoteStrategy is\n AbstractCCTPIntegrator,\n Generalized4626Strategy,\n Strategizable\n{\n using SafeERC20 for IERC20;\n using CrossChainStrategyHelper for bytes;\n\n event DepositUnderlyingFailed(string reason);\n event WithdrawalFailed(uint256 amountRequested, uint256 amountAvailable);\n event WithdrawUnderlyingFailed(string reason);\n\n modifier onlyOperatorOrStrategistOrGovernor() {\n require(\n msg.sender == operator ||\n msg.sender == strategistAddr ||\n isGovernor(),\n \"Caller is not the Operator, Strategist or the Governor\"\n );\n _;\n }\n\n modifier onlyGovernorOrStrategist()\n override(InitializableAbstractStrategy, Strategizable) {\n require(\n msg.sender == strategistAddr || isGovernor(),\n \"Caller is not the Strategist or Governor\"\n );\n _;\n }\n\n constructor(\n BaseStrategyConfig memory _baseConfig,\n CCTPIntegrationConfig memory _cctpConfig\n )\n AbstractCCTPIntegrator(_cctpConfig)\n Generalized4626Strategy(_baseConfig, _cctpConfig.usdcToken)\n {\n require(usdcToken == address(assetToken), \"Token mismatch\");\n require(\n _baseConfig.platformAddress != address(0),\n \"Invalid platform address\"\n );\n // Vault address must always be address(0) for the remote strategy\n require(\n _baseConfig.vaultAddress == address(0),\n \"Invalid vault address\"\n );\n }\n\n /**\n * @dev Initialize the strategy implementation\n * @param _strategist Address of the strategist\n * @param _operator Address of the operator\n * @param _minFinalityThreshold Minimum finality threshold\n * @param _feePremiumBps Fee premium in basis points\n */\n function initialize(\n address _strategist,\n address _operator,\n uint16 _minFinalityThreshold,\n uint16 _feePremiumBps\n ) external virtual onlyGovernor initializer {\n _initialize(_operator, _minFinalityThreshold, _feePremiumBps);\n _setStrategistAddr(_strategist);\n\n address[] memory rewardTokens = new address[](0);\n address[] memory assets = new address[](1);\n address[] memory pTokens = new address[](1);\n\n assets[0] = address(usdcToken);\n pTokens[0] = address(platformAddress);\n\n InitializableAbstractStrategy._initialize(\n rewardTokens,\n assets,\n pTokens\n );\n }\n\n /// @inheritdoc Generalized4626Strategy\n function deposit(address _asset, uint256 _amount)\n external\n virtual\n override\n onlyGovernorOrStrategist\n nonReentrant\n {\n _deposit(_asset, _amount);\n }\n\n /// @inheritdoc Generalized4626Strategy\n function depositAll()\n external\n virtual\n override\n onlyGovernorOrStrategist\n nonReentrant\n {\n _deposit(usdcToken, IERC20(usdcToken).balanceOf(address(this)));\n }\n\n /// @inheritdoc Generalized4626Strategy\n /// @dev Interface requires a recipient, but for compatibility it must be address(this).\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external virtual override onlyGovernorOrStrategist nonReentrant {\n _withdraw(_recipient, _asset, _amount);\n }\n\n /// @inheritdoc Generalized4626Strategy\n function withdrawAll()\n external\n virtual\n override\n onlyGovernorOrStrategist\n nonReentrant\n {\n IERC4626 platform = IERC4626(platformAddress);\n uint256 availableMorphoVault = MorphoV2VaultUtils.maxWithdrawableAssets(\n platformAddress,\n usdcToken\n );\n uint256 amountToWithdraw = Math.min(\n availableMorphoVault,\n platform.previewRedeem(platform.balanceOf(address(this)))\n );\n\n if (amountToWithdraw > 0) {\n _withdraw(\n address(this),\n usdcToken,\n amountToWithdraw\n );\n }\n }\n\n /// @inheritdoc AbstractCCTPIntegrator\n function _onMessageReceived(bytes memory payload) internal override {\n uint32 messageType = payload.getMessageType();\n if (messageType == CrossChainStrategyHelper.DEPOSIT_MESSAGE) {\n // Received when Master strategy sends tokens to the remote strategy\n // Do nothing because we receive acknowledgement with token transfer,\n // so _onTokenReceived will handle it\n } else if (messageType == CrossChainStrategyHelper.WITHDRAW_MESSAGE) {\n // Received when Master strategy requests a withdrawal\n _processWithdrawMessage(payload);\n } else {\n revert(\"Unknown message type\");\n }\n }\n\n /**\n * @dev Process deposit message from peer strategy\n * @param tokenAmount Amount of tokens received\n * @param feeExecuted Fee executed\n * @param payload Payload of the message\n */\n function _processDepositMessage(\n // solhint-disable-next-line no-unused-vars\n uint256 tokenAmount,\n // solhint-disable-next-line no-unused-vars\n uint256 feeExecuted,\n bytes memory payload\n ) internal virtual {\n (uint64 nonce, ) = payload.decodeDepositMessage();\n\n // Replay protection is part of the _markNonceAsProcessed function\n _markNonceAsProcessed(nonce);\n\n // Deposit everything we got, not just what was bridged\n uint256 balance = IERC20(usdcToken).balanceOf(address(this));\n\n // Underlying call to deposit funds can fail. It mustn't affect the overall\n // flow as confirmation message should still be sent.\n if (balance >= MIN_TRANSFER_AMOUNT) {\n _deposit(usdcToken, balance);\n }\n\n // Send balance check message to the peer strategy\n bytes memory message = CrossChainStrategyHelper\n .encodeBalanceCheckMessage(\n lastTransferNonce,\n checkBalance(usdcToken),\n true,\n block.timestamp\n );\n _sendMessage(message);\n }\n\n /**\n * @dev Deposit assets by converting them to shares\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n */\n function _deposit(address _asset, uint256 _amount) internal override {\n // By design, this function should not revert. Otherwise, it'd\n // not be able to process messages and might freeze the contracts\n // state. However these two require statements would never fail\n // in every function invoking this. The same kind of checks should\n // be enforced in all the calling functions for these two and any\n // other require statements added to this function.\n require(_amount > 0, \"Must deposit something\");\n require(_asset == address(usdcToken), \"Unexpected asset address\");\n\n // This call can fail, and the failure doesn't need to bubble up to the _processDepositMessage function\n // as the flow is not affected by the failure.\n\n try IERC4626(platformAddress).deposit(_amount, address(this)) {\n emit Deposit(_asset, address(shareToken), _amount);\n } catch Error(string memory reason) {\n emit DepositUnderlyingFailed(\n string(abi.encodePacked(\"Deposit failed: \", reason))\n );\n } catch (bytes memory lowLevelData) {\n emit DepositUnderlyingFailed(\n string(\n abi.encodePacked(\n \"Deposit failed: low-level call failed with data \",\n lowLevelData\n )\n )\n );\n }\n }\n\n /**\n * @dev Process withdrawal message from peer strategy\n * @param payload Payload of the message\n */\n function _processWithdrawMessage(bytes memory payload) internal virtual {\n (uint64 nonce, uint256 withdrawAmount) = payload\n .decodeWithdrawMessage();\n\n // Replay protection is part of the _markNonceAsProcessed function\n _markNonceAsProcessed(nonce);\n\n uint256 usdcBalance = IERC20(usdcToken).balanceOf(address(this));\n\n if (usdcBalance < withdrawAmount) {\n // Withdraw the missing funds from the remote strategy. This call can fail and\n // the failure doesn't bubble up to the _processWithdrawMessage function\n _withdraw(address(this), usdcToken, withdrawAmount - usdcBalance);\n\n // Update the possible increase in the balance on the contract.\n usdcBalance = IERC20(usdcToken).balanceOf(address(this));\n }\n\n // Check balance after withdrawal\n uint256 strategyBalance = checkBalance(usdcToken);\n\n // If there are some tokens to be sent AND the balance is sufficient\n // to satisfy the withdrawal request then send the funds to the peer strategy.\n // In case a direct withdraw(All) has previously been called\n // there is a possibility of USDC funds remaining on the contract.\n // A separate withdraw to extract or deposit to the Morpho vault needs to be\n // initiated from the peer Master strategy to utilise USDC funds.\n if (\n withdrawAmount >= MIN_TRANSFER_AMOUNT &&\n usdcBalance >= withdrawAmount\n ) {\n // The new balance on the contract needs to have USDC subtracted from it as\n // that will be withdrawn in the next step\n bytes memory message = CrossChainStrategyHelper\n .encodeBalanceCheckMessage(\n lastTransferNonce,\n strategyBalance - withdrawAmount,\n true,\n block.timestamp\n );\n _sendTokens(withdrawAmount, message);\n } else {\n // Contract either:\n // - only has small dust amount of USDC\n // - doesn't have sufficient funds to satisfy the withdrawal request\n // In both cases send the balance update message to the peer strategy.\n bytes memory message = CrossChainStrategyHelper\n .encodeBalanceCheckMessage(\n lastTransferNonce,\n strategyBalance,\n true,\n block.timestamp\n );\n _sendMessage(message);\n emit WithdrawalFailed(withdrawAmount, usdcBalance);\n }\n }\n\n /**\n * @dev Withdraw asset by burning shares\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n */\n function _withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) internal override {\n require(_amount > 0, \"Must withdraw something\");\n require(_recipient == address(this), \"Invalid recipient\");\n require(_asset == address(usdcToken), \"Unexpected asset address\");\n\n // This call can fail, and the failure doesn't need to bubble up to the _processWithdrawMessage function\n // as the flow is not affected by the failure.\n try\n // slither-disable-next-line unused-return\n IERC4626(platformAddress).withdraw(\n _amount,\n address(this),\n address(this)\n )\n {\n emit Withdrawal(_asset, address(shareToken), _amount);\n } catch Error(string memory reason) {\n emit WithdrawUnderlyingFailed(\n string(abi.encodePacked(\"Withdrawal failed: \", reason))\n );\n } catch (bytes memory lowLevelData) {\n emit WithdrawUnderlyingFailed(\n string(\n abi.encodePacked(\n \"Withdrawal failed: low-level call failed with data \",\n lowLevelData\n )\n )\n );\n }\n }\n\n /**\n * @dev Process token received message from peer strategy\n * @param tokenAmount Amount of tokens received\n * @param feeExecuted Fee executed\n * @param payload Payload of the message\n */\n function _onTokenReceived(\n uint256 tokenAmount,\n uint256 feeExecuted,\n bytes memory payload\n ) internal override {\n uint32 messageType = payload.getMessageType();\n\n require(\n messageType == CrossChainStrategyHelper.DEPOSIT_MESSAGE,\n \"Invalid message type\"\n );\n\n _processDepositMessage(tokenAmount, feeExecuted, payload);\n }\n\n /**\n * @dev Send balance update message to the peer strategy\n */\n function sendBalanceUpdate()\n external\n virtual\n onlyOperatorOrStrategistOrGovernor\n {\n uint256 balance = checkBalance(usdcToken);\n bytes memory message = CrossChainStrategyHelper\n .encodeBalanceCheckMessage(\n lastTransferNonce,\n balance,\n false,\n block.timestamp\n );\n _sendMessage(message);\n }\n\n /**\n * @notice Get the total asset value held in the platform and contract\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform and contract\n */\n function checkBalance(address _asset)\n public\n view\n override\n returns (uint256)\n {\n require(_asset == usdcToken, \"Unexpected asset address\");\n /**\n * Balance of USDC on the contract is counted towards the total balance, since a deposit\n * to the Morpho V2 might fail and the USDC might remain on this contract as a result of a\n * bridged transfer.\n */\n uint256 balanceOnContract = IERC20(usdcToken).balanceOf(address(this));\n\n IERC4626 platform = IERC4626(platformAddress);\n return\n platform.previewRedeem(platform.balanceOf(address(this))) +\n balanceOnContract;\n }\n}\n" + }, + "contracts/strategies/crosschain/CrossChainStrategyHelper.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title CrossChainStrategyHelper\n * @author Origin Protocol Inc\n * @dev This library is used to encode and decode the messages for the cross-chain strategy.\n * It is used to ensure that the messages are valid and to get the message version and type.\n */\n\nimport { BytesHelper } from \"../../utils/BytesHelper.sol\";\n\nlibrary CrossChainStrategyHelper {\n using BytesHelper for bytes;\n\n uint32 public constant DEPOSIT_MESSAGE = 1;\n uint32 public constant WITHDRAW_MESSAGE = 2;\n uint32 public constant BALANCE_CHECK_MESSAGE = 3;\n\n uint32 public constant CCTP_MESSAGE_VERSION = 1;\n uint32 public constant ORIGIN_MESSAGE_VERSION = 1010;\n\n // CCTP Message Header fields\n // Ref: https://developers.circle.com/cctp/technical-guide#message-header\n uint8 private constant VERSION_INDEX = 0;\n uint8 private constant SOURCE_DOMAIN_INDEX = 4;\n uint8 private constant SENDER_INDEX = 44;\n uint8 private constant RECIPIENT_INDEX = 76;\n uint8 private constant MESSAGE_BODY_INDEX = 148;\n\n /**\n * @dev Get the message version from the message.\n * It should always be 4 bytes long,\n * starting from the 0th index.\n * @param message The message to get the version from\n * @return The message version\n */\n function getMessageVersion(bytes memory message)\n internal\n pure\n returns (uint32)\n {\n // uint32 bytes 0 to 4 is Origin message version\n // uint32 bytes 4 to 8 is Message type\n return message.extractUint32(0);\n }\n\n /**\n * @dev Get the message type from the message.\n * It should always be 4 bytes long,\n * starting from the 4th index.\n * @param message The message to get the type from\n * @return The message type\n */\n function getMessageType(bytes memory message)\n internal\n pure\n returns (uint32)\n {\n // uint32 bytes 0 to 4 is Origin message version\n // uint32 bytes 4 to 8 is Message type\n return message.extractUint32(4);\n }\n\n /**\n * @dev Verify the message version and type.\n * The message version should be the same as the Origin message version,\n * and the message type should be the same as the expected message type.\n * @param _message The message to verify\n * @param _type The expected message type\n */\n function verifyMessageVersionAndType(bytes memory _message, uint32 _type)\n internal\n pure\n {\n require(\n getMessageVersion(_message) == ORIGIN_MESSAGE_VERSION,\n \"Invalid Origin Message Version\"\n );\n require(getMessageType(_message) == _type, \"Invalid Message type\");\n }\n\n /**\n * @dev Get the message payload from the message.\n * The payload starts at the 8th byte.\n * @param message The message to get the payload from\n * @return The message payload\n */\n function getMessagePayload(bytes memory message)\n internal\n pure\n returns (bytes memory)\n {\n // uint32 bytes 0 to 4 is Origin message version\n // uint32 bytes 4 to 8 is Message type\n // Payload starts at byte 8\n return message.extractSlice(8, message.length);\n }\n\n /**\n * @dev Encode the deposit message.\n * The message version and type are always encoded in the message.\n * @param nonce The nonce of the deposit\n * @param depositAmount The amount of the deposit\n * @return The encoded deposit message\n */\n function encodeDepositMessage(uint64 nonce, uint256 depositAmount)\n internal\n pure\n returns (bytes memory)\n {\n return\n abi.encodePacked(\n ORIGIN_MESSAGE_VERSION,\n DEPOSIT_MESSAGE,\n abi.encode(nonce, depositAmount)\n );\n }\n\n /**\n * @dev Decode the deposit message.\n * The message version and type are verified in the message.\n * @param message The message to decode\n * @return The nonce and the amount of the deposit\n */\n function decodeDepositMessage(bytes memory message)\n internal\n pure\n returns (uint64, uint256)\n {\n verifyMessageVersionAndType(message, DEPOSIT_MESSAGE);\n\n (uint64 nonce, uint256 depositAmount) = abi.decode(\n getMessagePayload(message),\n (uint64, uint256)\n );\n return (nonce, depositAmount);\n }\n\n /**\n * @dev Encode the withdrawal message.\n * The message version and type are always encoded in the message.\n * @param nonce The nonce of the withdrawal\n * @param withdrawAmount The amount of the withdrawal\n * @return The encoded withdrawal message\n */\n function encodeWithdrawMessage(uint64 nonce, uint256 withdrawAmount)\n internal\n pure\n returns (bytes memory)\n {\n return\n abi.encodePacked(\n ORIGIN_MESSAGE_VERSION,\n WITHDRAW_MESSAGE,\n abi.encode(nonce, withdrawAmount)\n );\n }\n\n /**\n * @dev Decode the withdrawal message.\n * The message version and type are verified in the message.\n * @param message The message to decode\n * @return The nonce and the amount of the withdrawal\n */\n function decodeWithdrawMessage(bytes memory message)\n internal\n pure\n returns (uint64, uint256)\n {\n verifyMessageVersionAndType(message, WITHDRAW_MESSAGE);\n\n (uint64 nonce, uint256 withdrawAmount) = abi.decode(\n getMessagePayload(message),\n (uint64, uint256)\n );\n return (nonce, withdrawAmount);\n }\n\n /**\n * @dev Encode the balance check message.\n * The message version and type are always encoded in the message.\n * @param nonce The nonce of the balance check\n * @param balance The balance to check\n * @param transferConfirmation Indicates if the message is a transfer confirmation. This is true\n * when the message is a result of a deposit or a withdrawal.\n * @return The encoded balance check message\n */\n function encodeBalanceCheckMessage(\n uint64 nonce,\n uint256 balance,\n bool transferConfirmation,\n uint256 timestamp\n ) internal pure returns (bytes memory) {\n return\n abi.encodePacked(\n ORIGIN_MESSAGE_VERSION,\n BALANCE_CHECK_MESSAGE,\n abi.encode(nonce, balance, transferConfirmation, timestamp)\n );\n }\n\n /**\n * @dev Decode the balance check message.\n * The message version and type are verified in the message.\n * @param message The message to decode\n * @return The nonce, the balance and indicates if the message is a transfer confirmation\n */\n function decodeBalanceCheckMessage(bytes memory message)\n internal\n pure\n returns (\n uint64,\n uint256,\n bool,\n uint256\n )\n {\n verifyMessageVersionAndType(message, BALANCE_CHECK_MESSAGE);\n\n (\n uint64 nonce,\n uint256 balance,\n bool transferConfirmation,\n uint256 timestamp\n ) = abi.decode(\n getMessagePayload(message),\n (uint64, uint256, bool, uint256)\n );\n return (nonce, balance, transferConfirmation, timestamp);\n }\n\n /**\n * @dev Decode the CCTP message header\n * @param message Message to decode\n * @return version Version of the message\n * @return sourceDomainID Source domain ID\n * @return sender Sender of the message\n * @return recipient Recipient of the message\n * @return messageBody Message body\n */\n function decodeMessageHeader(bytes memory message)\n internal\n pure\n returns (\n uint32 version,\n uint32 sourceDomainID,\n address sender,\n address recipient,\n bytes memory messageBody\n )\n {\n version = message.extractUint32(VERSION_INDEX);\n sourceDomainID = message.extractUint32(SOURCE_DOMAIN_INDEX);\n // Address of MessageTransmitterV2 caller on source domain\n sender = message.extractAddress(SENDER_INDEX);\n // Address to handle message body on destination domain\n recipient = message.extractAddress(RECIPIENT_INDEX);\n messageBody = message.extractSlice(MESSAGE_BODY_INDEX, message.length);\n }\n}\n" + }, + "contracts/strategies/Generalized4626Strategy.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title Generalized 4626 Strategy\n * @notice Investment strategy for ERC-4626 Tokenized Vaults\n * @dev This strategy should not be used for the Morpho V2 Vaults as those are not\n * completley ERC-4626 compliant - they don't implement the maxWithdraw() and \n * maxRedeem() functions and rather return 0 when any of them is called.\n * @author Origin Protocol Inc\n */\nimport { IERC4626 } from \"../../lib/openzeppelin/interfaces/IERC4626.sol\";\nimport { IERC20, InitializableAbstractStrategy } from \"../utils/InitializableAbstractStrategy.sol\";\nimport { IDistributor } from \"../interfaces/IMerkl.sol\";\n\ncontract Generalized4626Strategy is InitializableAbstractStrategy {\n /// @notice The address of the Merkle Distributor contract.\n IDistributor public constant merkleDistributor =\n IDistributor(0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae);\n\n /// @dev Replaced with an immutable variable\n // slither-disable-next-line constable-states\n address private _deprecate_shareToken;\n /// @dev Replaced with an immutable variable\n // slither-disable-next-line constable-states\n address private _deprecate_assetToken;\n\n IERC20 public immutable shareToken;\n IERC20 public immutable assetToken;\n\n // For future use\n uint256[50] private __gap;\n\n event ClaimedRewards(address indexed token, uint256 amount);\n\n /**\n * @param _baseConfig Base strategy config with platformAddress (ERC-4626 Vault contract), eg sfrxETH or sDAI,\n * and vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy\n * @param _assetToken Address of the ERC-4626 asset token. eg frxETH or DAI\n */\n constructor(BaseStrategyConfig memory _baseConfig, address _assetToken)\n InitializableAbstractStrategy(_baseConfig)\n {\n shareToken = IERC20(_baseConfig.platformAddress);\n assetToken = IERC20(_assetToken);\n }\n\n function initialize() external virtual onlyGovernor initializer {\n address[] memory rewardTokens = new address[](0);\n address[] memory assets = new address[](1);\n address[] memory pTokens = new address[](1);\n\n assets[0] = address(assetToken);\n pTokens[0] = address(platformAddress);\n\n InitializableAbstractStrategy._initialize(\n rewardTokens,\n assets,\n pTokens\n );\n }\n\n /**\n * @dev Deposit assets by converting them to shares\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n */\n function deposit(address _asset, uint256 _amount)\n external\n virtual\n override\n onlyVault\n nonReentrant\n {\n _deposit(_asset, _amount);\n }\n\n /**\n * @dev Deposit assets by converting them to shares\n * @param _asset Address of asset to deposit\n * @param _amount Amount of asset to deposit\n */\n function _deposit(address _asset, uint256 _amount) internal virtual {\n require(_amount > 0, \"Must deposit something\");\n require(_asset == address(assetToken), \"Unexpected asset address\");\n\n // slither-disable-next-line unused-return\n IERC4626(platformAddress).deposit(_amount, address(this));\n emit Deposit(_asset, address(shareToken), _amount);\n }\n\n /**\n * @dev Deposit the entire balance of assetToken to gain shareToken\n */\n function depositAll() external virtual override onlyVault nonReentrant {\n uint256 balance = assetToken.balanceOf(address(this));\n if (balance > 0) {\n _deposit(address(assetToken), balance);\n }\n }\n\n /**\n * @dev Withdraw asset by burning shares\n * @param _recipient Address to receive withdrawn asset\n * @param _asset Address of asset to withdraw\n * @param _amount Amount of asset to withdraw\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external virtual override onlyVault nonReentrant {\n _withdraw(_recipient, _asset, _amount);\n }\n\n function _withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) internal virtual {\n require(_amount > 0, \"Must withdraw something\");\n require(_recipient != address(0), \"Must specify recipient\");\n require(_asset == address(assetToken), \"Unexpected asset address\");\n\n // slither-disable-next-line unused-return\n IERC4626(platformAddress).withdraw(_amount, _recipient, address(this));\n emit Withdrawal(_asset, address(shareToken), _amount);\n }\n\n /**\n * @dev Internal method to respond to the addition of new asset / share tokens\n */\n function _abstractSetPToken(address, address) internal virtual override {\n _approveBase();\n }\n\n /**\n * @dev Remove all assets from platform and send them to Vault contract.\n */\n function withdrawAll()\n external\n virtual\n override\n onlyVaultOrGovernor\n nonReentrant\n {\n // @dev Don't use for Morpho V2 Vaults as below line will return 0\n uint256 sharesToRedeem = IERC4626(platformAddress).maxRedeem(address(this));\n\n uint256 assetAmount = 0;\n if (sharesToRedeem > 0) {\n assetAmount = IERC4626(platformAddress).redeem(\n sharesToRedeem,\n vaultAddress,\n address(this)\n );\n emit Withdrawal(\n address(assetToken),\n address(shareToken),\n assetAmount\n );\n }\n }\n\n /**\n * @notice Get the total asset value held in the platform\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n public\n view\n virtual\n override\n returns (uint256 balance)\n {\n require(_asset == address(assetToken), \"Unexpected asset address\");\n /* We are intentionally not counting the amount of assetToken parked on the\n * contract toward the checkBalance. The deposit and withdraw functions\n * should not result in assetToken being unused and owned by this strategy\n * contract.\n */\n IERC4626 platform = IERC4626(platformAddress);\n return platform.previewRedeem(platform.balanceOf(address(this)));\n }\n\n /**\n * @notice Governor approves the ERC-4626 Tokenized Vault to spend the asset.\n */\n function safeApproveAllTokens() external override onlyGovernor {\n _approveBase();\n }\n\n function _approveBase() internal virtual {\n // Approval the asset to be transferred to the ERC-4626 Tokenized Vault.\n // Used by the ERC-4626 deposit() and mint() functions\n // slither-disable-next-line unused-return\n assetToken.approve(platformAddress, type(uint256).max);\n }\n\n /**\n * @dev Returns bool indicating whether asset is supported by strategy\n * @param _asset Address of the asset\n */\n function supportsAsset(address _asset)\n public\n view\n virtual\n override\n returns (bool)\n {\n return _asset == address(assetToken);\n }\n\n /**\n * @notice is not supported for this strategy as the asset and\n * ERC-4626 Tokenized Vault are set at deploy time.\n * @dev If the ERC-4626 Tokenized Vault needed to be changed, a new\n * contract would need to be deployed and the proxy updated.\n */\n function setPTokenAddress(address, address) external override onlyGovernor {\n revert(\"unsupported function\");\n }\n\n /**\n * @notice is not supported for this strategy as the asset and\n * ERC-4626 Tokenized Vault are set at deploy time.\n * @dev If the ERC-4626 Tokenized Vault needed to be changed, a new\n * contract would need to be deployed and the proxy updated.\n */\n function removePToken(uint256) external override onlyGovernor {\n revert(\"unsupported function\");\n }\n\n /// @notice Claim tokens from the Merkle Distributor\n /// @param token The address of the token to claim.\n /// @param amount The amount of tokens to claim.\n /// @param proof The Merkle proof to validate the claim.\n function merkleClaim(\n address token,\n uint256 amount,\n bytes32[] calldata proof\n ) external {\n address[] memory users = new address[](1);\n users[0] = address(this);\n\n address[] memory tokens = new address[](1);\n tokens[0] = token;\n\n uint256[] memory amounts = new uint256[](1);\n amounts[0] = amount;\n\n bytes32[][] memory proofs = new bytes32[][](1);\n proofs[0] = proof;\n\n merkleDistributor.claim(users, tokens, amounts, proofs);\n\n emit ClaimedRewards(token, amount);\n }\n}\n" + }, + "contracts/strategies/MorphoV2Strategy.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title Generalized 4626 Strategy when the underlying platform is Morpho V2\n * @notice Investment strategy for ERC-4626 Tokenized Vaults for the Morpho V2 platform.\n * @author Origin Protocol Inc\n */\nimport { Generalized4626Strategy } from \"./Generalized4626Strategy.sol\";\nimport { MorphoV2VaultUtils } from \"./MorphoV2VaultUtils.sol\";\nimport { IVaultV2 } from \"../interfaces/morpho/IVaultV2.sol\";\nimport { Math } from \"@openzeppelin/contracts/utils/math/Math.sol\";\n\ncontract MorphoV2Strategy is Generalized4626Strategy {\n\n /**\n * @param _baseConfig Base strategy config with Morpho V2 Vault and\n * vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy\n * @param _assetToken Address of the ERC-4626 asset token. e.g. USDC\n */\n constructor(BaseStrategyConfig memory _baseConfig, address _assetToken)\n Generalized4626Strategy(_baseConfig, _assetToken)\n {}\n\n /**\n * @notice Remove all the liquidity that is available in the Morpho V2 vault.\n * Which might not be all of the liquidity owned by the strategy.\n * @dev Remove all the liquidity that is available in the Morpho V2 vault\n * The particular behaviour of the Morpho V2 vault is that it can hold\n * multiple Morpho V1 vaults as adapters but only one liquidity adapter.\n * The immediate available funds on the Morpho V2 vault are therfore any\n * liquid assets residing on the Vault V2 contract and the maxWithdraw\n * amount that the Morpho V1 contract can supply.\n */\n function withdrawAll()\n external\n virtual\n override\n onlyVaultOrGovernor\n nonReentrant\n {\n uint256 availableMorphoVault = _maxWithdraw();\n uint256 balanceToWithdraw = Math.min(\n availableMorphoVault,\n checkBalance(address(assetToken))\n );\n\n if (balanceToWithdraw > 0) {\n // slither-disable-next-line unused-return\n IVaultV2(platformAddress).withdraw(\n balanceToWithdraw,\n vaultAddress,\n address(this)\n );\n }\n\n emit Withdrawal(\n address(assetToken),\n address(shareToken),\n balanceToWithdraw\n );\n }\n\n function maxWithdraw() external view returns (uint256) {\n return _maxWithdraw();\n }\n\n function _maxWithdraw()\n internal\n view\n returns (uint256 availableAssetLiquidity)\n {\n availableAssetLiquidity = MorphoV2VaultUtils.maxWithdrawableAssets(\n platformAddress,\n address(assetToken)\n );\n }\n}\n" + }, + "contracts/strategies/MorphoV2VaultUtils.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { IERC20 } from \"../utils/InitializableAbstractStrategy.sol\";\nimport { IERC4626 } from \"../../lib/openzeppelin/interfaces/IERC4626.sol\";\nimport { IVaultV2 } from \"../interfaces/morpho/IVaultV2.sol\";\nimport { IMorphoV2Adapter } from \"../interfaces/morpho/IMorphoV2Adapter.sol\";\n\nlibrary MorphoV2VaultUtils {\n error IncompatibleAdapter(address adapter);\n\n /**\n * @notice Return maximum amount that can be safely withdrawn from a Morpho V2 vault.\n * @dev Available liquidity is:\n * 1) asset balance parked on Morpho V2 vault contract\n * 2) additional liquidity from the active adapter if it resolves to a Morpho V1 vault\n * and, when provided, matches the expected adapter\n */\n function maxWithdrawableAssets(\n address platformAddress,\n address assetToken\n ) internal view returns (uint256 availableAssetLiquidity) {\n availableAssetLiquidity = IERC20(assetToken).balanceOf(platformAddress);\n\n address liquidityAdapter = IVaultV2(platformAddress).liquidityAdapter();\n // this is a sufficient check to ensure the adapter is Morpho V1\n try IMorphoV2Adapter(liquidityAdapter).morphoVaultV1() returns (\n address underlyingVault\n ) {\n availableAssetLiquidity += IERC4626(underlyingVault).maxWithdraw(\n liquidityAdapter\n );\n } catch {\n revert IncompatibleAdapter(liquidityAdapter);\n }\n }\n\n}\n" + }, + "contracts/token/OUSD.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title OUSD Token Contract\n * @dev ERC20 compatible contract for OUSD\n * @dev Implements an elastic supply\n * @author Origin Protocol Inc\n */\nimport { IVault } from \"../interfaces/IVault.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\ncontract OUSD is Governable {\n using SafeCast for int256;\n using SafeCast for uint256;\n\n /// @dev Event triggered when the supply changes\n /// @param totalSupply Updated token total supply\n /// @param rebasingCredits Updated token rebasing credits\n /// @param rebasingCreditsPerToken Updated token rebasing credits per token\n event TotalSupplyUpdatedHighres(\n uint256 totalSupply,\n uint256 rebasingCredits,\n uint256 rebasingCreditsPerToken\n );\n /// @dev Event triggered when an account opts in for rebasing\n /// @param account Address of the account\n event AccountRebasingEnabled(address account);\n /// @dev Event triggered when an account opts out of rebasing\n /// @param account Address of the account\n event AccountRebasingDisabled(address account);\n /// @dev Emitted when `value` tokens are moved from one account `from` to\n /// another `to`.\n /// @param from Address of the account tokens are moved from\n /// @param to Address of the account tokens are moved to\n /// @param value Amount of tokens transferred\n event Transfer(address indexed from, address indexed to, uint256 value);\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 /// @param owner Address of the owner approving allowance\n /// @param spender Address of the spender allowance is granted to\n /// @param value Amount of tokens spender can transfer\n event Approval(\n address indexed owner,\n address indexed spender,\n uint256 value\n );\n /// @dev Yield resulting from {changeSupply} that a `source` account would\n /// receive is directed to `target` account.\n /// @param source Address of the source forwarding the yield\n /// @param target Address of the target receiving the yield\n event YieldDelegated(address source, address target);\n /// @dev Yield delegation from `source` account to the `target` account is\n /// suspended.\n /// @param source Address of the source suspending yield forwarding\n /// @param target Address of the target no longer receiving yield from `source`\n /// account\n event YieldUndelegated(address source, address target);\n\n enum RebaseOptions {\n NotSet,\n StdNonRebasing,\n StdRebasing,\n YieldDelegationSource,\n YieldDelegationTarget\n }\n\n uint256[154] private _gap; // Slots to align with deployed contract\n uint256 private constant MAX_SUPPLY = type(uint128).max;\n /// @dev The amount of tokens in existence\n uint256 public totalSupply;\n mapping(address => mapping(address => uint256)) private allowances;\n /// @dev The vault with privileges to execute {mint}, {burn}\n /// and {changeSupply}\n address public vaultAddress;\n mapping(address => uint256) internal creditBalances;\n // the 2 storage variables below need trailing underscores to not name collide with public functions\n uint256 private rebasingCredits_; // Sum of all rebasing credits (creditBalances for rebasing accounts)\n uint256 private rebasingCreditsPerToken_;\n /// @dev The amount of tokens that are not rebasing - receiving yield\n uint256 public nonRebasingSupply;\n mapping(address => uint256) internal alternativeCreditsPerToken;\n /// @dev A map of all addresses and their respective RebaseOptions\n mapping(address => RebaseOptions) public rebaseState;\n mapping(address => uint256) private __deprecated_isUpgraded;\n /// @dev A map of addresses that have yields forwarded to. This is an\n /// inverse mapping of {yieldFrom}\n /// Key Account forwarding yield\n /// Value Account receiving yield\n mapping(address => address) public yieldTo;\n /// @dev A map of addresses that are receiving the yield. This is an\n /// inverse mapping of {yieldTo}\n /// Key Account receiving yield\n /// Value Account forwarding yield\n mapping(address => address) public yieldFrom;\n\n uint256 private constant RESOLUTION_INCREASE = 1e9;\n uint256[34] private __gap; // including below gap totals up to 200\n\n /// @dev Verifies that the caller is the Governor or Strategist.\n modifier onlyGovernorOrStrategist() {\n require(\n isGovernor() || msg.sender == IVault(vaultAddress).strategistAddr(),\n \"Caller is not the Strategist or Governor\"\n );\n _;\n }\n\n /// @dev Initializes the contract and sets necessary variables.\n /// @param _vaultAddress Address of the vault contract\n /// @param _initialCreditsPerToken The starting rebasing credits per token.\n function initialize(address _vaultAddress, uint256 _initialCreditsPerToken)\n external\n onlyGovernor\n {\n require(_vaultAddress != address(0), \"Zero vault address\");\n require(vaultAddress == address(0), \"Already initialized\");\n\n rebasingCreditsPerToken_ = _initialCreditsPerToken;\n vaultAddress = _vaultAddress;\n }\n\n /// @dev Returns the symbol of the token, a shorter version\n /// of the name.\n function symbol() external pure virtual returns (string memory) {\n return \"OUSD\";\n }\n\n /// @dev Returns the name of the token.\n function name() external pure virtual returns (string memory) {\n return \"Origin Dollar\";\n }\n\n /// @dev Returns the number of decimals used to get its user representation.\n function decimals() external pure virtual returns (uint8) {\n return 18;\n }\n\n /**\n * @dev Verifies that the caller is the Vault contract\n */\n modifier onlyVault() {\n require(vaultAddress == msg.sender, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @return High resolution rebasingCreditsPerToken\n */\n function rebasingCreditsPerTokenHighres() external view returns (uint256) {\n return rebasingCreditsPerToken_;\n }\n\n /**\n * @return Low resolution rebasingCreditsPerToken\n */\n function rebasingCreditsPerToken() external view returns (uint256) {\n return rebasingCreditsPerToken_ / RESOLUTION_INCREASE;\n }\n\n /**\n * @return High resolution total number of rebasing credits\n */\n function rebasingCreditsHighres() external view returns (uint256) {\n return rebasingCredits_;\n }\n\n /**\n * @return Low resolution total number of rebasing credits\n */\n function rebasingCredits() external view returns (uint256) {\n return rebasingCredits_ / RESOLUTION_INCREASE;\n }\n\n /**\n * @notice Gets the balance of the specified address.\n * @param _account Address to query the balance of.\n * @return A uint256 representing the amount of base units owned by the\n * specified address.\n */\n function balanceOf(address _account) public view returns (uint256) {\n RebaseOptions state = rebaseState[_account];\n if (state == RebaseOptions.YieldDelegationSource) {\n // Saves a slot read when transferring to or from a yield delegating source\n // since we know creditBalances equals the balance.\n return creditBalances[_account];\n }\n uint256 baseBalance = (creditBalances[_account] * 1e18) /\n _creditsPerToken(_account);\n if (state == RebaseOptions.YieldDelegationTarget) {\n // creditBalances of yieldFrom accounts equals token balances\n return baseBalance - creditBalances[yieldFrom[_account]];\n }\n return baseBalance;\n }\n\n /**\n * @notice Gets the credits balance of the specified address.\n * @dev Backwards compatible with old low res credits per token.\n * @param _account The address to query the balance of.\n * @return (uint256, uint256) Credit balance and credits per token of the\n * address\n */\n function creditsBalanceOf(address _account)\n external\n view\n returns (uint256, uint256)\n {\n uint256 cpt = _creditsPerToken(_account);\n if (cpt == 1e27) {\n // For a period before the resolution upgrade, we created all new\n // contract accounts at high resolution. Since they are not changing\n // as a result of this upgrade, we will return their true values\n return (creditBalances[_account], cpt);\n } else {\n return (\n creditBalances[_account] / RESOLUTION_INCREASE,\n cpt / RESOLUTION_INCREASE\n );\n }\n }\n\n /**\n * @notice Gets the credits balance of the specified address.\n * @param _account The address to query the balance of.\n * @return (uint256, uint256, bool) Credit balance, credits per token of the\n * address, and isUpgraded\n */\n function creditsBalanceOfHighres(address _account)\n external\n view\n returns (\n uint256,\n uint256,\n bool\n )\n {\n return (\n creditBalances[_account],\n _creditsPerToken(_account),\n true // all accounts have their resolution \"upgraded\"\n );\n }\n\n // Backwards compatible view\n function nonRebasingCreditsPerToken(address _account)\n external\n view\n returns (uint256)\n {\n return alternativeCreditsPerToken[_account];\n }\n\n /**\n * @notice Transfer tokens to a specified address.\n * @param _to the address to transfer to.\n * @param _value the amount to be transferred.\n * @return true on success.\n */\n function transfer(address _to, uint256 _value) external returns (bool) {\n require(_to != address(0), \"Transfer to zero address\");\n\n _executeTransfer(msg.sender, _to, _value);\n\n emit Transfer(msg.sender, _to, _value);\n return true;\n }\n\n /**\n * @notice Transfer tokens from one address to another.\n * @param _from The address you want to send tokens from.\n * @param _to The address you want to transfer to.\n * @param _value The amount of tokens to be transferred.\n * @return true on success.\n */\n function transferFrom(\n address _from,\n address _to,\n uint256 _value\n ) external returns (bool) {\n require(_to != address(0), \"Transfer to zero address\");\n uint256 userAllowance = allowances[_from][msg.sender];\n require(_value <= userAllowance, \"Allowance exceeded\");\n\n unchecked {\n allowances[_from][msg.sender] = userAllowance - _value;\n }\n\n _executeTransfer(_from, _to, _value);\n\n emit Transfer(_from, _to, _value);\n return true;\n }\n\n function _executeTransfer(\n address _from,\n address _to,\n uint256 _value\n ) internal {\n (\n int256 fromRebasingCreditsDiff,\n int256 fromNonRebasingSupplyDiff\n ) = _adjustAccount(_from, -_value.toInt256());\n (\n int256 toRebasingCreditsDiff,\n int256 toNonRebasingSupplyDiff\n ) = _adjustAccount(_to, _value.toInt256());\n\n _adjustGlobals(\n fromRebasingCreditsDiff + toRebasingCreditsDiff,\n fromNonRebasingSupplyDiff + toNonRebasingSupplyDiff\n );\n }\n\n function _adjustAccount(address _account, int256 _balanceChange)\n internal\n returns (int256 rebasingCreditsDiff, int256 nonRebasingSupplyDiff)\n {\n RebaseOptions state = rebaseState[_account];\n int256 currentBalance = balanceOf(_account).toInt256();\n if (currentBalance + _balanceChange < 0) {\n revert(\"Transfer amount exceeds balance\");\n }\n uint256 newBalance = (currentBalance + _balanceChange).toUint256();\n\n if (state == RebaseOptions.YieldDelegationSource) {\n address target = yieldTo[_account];\n uint256 targetOldBalance = balanceOf(target);\n uint256 targetNewCredits = _balanceToRebasingCredits(\n targetOldBalance + newBalance\n );\n rebasingCreditsDiff =\n targetNewCredits.toInt256() -\n creditBalances[target].toInt256();\n\n creditBalances[_account] = newBalance;\n creditBalances[target] = targetNewCredits;\n } else if (state == RebaseOptions.YieldDelegationTarget) {\n uint256 newCredits = _balanceToRebasingCredits(\n newBalance + creditBalances[yieldFrom[_account]]\n );\n rebasingCreditsDiff =\n newCredits.toInt256() -\n creditBalances[_account].toInt256();\n creditBalances[_account] = newCredits;\n } else {\n _autoMigrate(_account);\n uint256 alternativeCreditsPerTokenMem = alternativeCreditsPerToken[\n _account\n ];\n if (alternativeCreditsPerTokenMem > 0) {\n nonRebasingSupplyDiff = _balanceChange;\n if (alternativeCreditsPerTokenMem != 1e18) {\n alternativeCreditsPerToken[_account] = 1e18;\n }\n creditBalances[_account] = newBalance;\n } else {\n uint256 newCredits = _balanceToRebasingCredits(newBalance);\n rebasingCreditsDiff =\n newCredits.toInt256() -\n creditBalances[_account].toInt256();\n creditBalances[_account] = newCredits;\n }\n }\n }\n\n function _adjustGlobals(\n int256 _rebasingCreditsDiff,\n int256 _nonRebasingSupplyDiff\n ) internal {\n if (_rebasingCreditsDiff != 0) {\n rebasingCredits_ = (rebasingCredits_.toInt256() +\n _rebasingCreditsDiff).toUint256();\n }\n if (_nonRebasingSupplyDiff != 0) {\n nonRebasingSupply = (nonRebasingSupply.toInt256() +\n _nonRebasingSupplyDiff).toUint256();\n }\n }\n\n /**\n * @notice Function to check the amount of tokens that _owner has allowed\n * to `_spender`.\n * @param _owner The address which owns the funds.\n * @param _spender The address which will spend the funds.\n * @return The number of tokens still available for the _spender.\n */\n function allowance(address _owner, address _spender)\n external\n view\n returns (uint256)\n {\n return allowances[_owner][_spender];\n }\n\n /**\n * @notice Approve the passed address to spend the specified amount of\n * tokens on behalf of msg.sender.\n * @param _spender The address which will spend the funds.\n * @param _value The amount of tokens to be spent.\n * @return true on success.\n */\n function approve(address _spender, uint256 _value) external returns (bool) {\n allowances[msg.sender][_spender] = _value;\n emit Approval(msg.sender, _spender, _value);\n return true;\n }\n\n /**\n * @notice Creates `_amount` tokens and assigns them to `_account`,\n * increasing the total supply.\n */\n function mint(address _account, uint256 _amount) external onlyVault {\n require(_account != address(0), \"Mint to the zero address\");\n\n // Account\n (\n int256 toRebasingCreditsDiff,\n int256 toNonRebasingSupplyDiff\n ) = _adjustAccount(_account, _amount.toInt256());\n // Globals\n _adjustGlobals(toRebasingCreditsDiff, toNonRebasingSupplyDiff);\n totalSupply = totalSupply + _amount;\n\n require(totalSupply < MAX_SUPPLY, \"Max supply\");\n emit Transfer(address(0), _account, _amount);\n }\n\n /**\n * @notice Destroys `_amount` tokens from `_account`,\n * reducing the total supply.\n */\n function burn(address _account, uint256 _amount) external onlyVault {\n require(_account != address(0), \"Burn from the zero address\");\n if (_amount == 0) {\n return;\n }\n\n // Account\n (\n int256 toRebasingCreditsDiff,\n int256 toNonRebasingSupplyDiff\n ) = _adjustAccount(_account, -_amount.toInt256());\n // Globals\n _adjustGlobals(toRebasingCreditsDiff, toNonRebasingSupplyDiff);\n totalSupply = totalSupply - _amount;\n\n emit Transfer(_account, address(0), _amount);\n }\n\n /**\n * @dev Get the credits per token for an account. Returns a fixed amount\n * if the account is non-rebasing.\n * @param _account Address of the account.\n */\n function _creditsPerToken(address _account)\n internal\n view\n returns (uint256)\n {\n uint256 alternativeCreditsPerTokenMem = alternativeCreditsPerToken[\n _account\n ];\n if (alternativeCreditsPerTokenMem != 0) {\n return alternativeCreditsPerTokenMem;\n } else {\n return rebasingCreditsPerToken_;\n }\n }\n\n /**\n * @dev Auto migrate contracts to be non rebasing,\n * unless they have opted into yield.\n * @param _account Address of the account.\n */\n function _autoMigrate(address _account) internal {\n uint256 codeLen = _account.code.length;\n bool isEOA = (codeLen == 0) ||\n (codeLen == 23 && bytes3(_account.code) == 0xef0100);\n // In previous code versions, contracts would not have had their\n // rebaseState[_account] set to RebaseOptions.NonRebasing when migrated\n // therefore we check the actual accounting used on the account as well.\n if (\n (!isEOA) &&\n rebaseState[_account] == RebaseOptions.NotSet &&\n alternativeCreditsPerToken[_account] == 0\n ) {\n _rebaseOptOut(_account);\n }\n }\n\n /**\n * @dev Calculates credits from contract's global rebasingCreditsPerToken_, and\n * also balance that corresponds to those credits. The latter is important\n * when adjusting the contract's global nonRebasingSupply to circumvent any\n * possible rounding errors.\n *\n * @param _balance Balance of the account.\n */\n function _balanceToRebasingCredits(uint256 _balance)\n internal\n view\n returns (uint256 rebasingCredits)\n {\n // Rounds up, because we need to ensure that accounts always have\n // at least the balance that they should have.\n // Note this should always be used on an absolute account value,\n // not on a possibly negative diff, because then the rounding would be wrong.\n return ((_balance) * rebasingCreditsPerToken_ + 1e18 - 1) / 1e18;\n }\n\n /**\n * @notice The calling account will start receiving yield after a successful call.\n * @param _account Address of the account.\n */\n function governanceRebaseOptIn(address _account) external onlyGovernor {\n require(_account != address(0), \"Zero address not allowed\");\n _rebaseOptIn(_account);\n }\n\n /**\n * @notice The calling account will start receiving yield after a successful call.\n */\n function rebaseOptIn() external {\n _rebaseOptIn(msg.sender);\n }\n\n function _rebaseOptIn(address _account) internal {\n uint256 balance = balanceOf(_account);\n\n // prettier-ignore\n require(\n alternativeCreditsPerToken[_account] > 0 ||\n // Accounts may explicitly `rebaseOptIn` regardless of\n // accounting if they have a 0 balance.\n creditBalances[_account] == 0\n ,\n \"Account must be non-rebasing\"\n );\n RebaseOptions state = rebaseState[_account];\n // prettier-ignore\n require(\n state == RebaseOptions.StdNonRebasing ||\n state == RebaseOptions.NotSet,\n \"Only standard non-rebasing accounts can opt in\"\n );\n\n uint256 newCredits = _balanceToRebasingCredits(balance);\n\n // Account\n rebaseState[_account] = RebaseOptions.StdRebasing;\n alternativeCreditsPerToken[_account] = 0;\n creditBalances[_account] = newCredits;\n // Globals\n _adjustGlobals(newCredits.toInt256(), -balance.toInt256());\n\n emit AccountRebasingEnabled(_account);\n }\n\n /**\n * @notice The calling account will no longer receive yield\n */\n function rebaseOptOut() external {\n _rebaseOptOut(msg.sender);\n }\n\n function _rebaseOptOut(address _account) internal {\n require(\n alternativeCreditsPerToken[_account] == 0,\n \"Account must be rebasing\"\n );\n RebaseOptions state = rebaseState[_account];\n require(\n state == RebaseOptions.StdRebasing || state == RebaseOptions.NotSet,\n \"Only standard rebasing accounts can opt out\"\n );\n\n uint256 oldCredits = creditBalances[_account];\n uint256 balance = balanceOf(_account);\n\n // Account\n rebaseState[_account] = RebaseOptions.StdNonRebasing;\n alternativeCreditsPerToken[_account] = 1e18;\n creditBalances[_account] = balance;\n // Globals\n _adjustGlobals(-oldCredits.toInt256(), balance.toInt256());\n\n emit AccountRebasingDisabled(_account);\n }\n\n /**\n * @notice Distribute yield to users. This changes the exchange rate\n * between \"credits\" and OUSD tokens to change rebasing user's balances.\n * @param _newTotalSupply New total supply of OUSD.\n */\n function changeSupply(uint256 _newTotalSupply) external onlyVault {\n require(totalSupply > 0, \"Cannot increase 0 supply\");\n\n if (totalSupply == _newTotalSupply) {\n emit TotalSupplyUpdatedHighres(\n totalSupply,\n rebasingCredits_,\n rebasingCreditsPerToken_\n );\n return;\n }\n\n totalSupply = _newTotalSupply > MAX_SUPPLY\n ? MAX_SUPPLY\n : _newTotalSupply;\n\n uint256 rebasingSupply = totalSupply - nonRebasingSupply;\n // round up in the favour of the protocol\n rebasingCreditsPerToken_ =\n (rebasingCredits_ * 1e18 + rebasingSupply - 1) /\n rebasingSupply;\n\n require(rebasingCreditsPerToken_ > 0, \"Invalid change in supply\");\n\n emit TotalSupplyUpdatedHighres(\n totalSupply,\n rebasingCredits_,\n rebasingCreditsPerToken_\n );\n }\n\n /*\n * @notice Send the yield from one account to another account.\n * Each account keeps its own balances.\n */\n function delegateYield(address _from, address _to)\n external\n onlyGovernorOrStrategist\n {\n require(_from != address(0), \"Zero from address not allowed\");\n require(_to != address(0), \"Zero to address not allowed\");\n\n require(_from != _to, \"Cannot delegate to self\");\n require(\n yieldFrom[_to] == address(0) &&\n yieldTo[_to] == address(0) &&\n yieldFrom[_from] == address(0) &&\n yieldTo[_from] == address(0),\n \"Blocked by existing yield delegation\"\n );\n RebaseOptions stateFrom = rebaseState[_from];\n RebaseOptions stateTo = rebaseState[_to];\n\n require(\n stateFrom == RebaseOptions.NotSet ||\n stateFrom == RebaseOptions.StdNonRebasing ||\n stateFrom == RebaseOptions.StdRebasing,\n \"Invalid rebaseState from\"\n );\n\n require(\n stateTo == RebaseOptions.NotSet ||\n stateTo == RebaseOptions.StdNonRebasing ||\n stateTo == RebaseOptions.StdRebasing,\n \"Invalid rebaseState to\"\n );\n\n if (alternativeCreditsPerToken[_from] == 0) {\n _rebaseOptOut(_from);\n }\n if (alternativeCreditsPerToken[_to] > 0) {\n _rebaseOptIn(_to);\n }\n\n uint256 fromBalance = balanceOf(_from);\n uint256 toBalance = balanceOf(_to);\n uint256 oldToCredits = creditBalances[_to];\n uint256 newToCredits = _balanceToRebasingCredits(\n fromBalance + toBalance\n );\n\n // Set up the bidirectional links\n yieldTo[_from] = _to;\n yieldFrom[_to] = _from;\n\n // Local\n rebaseState[_from] = RebaseOptions.YieldDelegationSource;\n alternativeCreditsPerToken[_from] = 1e18;\n creditBalances[_from] = fromBalance;\n rebaseState[_to] = RebaseOptions.YieldDelegationTarget;\n creditBalances[_to] = newToCredits;\n\n // Global\n int256 creditsChange = newToCredits.toInt256() -\n oldToCredits.toInt256();\n _adjustGlobals(creditsChange, -(fromBalance).toInt256());\n emit YieldDelegated(_from, _to);\n }\n\n /*\n * @notice Stop sending the yield from one account to another account.\n */\n function undelegateYield(address _from) external onlyGovernorOrStrategist {\n // Require a delegation, which will also ensure a valid delegation\n require(yieldTo[_from] != address(0), \"Zero address not allowed\");\n\n address to = yieldTo[_from];\n uint256 fromBalance = balanceOf(_from);\n uint256 toBalance = balanceOf(to);\n uint256 oldToCredits = creditBalances[to];\n uint256 newToCredits = _balanceToRebasingCredits(toBalance);\n\n // Remove the bidirectional links\n yieldFrom[to] = address(0);\n yieldTo[_from] = address(0);\n\n // Local\n rebaseState[_from] = RebaseOptions.StdNonRebasing;\n // alternativeCreditsPerToken[from] already 1e18 from `delegateYield()`\n creditBalances[_from] = fromBalance;\n rebaseState[to] = RebaseOptions.StdRebasing;\n // alternativeCreditsPerToken[to] already 0 from `delegateYield()`\n creditBalances[to] = newToCredits;\n\n // Global\n int256 creditsChange = newToCredits.toInt256() -\n oldToCredits.toInt256();\n _adjustGlobals(creditsChange, fromBalance.toInt256());\n emit YieldUndelegated(_from, to);\n }\n}\n" + }, + "contracts/utils/BytesHelper.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nuint256 constant UINT32_LENGTH = 4;\nuint256 constant UINT64_LENGTH = 8;\nuint256 constant UINT256_LENGTH = 32;\n// Address is 20 bytes, but we expect the data to be padded with 0s to 32 bytes\nuint256 constant ADDRESS_LENGTH = 32;\n\nlibrary BytesHelper {\n /**\n * @dev Extract a slice from bytes memory\n * @param data The bytes memory to slice\n * @param start The start index (inclusive)\n * @param end The end index (exclusive)\n * @return result A new bytes memory containing the slice\n */\n function extractSlice(\n bytes memory data,\n uint256 start,\n uint256 end\n ) internal pure returns (bytes memory) {\n require(end >= start, \"Invalid slice range\");\n require(end <= data.length, \"Slice end exceeds data length\");\n\n uint256 length = end - start;\n bytes memory result = new bytes(length);\n\n // Simple byte-by-byte copy\n for (uint256 i = 0; i < length; i++) {\n result[i] = data[start + i];\n }\n\n return result;\n }\n\n /**\n * @dev Decode a uint32 from a bytes memory\n * @param data The bytes memory to decode\n * @return uint32 The decoded uint32\n */\n function decodeUint32(bytes memory data) internal pure returns (uint32) {\n require(data.length == 4, \"Invalid data length\");\n return uint32(uint256(bytes32(data)) >> 224);\n }\n\n /**\n * @dev Extract a uint32 from a bytes memory\n * @param data The bytes memory to extract from\n * @param start The start index (inclusive)\n * @return uint32 The extracted uint32\n */\n function extractUint32(bytes memory data, uint256 start)\n internal\n pure\n returns (uint32)\n {\n return decodeUint32(extractSlice(data, start, start + UINT32_LENGTH));\n }\n\n /**\n * @dev Decode an address from a bytes memory.\n * Expects the data to be padded with 0s to 32 bytes.\n * @param data The bytes memory to decode\n * @return address The decoded address\n */\n function decodeAddress(bytes memory data) internal pure returns (address) {\n // We expect the data to be padded with 0s, so length is 32 not 20\n require(data.length == 32, \"Invalid data length\");\n return abi.decode(data, (address));\n }\n\n /**\n * @dev Extract an address from a bytes memory\n * @param data The bytes memory to extract from\n * @param start The start index (inclusive)\n * @return address The extracted address\n */\n function extractAddress(bytes memory data, uint256 start)\n internal\n pure\n returns (address)\n {\n return decodeAddress(extractSlice(data, start, start + ADDRESS_LENGTH));\n }\n\n /**\n * @dev Decode a uint256 from a bytes memory\n * @param data The bytes memory to decode\n * @return uint256 The decoded uint256\n */\n function decodeUint256(bytes memory data) internal pure returns (uint256) {\n require(data.length == 32, \"Invalid data length\");\n return abi.decode(data, (uint256));\n }\n\n /**\n * @dev Extract a uint256 from a bytes memory\n * @param data The bytes memory to extract from\n * @param start The start index (inclusive)\n * @return uint256 The extracted uint256\n */\n function extractUint256(bytes memory data, uint256 start)\n internal\n pure\n returns (uint256)\n {\n return decodeUint256(extractSlice(data, start, start + UINT256_LENGTH));\n }\n}\n" + }, + "contracts/utils/Helpers.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\nimport { IBasicToken } from \"../interfaces/IBasicToken.sol\";\n\nlibrary Helpers {\n /**\n * @notice Fetch the `symbol()` from an ERC20 token\n * @dev Grabs the `symbol()` from a contract\n * @param _token Address of the ERC20 token\n * @return string Symbol of the ERC20 token\n */\n function getSymbol(address _token) internal view returns (string memory) {\n string memory symbol = IBasicToken(_token).symbol();\n return symbol;\n }\n\n /**\n * @notice Fetch the `decimals()` from an ERC20 token\n * @dev Grabs the `decimals()` from a contract and fails if\n * the decimal value does not live within a certain range\n * @param _token Address of the ERC20 token\n * @return uint256 Decimals of the ERC20 token\n */\n function getDecimals(address _token) internal view returns (uint256) {\n uint256 decimals = IBasicToken(_token).decimals();\n require(\n decimals >= 4 && decimals <= 18,\n \"Token must have sufficient decimal places\"\n );\n\n return decimals;\n }\n}\n" + }, + "contracts/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title Base contract any contracts that need to initialize state after deployment.\n * @author Origin Protocol Inc\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n */\n bool private initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private initializing;\n\n /**\n * @dev Modifier to protect an initializer function from being invoked twice.\n */\n modifier initializer() {\n require(\n initializing || !initialized,\n \"Initializable: contract is already initialized\"\n );\n\n bool isTopLevelCall = !initializing;\n if (isTopLevelCall) {\n initializing = true;\n initialized = true;\n }\n\n _;\n\n if (isTopLevelCall) {\n initializing = false;\n }\n }\n\n uint256[50] private ______gap;\n}\n" + }, + "contracts/utils/InitializableAbstractStrategy.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title Base contract for vault strategies.\n * @author Origin Protocol Inc\n */\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { Initializable } from \"../utils/Initializable.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { IVault } from \"../interfaces/IVault.sol\";\n\nabstract contract InitializableAbstractStrategy is Initializable, Governable {\n using SafeERC20 for IERC20;\n\n event PTokenAdded(address indexed _asset, address _pToken);\n event PTokenRemoved(address indexed _asset, address _pToken);\n event Deposit(address indexed _asset, address _pToken, uint256 _amount);\n event Withdrawal(address indexed _asset, address _pToken, uint256 _amount);\n event RewardTokenCollected(\n address recipient,\n address rewardToken,\n uint256 amount\n );\n event RewardTokenAddressesUpdated(\n address[] _oldAddresses,\n address[] _newAddresses\n );\n event HarvesterAddressesUpdated(\n address _oldHarvesterAddress,\n address _newHarvesterAddress\n );\n\n /// @notice Address of the underlying platform\n address public immutable platformAddress;\n /// @notice Address of the OToken vault\n address public immutable vaultAddress;\n\n /// @dev Replaced with an immutable variable\n // slither-disable-next-line constable-states\n address private _deprecated_platformAddress;\n\n /// @dev Replaced with an immutable\n // slither-disable-next-line constable-states\n address private _deprecated_vaultAddress;\n\n /// @notice asset => pToken (Platform Specific Token Address)\n mapping(address => address) public assetToPToken;\n\n /// @notice Full list of all assets supported by the strategy\n address[] internal assetsMapped;\n\n // Deprecated: Reward token address\n // slither-disable-next-line constable-states\n address private _deprecated_rewardTokenAddress;\n\n // Deprecated: now resides in Harvester's rewardTokenConfigs\n // slither-disable-next-line constable-states\n uint256 private _deprecated_rewardLiquidationThreshold;\n\n /// @notice Address of the Harvester contract allowed to collect reward tokens\n address public harvesterAddress;\n\n /// @notice Address of the reward tokens. eg CRV, BAL, CVX, AURA\n address[] public rewardTokenAddresses;\n\n /* Reserved for future expansion. Used to be 100 storage slots\n * and has decreased to accommodate:\n * - harvesterAddress\n * - rewardTokenAddresses\n */\n int256[98] private _reserved;\n\n struct BaseStrategyConfig {\n address platformAddress; // Address of the underlying platform\n address vaultAddress; // Address of the OToken's Vault\n }\n\n /**\n * @dev Verifies that the caller is the Governor or Strategist.\n */\n modifier onlyGovernorOrStrategist() virtual {\n require(\n isGovernor() || msg.sender == IVault(vaultAddress).strategistAddr(),\n \"Caller is not the Strategist or Governor\"\n );\n _;\n }\n\n /**\n * @param _config The platform and OToken vault addresses\n */\n constructor(BaseStrategyConfig memory _config) {\n platformAddress = _config.platformAddress;\n vaultAddress = _config.vaultAddress;\n }\n\n /**\n * @dev Internal initialize function, to set up initial internal state\n * @param _rewardTokenAddresses Address of reward token for platform\n * @param _assets Addresses of initial supported assets\n * @param _pTokens Platform Token corresponding addresses\n */\n function _initialize(\n address[] memory _rewardTokenAddresses,\n address[] memory _assets,\n address[] memory _pTokens\n ) internal {\n rewardTokenAddresses = _rewardTokenAddresses;\n\n uint256 assetCount = _assets.length;\n require(assetCount == _pTokens.length, \"Invalid input arrays\");\n for (uint256 i = 0; i < assetCount; ++i) {\n _setPTokenAddress(_assets[i], _pTokens[i]);\n }\n }\n\n /**\n * @notice Collect accumulated reward token and send to Vault.\n */\n function collectRewardTokens() external virtual onlyHarvester nonReentrant {\n _collectRewardTokens();\n }\n\n /**\n * @dev Default implementation that transfers reward tokens to the Harvester\n * Implementing strategies need to add custom logic to collect the rewards.\n */\n function _collectRewardTokens() internal virtual {\n uint256 rewardTokenCount = rewardTokenAddresses.length;\n for (uint256 i = 0; i < rewardTokenCount; ++i) {\n IERC20 rewardToken = IERC20(rewardTokenAddresses[i]);\n uint256 balance = rewardToken.balanceOf(address(this));\n if (balance > 0) {\n emit RewardTokenCollected(\n harvesterAddress,\n address(rewardToken),\n balance\n );\n rewardToken.safeTransfer(harvesterAddress, balance);\n }\n }\n }\n\n /**\n * @dev Verifies that the caller is the Vault.\n */\n modifier onlyVault() {\n require(msg.sender == vaultAddress, \"Caller is not the Vault\");\n _;\n }\n\n /**\n * @dev Verifies that the caller is the Harvester.\n */\n modifier onlyHarvester() {\n require(msg.sender == harvesterAddress, \"Caller is not the Harvester\");\n _;\n }\n\n /**\n * @dev Verifies that the caller is the Vault or Governor.\n */\n modifier onlyVaultOrGovernor() {\n require(\n msg.sender == vaultAddress || msg.sender == governor(),\n \"Caller is not the Vault or Governor\"\n );\n _;\n }\n\n /**\n * @dev Verifies that the caller is the Vault, Governor, or Strategist.\n */\n modifier onlyVaultOrGovernorOrStrategist() {\n require(\n msg.sender == vaultAddress ||\n msg.sender == governor() ||\n msg.sender == IVault(vaultAddress).strategistAddr(),\n \"Caller is not the Vault, Governor, or Strategist\"\n );\n _;\n }\n\n /**\n * @notice Set the reward token addresses. Any old addresses will be overwritten.\n * @param _rewardTokenAddresses Array of reward token addresses\n */\n function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses)\n external\n onlyGovernor\n {\n uint256 rewardTokenCount = _rewardTokenAddresses.length;\n for (uint256 i = 0; i < rewardTokenCount; ++i) {\n require(\n _rewardTokenAddresses[i] != address(0),\n \"Can not set an empty address as a reward token\"\n );\n }\n\n emit RewardTokenAddressesUpdated(\n rewardTokenAddresses,\n _rewardTokenAddresses\n );\n rewardTokenAddresses = _rewardTokenAddresses;\n }\n\n /**\n * @notice Get the reward token addresses.\n * @return address[] the reward token addresses.\n */\n function getRewardTokenAddresses()\n external\n view\n returns (address[] memory)\n {\n return rewardTokenAddresses;\n }\n\n /**\n * @notice Provide support for asset by passing its pToken address.\n * This method can only be called by the system Governor\n * @param _asset Address for the asset\n * @param _pToken Address for the corresponding platform token\n */\n function setPTokenAddress(address _asset, address _pToken)\n external\n virtual\n onlyGovernor\n {\n _setPTokenAddress(_asset, _pToken);\n }\n\n /**\n * @notice Remove a supported asset by passing its index.\n * This method can only be called by the system Governor\n * @param _assetIndex Index of the asset to be removed\n */\n function removePToken(uint256 _assetIndex) external virtual onlyGovernor {\n require(_assetIndex < assetsMapped.length, \"Invalid index\");\n address asset = assetsMapped[_assetIndex];\n address pToken = assetToPToken[asset];\n\n if (_assetIndex < assetsMapped.length - 1) {\n assetsMapped[_assetIndex] = assetsMapped[assetsMapped.length - 1];\n }\n assetsMapped.pop();\n assetToPToken[asset] = address(0);\n\n emit PTokenRemoved(asset, pToken);\n }\n\n /**\n * @notice Provide support for asset by passing its pToken address.\n * Add to internal mappings and execute the platform specific,\n * abstract method `_abstractSetPToken`\n * @param _asset Address for the asset\n * @param _pToken Address for the corresponding platform token\n */\n function _setPTokenAddress(address _asset, address _pToken) internal {\n require(assetToPToken[_asset] == address(0), \"pToken already set\");\n require(\n _asset != address(0) && _pToken != address(0),\n \"Invalid addresses\"\n );\n\n assetToPToken[_asset] = _pToken;\n assetsMapped.push(_asset);\n\n emit PTokenAdded(_asset, _pToken);\n\n _abstractSetPToken(_asset, _pToken);\n }\n\n /**\n * @notice Transfer token to governor. Intended for recovering tokens stuck in\n * strategy contracts, i.e. mistaken sends.\n * @param _asset Address for the asset\n * @param _amount Amount of the asset to transfer\n */\n function transferToken(address _asset, uint256 _amount)\n public\n virtual\n onlyGovernor\n {\n require(!supportsAsset(_asset), \"Cannot transfer supported asset\");\n IERC20(_asset).safeTransfer(governor(), _amount);\n }\n\n /**\n * @notice Set the Harvester contract that can collect rewards.\n * @param _harvesterAddress Address of the harvester contract.\n */\n function setHarvesterAddress(address _harvesterAddress)\n external\n onlyGovernor\n {\n emit HarvesterAddressesUpdated(harvesterAddress, _harvesterAddress);\n harvesterAddress = _harvesterAddress;\n }\n\n /***************************************\n Abstract\n ****************************************/\n\n function _abstractSetPToken(address _asset, address _pToken)\n internal\n virtual;\n\n function safeApproveAllTokens() external virtual;\n\n /**\n * @notice Deposit an amount of assets into the platform\n * @param _asset Address for the asset\n * @param _amount Units of asset to deposit\n */\n function deposit(address _asset, uint256 _amount) external virtual;\n\n /**\n * @notice Deposit all supported assets in this strategy contract to the platform\n */\n function depositAll() external virtual;\n\n /**\n * @notice Withdraw an `amount` of assets from the platform and\n * send to the `_recipient`.\n * @param _recipient Address to which the asset should be sent\n * @param _asset Address of the asset\n * @param _amount Units of asset to withdraw\n */\n function withdraw(\n address _recipient,\n address _asset,\n uint256 _amount\n ) external virtual;\n\n /**\n * @notice Withdraw all supported assets from platform and\n * sends to the OToken's Vault.\n */\n function withdrawAll() external virtual;\n\n /**\n * @notice Get the total asset value held in the platform.\n * This includes any interest that was generated since depositing.\n * @param _asset Address of the asset\n * @return balance Total value of the asset in the platform\n */\n function checkBalance(address _asset)\n external\n view\n virtual\n returns (uint256 balance);\n\n /**\n * @notice Check if an asset is supported.\n * @param _asset Address of the asset\n * @return bool Whether asset is supported\n */\n function supportsAsset(address _asset) public view virtual returns (bool);\n}\n" + }, + "contracts/vault/VaultStorage.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\npragma solidity ^0.8.0;\n\n/**\n * @title OToken VaultStorage contract\n * @notice The VaultStorage contract defines the storage for the Vault contracts\n * @author Origin Protocol Inc\n */\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\nimport { IStrategy } from \"../interfaces/IStrategy.sol\";\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { Governable } from \"../governance/Governable.sol\";\nimport { OUSD } from \"../token/OUSD.sol\";\nimport { Initializable } from \"../utils/Initializable.sol\";\nimport \"../utils/Helpers.sol\";\n\nabstract contract VaultStorage is Initializable, Governable {\n using SafeERC20 for IERC20;\n\n event AssetAllocated(address _asset, address _strategy, uint256 _amount);\n event StrategyApproved(address _addr);\n event StrategyRemoved(address _addr);\n event Mint(address _addr, uint256 _value);\n event Redeem(address _addr, uint256 _value);\n event CapitalPaused();\n event CapitalUnpaused();\n event DefaultStrategyUpdated(address _strategy);\n event RebasePaused();\n event RebaseUnpaused();\n event VaultBufferUpdated(uint256 _vaultBuffer);\n event AllocateThresholdUpdated(uint256 _threshold);\n event RebaseThresholdUpdated(uint256 _threshold);\n event StrategistUpdated(address _address);\n event MaxSupplyDiffChanged(uint256 maxSupplyDiff);\n event YieldDistribution(address _to, uint256 _yield, uint256 _fee);\n event TrusteeFeeBpsChanged(uint256 _basis);\n event TrusteeAddressChanged(address _address);\n event StrategyAddedToMintWhitelist(address indexed strategy);\n event StrategyRemovedFromMintWhitelist(address indexed strategy);\n event RebasePerSecondMaxChanged(uint256 rebaseRatePerSecond);\n event DripDurationChanged(uint256 dripDuration);\n event WithdrawalRequested(\n address indexed _withdrawer,\n uint256 indexed _requestId,\n uint256 _amount,\n uint256 _queued\n );\n event WithdrawalClaimed(\n address indexed _withdrawer,\n uint256 indexed _requestId,\n uint256 _amount\n );\n event WithdrawalClaimable(uint256 _claimable, uint256 _newClaimable);\n event WithdrawalClaimDelayUpdated(uint256 _newDelay);\n\n // Since we are proxy, all state should be uninitalized.\n // Since this storage contract does not have logic directly on it\n // we should not be checking for to see if these variables can be constant.\n // slither-disable-start uninitialized-state\n // slither-disable-start constable-states\n\n /// @dev mapping of supported vault assets to their configuration\n uint256 private _deprecated_assets;\n /// @dev list of all assets supported by the vault.\n address[] private _deprecated_allAssets;\n\n // Strategies approved for use by the Vault\n struct Strategy {\n bool isSupported;\n uint256 _deprecated; // Deprecated storage slot\n }\n /// @dev mapping of strategy contracts to their configuration\n mapping(address => Strategy) public strategies;\n /// @dev list of all vault strategies\n address[] internal allStrategies;\n\n /// @notice Address of the Oracle price provider contract\n address private _deprecated_priceProvider;\n /// @notice pause rebasing if true\n bool public rebasePaused;\n /// @notice pause operations that change the OToken supply.\n /// eg mint, redeem, allocate, mint/burn for strategy\n bool public capitalPaused;\n /// @notice Redemption fee in basis points. eg 50 = 0.5%\n uint256 private _deprecated_redeemFeeBps;\n /// @notice Percentage of assets to keep in Vault to handle (most) withdrawals. 100% = 1e18.\n uint256 public vaultBuffer;\n /// @notice OToken mints over this amount automatically allocate funds. 18 decimals.\n uint256 public autoAllocateThreshold;\n /// @notice OToken mints over this amount automatically rebase. 18 decimals.\n uint256 public rebaseThreshold;\n\n /// @dev Address of the OToken token. eg OUSD or OETH.\n OUSD public oToken;\n\n /// @dev Address of the contract responsible for post rebase syncs with AMMs\n address private _deprecated_rebaseHooksAddr = address(0);\n\n /// @dev Deprecated: Address of Uniswap\n address private _deprecated_uniswapAddr = address(0);\n\n /// @notice Address of the Strategist\n address public strategistAddr = address(0);\n\n /// @notice Mapping of asset address to the Strategy that they should automatically\n // be allocated to\n uint256 private _deprecated_assetDefaultStrategies;\n\n /// @notice Max difference between total supply and total value of assets. 18 decimals.\n uint256 public maxSupplyDiff;\n\n /// @notice Trustee contract that can collect a percentage of yield\n address public trusteeAddress;\n\n /// @notice Amount of yield collected in basis points. eg 2000 = 20%\n uint256 public trusteeFeeBps;\n\n /// @dev Deprecated: Tokens that should be swapped for stablecoins\n address[] private _deprecated_swapTokens;\n\n /// @notice Metapool strategy that is allowed to mint/burn OTokens without changing collateral\n\n address private _deprecated_ousdMetaStrategy;\n\n /// @notice How much OTokens are currently minted by the strategy\n int256 private _deprecated_netOusdMintedForStrategy;\n\n /// @notice How much net total OTokens are allowed to be minted by all strategies\n uint256 private _deprecated_netOusdMintForStrategyThreshold;\n\n uint256 private _deprecated_swapConfig;\n\n // List of strategies that can mint oTokens directly\n // Used in OETHBaseVaultCore\n mapping(address => bool) public isMintWhitelistedStrategy;\n\n /// @notice Address of the Dripper contract that streams harvested rewards to the Vault\n /// @dev The vault is proxied so needs to be set with setDripper against the proxy contract.\n address private _deprecated_dripper;\n\n /// Withdrawal Queue Storage /////\n\n struct WithdrawalQueueMetadata {\n // cumulative total of all withdrawal requests included the ones that have already been claimed\n uint128 queued;\n // cumulative total of all the requests that can be claimed including the ones that have already been claimed\n uint128 claimable;\n // total of all the requests that have been claimed\n uint128 claimed;\n // index of the next withdrawal request starting at 0\n uint128 nextWithdrawalIndex;\n }\n\n /// @notice Global metadata for the withdrawal queue including:\n /// queued - cumulative total of all withdrawal requests included the ones that have already been claimed\n /// claimable - cumulative total of all the requests that can be claimed including the ones already claimed\n /// claimed - total of all the requests that have been claimed\n /// nextWithdrawalIndex - index of the next withdrawal request starting at 0\n WithdrawalQueueMetadata public withdrawalQueueMetadata;\n\n struct WithdrawalRequest {\n address withdrawer;\n bool claimed;\n uint40 timestamp; // timestamp of the withdrawal request\n // Amount of oTokens to redeem. eg OETH\n uint128 amount;\n // cumulative total of all withdrawal requests including this one.\n // this request can be claimed when this queued amount is less than or equal to the queue's claimable amount.\n uint128 queued;\n }\n\n /// @notice Mapping of withdrawal request indices to the user withdrawal request data\n mapping(uint256 => WithdrawalRequest) public withdrawalRequests;\n\n /// @notice Sets a minimum delay that is required to elapse between\n /// requesting async withdrawals and claiming the request.\n /// When set to 0 async withdrawals are disabled.\n uint256 public withdrawalClaimDelay;\n\n /// @notice Time in seconds that the vault last rebased yield.\n uint64 public lastRebase;\n\n /// @notice Automatic rebase yield calculations. In seconds. Set to 0 or 1 to disable.\n uint64 public dripDuration;\n\n /// @notice max rebase percentage per second\n /// Can be used to set maximum yield of the protocol,\n /// spreading out yield over time\n uint64 public rebasePerSecondMax;\n\n /// @notice target rebase rate limit, based on past rates and funds available.\n uint64 public rebasePerSecondTarget;\n\n uint256 internal constant MAX_REBASE = 0.02 ether;\n uint256 internal constant MAX_REBASE_PER_SECOND =\n uint256(0.05 ether) / 1 days;\n\n /// @notice Default strategy for asset\n address public defaultStrategy;\n\n // For future use\n uint256[42] private __gap;\n\n /// @notice Index of WETH asset in allAssets array\n /// Legacy OETHVaultCore code, relocated here for vault consistency.\n uint256 private _deprecated_wethAssetIndex;\n\n /// @dev Address of the asset (eg. WETH or USDC)\n address public immutable asset;\n uint8 internal immutable assetDecimals;\n\n // slither-disable-end constable-states\n // slither-disable-end uninitialized-state\n\n constructor(address _asset) {\n uint8 _decimals = IERC20Metadata(_asset).decimals();\n require(_decimals <= 18, \"invalid asset decimals\");\n asset = _asset;\n assetDecimals = _decimals;\n }\n\n /// @notice Deprecated: use `oToken()` instead.\n function oUSD() external view returns (OUSD) {\n return oToken;\n }\n}\n" + }, + "lib/openzeppelin/interfaces/IERC4626.sol": { + "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IERC4626 is IERC20, IERC20Metadata {\n event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);\n\n event Withdraw(\n address indexed caller,\n address indexed receiver,\n address indexed owner,\n uint256 assets,\n uint256 shares\n );\n\n /**\n * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n *\n * - MUST be an ERC-20 token contract.\n * - MUST NOT revert.\n */\n function asset() external view returns (address assetTokenAddress);\n\n /**\n * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n *\n * - SHOULD include any compounding that occurs from yield.\n * - MUST be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT revert.\n */\n function totalAssets() external view returns (uint256 totalManagedAssets);\n\n /**\n * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n * scenario where all the conditions are met.\n *\n * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n * - MUST NOT show any variations depending on the caller.\n * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n * - MUST NOT revert.\n *\n * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n * from.\n */\n function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n * through a deposit call.\n *\n * - MUST return a limited value if receiver is subject to some deposit limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n * - MUST NOT revert.\n */\n function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n * call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n * in the same transaction.\n * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n * deposit would be accepted, regardless if the user has enough tokens approved, etc.\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n */\n function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n *\n * - MUST emit the Deposit event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * deposit execution, and are accounted for during deposit.\n * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n * approving enough underlying tokens to the Vault contract, etc).\n *\n * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n */\n function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n /**\n * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n * - MUST return a limited value if receiver is subject to some mint limit.\n * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n * - MUST NOT revert.\n */\n function maxMint(address receiver) external view returns (uint256 maxShares);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n * current on-chain conditions.\n *\n * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n * in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n * same transaction.\n * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n * would be accepted, regardless if the user has enough tokens approved, etc.\n * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by minting.\n */\n function previewMint(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n *\n * - MUST emit the Deposit event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n * execution, and are accounted for during mint.\n * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n * approving enough underlying tokens to the Vault contract, etc).\n *\n * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n */\n function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n /**\n * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n * Vault, through a withdraw call.\n *\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n * - MUST NOT revert.\n */\n function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n * given current on-chain conditions.\n *\n * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n * call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n * called\n * in the same transaction.\n * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n * the withdrawal would be accepted, regardless if the user has enough shares, etc.\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n */\n function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n /**\n * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n *\n * - MUST emit the Withdraw event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * withdraw execution, and are accounted for during withdraw.\n * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n * not having enough shares, etc).\n *\n * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n * Those methods should be performed separately.\n */\n function withdraw(\n uint256 assets,\n address receiver,\n address owner\n ) external returns (uint256 shares);\n\n /**\n * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n * through a redeem call.\n *\n * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n * - MUST NOT revert.\n */\n function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n /**\n * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n * given current on-chain conditions.\n *\n * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n * in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n * same transaction.\n * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n * redemption would be accepted, regardless if the user has enough shares, etc.\n * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n * - MUST NOT revert.\n *\n * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n */\n function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n /**\n * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n *\n * - MUST emit the Withdraw event.\n * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n * redeem execution, and are accounted for during redeem.\n * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n * not having enough shares, etc).\n *\n * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n * Those methods should be performed separately.\n */\n function redeem(\n uint256 shares,\n address receiver,\n address owner\n ) external returns (uint256 assets);\n}" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "paris", + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/contracts/storageLayout/mainnet/MorphoV2Strategy.json b/contracts/storageLayout/mainnet/MorphoV2Strategy.json new file mode 100644 index 0000000000..f17d80f9bf --- /dev/null +++ b/contracts/storageLayout/mainnet/MorphoV2Strategy.json @@ -0,0 +1,160 @@ +{ + "solcVersion": "0.8.28", + "storage": [ + { + "label": "initialized", + "offset": 0, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "contracts/utils/Initializable.sol:12" + }, + { + "label": "initializing", + "offset": 1, + "slot": "0", + "type": "t_bool", + "contract": "Initializable", + "src": "contracts/utils/Initializable.sol:17" + }, + { + "label": "______gap", + "offset": 0, + "slot": "1", + "type": "t_array(t_uint256)50_storage", + "contract": "Initializable", + "src": "contracts/utils/Initializable.sol:41" + }, + { + "label": "_deprecated_platformAddress", + "offset": 0, + "slot": "51", + "type": "t_address", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:43" + }, + { + "label": "_deprecated_vaultAddress", + "offset": 0, + "slot": "52", + "type": "t_address", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:47" + }, + { + "label": "assetToPToken", + "offset": 0, + "slot": "53", + "type": "t_mapping(t_address,t_address)", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:50" + }, + { + "label": "assetsMapped", + "offset": 0, + "slot": "54", + "type": "t_array(t_address)dyn_storage", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:53" + }, + { + "label": "_deprecated_rewardTokenAddress", + "offset": 0, + "slot": "55", + "type": "t_address", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:57" + }, + { + "label": "_deprecated_rewardLiquidationThreshold", + "offset": 0, + "slot": "56", + "type": "t_uint256", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:61" + }, + { + "label": "harvesterAddress", + "offset": 0, + "slot": "57", + "type": "t_address", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:64" + }, + { + "label": "rewardTokenAddresses", + "offset": 0, + "slot": "58", + "type": "t_array(t_address)dyn_storage", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:67" + }, + { + "label": "_reserved", + "offset": 0, + "slot": "59", + "type": "t_array(t_int256)98_storage", + "contract": "InitializableAbstractStrategy", + "src": "contracts/utils/InitializableAbstractStrategy.sol:74" + }, + { + "label": "_deprecate_shareToken", + "offset": 0, + "slot": "157", + "type": "t_address", + "contract": "Generalized4626Strategy", + "src": "contracts/strategies/Generalized4626Strategy.sol:23" + }, + { + "label": "_deprecate_assetToken", + "offset": 0, + "slot": "158", + "type": "t_address", + "contract": "Generalized4626Strategy", + "src": "contracts/strategies/Generalized4626Strategy.sol:26" + }, + { + "label": "__gap", + "offset": 0, + "slot": "159", + "type": "t_array(t_uint256)50_storage", + "contract": "Generalized4626Strategy", + "src": "contracts/strategies/Generalized4626Strategy.sol:32" + } + ], + "types": { + "t_address": { + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_address)dyn_storage": { + "label": "address[]", + "numberOfBytes": "32" + }, + "t_array(t_int256)98_storage": { + "label": "int256[98]", + "numberOfBytes": "3136" + }, + "t_array(t_uint256)50_storage": { + "label": "uint256[50]", + "numberOfBytes": "1600" + }, + "t_bool": { + "label": "bool", + "numberOfBytes": "1" + }, + "t_int256": { + "label": "int256", + "numberOfBytes": "32" + }, + "t_mapping(t_address,t_address)": { + "label": "mapping(address => address)", + "numberOfBytes": "32" + }, + "t_uint256": { + "label": "uint256", + "numberOfBytes": "32" + } + }, + "namespaces": {} +} \ No newline at end of file