From 6b0d73d16c7ff7e73f47bf951cc120d239379b7e Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Thu, 5 Mar 2026 23:44:17 +0100 Subject: [PATCH 1/2] upgrade cross-chain remote strategy --- ...te.js => 046_crosschain_upgrade_remote.js} | 2 +- contracts/deployments/base/.migrations.json | 3 +- .../base/CrossChainRemoteStrategy.json | 87 +++++++----- ...046_crosschain_upgrade_remote.execute.json | 52 +++++++ ...46_crosschain_upgrade_remote.schedule.json | 57 ++++++++ .../ca5c08626bc4341b9af4973050a80d7d.json | 132 ++++++++++++++++++ .../base/CrossChainRemoteStrategy.json | 6 +- 7 files changed, 296 insertions(+), 43 deletions(-) rename contracts/deploy/base/{045_crosschain_upgrade_remote.js => 046_crosschain_upgrade_remote.js} (96%) create mode 100644 contracts/deployments/base/operations/046_crosschain_upgrade_remote.execute.json create mode 100644 contracts/deployments/base/operations/046_crosschain_upgrade_remote.schedule.json create mode 100644 contracts/deployments/base/solcInputs/ca5c08626bc4341b9af4973050a80d7d.json diff --git a/contracts/deploy/base/045_crosschain_upgrade_remote.js b/contracts/deploy/base/046_crosschain_upgrade_remote.js similarity index 96% rename from contracts/deploy/base/045_crosschain_upgrade_remote.js rename to contracts/deploy/base/046_crosschain_upgrade_remote.js index c0fcf4179d..ccd98c9c31 100644 --- a/contracts/deploy/base/045_crosschain_upgrade_remote.js +++ b/contracts/deploy/base/046_crosschain_upgrade_remote.js @@ -8,7 +8,7 @@ const { cctpDomainIds } = require("../../utils/cctp"); module.exports = deployOnBase( { - deployName: "045_crosschain_upgrade_remote", + deployName: "046_crosschain_upgrade_remote", }, async () => { const crossChainStrategyProxyAddress = await getCreate2ProxyAddress( diff --git a/contracts/deployments/base/.migrations.json b/contracts/deployments/base/.migrations.json index 3241cc4e1d..45a4061b3e 100644 --- a/contracts/deployments/base/.migrations.json +++ b/contracts/deployments/base/.migrations.json @@ -42,5 +42,6 @@ "042_crosschain_strategy": 1770807435, "043_change_crosschain_strategy_operator": 1771403173, "044_bridge_helper_module": 1772010908, - "045_deploy_pool_booster_merkl_factory": 1772622327 + "045_deploy_pool_booster_merkl_factory": 1772622327, + "046_crosschain_upgrade_remote": 1772750064 } \ No newline at end of file diff --git a/contracts/deployments/base/CrossChainRemoteStrategy.json b/contracts/deployments/base/CrossChainRemoteStrategy.json index 4316962618..068ec5e568 100644 --- a/contracts/deployments/base/CrossChainRemoteStrategy.json +++ b/contracts/deployments/base/CrossChainRemoteStrategy.json @@ -1,5 +1,5 @@ { - "address": "0x5F81a5a22375ebCC2075b162D23a5b16a1e7A92d", + "address": "0xAA8af8Db4B6a827B51786334d26349eb03569731", "abi": [ { "inputs": [ @@ -61,6 +61,17 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "address", + "name": "adapter", + "type": "address" + } + ], + "name": "IncompatibleAdapter", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -1234,19 +1245,19 @@ "type": "function" } ], - "transactionHash": "0xf13e92fc9595d4cc5bb89ab82a2eea1ba9f5b3d2f607cbadce42bb77021d6c9c", + "transactionHash": "0x3d63006cd702c424d45fec41b84e6d703b23340d6bb78430c4fc55b71e5c2dc7", "receipt": { "to": null, - "from": "0x58890A9cB27586E83Cb51d2d26bbE18a1a647245", - "contractAddress": "0x5F81a5a22375ebCC2075b162D23a5b16a1e7A92d", - "transactionIndex": 192, - "gasUsed": "4435260", + "from": "0xDba474FeF81bc7475f70e28DFC12410f032A83Db", + "contractAddress": "0xAA8af8Db4B6a827B51786334d26349eb03569731", + "transactionIndex": 92, + "gasUsed": "4554942", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x9605b0b017bf2b3c188e18e008567a6c90953a43546329882b5fca93e13ad8b4", - "transactionHash": "0xf13e92fc9595d4cc5bb89ab82a2eea1ba9f5b3d2f607cbadce42bb77021d6c9c", + "blockHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "transactionHash": "0x3d63006cd702c424d45fec41b84e6d703b23340d6bb78430c4fc55b71e5c2dc7", "logs": [], - "blockNumber": 41974179, - "cumulativeGasUsed": "39029825", + "blockNumber": 42980346, + "cumulativeGasUsed": "21781270", "status": 1, "byzantium": true }, @@ -1264,11 +1275,11 @@ "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" ] ], - "numDeployments": 1, - "solcInputHash": "00a8ab5ddcdb46bc9891a2222be9eb31", - "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\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"cctpTokenMessenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cctpMessageTransmitter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"peerDomainID\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"peerStrategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"usdcToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"peerUsdcToken\",\"type\":\"address\"}],\"internalType\":\"struct AbstractCCTPIntegrator.CCTPIntegrationConfig\",\"name\":\"_cctpConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"feePremiumBps\",\"type\":\"uint16\"}],\"name\":\"CCTPFeePremiumBpsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minFinalityThreshold\",\"type\":\"uint16\"}],\"name\":\"CCTPMinFinalityThresholdSet\",\"type\":\"event\"},{\"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\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"DepositUnderlyingFailed\",\"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\":false,\"internalType\":\"uint64\",\"name\":\"lastTransferNonce\",\"type\":\"uint64\"}],\"name\":\"LastTransferNonceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"peerStrategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"minFinalityThreshold\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"MessageTransmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"NonceProcessed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"OperatorChanged\",\"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\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"peerStrategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"minFinalityThreshold\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"hookData\",\"type\":\"bytes\"}],\"name\":\"TokensBridged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"WithdrawUnderlyingFailed\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountRequested\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountAvailable\",\"type\":\"uint256\"}],\"name\":\"WithdrawalFailed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TRANSFER_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_TRANSFER_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":[],\"name\":\"cctpMessageTransmitter\",\"outputs\":[{\"internalType\":\"contract ICCTPMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cctpTokenMessenger\",\"outputs\":[{\"internalType\":\"contract ICCTPTokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"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\":\"feePremiumBps\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"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\":[{\"internalType\":\"uint32\",\"name\":\"sourceDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"finalityThresholdExecuted\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"handleReceiveFinalizedMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"sourceDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"finalityThresholdExecuted\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"handleReceiveUnfinalizedMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"harvesterAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategist\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_minFinalityThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"_feePremiumBps\",\"type\":\"uint16\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"isNonceProcessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTransferPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTransferNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"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\":\"minFinalityThreshold\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"peerDomainID\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"peerStrategy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"peerUsdcToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"platformAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attestation\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":[],\"name\":\"sendBalanceUpdate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_feePremiumBps\",\"type\":\"uint16\"}],\"name\":\"setFeePremiumBps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_harvesterAddress\",\"type\":\"address\"}],\"name\":\"setHarvesterAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_minFinalityThreshold\",\"type\":\"uint16\"}],\"name\":\"setMinFinalityThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"setOperator\",\"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\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setStrategistAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shareToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"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\":\"usdcToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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\":{\"_0\":\"balance Total value of the asset in the platform and contract\"}},\"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.\"}},\"handleReceiveFinalizedMessage(uint32,bytes32,uint32,bytes)\":{\"details\":\"Handles a finalized CCTP message\",\"params\":{\"finalityThresholdExecuted\":\"Fidelity threshold executed\",\"messageBody\":\"Message body\",\"sender\":\"Sender of the message\",\"sourceDomain\":\"Source domain of the message\"}},\"handleReceiveUnfinalizedMessage(uint32,bytes32,uint32,bytes)\":{\"details\":\"Handles an unfinalized but safe CCTP message\",\"params\":{\"finalityThresholdExecuted\":\"Fidelity threshold executed\",\"messageBody\":\"Message body\",\"sender\":\"Sender of the message\",\"sourceDomain\":\"Source domain of the message\"}},\"initialize(address,address,uint16,uint16)\":{\"details\":\"Initialize the strategy implementation\",\"params\":{\"_feePremiumBps\":\"Fee premium in basis points\",\"_minFinalityThreshold\":\"Minimum finality threshold\",\"_operator\":\"Address of the operator\",\"_strategist\":\"Address of the strategist\"}},\"isNonceProcessed(uint64)\":{\"details\":\"Checks if a given nonce is processed. Nonce starts at 1, so 0 is disregarded.\",\"params\":{\"nonce\":\"Nonce to check\"},\"returns\":{\"_0\":\"True if the nonce is processed, false otherwise\"}},\"isTransferPending()\":{\"details\":\"Checks if the last known transfer is pending. Nonce starts at 1, so 0 is disregarded.\",\"returns\":{\"_0\":\"True if a transfer is pending, false otherwise\"}},\"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.\"}},\"relay(bytes,bytes)\":{\"details\":\"Receives a message from the peer strategy on the other chain, does some basic checks and relays it to the local MessageTransmitterV2. If the message is a burn message, it will also handle the hook data and call the _onTokenReceived function.\",\"params\":{\"attestation\":\"Attestation of the message\",\"message\":\"Payload of the message to send\"}},\"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.\"},\"sendBalanceUpdate()\":{\"details\":\"Send balance update message to the peer strategy\"},\"setFeePremiumBps(uint16)\":{\"details\":\"Set the fee premium in basis points. Cannot be higher than 30% (3000 basis points).\",\"params\":{\"_feePremiumBps\":\"Fee premium in basis points\"}},\"setHarvesterAddress(address)\":{\"params\":{\"_harvesterAddress\":\"Address of the harvester contract.\"}},\"setMinFinalityThreshold(uint16)\":{\"details\":\"Set the minimum finality threshold at which the message is considered to be finalized to relay. Only accepts a value of 1000 (Safe, after 1 epoch) or 2000 (Finalized, after 2 epochs).\",\"params\":{\"_minFinalityThreshold\":\"Minimum finality threshold\"}},\"setOperator(address)\":{\"details\":\"Set the operator address\",\"params\":{\"_operator\":\"Operator address\"}},\"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\"}},\"setStrategistAddr(address)\":{\"details\":\"Set address of Strategist\",\"params\":{\"_address\":\"Address of Strategist\"}},\"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\":\"Interface requires a recipient, but for compatibility it must be address(this).\",\"params\":{\"_amount\":\"Amount of asset to withdraw\",\"_asset\":\"Address of asset to withdraw\",\"_recipient\":\"Address to receive withdrawn asset\"}},\"withdrawAll()\":{\"details\":\"Remove all assets from platform and send them to Vault contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MAX_TRANSFER_AMOUNT()\":{\"notice\":\"Max transfer threshold imposed by the CCTP Ref: https://developers.circle.com/cctp/evm-smart-contracts#depositforburn\"},\"MIN_TRANSFER_AMOUNT()\":{\"notice\":\"Minimum transfer amount to avoid zero or dust transfers\"},\"assetToPToken(address)\":{\"notice\":\"asset => pToken (Platform Specific Token Address)\"},\"cctpMessageTransmitter()\":{\"notice\":\"CCTP message transmitter contract\"},\"cctpTokenMessenger()\":{\"notice\":\"CCTP token messenger contract\"},\"checkBalance(address)\":{\"notice\":\"Get the total asset value held in the platform and contract\"},\"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.\"},\"feePremiumBps()\":{\"notice\":\"Fee premium in basis points\"},\"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.\"},\"lastTransferNonce()\":{\"notice\":\"Nonce of the last known deposit or withdrawal\"},\"merkleClaim(address,uint256,bytes32[])\":{\"notice\":\"Claim tokens from the Merkle Distributor\"},\"merkleDistributor()\":{\"notice\":\"The address of the Merkle Distributor contract.\"},\"minFinalityThreshold()\":{\"notice\":\"Minimum finality threshold Can be 1000 (safe, after 1 epoch) or 2000 (finalized, after 2 epochs). Ref: https://developers.circle.com/cctp/technical-guide#finality-thresholds\"},\"operator()\":{\"notice\":\"Operator address: Can relay CCTP messages\"},\"peerDomainID()\":{\"notice\":\"Domain ID of the chain from which messages are accepted\"},\"peerStrategy()\":{\"notice\":\"Strategy address on other chain\"},\"peerUsdcToken()\":{\"notice\":\"USDC address on remote chain\"},\"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.\"},\"usdcToken()\":{\"notice\":\"USDC address on local chain\"},\"vaultAddress()\":{\"notice\":\"Address of the OToken vault\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/strategies/crosschain/CrossChainRemoteStrategy.sol\":\"CrossChainRemoteStrategy\"},\"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/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/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\",\"keccak256\":\"0x9989400db5353221a725dd76a8b18c27e5c0b24c4732f3bb1e9324640a53290b\",\"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(\\n address _asset,\\n uint256 _amount,\\n uint256 _minimumOusdAmount\\n ) external;\\n\\n function mintForStrategy(uint256 _amount) external;\\n\\n function redeem(uint256 _amount, uint256 _minimumUnitAmount) 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 /// @notice Deprecated: use calculateRedeemOutput\\n function calculateRedeemOutputs(uint256 _amount)\\n external\\n view\\n returns (uint256[] memory);\\n\\n function calculateRedeemOutput(uint256 _amount)\\n external\\n view\\n 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 dripper() external view returns (address);\\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 function weth() external view returns (address);\\n\\n // slither-disable-end constable-states\\n}\\n\",\"keccak256\":\"0x61e2ad6f41abac69275ba86e51d9d3cd95dfd6fc6b81960cf75b1e06adb6251d\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0x67c60863105b4a694bc6edc77777560120262fd4f883a5bbece53f0c70d88e7b\",\"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 * @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 uint256 shareBalance = shareToken.balanceOf(address(this));\\n uint256 assetAmount = 0;\\n if (shareBalance > 0) {\\n assetAmount = IERC4626(platformAddress).redeem(\\n shareBalance,\\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\":\"0xf03f2e6ad89700985bfa22a6bafd30eccee765fd6cad97e272f983085ff9c7a0\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0x25f8398d7225b832a4d633e7478743272de704293210a2edf13c156bd1c6a9f0\",\"license\":\"BUSL-1.1\"},\"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 { IERC20 } from \\\"../../utils/InitializableAbstractStrategy.sol\\\";\\nimport { IERC4626 } from \\\"../../../lib/openzeppelin/interfaces/IERC4626.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\\\";\\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 _withdraw(\\n address(this),\\n usdcToken,\\n platform.previewRedeem(platform.balanceOf(address(this)))\\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\",\"keccak256\":\"0x2a216504cf878c7d92ef2f0f3f697ca2e75f3f8c077f6d6b8720bb99281c8c6c\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0xbe640419f622ed08d59c10f3ce206a015c524eaa2543c8882ff55a0cea4c6297\",\"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/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\",\"keccak256\":\"0x471aff77f4b6750abd8ed018fa3e89707f045ae377c73b225d413d62c1e9b28f\",\"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": "0x6101c060405234801561001157600080fd5b506040516158a13803806158a18339810160408190526100309161066a565b6080810151829081836001600160a01b0383166100945760405162461bcd60e51b815260206004820152601460248201527f496e76616c69642055534443206164647265737300000000000000000000000060448201526064015b60405180910390fd5b60a08101516001600160a01b03166100ee5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420706565722055534443206164647265737300000000000000604482015260640161008b565b80516001600160a01b031661013b5760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964204343545020636f6e66696760681b604482015260640161008b565b60208101516001600160a01b031661018b5760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964204343545020636f6e66696760681b604482015260640161008b565b60608101516001600160a01b03166101e55760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420706565722073747261746567792061646472657373000000604482015260640161008b565b60208101516001600160a01b0390811660809081528251821660a052604083015163ffffffff166101005260608301518216610120528201805190911660c052516000906102329061046d565b90506000610249836080015161054d60201b60201c565b90508160061461029b5760405162461bcd60e51b815260206004820152601d60248201527f4261736520746f6b656e20646563696d616c73206d7573742062652036000000604482015260640161008b565b604051635553444360e01b602082015260240160405160208183030381529060405280519060200120816040516020016102d5919061076b565b60405160208183030381529060405280519060200120146103385760405162461bcd60e51b815260206004820152601960248201527f546f6b656e2073796d626f6c206d757374206265205553444300000000000000604482015260640161008b565b505060a001516001600160a01b0390811660e0528151811661014052602090910151811661016052915182166101805281166101a081905260c051909116146103b45760405162461bcd60e51b815260206004820152600e60248201526d0a8ded6cadc40dad2e6dac2e8c6d60931b604482015260640161008b565b81516001600160a01b031661040b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420706c6174666f726d20616464726573730000000000000000604482015260640161008b565b60208201516001600160a01b0316156104665760405162461bcd60e51b815260206004820152601560248201527f496e76616c6964207661756c7420616464726573730000000000000000000000604482015260640161008b565b505061083e565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d29190610787565b60ff169050600481101580156104e9575060128111155b6105475760405162461bcd60e51b815260206004820152602960248201527f546f6b656e206d75737420686176652073756666696369656e7420646563696d604482015268616c20706c6163657360b81b606482015260840161008b565b92915050565b60606000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105b791908101906107aa565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156105f6576105f66105be565b60405290565b60405160c081016001600160401b03811182821017156105f6576105f66105be565b604051601f8201601f191681016001600160401b0381118282101715610646576106466105be565b604052919050565b80516001600160a01b038116811461066557600080fd5b919050565b60008082840361010081121561067f57600080fd5b604081121561068d57600080fd5b6106956105d4565b61069e8561064e565b81526106ac6020860161064e565b6020820152925060c0603f19820112156106c557600080fd5b506106ce6105fc565b6106da6040850161064e565b81526106e86060850161064e565b6020820152608084015163ffffffff8116811461070457600080fd5b604082015261071560a0850161064e565b606082015261072660c0850161064e565b608082015261073760e0850161064e565b60a0820152809150509250929050565b60005b8381101561076257818101518382015260200161074a565b50506000910152565b6000825161077d818460208701610747565b9190910192915050565b60006020828403121561079957600080fd5b815160ff811681146105b757600080fd5b6000602082840312156107bc57600080fd5b81516001600160401b038111156107d257600080fd5b8201601f810184136107e357600080fd5b80516001600160401b038111156107fc576107fc6105be565b61080f601f8201601f191660200161061e565b81815285602083850101111561082457600080fd5b610835826020830160208601610747565b95945050505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a051614e83610a1e6000396000818161038c01528181610707015281816108fb015281816118ff01526130940152600081816105ba015281816127a30152612ff0015260006104bb0152600081816107ca015281816115b50152818161195301528181611a4d015281816120ee0152818161263f01528181612e8b01526130640152600081816105800152818161118b015281816122a9015281816123ff015281816124b501528181613d660152613e4201526000818161065101528181610f1d01528181612235015281816123dd0152818161249301528181613d440152613e2001526000818161061a01526110460152600081816103d601528181610d3c015281816114c30152818161152a01528181611a7401528181611f410152818161209a015281816125d401528181612e19015281816133d70152818161345b0152818161349f015281816136ea0152818161376d015281816137ab0152818161382801528181613c7001528181613d8b0152613e640152600081816106d501528181610f9f01528181613c920152613d1401526000818161068d015281816109990152818161122f0152818161170901526123af0152614e836000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c80636c9fa59e1161019d578063ad1728cb116100e9578063d9caed12116100a2578063df4426781161007c578063df442678146107f4578063f4537f7814610807578063f6ca71b014610822578063fc1b31131461083757600080fd5b8063d9caed12146107b2578063dbe55e56146107c5578063de5f6268146107ec57600080fd5b8063ad1728cb14610737578063b3ab15fb1461073f578063c2e1e3f414610752578063c7af335214610765578063d38bfff41461076d578063d7dd614b1461078057600080fd5b8063853828b6116101565780639136616a116101305780639136616a146106af57806396d538bb146106bd5780639748cf7c146106d0578063aa388af6146106f757600080fd5b8063853828b6146106445780638949f6f31461064c5780638c73eb041461068857600080fd5b80636c9fa59e146105b5578063773540b3146105dc5780637b2d9b2c146105ef5780637c92f219146106025780637ddfce2d146106155780638129fc1c1461063c57600080fd5b806342c8c11c1161025c578063570d8e1d116102155780635d36b190116101ef5780635d36b190146105605780635f515226146105685780636369e49f1461057b57806367c7066c146105a257600080fd5b8063570d8e1d146105315780635a063f63146105455780635a2364171461054d57600080fd5b806342c8c11c146104a3578063430bf08a146104b657806347e7ef24146104dd5780635324df32146104f0578063564a515814610504578063570ca7351461051757600080fd5b806311eac855116102c9578063237839f0116102a3578063237839f01461044457806323c9ab3d146104575780633335ad7f146104835780633c3dbbc71461048b57600080fd5b806311eac855146103d157806316a0f250146103f85780631801c4081461041957600080fd5b80630c340a24146103115780630ed57b3a146103365780630fc3b4c41461034b5780631072cbea146103745780631083f7611461038757806311cffb67146103ae575b600080fd5b610319610844565b6040516001600160a01b0390911681526020015b60405180910390f35b6103496103443660046141a2565b610861565b005b6103196103593660046141db565b6067602052600090815260409020546001600160a01b031681565b6103496103823660046141f8565b6108cd565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c16103bc3660046142f2565b61098c565b604051901515815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6033546104069061ffff1681565b60405161ffff909116815260200161032d565b603354600160201b90046001600160401b031660009081526034602052604090205460ff16156103c1565b6103496104523660046143a4565b610a72565b6103c1610465366004614414565b6001600160401b031660009081526034602052604090205460ff1690565b610349610c91565b610495620f424081565b60405190815260200161032d565b6103496104b1366004614443565b610d91565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496104eb3660046141f8565b610dc1565b6033546104069062010000900461ffff1681565b61034961051236600461445e565b610e43565b60335461031990600160601b90046001600160a01b031681565b61010354610319906001600160a01b031681565b61034961134d565b61034961055b366004614443565b6113ec565b610349611419565b6104956105763660046141db565b6114bf565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b606b54610319906001600160a01b031681565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496105ea3660046141db565b6116a5565b6103196105fd3660046144c5565b6116d2565b6103c16106103660046142f2565b6116fc565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611834565b6103496119c7565b6106737f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496103443660046144c5565b6103496106cb3660046144de565b611b5d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c16107053660046141db565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610349611c7a565b61034961074d3660046141db565b611ca6565b6103496107603660046141db565b611cd3565b6103c1611d60565b61034961077b3660046141db565b611d91565b60335461079a90600160201b90046001600160401b031681565b6040516001600160401b03909116815260200161032d565b6103496107c0366004614513565b611e35565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611eb9565b610349610802366004614554565b611fbb565b610319733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b61082a612167565b60405161032d91906145f1565b6104956509184e72a00081565b600061085c600080516020614e2e8339815191525490565b905090565b610869611d60565b61088e5760405162461bcd60e51b815260040161088590614604565b60405180910390fd5b60405162461bcd60e51b81526020600482015260146024820152733ab739bab83837b93a32b210333ab731ba34b7b760611b6044820152606401610885565b6108d5611d60565b6108f15760405162461bcd60e51b815260040161088590614604565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169083160361096c5760405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220737570706f72746564206173736574006044820152606401610885565b610988610977610844565b6001600160a01b03841690836121c9565b5050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a065760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b6107d08363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b610a69858584612231565b95945050505050565b604080516001808252818301909252600091602080830190803683370190505090503081600081518110610aa857610aa861463b565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610af957610af961463b565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610b4a57610b4a61463b565b6020908102919091010152604080516001808252818301909252600091816020015b6060815260200190600190039081610b6c5790505090508585808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250855186945090925015159050610bca57610bca61463b565b60209081029190910101526040516301c7ba5760e61b8152733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae906371ee95c090610c12908790879087908790600401614651565b600060405180830381600087803b158015610c2c57600080fd5b505af1158015610c40573d6000803e3d6000fd5b50505050876001600160a01b03167f2d5429efdeca7741a8cd94067b18d988bc4e5f1d5b8272c37b7bfc31e9bfa32c88604051610c7f91815260200190565b60405180910390a25050505050505050565b603354600160601b90046001600160a01b0316331480610cbc5750610103546001600160a01b031633145b80610cca5750610cca611d60565b610d355760405162461bcd60e51b815260206004820152603660248201527f43616c6c6572206973206e6f7420746865204f70657261746f722c20537472616044820152753a32b3b4b9ba1037b9103a34329023b7bb32b93737b960511b6064820152608401610885565b6000610d607f00000000000000000000000000000000000000000000000000000000000000006114bf565b90506000610d86603360049054906101000a90046001600160401b03168360004261232a565b905061098881612395565b610d99611d60565b610db55760405162461bcd60e51b815260040161088590614604565b610dbe816124ee565b50565b610103546001600160a01b0316331480610dde5750610dde611d60565b610dfa5760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101610e2c5760405162461bcd60e51b815260040161088590614787565b60028255610e3a8484612589565b50600190555050565b603354600160601b90046001600160a01b03163314610ea45760405162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865204f70657261746f720000000000006044820152606401610885565b6000806000806000610eb5876127ff565b94509450945094509450600163ffffffff168563ffffffff1614610f1b5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c69642043435450206d6573736167652076657273696f6e000000006044820152606401610885565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff1614610f8e5760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b610f99816000612855565b945060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614905080156110da578563ffffffff166001148015610ff25750815160e411155b6110355760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206275726e206d65737361676560601b6044820152606401610885565b600061104283600461287d565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146110ba5760405162461bcd60e51b815260206004820152601260248201527124b73b30b634b210313ab937103a37b5b2b760711b6044820152606401610885565b6110c583606461287d565b94506110d283602461287d565b935050611131565b63ffffffff86166103f2146111315760405162461bcd60e51b815260206004820152601b60248201527f556e737570706f72746564206d6573736167652076657273696f6e00000000006044820152606401610885565b306001600160a01b038416146111895760405162461bcd60e51b815260206004820152601c60248201527f556e657870656374656420726563697069656e742061646472657373000000006044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146112155760405162461bcd60e51b815260206004820152602260248201527f496e636f72726563742073656e6465722f726563697069656e74206164647265604482015261737360f01b6064820152608401610885565b604051630afd9fa560e31b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906357ecfd2890611266908c908c906004016147ff565b6020604051808303816000875af1158015611285573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a99190614824565b9050806112f15760405162461bcd60e51b8152602060048201526016602482015275149958d95a5d99481b595cdcd859d94819985a5b195960521b6044820152606401610885565b811561134257825160009061130a90859060e490612897565b905060006113198560446129f1565b905060006113288660a46129f1565b905061133e611337828461485c565b8285612a0b565b5050505b505050505050505050565b606b546001600160a01b031633146113a75760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206973206e6f74207468652048617276657374657200000000006044820152606401610885565b600080516020614e0e833981519152805460011981016113d95760405162461bcd60e51b815260040161088590614787565b600282556113e5612a70565b5060019055565b6113f4611d60565b6114105760405162461bcd60e51b815260040161088590614604565b610dbe81612b84565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146114b45760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b6064820152608401610885565b6114bd33612c21565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146115125760405162461bcd60e51b81526004016108859061486f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159d91906148a6565b6040516370a0823160e01b81523060048201529091507f00000000000000000000000000000000000000000000000000000000000000009082906001600160a01b03831690634cdad5069082906370a0823190602401602060405180830381865afa158015611610573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163491906148a6565b6040518263ffffffff1660e01b815260040161165291815260200190565b602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169391906148a6565b61169d91906148bf565b949350505050565b6116ad611d60565b6116c95760405162461bcd60e51b815260040161088590614604565b610dbe81612c80565b606c81815481106116e257600080fd5b6000918252602090912001546001600160a01b0316905081565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117765760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b60335461ffff166103e8146117dc5760405162461bcd60e51b815260206004820152602660248201527f556e66696e616c697a6564206d6573736167657320617265206e6f74207375706044820152651c1bdc9d195960d21b6064820152608401610885565b6103e88363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b61183c611d60565b6118585760405162461bcd60e51b815260040161088590614604565b600054610100900460ff1680611871575060005460ff16155b61188d5760405162461bcd60e51b8152600401610885906148d2565b600054610100900460ff161580156118af576000805461ffff19166101011790555b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000826000815181106119315761193161463b565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816000815181106119855761198561463b565b60200260200101906001600160a01b031690816001600160a01b0316815250506119b0838383612ccf565b5050508015610dbe576000805461ff001916905550565b610103546001600160a01b03163314806119e457506119e4611d60565b611a005760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101611a325760405162461bcd60e51b815260040161088590614787565b600282556040516370a0823160e01b815230600482018190527f000000000000000000000000000000000000000000000000000000000000000091611b5591907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03851690634cdad5069082906370a0823190602401602060405180830381865afa158015611acd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af191906148a6565b6040518263ffffffff1660e01b8152600401611b0f91815260200190565b602060405180830381865afa158015611b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5091906148a6565b612d7b565b505060019055565b611b65611d60565b611b815760405162461bcd60e51b815260040161088590614604565b8060005b81811015611c2b576000848483818110611ba157611ba161463b565b9050602002016020810190611bb691906141db565b6001600160a01b031603611c235760405162461bcd60e51b815260206004820152602e60248201527f43616e206e6f742073657420616e20656d70747920616464726573732061732060448201526d30903932bbb0b932103a37b5b2b760911b6064820152608401610885565b600101611b85565b507f04c0b9649497d316554306e53678d5f5f5dbc3a06f97dec13ff4cfe98b986bbc606c8484604051611c6093929190614920565b60405180910390a1611c74606c84846140c0565b50505050565b611c82611d60565b611c9e5760405162461bcd60e51b815260040161088590614604565b6114bd61304d565b611cae611d60565b611cca5760405162461bcd60e51b815260040161088590614604565b610dbe81613101565b611cdb611d60565b611cf75760405162461bcd60e51b815260040161088590614604565b606b54604080516001600160a01b03928316815291831660208301527fe48386b84419f4d36e0f96c10cc3510b6fb1a33795620c5098b22472bbe90796910160405180910390a1606b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611d78600080516020614e2e8339815191525490565b6001600160a01b0316336001600160a01b031614905090565b611d99611d60565b611db55760405162461bcd60e51b815260040161088590614604565b611ddd817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316611dfd600080516020614e2e8339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610103546001600160a01b0316331480611e525750611e52611d60565b611e6e5760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101611ea05760405162461bcd60e51b815260040161088590614787565b60028255611eaf858585612d7b565b5060019055505050565b610103546001600160a01b0316331480611ed65750611ed6611d60565b611ef25760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101611f245760405162461bcd60e51b815260040161088590614787565b600282556040516370a0823160e01b81523060048201526113e5907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038216906370a0823190602401602060405180830381865afa158015611f92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb691906148a6565b612589565b611fc3611d60565b611fdf5760405162461bcd60e51b815260040161088590614604565b600054610100900460ff1680611ff8575060005460ff16155b6120145760405162461bcd60e51b8152600401610885906148d2565b600054610100900460ff16158015612036576000805461ffff19166101011790555b61204184848461315c565b61204a85612c80565b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000826000815181106120cc576120cc61463b565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816000815181106121205761212061463b565b60200260200101906001600160a01b031690816001600160a01b03168152505061214b838383612ccf565b5050508015612160576000805461ff00191690555b5050505050565b6060606c8054806020026020016040519081016040528092919081815260200182805480156121bf57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121a1575b5050505050905090565b6040516001600160a01b03831660248201526044810182905261222c90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131b1565b505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff16146122a65760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116908216146123145760405162461bcd60e51b815260206004820152600e60248201526d2ab735b737bbb71029b2b73232b960911b6044820152606401610885565b61231d83613283565b60019150505b9392505050565b604080516001600160401b038616602082015280820185905283151560608083019190915260808083018590528351808403909101815260a083019093529161237c916103f29160039160c0016149bb565b6040516020818303038152906040529050949350505050565b6033546040516314b157ab60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926314b157ab92612433927f0000000000000000000000000000000000000000000000000000000000000000927f000000000000000000000000000000000000000000000000000000000000000090911691829161ffff16908890600401614a00565b600060405180830381600087803b15801561244d57600080fd5b505af1158015612461573d6000803e3d6000fd5b50506033546040517f90d92e80437532a834bc16642d235a7c34efc4d5690f3f6e69794c6d8c5c729093506124e392507f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009161ffff909116908690614a37565b60405180910390a150565b610bb88161ffff16111561253b5760405162461bcd60e51b815260206004820152601460248201527308ccaca40e0e4cadad2eada40e8dede40d0d2ced60631b6044820152606401610885565b6033805463ffff000019166201000061ffff8416908102919091179091556040519081527f938c72cb9ba014c7d4d26f156021299f8926dee2aab1421b32a2408a8261cf60906020016124e3565b600081116125d25760405162461bcd60e51b81526020600482015260166024820152754d757374206465706f73697420736f6d657468696e6760501b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146126235760405162461bcd60e51b81526004016108859061486f565b604051636e553f6560e01b8152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303816000875af19250505080156126ac575060408051601f3d908101601f191682019092526126a9918101906148a6565b60015b612794576126b8614a79565b806308c379a00361273057506126cc614a95565b806126d75750612732565b7fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d4816040516020016127099190614b18565b60408051601f198184030181529082905261272391614b50565b60405180910390a1505050565b505b3d80801561275c576040519150601f19603f3d011682016040523d82523d6000602084013e612761565b606091505b507fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d4816040516020016127099190614b63565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b600080808060606128108683612855565b945061281d866004612855565b935061282a86602c61287d565b925061283786604c61287d565b865190925061284a908790609490612897565b905091939590929450565b600061287461286f848461286a6004826148bf565b612897565b6132f7565b90505b92915050565b6000612874612892848461286a6020826148bf565b61332d565b6060828210156128df5760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420736c6963652072616e676560681b6044820152606401610885565b83518211156129305760405162461bcd60e51b815260206004820152601d60248201527f536c69636520656e6420657863656564732064617461206c656e6774680000006044820152606401610885565b600061293c848461485c565b90506000816001600160401b038111156129585761295861423d565b6040519080825280601f01601f191660200182016040528015612982576020820181803683370190505b50905060005b828110156129e7578661299b82886148bf565b815181106129ab576129ab61463b565b602001015160f81c60f81b8282815181106129c8576129c861463b565b60200101906001600160f81b031916908160001a905350600101612988565b5095945050505050565b6000612874612a06848461286a6020826148bf565b613364565b6000612a168261339b565b905063ffffffff8116600114612a655760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206d657373616765207479706560601b6044820152606401610885565b611c748484846133a8565b606c5460005b81811015610988576000606c8281548110612a9357612a9361463b565b60009182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa158015612ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0a91906148a6565b90508015612b7a57606b54604080516001600160a01b039283168152918416602083015281018290527ff6c07a063ed4e63808eb8da7112d46dbcd38de2b40a73dbcc9353c5a94c723539060600160405180910390a1606b54612b7a906001600160a01b038481169116836121c9565b5050600101612a76565b8061ffff166103e81480612b9d57508061ffff166107d0145b612bdd5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152606401610885565b6033805461ffff191661ffff83169081179091556040519081527fe8fbd074d54232549e55ac463e02d202c16b1023e5d6aae276b3d8391b8c14bc906020016124e3565b6001600160a01b038116612c775760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f7220697320616464726573732830290000000000006044820152606401610885565b610dbe816134de565b61010380546001600160a01b0319166001600160a01b0383169081179091556040519081527f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee906020016124e3565b8251612ce290606c906020860190614123565b50815181518114612d2c5760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420696e7075742061727261797360601b6044820152606401610885565b60005b8181101561216057612d73848281518110612d4c57612d4c61463b565b6020026020010151848381518110612d6657612d6661463b565b6020026020010151613545565b600101612d2f565b60008111612dcb5760405162461bcd60e51b815260206004820152601760248201527f4d75737420776974686472617720736f6d657468696e670000000000000000006044820152606401610885565b6001600160a01b0383163014612e175760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614612e685760405162461bcd60e51b81526004016108859061486f565b604051632d182be560e21b815260048101829052306024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b460af94906064016020604051808303816000875af1925050508015612ef8575060408051601f3d908101601f19168201909252612ef5918101906148a6565b60015b612fe157612f04614a79565b806308c379a003612f7d5750612f18614a95565b80612f235750612f7f565b7f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f83481604051602001612f559190614bc1565b60408051601f1981840301815290829052612f6f91614b50565b60405180910390a150505050565b505b3d808015612fa9576040519150601f19603f3d011682016040523d82523d6000602084013e612fae565b606091505b507f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f83481604051602001612f559190614bfc565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a2505050565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af11580156130dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbe9190614824565b603380546bffffffffffffffffffffffff16600160601b6001600160a01b038416908102919091179091556040519081527f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e54906020016124e3565b61316583613101565b61316e82612b84565b613177816124ee565b5050600080525060346020527f2dc2afdad33a5feea586a9545052327b65d28efb10d11fa69e77da986a1031cd805460ff19166001179055565b6000613206826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136aa9092919063ffffffff16565b80519091501561222c57808060200190518101906132249190614824565b61222c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610885565b600061328e8261339b565b905060001963ffffffff821601156109885760011963ffffffff8216016132b857610988826136b9565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206d657373616765207479706560601b6044820152606401610885565b6000815160041461331a5760405162461bcd60e51b815260040161088590614c5d565b60e061332583614c8a565b901c92915050565b600081516020146133505760405162461bcd60e51b815260040161088590614c5d565b818060200190518101906128779190614cb1565b600081516020146133875760405162461bcd60e51b815260040161088590614c5d565b8180602001905181019061287791906148a6565b6000612877826004612855565b60006133b38261390b565b5090506133bf81613944565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344a91906148a6565b9050620f42408110613480576134807f000000000000000000000000000000000000000000000000000000000000000082612589565b6033546000906134cb90600160201b90046001600160401b03166134c37f00000000000000000000000000000000000000000000000000000000000000006114bf565b60014261232a565b90506134d681612395565b505050505050565b806001600160a01b03166134fe600080516020614e2e8339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3600080516020614e2e83398151915255565b6001600160a01b0382811660009081526067602052604090205416156135a25760405162461bcd60e51b81526020600482015260126024820152711c151bdad95b88185b1c9958591e481cd95d60721b6044820152606401610885565b6001600160a01b038216158015906135c257506001600160a01b03811615155b6136025760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b6044820152606401610885565b6001600160a01b03828116600081815260676020908152604080832080549587166001600160a01b031996871681179091556068805460018101825594527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c2209775390930180549095168417909455925190815290917fef6485b84315f9b1483beffa32aae9a0596890395e3d7521f1c5fbb51790e765910160405180910390a26109888282613ad7565b606061169d8484600085613adf565b6000806136c583613c07565b915091506136d282613944565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375d91906148a6565b90508181101561382157613796307f0000000000000000000000000000000000000000000000000000000000000000611b50848661485c565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156137fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381e91906148a6565b90505b600061384c7f00000000000000000000000000000000000000000000000000000000000000006114bf565b9050620f424083101580156138615750828210155b1561389c5760335460009061388a90600160201b90046001600160401b03166134c3868561485c565b90506138968482613c15565b50612160565b6033546000906138bf90600160201b90046001600160401b03168360014261232a565b90506138ca81612395565b60408051858152602081018590527fff463b52b1f42eb360c2a871ee18d12dbc93807adffafa5b8fc6dea0051857a9910160405180910390a1505050505050565b600080613919836001613e94565b60008061392585613f4d565b8060200190518101906139389190614cce565b90969095509350505050565b6033546001600160401b03600160201b909104811690821681111561399b5760405162461bcd60e51b815260206004820152600d60248201526c4e6f6e636520746f6f206c6f7760981b6044820152606401610885565b6001600160401b03821660009081526034602052604090205460ff1615613a045760405162461bcd60e51b815260206004820152601760248201527f4e6f6e636520616c72656164792070726f6365737365640000000000000000006044820152606401610885565b6001600160401b038216600081815260346020908152604091829020805460ff1916600117905590519182527f8aa30b3e46076ef0187550969c01982aeb9af5db2eada56ab253a53e4c9946e9910160405180910390a1806001600160401b0316826001600160401b03161461098857603380546bffffffffffffffff000000001916600160201b6001600160401b038516908102919091179091556040519081527fc328b88555c22b57c1f2678e88ad3d9982d056ca6b05be82546e7b6bc6fda2db9060200160405180910390a15050565b61098861304d565b606082471015613b405760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610885565b843b613b8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610885565b600080866001600160a01b03168587604051613baa9190614cfc565b60006040518083038185875af1925050503d8060008114613be7576040519150601f19603f3d011682016040523d82523d6000602084013e613bec565b606091505b5091509150613bfc828286613f66565b979650505050505050565b600080613919836002613e94565b6509184e72a000821115613c635760405162461bcd60e51b81526020600482015260156024820152740a8ded6cadc40c2dadeeadce840e8dede40d0d2ced605b1b6044820152606401610885565b613cb76001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084613f9f565b60335460009062010000900461ffff16613cd2576000613cf7565b60335461271090613ced9062010000900461ffff1685614d18565b613cf79190614d2f565b60335460405163779b432d60e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263779b432d92613dc09288927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000909216917f00000000000000000000000000000000000000000000000000000000000000009183918a9161ffff909116908c90600401614d51565b600060405180830381600087803b158015613dda57600080fd5b505af1158015613dee573d6000803e3d6000fd5b50506033546040517f149007d4a77eb98d041de59e6ca469bd27b351b74f16c4d0648978322a1b8a77935061272392507f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918991889161ffff16908a90614db2565b6103f2613ea0836140b4565b63ffffffff1614613ef35760405162461bcd60e51b815260206004820152601e60248201527f496e76616c6964204f726967696e204d6573736167652056657273696f6e00006044820152606401610885565b8063ffffffff16613f038361339b565b63ffffffff16146109885760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964204d657373616765207479706560601b6044820152606401610885565b606061287760088351846128979092919063ffffffff16565b60608315613f75575081612323565b825115613f855782518084602001fd5b8160405162461bcd60e51b81526004016108859190614b50565b8015806140195750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613ff3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061401791906148a6565b155b6140845760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610885565b6040516001600160a01b03831660248201526044810182905261222c90849063095ea7b360e01b906064016121f5565b60006128778282612855565b828054828255906000526020600020908101928215614113579160200282015b828111156141135781546001600160a01b0319166001600160a01b038435161782556020909201916001909101906140e0565b5061411f929150614178565b5090565b828054828255906000526020600020908101928215614113579160200282015b8281111561411357825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614143565b5b8082111561411f5760008155600101614179565b6001600160a01b0381168114610dbe57600080fd5b600080604083850312156141b557600080fd5b82356141c08161418d565b915060208301356141d08161418d565b809150509250929050565b6000602082840312156141ed57600080fd5b81356123238161418d565b6000806040838503121561420b57600080fd5b82356142168161418d565b946020939093013593505050565b803563ffffffff8116811461423857600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b03811182821017156142785761427861423d565b6040525050565b600082601f83011261429057600080fd5b81356001600160401b038111156142a9576142a961423d565b6040516142c0601f8301601f191660200182614253565b8181528460208386010111156142d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561430857600080fd5b61431185614224565b93506020850135925061432660408601614224565b915060608501356001600160401b0381111561434157600080fd5b61434d8782880161427f565b91505092959194509250565b60008083601f84011261436b57600080fd5b5081356001600160401b0381111561438257600080fd5b6020830191508360208260051b850101111561439d57600080fd5b9250929050565b600080600080606085870312156143ba57600080fd5b84356143c58161418d565b93506020850135925060408501356001600160401b038111156143e757600080fd5b6143f387828801614359565b95989497509550505050565b6001600160401b0381168114610dbe57600080fd5b60006020828403121561442657600080fd5b8135612323816143ff565b803561ffff8116811461423857600080fd5b60006020828403121561445557600080fd5b61287482614431565b6000806040838503121561447157600080fd5b82356001600160401b0381111561448757600080fd5b6144938582860161427f565b92505060208301356001600160401b038111156144af57600080fd5b6144bb8582860161427f565b9150509250929050565b6000602082840312156144d757600080fd5b5035919050565b600080602083850312156144f157600080fd5b82356001600160401b0381111561450757600080fd5b61393885828601614359565b60008060006060848603121561452857600080fd5b83356145338161418d565b925060208401356145438161418d565b929592945050506040919091013590565b6000806000806080858703121561456a57600080fd5b84356145758161418d565b935060208501356145858161418d565b925061459360408601614431565b91506145a160608601614431565b905092959194509250565b600081518084526020840193506020830160005b828110156145e75781516001600160a01b03168652602095860195909101906001016145c0565b5093949350505050565b60208152600061287460208301846145ac565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60808152600061466460808301876145ac565b828103602084015261467681876145ac565b83810360408501528551808252602080880193509091019060005b818110156146af578351835260209384019390920191600101614691565b50508381036060850152845180825260208083019350600582901b8301810190870160005b8381101561472f57848303601f190186528151805180855260209182019185019060005b818110156147165783518352602093840193909201916001016146f8565b50506020978801979094509290920191506001016146d4565b50909a9950505050505050505050565b60208082526028908201527f43616c6c6572206973206e6f74207468652053747261746567697374206f722060408201526723b7bb32b93737b960c11b606082015260800190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60005b838110156147ca5781810151838201526020016147b2565b50506000910152565b600081518084526147eb8160208601602086016147af565b601f01601f19169290920160200192915050565b60408152600061481260408301856147d3565b8281036020840152610a6981856147d3565b60006020828403121561483657600080fd5b8151801515811461232357600080fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561287757612877614846565b60208082526018908201527f556e657870656374656420617373657420616464726573730000000000000000604082015260600190565b6000602082840312156148b857600080fd5b5051919050565b8082018082111561287757612877614846565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6040808252845490820181905260008581526020812090916060840190835b818110156149665783546001600160a01b031683526001938401936020909301920161493f565b50508381036020808601919091528582520190508460005b858110156149af5781356149918161418d565b6001600160a01b03168352602092830192919091019060010161497e565b50909695505050505050565b63ffffffff60e01b8460e01b16815263ffffffff60e01b8360e01b166004820152600082516149f18160088501602087016147af565b91909101600801949350505050565b63ffffffff8616815284602082015283604082015263ffffffff8316606082015260a060808201526000613bfc60a08301846147d3565b63ffffffff85811682526001600160a01b038516602083015283166040820152608060608201819052600090614a6f908301846147d3565b9695505050505050565b600060033d1115614a925760046000803e5060005160e01c5b90565b600060443d1015614aa35790565b6040513d600319016004823e80513d60248201116001600160401b0382111715614acc57505090565b80820180516001600160401b03811115614ae7575050505090565b3d8401600319018282016020011115614b01575050505090565b614b1060208285010185614253565b509392505050565b6f02232b837b9b4ba103330b4b632b21d160851b815260008251614b438160108501602087016147af565b9190910160100192915050565b60208152600061287460208301846147d3565b7f4465706f736974206661696c65643a206c6f772d6c6576656c2063616c6c206681526f030b4b632b2103bb4ba34103230ba30960851b602082015260008251614bb48160308501602087016147af565b9190910160300192915050565b7202bb4ba34323930bbb0b6103330b4b632b21d1606d1b815260008251614bef8160138501602087016147af565b9190910160130192915050565b7f5769746864726177616c206661696c65643a206c6f772d6c6576656c2063616c815272036103330b4b632b2103bb4ba34103230ba309606d1b602082015260008251614c508160338501602087016147af565b9190910160330192915050565b602080825260139082015272092dcecc2d8d2c840c8c2e8c240d8cadccee8d606b1b604082015260600190565b80516020808301519190811015614cab576000198160200360031b1b821691505b50919050565b600060208284031215614cc357600080fd5b81516123238161418d565b60008060408385031215614ce157600080fd5b8251614cec816143ff565b6020939093015192949293505050565b60008251614d0e8184602087016147af565b9190910192915050565b808202811582820484141761287757612877614846565b600082614d4c57634e487b7160e01b600052601260045260246000fd5b500490565b88815263ffffffff8816602082015286604082015260018060a01b03861660608201528460808201528360a082015263ffffffff831660c082015261010060e08201526000614da46101008301846147d3565b9a9950505050505050505050565b63ffffffff88811682526001600160a01b038881166020840152871660408301526060820186905260808201859052831660a082015260e060c08201819052600090614e00908301846147d3565b999850505050505050505056fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45357bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa2646970667358221220e2f059eccac446855423527343f655a81f4122f7e91825b0c4623d4ffd9afd4d64736f6c634300081c0033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061030c5760003560e01c80636c9fa59e1161019d578063ad1728cb116100e9578063d9caed12116100a2578063df4426781161007c578063df442678146107f4578063f4537f7814610807578063f6ca71b014610822578063fc1b31131461083757600080fd5b8063d9caed12146107b2578063dbe55e56146107c5578063de5f6268146107ec57600080fd5b8063ad1728cb14610737578063b3ab15fb1461073f578063c2e1e3f414610752578063c7af335214610765578063d38bfff41461076d578063d7dd614b1461078057600080fd5b8063853828b6116101565780639136616a116101305780639136616a146106af57806396d538bb146106bd5780639748cf7c146106d0578063aa388af6146106f757600080fd5b8063853828b6146106445780638949f6f31461064c5780638c73eb041461068857600080fd5b80636c9fa59e146105b5578063773540b3146105dc5780637b2d9b2c146105ef5780637c92f219146106025780637ddfce2d146106155780638129fc1c1461063c57600080fd5b806342c8c11c1161025c578063570d8e1d116102155780635d36b190116101ef5780635d36b190146105605780635f515226146105685780636369e49f1461057b57806367c7066c146105a257600080fd5b8063570d8e1d146105315780635a063f63146105455780635a2364171461054d57600080fd5b806342c8c11c146104a3578063430bf08a146104b657806347e7ef24146104dd5780635324df32146104f0578063564a515814610504578063570ca7351461051757600080fd5b806311eac855116102c9578063237839f0116102a3578063237839f01461044457806323c9ab3d146104575780633335ad7f146104835780633c3dbbc71461048b57600080fd5b806311eac855146103d157806316a0f250146103f85780631801c4081461041957600080fd5b80630c340a24146103115780630ed57b3a146103365780630fc3b4c41461034b5780631072cbea146103745780631083f7611461038757806311cffb67146103ae575b600080fd5b610319610844565b6040516001600160a01b0390911681526020015b60405180910390f35b6103496103443660046141a2565b610861565b005b6103196103593660046141db565b6067602052600090815260409020546001600160a01b031681565b6103496103823660046141f8565b6108cd565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c16103bc3660046142f2565b61098c565b604051901515815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6033546104069061ffff1681565b60405161ffff909116815260200161032d565b603354600160201b90046001600160401b031660009081526034602052604090205460ff16156103c1565b6103496104523660046143a4565b610a72565b6103c1610465366004614414565b6001600160401b031660009081526034602052604090205460ff1690565b610349610c91565b610495620f424081565b60405190815260200161032d565b6103496104b1366004614443565b610d91565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496104eb3660046141f8565b610dc1565b6033546104069062010000900461ffff1681565b61034961051236600461445e565b610e43565b60335461031990600160601b90046001600160a01b031681565b61010354610319906001600160a01b031681565b61034961134d565b61034961055b366004614443565b6113ec565b610349611419565b6104956105763660046141db565b6114bf565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b606b54610319906001600160a01b031681565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496105ea3660046141db565b6116a5565b6103196105fd3660046144c5565b6116d2565b6103c16106103660046142f2565b6116fc565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611834565b6103496119c7565b6106737f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496103443660046144c5565b6103496106cb3660046144de565b611b5d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c16107053660046141db565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610349611c7a565b61034961074d3660046141db565b611ca6565b6103496107603660046141db565b611cd3565b6103c1611d60565b61034961077b3660046141db565b611d91565b60335461079a90600160201b90046001600160401b031681565b6040516001600160401b03909116815260200161032d565b6103496107c0366004614513565b611e35565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611eb9565b610349610802366004614554565b611fbb565b610319733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b61082a612167565b60405161032d91906145f1565b6104956509184e72a00081565b600061085c600080516020614e2e8339815191525490565b905090565b610869611d60565b61088e5760405162461bcd60e51b815260040161088590614604565b60405180910390fd5b60405162461bcd60e51b81526020600482015260146024820152733ab739bab83837b93a32b210333ab731ba34b7b760611b6044820152606401610885565b6108d5611d60565b6108f15760405162461bcd60e51b815260040161088590614604565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169083160361096c5760405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220737570706f72746564206173736574006044820152606401610885565b610988610977610844565b6001600160a01b03841690836121c9565b5050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a065760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b6107d08363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b610a69858584612231565b95945050505050565b604080516001808252818301909252600091602080830190803683370190505090503081600081518110610aa857610aa861463b565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610af957610af961463b565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610b4a57610b4a61463b565b6020908102919091010152604080516001808252818301909252600091816020015b6060815260200190600190039081610b6c5790505090508585808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250855186945090925015159050610bca57610bca61463b565b60209081029190910101526040516301c7ba5760e61b8152733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae906371ee95c090610c12908790879087908790600401614651565b600060405180830381600087803b158015610c2c57600080fd5b505af1158015610c40573d6000803e3d6000fd5b50505050876001600160a01b03167f2d5429efdeca7741a8cd94067b18d988bc4e5f1d5b8272c37b7bfc31e9bfa32c88604051610c7f91815260200190565b60405180910390a25050505050505050565b603354600160601b90046001600160a01b0316331480610cbc5750610103546001600160a01b031633145b80610cca5750610cca611d60565b610d355760405162461bcd60e51b815260206004820152603660248201527f43616c6c6572206973206e6f7420746865204f70657261746f722c20537472616044820152753a32b3b4b9ba1037b9103a34329023b7bb32b93737b960511b6064820152608401610885565b6000610d607f00000000000000000000000000000000000000000000000000000000000000006114bf565b90506000610d86603360049054906101000a90046001600160401b03168360004261232a565b905061098881612395565b610d99611d60565b610db55760405162461bcd60e51b815260040161088590614604565b610dbe816124ee565b50565b610103546001600160a01b0316331480610dde5750610dde611d60565b610dfa5760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101610e2c5760405162461bcd60e51b815260040161088590614787565b60028255610e3a8484612589565b50600190555050565b603354600160601b90046001600160a01b03163314610ea45760405162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865204f70657261746f720000000000006044820152606401610885565b6000806000806000610eb5876127ff565b94509450945094509450600163ffffffff168563ffffffff1614610f1b5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c69642043435450206d6573736167652076657273696f6e000000006044820152606401610885565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff1614610f8e5760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b610f99816000612855565b945060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614905080156110da578563ffffffff166001148015610ff25750815160e411155b6110355760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206275726e206d65737361676560601b6044820152606401610885565b600061104283600461287d565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146110ba5760405162461bcd60e51b815260206004820152601260248201527124b73b30b634b210313ab937103a37b5b2b760711b6044820152606401610885565b6110c583606461287d565b94506110d283602461287d565b935050611131565b63ffffffff86166103f2146111315760405162461bcd60e51b815260206004820152601b60248201527f556e737570706f72746564206d6573736167652076657273696f6e00000000006044820152606401610885565b306001600160a01b038416146111895760405162461bcd60e51b815260206004820152601c60248201527f556e657870656374656420726563697069656e742061646472657373000000006044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146112155760405162461bcd60e51b815260206004820152602260248201527f496e636f72726563742073656e6465722f726563697069656e74206164647265604482015261737360f01b6064820152608401610885565b604051630afd9fa560e31b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906357ecfd2890611266908c908c906004016147ff565b6020604051808303816000875af1158015611285573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a99190614824565b9050806112f15760405162461bcd60e51b8152602060048201526016602482015275149958d95a5d99481b595cdcd859d94819985a5b195960521b6044820152606401610885565b811561134257825160009061130a90859060e490612897565b905060006113198560446129f1565b905060006113288660a46129f1565b905061133e611337828461485c565b8285612a0b565b5050505b505050505050505050565b606b546001600160a01b031633146113a75760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206973206e6f74207468652048617276657374657200000000006044820152606401610885565b600080516020614e0e833981519152805460011981016113d95760405162461bcd60e51b815260040161088590614787565b600282556113e5612a70565b5060019055565b6113f4611d60565b6114105760405162461bcd60e51b815260040161088590614604565b610dbe81612b84565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146114b45760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b6064820152608401610885565b6114bd33612c21565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146115125760405162461bcd60e51b81526004016108859061486f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159d91906148a6565b6040516370a0823160e01b81523060048201529091507f00000000000000000000000000000000000000000000000000000000000000009082906001600160a01b03831690634cdad5069082906370a0823190602401602060405180830381865afa158015611610573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061163491906148a6565b6040518263ffffffff1660e01b815260040161165291815260200190565b602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169391906148a6565b61169d91906148bf565b949350505050565b6116ad611d60565b6116c95760405162461bcd60e51b815260040161088590614604565b610dbe81612c80565b606c81815481106116e257600080fd5b6000918252602090912001546001600160a01b0316905081565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117765760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b60335461ffff166103e8146117dc5760405162461bcd60e51b815260206004820152602660248201527f556e66696e616c697a6564206d6573736167657320617265206e6f74207375706044820152651c1bdc9d195960d21b6064820152608401610885565b6103e88363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b61183c611d60565b6118585760405162461bcd60e51b815260040161088590614604565b600054610100900460ff1680611871575060005460ff16155b61188d5760405162461bcd60e51b8152600401610885906148d2565b600054610100900460ff161580156118af576000805461ffff19166101011790555b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000826000815181106119315761193161463b565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816000815181106119855761198561463b565b60200260200101906001600160a01b031690816001600160a01b0316815250506119b0838383612ccf565b5050508015610dbe576000805461ff001916905550565b610103546001600160a01b03163314806119e457506119e4611d60565b611a005760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101611a325760405162461bcd60e51b815260040161088590614787565b600282556040516370a0823160e01b815230600482018190527f000000000000000000000000000000000000000000000000000000000000000091611b5591907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03851690634cdad5069082906370a0823190602401602060405180830381865afa158015611acd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611af191906148a6565b6040518263ffffffff1660e01b8152600401611b0f91815260200190565b602060405180830381865afa158015611b2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5091906148a6565b612d7b565b505060019055565b611b65611d60565b611b815760405162461bcd60e51b815260040161088590614604565b8060005b81811015611c2b576000848483818110611ba157611ba161463b565b9050602002016020810190611bb691906141db565b6001600160a01b031603611c235760405162461bcd60e51b815260206004820152602e60248201527f43616e206e6f742073657420616e20656d70747920616464726573732061732060448201526d30903932bbb0b932103a37b5b2b760911b6064820152608401610885565b600101611b85565b507f04c0b9649497d316554306e53678d5f5f5dbc3a06f97dec13ff4cfe98b986bbc606c8484604051611c6093929190614920565b60405180910390a1611c74606c84846140c0565b50505050565b611c82611d60565b611c9e5760405162461bcd60e51b815260040161088590614604565b6114bd61304d565b611cae611d60565b611cca5760405162461bcd60e51b815260040161088590614604565b610dbe81613101565b611cdb611d60565b611cf75760405162461bcd60e51b815260040161088590614604565b606b54604080516001600160a01b03928316815291831660208301527fe48386b84419f4d36e0f96c10cc3510b6fb1a33795620c5098b22472bbe90796910160405180910390a1606b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611d78600080516020614e2e8339815191525490565b6001600160a01b0316336001600160a01b031614905090565b611d99611d60565b611db55760405162461bcd60e51b815260040161088590614604565b611ddd817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316611dfd600080516020614e2e8339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610103546001600160a01b0316331480611e525750611e52611d60565b611e6e5760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101611ea05760405162461bcd60e51b815260040161088590614787565b60028255611eaf858585612d7b565b5060019055505050565b610103546001600160a01b0316331480611ed65750611ed6611d60565b611ef25760405162461bcd60e51b81526004016108859061473f565b600080516020614e0e83398151915280546001198101611f245760405162461bcd60e51b815260040161088590614787565b600282556040516370a0823160e01b81523060048201526113e5907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038216906370a0823190602401602060405180830381865afa158015611f92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fb691906148a6565b612589565b611fc3611d60565b611fdf5760405162461bcd60e51b815260040161088590614604565b600054610100900460ff1680611ff8575060005460ff16155b6120145760405162461bcd60e51b8152600401610885906148d2565b600054610100900460ff16158015612036576000805461ffff19166101011790555b61204184848461315c565b61204a85612c80565b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000826000815181106120cc576120cc61463b565b60200260200101906001600160a01b031690816001600160a01b0316815250507f0000000000000000000000000000000000000000000000000000000000000000816000815181106121205761212061463b565b60200260200101906001600160a01b031690816001600160a01b03168152505061214b838383612ccf565b5050508015612160576000805461ff00191690555b5050505050565b6060606c8054806020026020016040519081016040528092919081815260200182805480156121bf57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121a1575b5050505050905090565b6040516001600160a01b03831660248201526044810182905261222c90849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526131b1565b505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff16146122a65760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116908216146123145760405162461bcd60e51b815260206004820152600e60248201526d2ab735b737bbb71029b2b73232b960911b6044820152606401610885565b61231d83613283565b60019150505b9392505050565b604080516001600160401b038616602082015280820185905283151560608083019190915260808083018590528351808403909101815260a083019093529161237c916103f29160039160c0016149bb565b6040516020818303038152906040529050949350505050565b6033546040516314b157ab60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926314b157ab92612433927f0000000000000000000000000000000000000000000000000000000000000000927f000000000000000000000000000000000000000000000000000000000000000090911691829161ffff16908890600401614a00565b600060405180830381600087803b15801561244d57600080fd5b505af1158015612461573d6000803e3d6000fd5b50506033546040517f90d92e80437532a834bc16642d235a7c34efc4d5690f3f6e69794c6d8c5c729093506124e392507f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009161ffff909116908690614a37565b60405180910390a150565b610bb88161ffff16111561253b5760405162461bcd60e51b815260206004820152601460248201527308ccaca40e0e4cadad2eada40e8dede40d0d2ced60631b6044820152606401610885565b6033805463ffff000019166201000061ffff8416908102919091179091556040519081527f938c72cb9ba014c7d4d26f156021299f8926dee2aab1421b32a2408a8261cf60906020016124e3565b600081116125d25760405162461bcd60e51b81526020600482015260166024820152754d757374206465706f73697420736f6d657468696e6760501b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146126235760405162461bcd60e51b81526004016108859061486f565b604051636e553f6560e01b8152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303816000875af19250505080156126ac575060408051601f3d908101601f191682019092526126a9918101906148a6565b60015b612794576126b8614a79565b806308c379a00361273057506126cc614a95565b806126d75750612732565b7fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d4816040516020016127099190614b18565b60408051601f198184030181529082905261272391614b50565b60405180910390a1505050565b505b3d80801561275c576040519150601f19603f3d011682016040523d82523d6000602084013e612761565b606091505b507fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d4816040516020016127099190614b63565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b600080808060606128108683612855565b945061281d866004612855565b935061282a86602c61287d565b925061283786604c61287d565b865190925061284a908790609490612897565b905091939590929450565b600061287461286f848461286a6004826148bf565b612897565b6132f7565b90505b92915050565b6000612874612892848461286a6020826148bf565b61332d565b6060828210156128df5760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420736c6963652072616e676560681b6044820152606401610885565b83518211156129305760405162461bcd60e51b815260206004820152601d60248201527f536c69636520656e6420657863656564732064617461206c656e6774680000006044820152606401610885565b600061293c848461485c565b90506000816001600160401b038111156129585761295861423d565b6040519080825280601f01601f191660200182016040528015612982576020820181803683370190505b50905060005b828110156129e7578661299b82886148bf565b815181106129ab576129ab61463b565b602001015160f81c60f81b8282815181106129c8576129c861463b565b60200101906001600160f81b031916908160001a905350600101612988565b5095945050505050565b6000612874612a06848461286a6020826148bf565b613364565b6000612a168261339b565b905063ffffffff8116600114612a655760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206d657373616765207479706560601b6044820152606401610885565b611c748484846133a8565b606c5460005b81811015610988576000606c8281548110612a9357612a9361463b565b60009182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa158015612ae6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b0a91906148a6565b90508015612b7a57606b54604080516001600160a01b039283168152918416602083015281018290527ff6c07a063ed4e63808eb8da7112d46dbcd38de2b40a73dbcc9353c5a94c723539060600160405180910390a1606b54612b7a906001600160a01b038481169116836121c9565b5050600101612a76565b8061ffff166103e81480612b9d57508061ffff166107d0145b612bdd5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152606401610885565b6033805461ffff191661ffff83169081179091556040519081527fe8fbd074d54232549e55ac463e02d202c16b1023e5d6aae276b3d8391b8c14bc906020016124e3565b6001600160a01b038116612c775760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f7220697320616464726573732830290000000000006044820152606401610885565b610dbe816134de565b61010380546001600160a01b0319166001600160a01b0383169081179091556040519081527f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee906020016124e3565b8251612ce290606c906020860190614123565b50815181518114612d2c5760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420696e7075742061727261797360601b6044820152606401610885565b60005b8181101561216057612d73848281518110612d4c57612d4c61463b565b6020026020010151848381518110612d6657612d6661463b565b6020026020010151613545565b600101612d2f565b60008111612dcb5760405162461bcd60e51b815260206004820152601760248201527f4d75737420776974686472617720736f6d657468696e670000000000000000006044820152606401610885565b6001600160a01b0383163014612e175760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614612e685760405162461bcd60e51b81526004016108859061486f565b604051632d182be560e21b815260048101829052306024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b460af94906064016020604051808303816000875af1925050508015612ef8575060408051601f3d908101601f19168201909252612ef5918101906148a6565b60015b612fe157612f04614a79565b806308c379a003612f7d5750612f18614a95565b80612f235750612f7f565b7f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f83481604051602001612f559190614bc1565b60408051601f1981840301815290829052612f6f91614b50565b60405180910390a150505050565b505b3d808015612fa9576040519150601f19603f3d011682016040523d82523d6000602084013e612fae565b606091505b507f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f83481604051602001612f559190614bfc565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a2505050565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af11580156130dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbe9190614824565b603380546bffffffffffffffffffffffff16600160601b6001600160a01b038416908102919091179091556040519081527f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e54906020016124e3565b61316583613101565b61316e82612b84565b613177816124ee565b5050600080525060346020527f2dc2afdad33a5feea586a9545052327b65d28efb10d11fa69e77da986a1031cd805460ff19166001179055565b6000613206826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166136aa9092919063ffffffff16565b80519091501561222c57808060200190518101906132249190614824565b61222c5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610885565b600061328e8261339b565b905060001963ffffffff821601156109885760011963ffffffff8216016132b857610988826136b9565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206d657373616765207479706560601b6044820152606401610885565b6000815160041461331a5760405162461bcd60e51b815260040161088590614c5d565b60e061332583614c8a565b901c92915050565b600081516020146133505760405162461bcd60e51b815260040161088590614c5d565b818060200190518101906128779190614cb1565b600081516020146133875760405162461bcd60e51b815260040161088590614c5d565b8180602001905181019061287791906148a6565b6000612877826004612855565b60006133b38261390b565b5090506133bf81613944565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613426573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061344a91906148a6565b9050620f42408110613480576134807f000000000000000000000000000000000000000000000000000000000000000082612589565b6033546000906134cb90600160201b90046001600160401b03166134c37f00000000000000000000000000000000000000000000000000000000000000006114bf565b60014261232a565b90506134d681612395565b505050505050565b806001600160a01b03166134fe600080516020614e2e8339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a3600080516020614e2e83398151915255565b6001600160a01b0382811660009081526067602052604090205416156135a25760405162461bcd60e51b81526020600482015260126024820152711c151bdad95b88185b1c9958591e481cd95d60721b6044820152606401610885565b6001600160a01b038216158015906135c257506001600160a01b03811615155b6136025760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b6044820152606401610885565b6001600160a01b03828116600081815260676020908152604080832080549587166001600160a01b031996871681179091556068805460018101825594527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c2209775390930180549095168417909455925190815290917fef6485b84315f9b1483beffa32aae9a0596890395e3d7521f1c5fbb51790e765910160405180910390a26109888282613ad7565b606061169d8484600085613adf565b6000806136c583613c07565b915091506136d282613944565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061375d91906148a6565b90508181101561382157613796307f0000000000000000000000000000000000000000000000000000000000000000611b50848661485c565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa1580156137fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061381e91906148a6565b90505b600061384c7f00000000000000000000000000000000000000000000000000000000000000006114bf565b9050620f424083101580156138615750828210155b1561389c5760335460009061388a90600160201b90046001600160401b03166134c3868561485c565b90506138968482613c15565b50612160565b6033546000906138bf90600160201b90046001600160401b03168360014261232a565b90506138ca81612395565b60408051858152602081018590527fff463b52b1f42eb360c2a871ee18d12dbc93807adffafa5b8fc6dea0051857a9910160405180910390a1505050505050565b600080613919836001613e94565b60008061392585613f4d565b8060200190518101906139389190614cce565b90969095509350505050565b6033546001600160401b03600160201b909104811690821681111561399b5760405162461bcd60e51b815260206004820152600d60248201526c4e6f6e636520746f6f206c6f7760981b6044820152606401610885565b6001600160401b03821660009081526034602052604090205460ff1615613a045760405162461bcd60e51b815260206004820152601760248201527f4e6f6e636520616c72656164792070726f6365737365640000000000000000006044820152606401610885565b6001600160401b038216600081815260346020908152604091829020805460ff1916600117905590519182527f8aa30b3e46076ef0187550969c01982aeb9af5db2eada56ab253a53e4c9946e9910160405180910390a1806001600160401b0316826001600160401b03161461098857603380546bffffffffffffffff000000001916600160201b6001600160401b038516908102919091179091556040519081527fc328b88555c22b57c1f2678e88ad3d9982d056ca6b05be82546e7b6bc6fda2db9060200160405180910390a15050565b61098861304d565b606082471015613b405760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610885565b843b613b8e5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610885565b600080866001600160a01b03168587604051613baa9190614cfc565b60006040518083038185875af1925050503d8060008114613be7576040519150601f19603f3d011682016040523d82523d6000602084013e613bec565b606091505b5091509150613bfc828286613f66565b979650505050505050565b600080613919836002613e94565b6509184e72a000821115613c635760405162461bcd60e51b81526020600482015260156024820152740a8ded6cadc40c2dadeeadce840e8dede40d0d2ced605b1b6044820152606401610885565b613cb76001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f000000000000000000000000000000000000000000000000000000000000000084613f9f565b60335460009062010000900461ffff16613cd2576000613cf7565b60335461271090613ced9062010000900461ffff1685614d18565b613cf79190614d2f565b60335460405163779b432d60e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263779b432d92613dc09288927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000909216917f00000000000000000000000000000000000000000000000000000000000000009183918a9161ffff909116908c90600401614d51565b600060405180830381600087803b158015613dda57600080fd5b505af1158015613dee573d6000803e3d6000fd5b50506033546040517f149007d4a77eb98d041de59e6ca469bd27b351b74f16c4d0648978322a1b8a77935061272392507f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918991889161ffff16908a90614db2565b6103f2613ea0836140b4565b63ffffffff1614613ef35760405162461bcd60e51b815260206004820152601e60248201527f496e76616c6964204f726967696e204d6573736167652056657273696f6e00006044820152606401610885565b8063ffffffff16613f038361339b565b63ffffffff16146109885760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964204d657373616765207479706560601b6044820152606401610885565b606061287760088351846128979092919063ffffffff16565b60608315613f75575081612323565b825115613f855782518084602001fd5b8160405162461bcd60e51b81526004016108859190614b50565b8015806140195750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015613ff3573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061401791906148a6565b155b6140845760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610885565b6040516001600160a01b03831660248201526044810182905261222c90849063095ea7b360e01b906064016121f5565b60006128778282612855565b828054828255906000526020600020908101928215614113579160200282015b828111156141135781546001600160a01b0319166001600160a01b038435161782556020909201916001909101906140e0565b5061411f929150614178565b5090565b828054828255906000526020600020908101928215614113579160200282015b8281111561411357825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190614143565b5b8082111561411f5760008155600101614179565b6001600160a01b0381168114610dbe57600080fd5b600080604083850312156141b557600080fd5b82356141c08161418d565b915060208301356141d08161418d565b809150509250929050565b6000602082840312156141ed57600080fd5b81356123238161418d565b6000806040838503121561420b57600080fd5b82356142168161418d565b946020939093013593505050565b803563ffffffff8116811461423857600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b03811182821017156142785761427861423d565b6040525050565b600082601f83011261429057600080fd5b81356001600160401b038111156142a9576142a961423d565b6040516142c0601f8301601f191660200182614253565b8181528460208386010111156142d557600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561430857600080fd5b61431185614224565b93506020850135925061432660408601614224565b915060608501356001600160401b0381111561434157600080fd5b61434d8782880161427f565b91505092959194509250565b60008083601f84011261436b57600080fd5b5081356001600160401b0381111561438257600080fd5b6020830191508360208260051b850101111561439d57600080fd5b9250929050565b600080600080606085870312156143ba57600080fd5b84356143c58161418d565b93506020850135925060408501356001600160401b038111156143e757600080fd5b6143f387828801614359565b95989497509550505050565b6001600160401b0381168114610dbe57600080fd5b60006020828403121561442657600080fd5b8135612323816143ff565b803561ffff8116811461423857600080fd5b60006020828403121561445557600080fd5b61287482614431565b6000806040838503121561447157600080fd5b82356001600160401b0381111561448757600080fd5b6144938582860161427f565b92505060208301356001600160401b038111156144af57600080fd5b6144bb8582860161427f565b9150509250929050565b6000602082840312156144d757600080fd5b5035919050565b600080602083850312156144f157600080fd5b82356001600160401b0381111561450757600080fd5b61393885828601614359565b60008060006060848603121561452857600080fd5b83356145338161418d565b925060208401356145438161418d565b929592945050506040919091013590565b6000806000806080858703121561456a57600080fd5b84356145758161418d565b935060208501356145858161418d565b925061459360408601614431565b91506145a160608601614431565b905092959194509250565b600081518084526020840193506020830160005b828110156145e75781516001600160a01b03168652602095860195909101906001016145c0565b5093949350505050565b60208152600061287460208301846145ac565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60808152600061466460808301876145ac565b828103602084015261467681876145ac565b83810360408501528551808252602080880193509091019060005b818110156146af578351835260209384019390920191600101614691565b50508381036060850152845180825260208083019350600582901b8301810190870160005b8381101561472f57848303601f190186528151805180855260209182019185019060005b818110156147165783518352602093840193909201916001016146f8565b50506020978801979094509290920191506001016146d4565b50909a9950505050505050505050565b60208082526028908201527f43616c6c6572206973206e6f74207468652053747261746567697374206f722060408201526723b7bb32b93737b960c11b606082015260800190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60005b838110156147ca5781810151838201526020016147b2565b50506000910152565b600081518084526147eb8160208601602086016147af565b601f01601f19169290920160200192915050565b60408152600061481260408301856147d3565b8281036020840152610a6981856147d3565b60006020828403121561483657600080fd5b8151801515811461232357600080fd5b634e487b7160e01b600052601160045260246000fd5b8181038181111561287757612877614846565b60208082526018908201527f556e657870656374656420617373657420616464726573730000000000000000604082015260600190565b6000602082840312156148b857600080fd5b5051919050565b8082018082111561287757612877614846565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6040808252845490820181905260008581526020812090916060840190835b818110156149665783546001600160a01b031683526001938401936020909301920161493f565b50508381036020808601919091528582520190508460005b858110156149af5781356149918161418d565b6001600160a01b03168352602092830192919091019060010161497e565b50909695505050505050565b63ffffffff60e01b8460e01b16815263ffffffff60e01b8360e01b166004820152600082516149f18160088501602087016147af565b91909101600801949350505050565b63ffffffff8616815284602082015283604082015263ffffffff8316606082015260a060808201526000613bfc60a08301846147d3565b63ffffffff85811682526001600160a01b038516602083015283166040820152608060608201819052600090614a6f908301846147d3565b9695505050505050565b600060033d1115614a925760046000803e5060005160e01c5b90565b600060443d1015614aa35790565b6040513d600319016004823e80513d60248201116001600160401b0382111715614acc57505090565b80820180516001600160401b03811115614ae7575050505090565b3d8401600319018282016020011115614b01575050505090565b614b1060208285010185614253565b509392505050565b6f02232b837b9b4ba103330b4b632b21d160851b815260008251614b438160108501602087016147af565b9190910160100192915050565b60208152600061287460208301846147d3565b7f4465706f736974206661696c65643a206c6f772d6c6576656c2063616c6c206681526f030b4b632b2103bb4ba34103230ba30960851b602082015260008251614bb48160308501602087016147af565b9190910160300192915050565b7202bb4ba34323930bbb0b6103330b4b632b21d1606d1b815260008251614bef8160138501602087016147af565b9190910160130192915050565b7f5769746864726177616c206661696c65643a206c6f772d6c6576656c2063616c815272036103330b4b632b2103bb4ba34103230ba309606d1b602082015260008251614c508160338501602087016147af565b9190910160330192915050565b602080825260139082015272092dcecc2d8d2c840c8c2e8c240d8cadccee8d606b1b604082015260600190565b80516020808301519190811015614cab576000198160200360031b1b821691505b50919050565b600060208284031215614cc357600080fd5b81516123238161418d565b60008060408385031215614ce157600080fd5b8251614cec816143ff565b6020939093015192949293505050565b60008251614d0e8184602087016147af565b9190910192915050565b808202811582820484141761287757612877614846565b600082614d4c57634e487b7160e01b600052601260045260246000fd5b500490565b88815263ffffffff8816602082015286604082015260018060a01b03861660608201528460808201528360a082015263ffffffff831660c082015261010060e08201526000614da46101008301846147d3565b9a9950505050505050505050565b63ffffffff88811682526001600160a01b038881166020840152871660408301526060820186905260808201859052831660a082015260e060c08201819052600090614e00908301846147d3565b999850505050505050505056fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45357bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa2646970667358221220e2f059eccac446855423527343f655a81f4122f7e91825b0c4623d4ffd9afd4d64736f6c634300081c0033", + "numDeployments": 2, + "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\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"cctpTokenMessenger\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"cctpMessageTransmitter\",\"type\":\"address\"},{\"internalType\":\"uint32\",\"name\":\"peerDomainID\",\"type\":\"uint32\"},{\"internalType\":\"address\",\"name\":\"peerStrategy\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"usdcToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"peerUsdcToken\",\"type\":\"address\"}],\"internalType\":\"struct AbstractCCTPIntegrator.CCTPIntegrationConfig\",\"name\":\"_cctpConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"adapter\",\"type\":\"address\"}],\"name\":\"IncompatibleAdapter\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"feePremiumBps\",\"type\":\"uint16\"}],\"name\":\"CCTPFeePremiumBpsSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint16\",\"name\":\"minFinalityThreshold\",\"type\":\"uint16\"}],\"name\":\"CCTPMinFinalityThresholdSet\",\"type\":\"event\"},{\"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\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"DepositUnderlyingFailed\",\"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\":false,\"internalType\":\"uint64\",\"name\":\"lastTransferNonce\",\"type\":\"uint64\"}],\"name\":\"LastTransferNonceUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"peerStrategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"minFinalityThreshold\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"}],\"name\":\"MessageTransmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"NonceProcessed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"}],\"name\":\"OperatorChanged\",\"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\":false,\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"StrategistUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"destinationDomain\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"peerStrategy\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"tokenAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint32\",\"name\":\"minFinalityThreshold\",\"type\":\"uint32\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"hookData\",\"type\":\"bytes\"}],\"name\":\"TokensBridged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"reason\",\"type\":\"string\"}],\"name\":\"WithdrawUnderlyingFailed\",\"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\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountRequested\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amountAvailable\",\"type\":\"uint256\"}],\"name\":\"WithdrawalFailed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_TRANSFER_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"MIN_TRANSFER_AMOUNT\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"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\":[],\"name\":\"cctpMessageTransmitter\",\"outputs\":[{\"internalType\":\"contract ICCTPMessageTransmitter\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cctpTokenMessenger\",\"outputs\":[{\"internalType\":\"contract ICCTPTokenMessenger\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_asset\",\"type\":\"address\"}],\"name\":\"checkBalance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"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\":\"feePremiumBps\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"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\":[{\"internalType\":\"uint32\",\"name\":\"sourceDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"finalityThresholdExecuted\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"handleReceiveFinalizedMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"sourceDomain\",\"type\":\"uint32\"},{\"internalType\":\"bytes32\",\"name\":\"sender\",\"type\":\"bytes32\"},{\"internalType\":\"uint32\",\"name\":\"finalityThresholdExecuted\",\"type\":\"uint32\"},{\"internalType\":\"bytes\",\"name\":\"messageBody\",\"type\":\"bytes\"}],\"name\":\"handleReceiveUnfinalizedMessage\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"harvesterAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_strategist\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"uint16\",\"name\":\"_minFinalityThreshold\",\"type\":\"uint16\"},{\"internalType\":\"uint16\",\"name\":\"_feePremiumBps\",\"type\":\"uint16\"}],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isGovernor\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"nonce\",\"type\":\"uint64\"}],\"name\":\"isNonceProcessed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isTransferPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastTransferNonce\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"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\":\"minFinalityThreshold\",\"outputs\":[{\"internalType\":\"uint16\",\"name\":\"\",\"type\":\"uint16\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"operator\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"peerDomainID\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"peerStrategy\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"peerUsdcToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"platformAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"message\",\"type\":\"bytes\"},{\"internalType\":\"bytes\",\"name\":\"attestation\",\"type\":\"bytes\"}],\"name\":\"relay\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"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\":[],\"name\":\"sendBalanceUpdate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_feePremiumBps\",\"type\":\"uint16\"}],\"name\":\"setFeePremiumBps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_harvesterAddress\",\"type\":\"address\"}],\"name\":\"setHarvesterAddress\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint16\",\"name\":\"_minFinalityThreshold\",\"type\":\"uint16\"}],\"name\":\"setMinFinalityThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"setOperator\",\"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\":[{\"internalType\":\"address\",\"name\":\"_address\",\"type\":\"address\"}],\"name\":\"setStrategistAddr\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"shareToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"strategistAddr\",\"outputs\":[{\"internalType\":\"address\",\"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\":\"usdcToken\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"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\":{\"_0\":\"balance Total value of the asset in the platform and contract\"}},\"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.\"}},\"handleReceiveFinalizedMessage(uint32,bytes32,uint32,bytes)\":{\"details\":\"Handles a finalized CCTP message\",\"params\":{\"finalityThresholdExecuted\":\"Fidelity threshold executed\",\"messageBody\":\"Message body\",\"sender\":\"Sender of the message\",\"sourceDomain\":\"Source domain of the message\"}},\"handleReceiveUnfinalizedMessage(uint32,bytes32,uint32,bytes)\":{\"details\":\"Handles an unfinalized but safe CCTP message\",\"params\":{\"finalityThresholdExecuted\":\"Fidelity threshold executed\",\"messageBody\":\"Message body\",\"sender\":\"Sender of the message\",\"sourceDomain\":\"Source domain of the message\"}},\"initialize(address,address,uint16,uint16)\":{\"details\":\"Initialize the strategy implementation\",\"params\":{\"_feePremiumBps\":\"Fee premium in basis points\",\"_minFinalityThreshold\":\"Minimum finality threshold\",\"_operator\":\"Address of the operator\",\"_strategist\":\"Address of the strategist\"}},\"isNonceProcessed(uint64)\":{\"details\":\"Checks if a given nonce is processed. Nonce starts at 1, so 0 is disregarded.\",\"params\":{\"nonce\":\"Nonce to check\"},\"returns\":{\"_0\":\"True if the nonce is processed, false otherwise\"}},\"isTransferPending()\":{\"details\":\"Checks if the last known transfer is pending. Nonce starts at 1, so 0 is disregarded.\",\"returns\":{\"_0\":\"True if a transfer is pending, false otherwise\"}},\"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.\"}},\"relay(bytes,bytes)\":{\"details\":\"Receives a message from the peer strategy on the other chain, does some basic checks and relays it to the local MessageTransmitterV2. If the message is a burn message, it will also handle the hook data and call the _onTokenReceived function.\",\"params\":{\"attestation\":\"Attestation of the message\",\"message\":\"Payload of the message to send\"}},\"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.\"},\"sendBalanceUpdate()\":{\"details\":\"Send balance update message to the peer strategy\"},\"setFeePremiumBps(uint16)\":{\"details\":\"Set the fee premium in basis points. Cannot be higher than 30% (3000 basis points).\",\"params\":{\"_feePremiumBps\":\"Fee premium in basis points\"}},\"setHarvesterAddress(address)\":{\"params\":{\"_harvesterAddress\":\"Address of the harvester contract.\"}},\"setMinFinalityThreshold(uint16)\":{\"details\":\"Set the minimum finality threshold at which the message is considered to be finalized to relay. Only accepts a value of 1000 (Safe, after 1 epoch) or 2000 (Finalized, after 2 epochs).\",\"params\":{\"_minFinalityThreshold\":\"Minimum finality threshold\"}},\"setOperator(address)\":{\"details\":\"Set the operator address\",\"params\":{\"_operator\":\"Operator address\"}},\"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\"}},\"setStrategistAddr(address)\":{\"details\":\"Set address of Strategist\",\"params\":{\"_address\":\"Address of Strategist\"}},\"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\":\"Interface requires a recipient, but for compatibility it must be address(this).\",\"params\":{\"_amount\":\"Amount of asset to withdraw\",\"_asset\":\"Address of asset to withdraw\",\"_recipient\":\"Address to receive withdrawn asset\"}},\"withdrawAll()\":{\"details\":\"Remove all assets from platform and send them to Vault contract.\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"MAX_TRANSFER_AMOUNT()\":{\"notice\":\"Max transfer threshold imposed by the CCTP Ref: https://developers.circle.com/cctp/evm-smart-contracts#depositforburn\"},\"MIN_TRANSFER_AMOUNT()\":{\"notice\":\"Minimum transfer amount to avoid zero or dust transfers\"},\"assetToPToken(address)\":{\"notice\":\"asset => pToken (Platform Specific Token Address)\"},\"cctpMessageTransmitter()\":{\"notice\":\"CCTP message transmitter contract\"},\"cctpTokenMessenger()\":{\"notice\":\"CCTP token messenger contract\"},\"checkBalance(address)\":{\"notice\":\"Get the total asset value held in the platform and contract\"},\"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.\"},\"feePremiumBps()\":{\"notice\":\"Fee premium in basis points\"},\"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.\"},\"lastTransferNonce()\":{\"notice\":\"Nonce of the last known deposit or withdrawal\"},\"merkleClaim(address,uint256,bytes32[])\":{\"notice\":\"Claim tokens from the Merkle Distributor\"},\"merkleDistributor()\":{\"notice\":\"The address of the Merkle Distributor contract.\"},\"minFinalityThreshold()\":{\"notice\":\"Minimum finality threshold Can be 1000 (safe, after 1 epoch) or 2000 (finalized, after 2 epochs). Ref: https://developers.circle.com/cctp/technical-guide#finality-thresholds\"},\"operator()\":{\"notice\":\"Operator address: Can relay CCTP messages\"},\"peerDomainID()\":{\"notice\":\"Domain ID of the chain from which messages are accepted\"},\"peerStrategy()\":{\"notice\":\"Strategy address on other chain\"},\"peerUsdcToken()\":{\"notice\":\"USDC address on remote chain\"},\"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.\"},\"usdcToken()\":{\"notice\":\"USDC address on local chain\"},\"vaultAddress()\":{\"notice\":\"Address of the OToken vault\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/strategies/crosschain/CrossChainRemoteStrategy.sol\":\"CrossChainRemoteStrategy\"},\"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/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\",\"keccak256\":\"0x9989400db5353221a725dd76a8b18c27e5c0b24c4732f3bb1e9324640a53290b\",\"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/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\",\"keccak256\":\"0x67c60863105b4a694bc6edc77777560120262fd4f883a5bbece53f0c70d88e7b\",\"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/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/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\",\"keccak256\":\"0x25f8398d7225b832a4d633e7478743272de704293210a2edf13c156bd1c6a9f0\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0x698e1d0bca8f9b8d6c5aa0a4b53c4378fb965eaf7c7c1a7980c306dfa4dcbc88\",\"license\":\"BUSL-1.1\"},\"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\",\"keccak256\":\"0xbe640419f622ed08d59c10f3ce206a015c524eaa2543c8882ff55a0cea4c6297\",\"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/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\",\"keccak256\":\"0x471aff77f4b6750abd8ed018fa3e89707f045ae377c73b225d413d62c1e9b28f\",\"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": "0x6101c060405234801561001157600080fd5b50604051615ad3380380615ad38339810160408190526100309161066a565b6080810151829081836001600160a01b0383166100945760405162461bcd60e51b815260206004820152601460248201527f496e76616c69642055534443206164647265737300000000000000000000000060448201526064015b60405180910390fd5b60a08101516001600160a01b03166100ee5760405162461bcd60e51b815260206004820152601960248201527f496e76616c696420706565722055534443206164647265737300000000000000604482015260640161008b565b80516001600160a01b031661013b5760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964204343545020636f6e66696760681b604482015260640161008b565b60208101516001600160a01b031661018b5760405162461bcd60e51b8152602060048201526013602482015272496e76616c6964204343545020636f6e66696760681b604482015260640161008b565b60608101516001600160a01b03166101e55760405162461bcd60e51b815260206004820152601d60248201527f496e76616c696420706565722073747261746567792061646472657373000000604482015260640161008b565b60208101516001600160a01b0390811660809081528251821660a052604083015163ffffffff166101005260608301518216610120528201805190911660c052516000906102329061046d565b90506000610249836080015161054d60201b60201c565b90508160061461029b5760405162461bcd60e51b815260206004820152601d60248201527f4261736520746f6b656e20646563696d616c73206d7573742062652036000000604482015260640161008b565b604051635553444360e01b602082015260240160405160208183030381529060405280519060200120816040516020016102d5919061076b565b60405160208183030381529060405280519060200120146103385760405162461bcd60e51b815260206004820152601960248201527f546f6b656e2073796d626f6c206d757374206265205553444300000000000000604482015260640161008b565b505060a001516001600160a01b0390811660e0528151811661014052602090910151811661016052915182166101805281166101a081905260c051909116146103b45760405162461bcd60e51b815260206004820152600e60248201526d0a8ded6cadc40dad2e6dac2e8c6d60931b604482015260640161008b565b81516001600160a01b031661040b5760405162461bcd60e51b815260206004820152601860248201527f496e76616c696420706c6174666f726d20616464726573730000000000000000604482015260640161008b565b60208201516001600160a01b0316156104665760405162461bcd60e51b815260206004820152601560248201527f496e76616c6964207661756c7420616464726573730000000000000000000000604482015260640161008b565b505061083e565b600080826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d29190610787565b60ff169050600481101580156104e9575060128111155b6105475760405162461bcd60e51b815260206004820152602960248201527f546f6b656e206d75737420686176652073756666696369656e7420646563696d604482015268616c20706c6163657360b81b606482015260840161008b565b92915050565b60606000826001600160a01b03166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa15801561058f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526105b791908101906107aa565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604080519081016001600160401b03811182821017156105f6576105f66105be565b60405290565b60405160c081016001600160401b03811182821017156105f6576105f66105be565b604051601f8201601f191681016001600160401b0381118282101715610646576106466105be565b604052919050565b80516001600160a01b038116811461066557600080fd5b919050565b60008082840361010081121561067f57600080fd5b604081121561068d57600080fd5b6106956105d4565b61069e8561064e565b81526106ac6020860161064e565b6020820152925060c0603f19820112156106c557600080fd5b506106ce6105fc565b6106da6040850161064e565b81526106e86060850161064e565b6020820152608084015163ffffffff8116811461070457600080fd5b604082015261071560a0850161064e565b606082015261072660c0850161064e565b608082015261073760e0850161064e565b60a0820152809150509250929050565b60005b8381101561076257818101518382015260200161074a565b50506000910152565b6000825161077d818460208701610747565b9190910192915050565b60006020828403121561079957600080fd5b815160ff811681146105b757600080fd5b6000602082840312156107bc57600080fd5b81516001600160401b038111156107d257600080fd5b8201601f810184136107e357600080fd5b80516001600160401b038111156107fc576107fc6105be565b61080f601f8201601f191660200161061e565b81815285602083850101111561082457600080fd5b610835826020830160208601610747565b95945050505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a0516150ae610a256000396000818161038c01528181610707015281816108fb015281816118ff01526132ba0152600081816105ba015281816127e70152613216015260006104bb0152600081816107ca015281816115b50152818161195301528181611a380152818161213201528181612683015281816130b1015261328a0152600081816105800152818161118b015281816122ed01528181612443015281816124f901528181613f91015261406d01526000818161065101528181610f1d0152818161227901528181612421015281816124d701528181613f6f015261404b01526000818161061a01526110460152600081816103d601528181610d3c015281816114c30152818161152a01528181611a5f01528181611b7101528181611f85015281816120de015281816126180152818161303f015281816135fd01528181613681015281816136c50152818161391001528181613993015281816139d601528181613a5301528181613e9b01528181613fb6015261408f0152600081816106d501528181610f9f01528181613ebd0152613f3f01526000818161068d015281816109990152818161122f0152818161170901526123f301526150ae6000f3fe608060405234801561001057600080fd5b506004361061030c5760003560e01c80636c9fa59e1161019d578063ad1728cb116100e9578063d9caed12116100a2578063df4426781161007c578063df442678146107f4578063f4537f7814610807578063f6ca71b014610822578063fc1b31131461083757600080fd5b8063d9caed12146107b2578063dbe55e56146107c5578063de5f6268146107ec57600080fd5b8063ad1728cb14610737578063b3ab15fb1461073f578063c2e1e3f414610752578063c7af335214610765578063d38bfff41461076d578063d7dd614b1461078057600080fd5b8063853828b6116101565780639136616a116101305780639136616a146106af57806396d538bb146106bd5780639748cf7c146106d0578063aa388af6146106f757600080fd5b8063853828b6146106445780638949f6f31461064c5780638c73eb041461068857600080fd5b80636c9fa59e146105b5578063773540b3146105dc5780637b2d9b2c146105ef5780637c92f219146106025780637ddfce2d146106155780638129fc1c1461063c57600080fd5b806342c8c11c1161025c578063570d8e1d116102155780635d36b190116101ef5780635d36b190146105605780635f515226146105685780636369e49f1461057b57806367c7066c146105a257600080fd5b8063570d8e1d146105315780635a063f63146105455780635a2364171461054d57600080fd5b806342c8c11c146104a3578063430bf08a146104b657806347e7ef24146104dd5780635324df32146104f0578063564a515814610504578063570ca7351461051757600080fd5b806311eac855116102c9578063237839f0116102a3578063237839f01461044457806323c9ab3d146104575780633335ad7f146104835780633c3dbbc71461048b57600080fd5b806311eac855146103d157806316a0f250146103f85780631801c4081461041957600080fd5b80630c340a24146103115780630ed57b3a146103365780630fc3b4c41461034b5780631072cbea146103745780631083f7611461038757806311cffb67146103ae575b600080fd5b610319610844565b6040516001600160a01b0390911681526020015b60405180910390f35b6103496103443660046143cd565b610861565b005b610319610359366004614406565b6067602052600090815260409020546001600160a01b031681565b610349610382366004614423565b6108cd565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c16103bc36600461451d565b61098c565b604051901515815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6033546104069061ffff1681565b60405161ffff909116815260200161032d565b603354600160201b90046001600160401b031660009081526034602052604090205460ff16156103c1565b6103496104523660046145cf565b610a72565b6103c161046536600461463f565b6001600160401b031660009081526034602052604090205460ff1690565b610349610c91565b610495620f424081565b60405190815260200161032d565b6103496104b136600461466e565b610d91565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496104eb366004614423565b610dc1565b6033546104069062010000900461ffff1681565b610349610512366004614689565b610e43565b60335461031990600160601b90046001600160a01b031681565b61010354610319906001600160a01b031681565b61034961134d565b61034961055b36600461466e565b6113ec565b610349611419565b610495610576366004614406565b6114bf565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b606b54610319906001600160a01b031681565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496105ea366004614406565b6116a5565b6103196105fd3660046146f0565b6116d2565b6103c161061036600461451d565b6116fc565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611834565b6103496119c7565b6106737f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496103443660046146f0565b6103496106cb366004614709565b611ba1565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c1610705366004614406565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610349611cbe565b61034961074d366004614406565b611cea565b610349610760366004614406565b611d17565b6103c1611da4565b61034961077b366004614406565b611dd5565b60335461079a90600160201b90046001600160401b031681565b6040516001600160401b03909116815260200161032d565b6103496107c036600461473e565b611e79565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611efd565b61034961080236600461477f565b611fff565b610319733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b61082a6121ab565b60405161032d919061481c565b6104956509184e72a00081565b600061085c6000805160206150598339815191525490565b905090565b610869611da4565b61088e5760405162461bcd60e51b81526004016108859061482f565b60405180910390fd5b60405162461bcd60e51b81526020600482015260146024820152733ab739bab83837b93a32b210333ab731ba34b7b760611b6044820152606401610885565b6108d5611da4565b6108f15760405162461bcd60e51b81526004016108859061482f565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169083160361096c5760405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220737570706f72746564206173736574006044820152606401610885565b610988610977610844565b6001600160a01b038416908361220d565b5050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a065760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b6107d08363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b610a69858584612275565b95945050505050565b604080516001808252818301909252600091602080830190803683370190505090503081600081518110610aa857610aa8614866565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610af957610af9614866565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610b4a57610b4a614866565b6020908102919091010152604080516001808252818301909252600091816020015b6060815260200190600190039081610b6c5790505090508585808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250855186945090925015159050610bca57610bca614866565b60209081029190910101526040516301c7ba5760e61b8152733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae906371ee95c090610c1290879087908790879060040161487c565b600060405180830381600087803b158015610c2c57600080fd5b505af1158015610c40573d6000803e3d6000fd5b50505050876001600160a01b03167f2d5429efdeca7741a8cd94067b18d988bc4e5f1d5b8272c37b7bfc31e9bfa32c88604051610c7f91815260200190565b60405180910390a25050505050505050565b603354600160601b90046001600160a01b0316331480610cbc5750610103546001600160a01b031633145b80610cca5750610cca611da4565b610d355760405162461bcd60e51b815260206004820152603660248201527f43616c6c6572206973206e6f7420746865204f70657261746f722c20537472616044820152753a32b3b4b9ba1037b9103a34329023b7bb32b93737b960511b6064820152608401610885565b6000610d607f00000000000000000000000000000000000000000000000000000000000000006114bf565b90506000610d86603360049054906101000a90046001600160401b03168360004261236e565b9050610988816123d9565b610d99611da4565b610db55760405162461bcd60e51b81526004016108859061482f565b610dbe81612532565b50565b610103546001600160a01b0316331480610dde5750610dde611da4565b610dfa5760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101610e2c5760405162461bcd60e51b8152600401610885906149b2565b60028255610e3a84846125cd565b50600190555050565b603354600160601b90046001600160a01b03163314610ea45760405162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865204f70657261746f720000000000006044820152606401610885565b6000806000806000610eb587612843565b94509450945094509450600163ffffffff168563ffffffff1614610f1b5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c69642043435450206d6573736167652076657273696f6e000000006044820152606401610885565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff1614610f8e5760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b610f99816000612899565b945060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614905080156110da578563ffffffff166001148015610ff25750815160e411155b6110355760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206275726e206d65737361676560601b6044820152606401610885565b60006110428360046128c1565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146110ba5760405162461bcd60e51b815260206004820152601260248201527124b73b30b634b210313ab937103a37b5b2b760711b6044820152606401610885565b6110c58360646128c1565b94506110d28360246128c1565b935050611131565b63ffffffff86166103f2146111315760405162461bcd60e51b815260206004820152601b60248201527f556e737570706f72746564206d6573736167652076657273696f6e00000000006044820152606401610885565b306001600160a01b038416146111895760405162461bcd60e51b815260206004820152601c60248201527f556e657870656374656420726563697069656e742061646472657373000000006044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146112155760405162461bcd60e51b815260206004820152602260248201527f496e636f72726563742073656e6465722f726563697069656e74206164647265604482015261737360f01b6064820152608401610885565b604051630afd9fa560e31b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906357ecfd2890611266908c908c90600401614a2a565b6020604051808303816000875af1158015611285573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a99190614a4f565b9050806112f15760405162461bcd60e51b8152602060048201526016602482015275149958d95a5d99481b595cdcd859d94819985a5b195960521b6044820152606401610885565b811561134257825160009061130a90859060e4906128db565b90506000611319856044612a35565b905060006113288660a4612a35565b905061133e6113378284614a87565b8285612a4f565b5050505b505050505050505050565b606b546001600160a01b031633146113a75760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206973206e6f74207468652048617276657374657200000000006044820152606401610885565b600080516020615039833981519152805460011981016113d95760405162461bcd60e51b8152600401610885906149b2565b600282556113e5612ab4565b5060019055565b6113f4611da4565b6114105760405162461bcd60e51b81526004016108859061482f565b610dbe81612bc8565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146114b45760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b6064820152608401610885565b6114bd33612c65565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146115125760405162461bcd60e51b815260040161088590614a9a565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159d9190614ad1565b6040516370a0823160e01b81523060048201529091507f00000000000000000000000000000000000000000000000000000000000000009082906001600160a01b03831690634cdad5069082906370a0823190602401602060405180830381865afa158015611610573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116349190614ad1565b6040518263ffffffff1660e01b815260040161165291815260200190565b602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116939190614ad1565b61169d9190614aea565b949350505050565b6116ad611da4565b6116c95760405162461bcd60e51b81526004016108859061482f565b610dbe81612cc4565b606c81815481106116e257600080fd5b6000918252602090912001546001600160a01b0316905081565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117765760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b60335461ffff166103e8146117dc5760405162461bcd60e51b815260206004820152602660248201527f556e66696e616c697a6564206d6573736167657320617265206e6f74207375706044820152651c1bdc9d195960d21b6064820152608401610885565b6103e88363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b61183c611da4565b6118585760405162461bcd60e51b81526004016108859061482f565b600054610100900460ff1680611871575060005460ff16155b61188d5760405162461bcd60e51b815260040161088590614afd565b600054610100900460ff161580156118af576000805461ffff19166101011790555b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008260008151811061193157611931614866565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160008151811061198557611985614866565b60200260200101906001600160a01b031690816001600160a01b0316815250506119b0838383612d13565b5050508015610dbe576000805461ff001916905550565b610103546001600160a01b03163314806119e457506119e4611da4565b611a005760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101611a325760405162461bcd60e51b8152600401610885906149b2565b600282557f00000000000000000000000000000000000000000000000000000000000000006000611a83827f0000000000000000000000000000000000000000000000000000000000000000612dbf565b6040516370a0823160e01b8152306004820152909150600090611b639083906001600160a01b03861690634cdad5069082906370a0823190602401602060405180830381865afa158015611adb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aff9190614ad1565b6040518263ffffffff1660e01b8152600401611b1d91815260200190565b602060405180830381865afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e9190614ad1565b612f8b565b90508015611b9657611b96307f000000000000000000000000000000000000000000000000000000000000000083612fa1565b505050600182555050565b611ba9611da4565b611bc55760405162461bcd60e51b81526004016108859061482f565b8060005b81811015611c6f576000848483818110611be557611be5614866565b9050602002016020810190611bfa9190614406565b6001600160a01b031603611c675760405162461bcd60e51b815260206004820152602e60248201527f43616e206e6f742073657420616e20656d70747920616464726573732061732060448201526d30903932bbb0b932103a37b5b2b760911b6064820152608401610885565b600101611bc9565b507f04c0b9649497d316554306e53678d5f5f5dbc3a06f97dec13ff4cfe98b986bbc606c8484604051611ca493929190614b4b565b60405180910390a1611cb8606c84846142eb565b50505050565b611cc6611da4565b611ce25760405162461bcd60e51b81526004016108859061482f565b6114bd613273565b611cf2611da4565b611d0e5760405162461bcd60e51b81526004016108859061482f565b610dbe81613327565b611d1f611da4565b611d3b5760405162461bcd60e51b81526004016108859061482f565b606b54604080516001600160a01b03928316815291831660208301527fe48386b84419f4d36e0f96c10cc3510b6fb1a33795620c5098b22472bbe90796910160405180910390a1606b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611dbc6000805160206150598339815191525490565b6001600160a01b0316336001600160a01b031614905090565b611ddd611da4565b611df95760405162461bcd60e51b81526004016108859061482f565b611e21817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316611e416000805160206150598339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610103546001600160a01b0316331480611e965750611e96611da4565b611eb25760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101611ee45760405162461bcd60e51b8152600401610885906149b2565b60028255611ef3858585612fa1565b5060019055505050565b610103546001600160a01b0316331480611f1a5750611f1a611da4565b611f365760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101611f685760405162461bcd60e51b8152600401610885906149b2565b600282556040516370a0823160e01b81523060048201526113e5907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038216906370a0823190602401602060405180830381865afa158015611fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ffa9190614ad1565b6125cd565b612007611da4565b6120235760405162461bcd60e51b81526004016108859061482f565b600054610100900460ff168061203c575060005460ff16155b6120585760405162461bcd60e51b815260040161088590614afd565b600054610100900460ff1615801561207a576000805461ffff19166101011790555b612085848484613382565b61208e85612cc4565b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008260008151811061211057612110614866565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160008151811061216457612164614866565b60200260200101906001600160a01b031690816001600160a01b03168152505061218f838383612d13565b50505080156121a4576000805461ff00191690555b5050505050565b6060606c80548060200260200160405190810160405280929190818152602001828054801561220357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121e5575b5050505050905090565b6040516001600160a01b03831660248201526044810182905261227090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526133d7565b505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff16146122ea5760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116908216146123585760405162461bcd60e51b815260206004820152600e60248201526d2ab735b737bbb71029b2b73232b960911b6044820152606401610885565b612361836134a9565b60019150505b9392505050565b604080516001600160401b038616602082015280820185905283151560608083019190915260808083018590528351808403909101815260a08301909352916123c0916103f29160039160c001614be6565b6040516020818303038152906040529050949350505050565b6033546040516314b157ab60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926314b157ab92612477927f0000000000000000000000000000000000000000000000000000000000000000927f000000000000000000000000000000000000000000000000000000000000000090911691829161ffff16908890600401614c2b565b600060405180830381600087803b15801561249157600080fd5b505af11580156124a5573d6000803e3d6000fd5b50506033546040517f90d92e80437532a834bc16642d235a7c34efc4d5690f3f6e69794c6d8c5c7290935061252792507f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009161ffff909116908690614c62565b60405180910390a150565b610bb88161ffff16111561257f5760405162461bcd60e51b815260206004820152601460248201527308ccaca40e0e4cadad2eada40e8dede40d0d2ced60631b6044820152606401610885565b6033805463ffff000019166201000061ffff8416908102919091179091556040519081527f938c72cb9ba014c7d4d26f156021299f8926dee2aab1421b32a2408a8261cf6090602001612527565b600081116126165760405162461bcd60e51b81526020600482015260166024820152754d757374206465706f73697420736f6d657468696e6760501b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146126675760405162461bcd60e51b815260040161088590614a9a565b604051636e553f6560e01b8152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303816000875af19250505080156126f0575060408051601f3d908101601f191682019092526126ed91810190614ad1565b60015b6127d8576126fc614ca4565b806308c379a0036127745750612710614cc0565b8061271b5750612776565b7fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d48160405160200161274d9190614d43565b60408051601f198184030181529082905261276791614d7b565b60405180910390a1505050565b505b3d8080156127a0576040519150601f19603f3d011682016040523d82523d6000602084013e6127a5565b606091505b507fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d48160405160200161274d9190614d8e565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b600080808060606128548683612899565b9450612861866004612899565b935061286e86602c6128c1565b925061287b86604c6128c1565b865190925061288e9087906094906128db565b905091939590929450565b60006128b86128b384846128ae600482614aea565b6128db565b61351d565b90505b92915050565b60006128b86128d684846128ae602082614aea565b613553565b6060828210156129235760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420736c6963652072616e676560681b6044820152606401610885565b83518211156129745760405162461bcd60e51b815260206004820152601d60248201527f536c69636520656e6420657863656564732064617461206c656e6774680000006044820152606401610885565b60006129808484614a87565b90506000816001600160401b0381111561299c5761299c614468565b6040519080825280601f01601f1916602001820160405280156129c6576020820181803683370190505b50905060005b82811015612a2b57866129df8288614aea565b815181106129ef576129ef614866565b602001015160f81c60f81b828281518110612a0c57612a0c614866565b60200101906001600160f81b031916908160001a9053506001016129cc565b5095945050505050565b60006128b8612a4a84846128ae602082614aea565b61358a565b6000612a5a826135c1565b905063ffffffff8116600114612aa95760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206d657373616765207479706560601b6044820152606401610885565b611cb88484846135ce565b606c5460005b81811015610988576000606c8281548110612ad757612ad7614866565b60009182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa158015612b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4e9190614ad1565b90508015612bbe57606b54604080516001600160a01b039283168152918416602083015281018290527ff6c07a063ed4e63808eb8da7112d46dbcd38de2b40a73dbcc9353c5a94c723539060600160405180910390a1606b54612bbe906001600160a01b0384811691168361220d565b5050600101612aba565b8061ffff166103e81480612be157508061ffff166107d0145b612c215760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152606401610885565b6033805461ffff191661ffff83169081179091556040519081527fe8fbd074d54232549e55ac463e02d202c16b1023e5d6aae276b3d8391b8c14bc90602001612527565b6001600160a01b038116612cbb5760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f7220697320616464726573732830290000000000006044820152606401610885565b610dbe81613704565b61010380546001600160a01b0319166001600160a01b0383169081179091556040519081527f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee90602001612527565b8251612d2690606c90602086019061434e565b50815181518114612d705760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420696e7075742061727261797360601b6044820152606401610885565b60005b818110156121a457612db7848281518110612d9057612d90614866565b6020026020010151848381518110612daa57612daa614866565b602002602001015161376b565b600101612d73565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908316906370a0823190602401602060405180830381865afa158015612e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2d9190614ad1565b90506000836001600160a01b031663ad468d116040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e939190614dec565b9050806001600160a01b031663e4baaddf6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612eef575060408051601f3d908101601f19168201909252612eec91810190614dec565b60015b612f1757604051630a10bc7f60e41b81526001600160a01b0382166004820152602401610885565b60405163ce96cb7760e01b81526001600160a01b03838116600483015282169063ce96cb7790602401602060405180830381865afa158015612f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f819190614ad1565b610a699084614aea565b6000818310612f9a57816128b8565b5090919050565b60008111612ff15760405162461bcd60e51b815260206004820152601760248201527f4d75737420776974686472617720736f6d657468696e670000000000000000006044820152606401610885565b6001600160a01b038316301461303d5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461308e5760405162461bcd60e51b815260040161088590614a9a565b604051632d182be560e21b815260048101829052306024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b460af94906064016020604051808303816000875af192505050801561311e575060408051601f3d908101601f1916820190925261311b91810190614ad1565b60015b6132075761312a614ca4565b806308c379a0036131a3575061313e614cc0565b8061314957506131a5565b7f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f8348160405160200161317b9190614e09565b60408051601f198184030181529082905261319591614d7b565b60405180910390a150505050565b505b3d8080156131cf576040519150601f19603f3d011682016040523d82523d6000602084013e6131d4565b606091505b507f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f8348160405160200161317b9190614e44565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a2505050565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015613303573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbe9190614a4f565b603380546bffffffffffffffffffffffff16600160601b6001600160a01b038416908102919091179091556040519081527f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e5490602001612527565b61338b83613327565b61339482612bc8565b61339d81612532565b5050600080525060346020527f2dc2afdad33a5feea586a9545052327b65d28efb10d11fa69e77da986a1031cd805460ff19166001179055565b600061342c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166138d09092919063ffffffff16565b805190915015612270578080602001905181019061344a9190614a4f565b6122705760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610885565b60006134b4826135c1565b905060001963ffffffff821601156109885760011963ffffffff8216016134de57610988826138df565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206d657373616765207479706560601b6044820152606401610885565b600081516004146135405760405162461bcd60e51b815260040161088590614ea5565b60e061354b83614ed2565b901c92915050565b600081516020146135765760405162461bcd60e51b815260040161088590614ea5565b818060200190518101906128bb9190614dec565b600081516020146135ad5760405162461bcd60e51b815260040161088590614ea5565b818060200190518101906128bb9190614ad1565b60006128bb826004612899565b60006135d982613b36565b5090506135e581613b6f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561364c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136709190614ad1565b9050620f424081106136a6576136a67f0000000000000000000000000000000000000000000000000000000000000000826125cd565b6033546000906136f190600160201b90046001600160401b03166136e97f00000000000000000000000000000000000000000000000000000000000000006114bf565b60014261236e565b90506136fc816123d9565b505050505050565b806001600160a01b03166137246000805160206150598339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a360008051602061505983398151915255565b6001600160a01b0382811660009081526067602052604090205416156137c85760405162461bcd60e51b81526020600482015260126024820152711c151bdad95b88185b1c9958591e481cd95d60721b6044820152606401610885565b6001600160a01b038216158015906137e857506001600160a01b03811615155b6138285760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b6044820152606401610885565b6001600160a01b03828116600081815260676020908152604080832080549587166001600160a01b031996871681179091556068805460018101825594527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c2209775390930180549095168417909455925190815290917fef6485b84315f9b1483beffa32aae9a0596890395e3d7521f1c5fbb51790e765910160405180910390a26109888282613d02565b606061169d8484600085613d0a565b6000806138eb83613e32565b915091506138f882613b6f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561395f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139839190614ad1565b905081811015613a4c576139c1307f00000000000000000000000000000000000000000000000000000000000000006139bc8486614a87565b612fa1565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613a25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a499190614ad1565b90505b6000613a777f00000000000000000000000000000000000000000000000000000000000000006114bf565b9050620f42408310158015613a8c5750828210155b15613ac757603354600090613ab590600160201b90046001600160401b03166136e98685614a87565b9050613ac18482613e40565b506121a4565b603354600090613aea90600160201b90046001600160401b03168360014261236e565b9050613af5816123d9565b60408051858152602081018590527fff463b52b1f42eb360c2a871ee18d12dbc93807adffafa5b8fc6dea0051857a9910160405180910390a1505050505050565b600080613b448360016140bf565b600080613b5085614178565b806020019051810190613b639190614ef9565b90969095509350505050565b6033546001600160401b03600160201b9091048116908216811115613bc65760405162461bcd60e51b815260206004820152600d60248201526c4e6f6e636520746f6f206c6f7760981b6044820152606401610885565b6001600160401b03821660009081526034602052604090205460ff1615613c2f5760405162461bcd60e51b815260206004820152601760248201527f4e6f6e636520616c72656164792070726f6365737365640000000000000000006044820152606401610885565b6001600160401b038216600081815260346020908152604091829020805460ff1916600117905590519182527f8aa30b3e46076ef0187550969c01982aeb9af5db2eada56ab253a53e4c9946e9910160405180910390a1806001600160401b0316826001600160401b03161461098857603380546bffffffffffffffff000000001916600160201b6001600160401b038516908102919091179091556040519081527fc328b88555c22b57c1f2678e88ad3d9982d056ca6b05be82546e7b6bc6fda2db9060200160405180910390a15050565b610988613273565b606082471015613d6b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610885565b843b613db95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610885565b600080866001600160a01b03168587604051613dd59190614f27565b60006040518083038185875af1925050503d8060008114613e12576040519150601f19603f3d011682016040523d82523d6000602084013e613e17565b606091505b5091509150613e27828286614191565b979650505050505050565b600080613b448360026140bf565b6509184e72a000821115613e8e5760405162461bcd60e51b81526020600482015260156024820152740a8ded6cadc40c2dadeeadce840e8dede40d0d2ced605b1b6044820152606401610885565b613ee26001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000846141ca565b60335460009062010000900461ffff16613efd576000613f22565b60335461271090613f189062010000900461ffff1685614f43565b613f229190614f5a565b60335460405163779b432d60e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263779b432d92613feb9288927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000909216917f00000000000000000000000000000000000000000000000000000000000000009183918a9161ffff909116908c90600401614f7c565b600060405180830381600087803b15801561400557600080fd5b505af1158015614019573d6000803e3d6000fd5b50506033546040517f149007d4a77eb98d041de59e6ca469bd27b351b74f16c4d0648978322a1b8a77935061276792507f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918991889161ffff16908a90614fdd565b6103f26140cb836142df565b63ffffffff161461411e5760405162461bcd60e51b815260206004820152601e60248201527f496e76616c6964204f726967696e204d6573736167652056657273696f6e00006044820152606401610885565b8063ffffffff1661412e836135c1565b63ffffffff16146109885760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964204d657373616765207479706560601b6044820152606401610885565b60606128bb60088351846128db9092919063ffffffff16565b606083156141a0575081612367565b8251156141b05782518084602001fd5b8160405162461bcd60e51b81526004016108859190614d7b565b8015806142445750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561421e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142429190614ad1565b155b6142af5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610885565b6040516001600160a01b03831660248201526044810182905261227090849063095ea7b360e01b90606401612239565b60006128bb8282612899565b82805482825590600052602060002090810192821561433e579160200282015b8281111561433e5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019061430b565b5061434a9291506143a3565b5090565b82805482825590600052602060002090810192821561433e579160200282015b8281111561433e57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061436e565b5b8082111561434a57600081556001016143a4565b6001600160a01b0381168114610dbe57600080fd5b600080604083850312156143e057600080fd5b82356143eb816143b8565b915060208301356143fb816143b8565b809150509250929050565b60006020828403121561441857600080fd5b8135612367816143b8565b6000806040838503121561443657600080fd5b8235614441816143b8565b946020939093013593505050565b803563ffffffff8116811461446357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b03811182821017156144a3576144a3614468565b6040525050565b600082601f8301126144bb57600080fd5b81356001600160401b038111156144d4576144d4614468565b6040516144eb601f8301601f19166020018261447e565b81815284602083860101111561450057600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561453357600080fd5b61453c8561444f565b9350602085013592506145516040860161444f565b915060608501356001600160401b0381111561456c57600080fd5b614578878288016144aa565b91505092959194509250565b60008083601f84011261459657600080fd5b5081356001600160401b038111156145ad57600080fd5b6020830191508360208260051b85010111156145c857600080fd5b9250929050565b600080600080606085870312156145e557600080fd5b84356145f0816143b8565b93506020850135925060408501356001600160401b0381111561461257600080fd5b61461e87828801614584565b95989497509550505050565b6001600160401b0381168114610dbe57600080fd5b60006020828403121561465157600080fd5b81356123678161462a565b803561ffff8116811461446357600080fd5b60006020828403121561468057600080fd5b6128b88261465c565b6000806040838503121561469c57600080fd5b82356001600160401b038111156146b257600080fd5b6146be858286016144aa565b92505060208301356001600160401b038111156146da57600080fd5b6146e6858286016144aa565b9150509250929050565b60006020828403121561470257600080fd5b5035919050565b6000806020838503121561471c57600080fd5b82356001600160401b0381111561473257600080fd5b613b6385828601614584565b60008060006060848603121561475357600080fd5b833561475e816143b8565b9250602084013561476e816143b8565b929592945050506040919091013590565b6000806000806080858703121561479557600080fd5b84356147a0816143b8565b935060208501356147b0816143b8565b92506147be6040860161465c565b91506147cc6060860161465c565b905092959194509250565b600081518084526020840193506020830160005b828110156148125781516001600160a01b03168652602095860195909101906001016147eb565b5093949350505050565b6020815260006128b860208301846147d7565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60808152600061488f60808301876147d7565b82810360208401526148a181876147d7565b83810360408501528551808252602080880193509091019060005b818110156148da5783518352602093840193909201916001016148bc565b50508381036060850152845180825260208083019350600582901b8301810190870160005b8381101561495a57848303601f190186528151805180855260209182019185019060005b81811015614941578351835260209384019390920191600101614923565b50506020978801979094509290920191506001016148ff565b50909a9950505050505050505050565b60208082526028908201527f43616c6c6572206973206e6f74207468652053747261746567697374206f722060408201526723b7bb32b93737b960c11b606082015260800190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60005b838110156149f55781810151838201526020016149dd565b50506000910152565b60008151808452614a168160208601602086016149da565b601f01601f19169290920160200192915050565b604081526000614a3d60408301856149fe565b8281036020840152610a6981856149fe565b600060208284031215614a6157600080fd5b8151801515811461236757600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156128bb576128bb614a71565b60208082526018908201527f556e657870656374656420617373657420616464726573730000000000000000604082015260600190565b600060208284031215614ae357600080fd5b5051919050565b808201808211156128bb576128bb614a71565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6040808252845490820181905260008581526020812090916060840190835b81811015614b915783546001600160a01b0316835260019384019360209093019201614b6a565b50508381036020808601919091528582520190508460005b85811015614bda578135614bbc816143b8565b6001600160a01b031683526020928301929190910190600101614ba9565b50909695505050505050565b63ffffffff60e01b8460e01b16815263ffffffff60e01b8360e01b16600482015260008251614c1c8160088501602087016149da565b91909101600801949350505050565b63ffffffff8616815284602082015283604082015263ffffffff8316606082015260a060808201526000613e2760a08301846149fe565b63ffffffff85811682526001600160a01b038516602083015283166040820152608060608201819052600090614c9a908301846149fe565b9695505050505050565b600060033d1115614cbd5760046000803e5060005160e01c5b90565b600060443d1015614cce5790565b6040513d600319016004823e80513d60248201116001600160401b0382111715614cf757505090565b80820180516001600160401b03811115614d12575050505090565b3d8401600319018282016020011115614d2c575050505090565b614d3b6020828501018561447e565b509392505050565b6f02232b837b9b4ba103330b4b632b21d160851b815260008251614d6e8160108501602087016149da565b9190910160100192915050565b6020815260006128b860208301846149fe565b7f4465706f736974206661696c65643a206c6f772d6c6576656c2063616c6c206681526f030b4b632b2103bb4ba34103230ba30960851b602082015260008251614ddf8160308501602087016149da565b9190910160300192915050565b600060208284031215614dfe57600080fd5b8151612367816143b8565b7202bb4ba34323930bbb0b6103330b4b632b21d1606d1b815260008251614e378160138501602087016149da565b9190910160130192915050565b7f5769746864726177616c206661696c65643a206c6f772d6c6576656c2063616c815272036103330b4b632b2103bb4ba34103230ba309606d1b602082015260008251614e988160338501602087016149da565b9190910160330192915050565b602080825260139082015272092dcecc2d8d2c840c8c2e8c240d8cadccee8d606b1b604082015260600190565b80516020808301519190811015614ef3576000198160200360031b1b821691505b50919050565b60008060408385031215614f0c57600080fd5b8251614f178161462a565b6020939093015192949293505050565b60008251614f398184602087016149da565b9190910192915050565b80820281158282048414176128bb576128bb614a71565b600082614f7757634e487b7160e01b600052601260045260246000fd5b500490565b88815263ffffffff8816602082015286604082015260018060a01b03861660608201528460808201528360a082015263ffffffff831660c082015261010060e08201526000614fcf6101008301846149fe565b9a9950505050505050505050565b63ffffffff88811682526001600160a01b038881166020840152871660408301526060820186905260808201859052831660a082015260e060c0820181905260009061502b908301846149fe565b999850505050505050505056fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45357bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa26469706673582212205efb2307624767aeb27588fe9404d68ff6927a3d5bce673b7daad0b21273912564736f6c634300081c0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061030c5760003560e01c80636c9fa59e1161019d578063ad1728cb116100e9578063d9caed12116100a2578063df4426781161007c578063df442678146107f4578063f4537f7814610807578063f6ca71b014610822578063fc1b31131461083757600080fd5b8063d9caed12146107b2578063dbe55e56146107c5578063de5f6268146107ec57600080fd5b8063ad1728cb14610737578063b3ab15fb1461073f578063c2e1e3f414610752578063c7af335214610765578063d38bfff41461076d578063d7dd614b1461078057600080fd5b8063853828b6116101565780639136616a116101305780639136616a146106af57806396d538bb146106bd5780639748cf7c146106d0578063aa388af6146106f757600080fd5b8063853828b6146106445780638949f6f31461064c5780638c73eb041461068857600080fd5b80636c9fa59e146105b5578063773540b3146105dc5780637b2d9b2c146105ef5780637c92f219146106025780637ddfce2d146106155780638129fc1c1461063c57600080fd5b806342c8c11c1161025c578063570d8e1d116102155780635d36b190116101ef5780635d36b190146105605780635f515226146105685780636369e49f1461057b57806367c7066c146105a257600080fd5b8063570d8e1d146105315780635a063f63146105455780635a2364171461054d57600080fd5b806342c8c11c146104a3578063430bf08a146104b657806347e7ef24146104dd5780635324df32146104f0578063564a515814610504578063570ca7351461051757600080fd5b806311eac855116102c9578063237839f0116102a3578063237839f01461044457806323c9ab3d146104575780633335ad7f146104835780633c3dbbc71461048b57600080fd5b806311eac855146103d157806316a0f250146103f85780631801c4081461041957600080fd5b80630c340a24146103115780630ed57b3a146103365780630fc3b4c41461034b5780631072cbea146103745780631083f7611461038757806311cffb67146103ae575b600080fd5b610319610844565b6040516001600160a01b0390911681526020015b60405180910390f35b6103496103443660046143cd565b610861565b005b610319610359366004614406565b6067602052600090815260409020546001600160a01b031681565b610349610382366004614423565b6108cd565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c16103bc36600461451d565b61098c565b604051901515815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6033546104069061ffff1681565b60405161ffff909116815260200161032d565b603354600160201b90046001600160401b031660009081526034602052604090205460ff16156103c1565b6103496104523660046145cf565b610a72565b6103c161046536600461463f565b6001600160401b031660009081526034602052604090205460ff1690565b610349610c91565b610495620f424081565b60405190815260200161032d565b6103496104b136600461466e565b610d91565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496104eb366004614423565b610dc1565b6033546104069062010000900461ffff1681565b610349610512366004614689565b610e43565b60335461031990600160601b90046001600160a01b031681565b61010354610319906001600160a01b031681565b61034961134d565b61034961055b36600461466e565b6113ec565b610349611419565b610495610576366004614406565b6114bf565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b606b54610319906001600160a01b031681565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496105ea366004614406565b6116a5565b6103196105fd3660046146f0565b6116d2565b6103c161061036600461451d565b6116fc565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611834565b6103496119c7565b6106737f000000000000000000000000000000000000000000000000000000000000000081565b60405163ffffffff909116815260200161032d565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103496103443660046146f0565b6103496106cb366004614709565b611ba1565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b6103c1610705366004614406565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610349611cbe565b61034961074d366004614406565b611cea565b610349610760366004614406565b611d17565b6103c1611da4565b61034961077b366004614406565b611dd5565b60335461079a90600160201b90046001600160401b031681565b6040516001600160401b03909116815260200161032d565b6103496107c036600461473e565b611e79565b6103197f000000000000000000000000000000000000000000000000000000000000000081565b610349611efd565b61034961080236600461477f565b611fff565b610319733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b61082a6121ab565b60405161032d919061481c565b6104956509184e72a00081565b600061085c6000805160206150598339815191525490565b905090565b610869611da4565b61088e5760405162461bcd60e51b81526004016108859061482f565b60405180910390fd5b60405162461bcd60e51b81526020600482015260146024820152733ab739bab83837b93a32b210333ab731ba34b7b760611b6044820152606401610885565b6108d5611da4565b6108f15760405162461bcd60e51b81526004016108859061482f565b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169083160361096c5760405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220737570706f72746564206173736574006044820152606401610885565b610988610977610844565b6001600160a01b038416908361220d565b5050565b6000336001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a065760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b6107d08363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b610a69858584612275565b95945050505050565b604080516001808252818301909252600091602080830190803683370190505090503081600081518110610aa857610aa8614866565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610af957610af9614866565b6001600160a01b0392909216602092830291909101909101526040805160018082528183019092526000918160200160208202803683370190505090508581600081518110610b4a57610b4a614866565b6020908102919091010152604080516001808252818301909252600091816020015b6060815260200190600190039081610b6c5790505090508585808060200260200160405190810160405280939291908181526020018383602002808284376000920182905250855186945090925015159050610bca57610bca614866565b60209081029190910101526040516301c7ba5760e61b8152733ef3d8ba38ebe18db133cec108f4d14ce00dd9ae906371ee95c090610c1290879087908790879060040161487c565b600060405180830381600087803b158015610c2c57600080fd5b505af1158015610c40573d6000803e3d6000fd5b50505050876001600160a01b03167f2d5429efdeca7741a8cd94067b18d988bc4e5f1d5b8272c37b7bfc31e9bfa32c88604051610c7f91815260200190565b60405180910390a25050505050505050565b603354600160601b90046001600160a01b0316331480610cbc5750610103546001600160a01b031633145b80610cca5750610cca611da4565b610d355760405162461bcd60e51b815260206004820152603660248201527f43616c6c6572206973206e6f7420746865204f70657261746f722c20537472616044820152753a32b3b4b9ba1037b9103a34329023b7bb32b93737b960511b6064820152608401610885565b6000610d607f00000000000000000000000000000000000000000000000000000000000000006114bf565b90506000610d86603360049054906101000a90046001600160401b03168360004261236e565b9050610988816123d9565b610d99611da4565b610db55760405162461bcd60e51b81526004016108859061482f565b610dbe81612532565b50565b610103546001600160a01b0316331480610dde5750610dde611da4565b610dfa5760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101610e2c5760405162461bcd60e51b8152600401610885906149b2565b60028255610e3a84846125cd565b50600190555050565b603354600160601b90046001600160a01b03163314610ea45760405162461bcd60e51b815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865204f70657261746f720000000000006044820152606401610885565b6000806000806000610eb587612843565b94509450945094509450600163ffffffff168563ffffffff1614610f1b5760405162461bcd60e51b815260206004820152601c60248201527f496e76616c69642043435450206d6573736167652076657273696f6e000000006044820152606401610885565b7f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff1614610f8e5760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b610f99816000612899565b945060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b031614905080156110da578563ffffffff166001148015610ff25750815160e411155b6110355760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206275726e206d65737361676560601b6044820152606401610885565b60006110428360046128c1565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146110ba5760405162461bcd60e51b815260206004820152601260248201527124b73b30b634b210313ab937103a37b5b2b760711b6044820152606401610885565b6110c58360646128c1565b94506110d28360246128c1565b935050611131565b63ffffffff86166103f2146111315760405162461bcd60e51b815260206004820152601b60248201527f556e737570706f72746564206d6573736167652076657273696f6e00000000006044820152606401610885565b306001600160a01b038416146111895760405162461bcd60e51b815260206004820152601c60248201527f556e657870656374656420726563697069656e742061646472657373000000006044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316846001600160a01b0316146112155760405162461bcd60e51b815260206004820152602260248201527f496e636f72726563742073656e6465722f726563697069656e74206164647265604482015261737360f01b6064820152608401610885565b604051630afd9fa560e31b81526000906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906357ecfd2890611266908c908c90600401614a2a565b6020604051808303816000875af1158015611285573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a99190614a4f565b9050806112f15760405162461bcd60e51b8152602060048201526016602482015275149958d95a5d99481b595cdcd859d94819985a5b195960521b6044820152606401610885565b811561134257825160009061130a90859060e4906128db565b90506000611319856044612a35565b905060006113288660a4612a35565b905061133e6113378284614a87565b8285612a4f565b5050505b505050505050505050565b606b546001600160a01b031633146113a75760405162461bcd60e51b815260206004820152601b60248201527f43616c6c6572206973206e6f74207468652048617276657374657200000000006044820152606401610885565b600080516020615039833981519152805460011981016113d95760405162461bcd60e51b8152600401610885906149b2565b600282556113e5612ab4565b5060019055565b6113f4611da4565b6114105760405162461bcd60e51b81526004016108859061482f565b610dbe81612bc8565b7f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db546001600160a01b0316336001600160a01b0316146114b45760405162461bcd60e51b815260206004820152603060248201527f4f6e6c79207468652070656e64696e6720476f7665726e6f722063616e20636f60448201526f6d706c6574652074686520636c61696d60801b6064820152608401610885565b6114bd33612c65565b565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146115125760405162461bcd60e51b815260040161088590614a9a565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015611579573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061159d9190614ad1565b6040516370a0823160e01b81523060048201529091507f00000000000000000000000000000000000000000000000000000000000000009082906001600160a01b03831690634cdad5069082906370a0823190602401602060405180830381865afa158015611610573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116349190614ad1565b6040518263ffffffff1660e01b815260040161165291815260200190565b602060405180830381865afa15801561166f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116939190614ad1565b61169d9190614aea565b949350505050565b6116ad611da4565b6116c95760405162461bcd60e51b81526004016108859061482f565b610dbe81612cc4565b606c81815481106116e257600080fd5b6000918252602090912001546001600160a01b0316905081565b6000336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146117765760405162461bcd60e51b815260206004820152601e60248201527f43616c6c6572206973206e6f742043435450207472616e736d697474657200006044820152606401610885565b60335461ffff166103e8146117dc5760405162461bcd60e51b815260206004820152602660248201527f556e66696e616c697a6564206d6573736167657320617265206e6f74207375706044820152651c1bdc9d195960d21b6064820152608401610885565b6103e88363ffffffff161015610a5e5760405162461bcd60e51b815260206004820152601a60248201527f46696e616c697479207468726573686f6c6420746f6f206c6f770000000000006044820152606401610885565b61183c611da4565b6118585760405162461bcd60e51b81526004016108859061482f565b600054610100900460ff1680611871575060005460ff16155b61188d5760405162461bcd60e51b815260040161088590614afd565b600054610100900460ff161580156118af576000805461ffff19166101011790555b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008260008151811061193157611931614866565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160008151811061198557611985614866565b60200260200101906001600160a01b031690816001600160a01b0316815250506119b0838383612d13565b5050508015610dbe576000805461ff001916905550565b610103546001600160a01b03163314806119e457506119e4611da4565b611a005760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101611a325760405162461bcd60e51b8152600401610885906149b2565b600282557f00000000000000000000000000000000000000000000000000000000000000006000611a83827f0000000000000000000000000000000000000000000000000000000000000000612dbf565b6040516370a0823160e01b8152306004820152909150600090611b639083906001600160a01b03861690634cdad5069082906370a0823190602401602060405180830381865afa158015611adb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aff9190614ad1565b6040518263ffffffff1660e01b8152600401611b1d91815260200190565b602060405180830381865afa158015611b3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b5e9190614ad1565b612f8b565b90508015611b9657611b96307f000000000000000000000000000000000000000000000000000000000000000083612fa1565b505050600182555050565b611ba9611da4565b611bc55760405162461bcd60e51b81526004016108859061482f565b8060005b81811015611c6f576000848483818110611be557611be5614866565b9050602002016020810190611bfa9190614406565b6001600160a01b031603611c675760405162461bcd60e51b815260206004820152602e60248201527f43616e206e6f742073657420616e20656d70747920616464726573732061732060448201526d30903932bbb0b932103a37b5b2b760911b6064820152608401610885565b600101611bc9565b507f04c0b9649497d316554306e53678d5f5f5dbc3a06f97dec13ff4cfe98b986bbc606c8484604051611ca493929190614b4b565b60405180910390a1611cb8606c84846142eb565b50505050565b611cc6611da4565b611ce25760405162461bcd60e51b81526004016108859061482f565b6114bd613273565b611cf2611da4565b611d0e5760405162461bcd60e51b81526004016108859061482f565b610dbe81613327565b611d1f611da4565b611d3b5760405162461bcd60e51b81526004016108859061482f565b606b54604080516001600160a01b03928316815291831660208301527fe48386b84419f4d36e0f96c10cc3510b6fb1a33795620c5098b22472bbe90796910160405180910390a1606b80546001600160a01b0319166001600160a01b0392909216919091179055565b6000611dbc6000805160206150598339815191525490565b6001600160a01b0316336001600160a01b031614905090565b611ddd611da4565b611df95760405162461bcd60e51b81526004016108859061482f565b611e21817f44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db55565b806001600160a01b0316611e416000805160206150598339815191525490565b6001600160a01b03167fa39cc5eb22d0f34d8beaefee8a3f17cc229c1a1d1ef87a5ad47313487b1c4f0d60405160405180910390a350565b610103546001600160a01b0316331480611e965750611e96611da4565b611eb25760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101611ee45760405162461bcd60e51b8152600401610885906149b2565b60028255611ef3858585612fa1565b5060019055505050565b610103546001600160a01b0316331480611f1a5750611f1a611da4565b611f365760405162461bcd60e51b81526004016108859061496a565b60008051602061503983398151915280546001198101611f685760405162461bcd60e51b8152600401610885906149b2565b600282556040516370a0823160e01b81523060048201526113e5907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038216906370a0823190602401602060405180830381865afa158015611fd6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ffa9190614ad1565b6125cd565b612007611da4565b6120235760405162461bcd60e51b81526004016108859061482f565b600054610100900460ff168061203c575060005460ff16155b6120585760405162461bcd60e51b815260040161088590614afd565b600054610100900460ff1615801561207a576000805461ffff19166101011790555b612085848484613382565b61208e85612cc4565b6040805160008082526001602080840182815260608501865293949293928501908036833750506040805160018082528183019092529293506000929150602080830190803683370190505090507f00000000000000000000000000000000000000000000000000000000000000008260008151811061211057612110614866565b60200260200101906001600160a01b031690816001600160a01b0316815250507f00000000000000000000000000000000000000000000000000000000000000008160008151811061216457612164614866565b60200260200101906001600160a01b031690816001600160a01b03168152505061218f838383612d13565b50505080156121a4576000805461ff00191690555b5050505050565b6060606c80548060200260200160405190810160405280929190818152602001828054801561220357602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116121e5575b5050505050905090565b6040516001600160a01b03831660248201526044810182905261227090849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526133d7565b505050565b60007f000000000000000000000000000000000000000000000000000000000000000063ffffffff168463ffffffff16146122ea5760405162461bcd60e51b81526020600482015260156024820152742ab735b737bbb71029b7bab931b2902237b6b0b4b760591b6044820152606401610885565b827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03908116908216146123585760405162461bcd60e51b815260206004820152600e60248201526d2ab735b737bbb71029b2b73232b960911b6044820152606401610885565b612361836134a9565b60019150505b9392505050565b604080516001600160401b038616602082015280820185905283151560608083019190915260808083018590528351808403909101815260a08301909352916123c0916103f29160039160c001614be6565b6040516020818303038152906040529050949350505050565b6033546040516314b157ab60e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116926314b157ab92612477927f0000000000000000000000000000000000000000000000000000000000000000927f000000000000000000000000000000000000000000000000000000000000000090911691829161ffff16908890600401614c2b565b600060405180830381600087803b15801561249157600080fd5b505af11580156124a5573d6000803e3d6000fd5b50506033546040517f90d92e80437532a834bc16642d235a7c34efc4d5690f3f6e69794c6d8c5c7290935061252792507f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009161ffff909116908690614c62565b60405180910390a150565b610bb88161ffff16111561257f5760405162461bcd60e51b815260206004820152601460248201527308ccaca40e0e4cadad2eada40e8dede40d0d2ced60631b6044820152606401610885565b6033805463ffff000019166201000061ffff8416908102919091179091556040519081527f938c72cb9ba014c7d4d26f156021299f8926dee2aab1421b32a2408a8261cf6090602001612527565b600081116126165760405162461bcd60e51b81526020600482015260166024820152754d757374206465706f73697420736f6d657468696e6760501b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b0316146126675760405162461bcd60e51b815260040161088590614a9a565b604051636e553f6560e01b8152600481018290523060248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636e553f65906044016020604051808303816000875af19250505080156126f0575060408051601f3d908101601f191682019092526126ed91810190614ad1565b60015b6127d8576126fc614ca4565b806308c379a0036127745750612710614cc0565b8061271b5750612776565b7fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d48160405160200161274d9190614d43565b60408051601f198184030181529082905261276791614d7b565b60405180910390a1505050565b505b3d8080156127a0576040519150601f19603f3d011682016040523d82523d6000602084013e6127a5565b606091505b507fcce3c000dc0fa4d3156e53ca2c0771b6dfa039640d4885f2df488a7f732540d48160405160200161274d9190614d8e565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b600080808060606128548683612899565b9450612861866004612899565b935061286e86602c6128c1565b925061287b86604c6128c1565b865190925061288e9087906094906128db565b905091939590929450565b60006128b86128b384846128ae600482614aea565b6128db565b61351d565b90505b92915050565b60006128b86128d684846128ae602082614aea565b613553565b6060828210156129235760405162461bcd60e51b8152602060048201526013602482015272496e76616c696420736c6963652072616e676560681b6044820152606401610885565b83518211156129745760405162461bcd60e51b815260206004820152601d60248201527f536c69636520656e6420657863656564732064617461206c656e6774680000006044820152606401610885565b60006129808484614a87565b90506000816001600160401b0381111561299c5761299c614468565b6040519080825280601f01601f1916602001820160405280156129c6576020820181803683370190505b50905060005b82811015612a2b57866129df8288614aea565b815181106129ef576129ef614866565b602001015160f81c60f81b828281518110612a0c57612a0c614866565b60200101906001600160f81b031916908160001a9053506001016129cc565b5095945050505050565b60006128b8612a4a84846128ae602082614aea565b61358a565b6000612a5a826135c1565b905063ffffffff8116600114612aa95760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964206d657373616765207479706560601b6044820152606401610885565b611cb88484846135ce565b606c5460005b81811015610988576000606c8281548110612ad757612ad7614866565b60009182526020822001546040516370a0823160e01b81523060048201526001600160a01b03909116925082906370a0823190602401602060405180830381865afa158015612b2a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b4e9190614ad1565b90508015612bbe57606b54604080516001600160a01b039283168152918416602083015281018290527ff6c07a063ed4e63808eb8da7112d46dbcd38de2b40a73dbcc9353c5a94c723539060600160405180910390a1606b54612bbe906001600160a01b0384811691168361220d565b5050600101612aba565b8061ffff166103e81480612be157508061ffff166107d0145b612c215760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081d1a1c995cda1bdb19607a1b6044820152606401610885565b6033805461ffff191661ffff83169081179091556040519081527fe8fbd074d54232549e55ac463e02d202c16b1023e5d6aae276b3d8391b8c14bc90602001612527565b6001600160a01b038116612cbb5760405162461bcd60e51b815260206004820152601a60248201527f4e657720476f7665726e6f7220697320616464726573732830290000000000006044820152606401610885565b610dbe81613704565b61010380546001600160a01b0319166001600160a01b0383169081179091556040519081527f869e0abd13cc3a975de7b93be3df1cb2255c802b1cead85963cc79d99f131bee90602001612527565b8251612d2690606c90602086019061434e565b50815181518114612d705760405162461bcd60e51b8152602060048201526014602482015273496e76616c696420696e7075742061727261797360601b6044820152606401610885565b60005b818110156121a457612db7848281518110612d9057612d90614866565b6020026020010151848381518110612daa57612daa614866565b602002602001015161376b565b600101612d73565b6040516370a0823160e01b81526001600160a01b038381166004830152600091908316906370a0823190602401602060405180830381865afa158015612e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2d9190614ad1565b90506000836001600160a01b031663ad468d116040518163ffffffff1660e01b8152600401602060405180830381865afa158015612e6f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e939190614dec565b9050806001600160a01b031663e4baaddf6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612eef575060408051601f3d908101601f19168201909252612eec91810190614dec565b60015b612f1757604051630a10bc7f60e41b81526001600160a01b0382166004820152602401610885565b60405163ce96cb7760e01b81526001600160a01b03838116600483015282169063ce96cb7790602401602060405180830381865afa158015612f5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f819190614ad1565b610a699084614aea565b6000818310612f9a57816128b8565b5090919050565b60008111612ff15760405162461bcd60e51b815260206004820152601760248201527f4d75737420776974686472617720736f6d657468696e670000000000000000006044820152606401610885565b6001600160a01b038316301461303d5760405162461bcd60e51b8152602060048201526011602482015270125b9d985b1a59081c9958da5c1a595b9d607a1b6044820152606401610885565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b03161461308e5760405162461bcd60e51b815260040161088590614a9a565b604051632d182be560e21b815260048101829052306024820181905260448201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063b460af94906064016020604051808303816000875af192505050801561311e575060408051601f3d908101601f1916820190925261311b91810190614ad1565b60015b6132075761312a614ca4565b806308c379a0036131a3575061313e614cc0565b8061314957506131a5565b7f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f8348160405160200161317b9190614e09565b60408051601f198184030181529082905261319591614d7b565b60405180910390a150505050565b505b3d8080156131cf576040519150601f19603f3d011682016040523d82523d6000602084013e6131d4565b606091505b507f338db40d86fc8697e35f615235de184a040fdca34021e6bf367dabb0a408f8348160405160200161317b9190614e44565b50604080516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081168252602082018490528416917f2717ead6b9200dd235aad468c9809ea400fe33ac69b5bfaa6d3e90fc922b6398910160405180910390a2505050565b60405163095ea7b360e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000008116600483015260001960248301527f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b3906044016020604051808303816000875af1158015613303573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dbe9190614a4f565b603380546bffffffffffffffffffffffff16600160601b6001600160a01b038416908102919091179091556040519081527f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e5490602001612527565b61338b83613327565b61339482612bc8565b61339d81612532565b5050600080525060346020527f2dc2afdad33a5feea586a9545052327b65d28efb10d11fa69e77da986a1031cd805460ff19166001179055565b600061342c826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166138d09092919063ffffffff16565b805190915015612270578080602001905181019061344a9190614a4f565b6122705760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610885565b60006134b4826135c1565b905060001963ffffffff821601156109885760011963ffffffff8216016134de57610988826138df565b60405162461bcd60e51b8152602060048201526014602482015273556e6b6e6f776e206d657373616765207479706560601b6044820152606401610885565b600081516004146135405760405162461bcd60e51b815260040161088590614ea5565b60e061354b83614ed2565b901c92915050565b600081516020146135765760405162461bcd60e51b815260040161088590614ea5565b818060200190518101906128bb9190614dec565b600081516020146135ad5760405162461bcd60e51b815260040161088590614ea5565b818060200190518101906128bb9190614ad1565b60006128bb826004612899565b60006135d982613b36565b5090506135e581613b6f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561364c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136709190614ad1565b9050620f424081106136a6576136a67f0000000000000000000000000000000000000000000000000000000000000000826125cd565b6033546000906136f190600160201b90046001600160401b03166136e97f00000000000000000000000000000000000000000000000000000000000000006114bf565b60014261236e565b90506136fc816123d9565b505050505050565b806001600160a01b03166137246000805160206150598339815191525490565b6001600160a01b03167fc7c0c772add429241571afb3805861fb3cfa2af374534088b76cdb4325a87e9a60405160405180910390a360008051602061505983398151915255565b6001600160a01b0382811660009081526067602052604090205416156137c85760405162461bcd60e51b81526020600482015260126024820152711c151bdad95b88185b1c9958591e481cd95d60721b6044820152606401610885565b6001600160a01b038216158015906137e857506001600160a01b03811615155b6138285760405162461bcd60e51b8152602060048201526011602482015270496e76616c69642061646472657373657360781b6044820152606401610885565b6001600160a01b03828116600081815260676020908152604080832080549587166001600160a01b031996871681179091556068805460018101825594527fa2153420d844928b4421650203c77babc8b33d7f2e7b450e2966db0c2209775390930180549095168417909455925190815290917fef6485b84315f9b1483beffa32aae9a0596890395e3d7521f1c5fbb51790e765910160405180910390a26109888282613d02565b606061169d8484600085613d0a565b6000806138eb83613e32565b915091506138f882613b6f565b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa15801561395f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139839190614ad1565b905081811015613a4c576139c1307f00000000000000000000000000000000000000000000000000000000000000006139bc8486614a87565b612fa1565b6040516370a0823160e01b81523060048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015613a25573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613a499190614ad1565b90505b6000613a777f00000000000000000000000000000000000000000000000000000000000000006114bf565b9050620f42408310158015613a8c5750828210155b15613ac757603354600090613ab590600160201b90046001600160401b03166136e98685614a87565b9050613ac18482613e40565b506121a4565b603354600090613aea90600160201b90046001600160401b03168360014261236e565b9050613af5816123d9565b60408051858152602081018590527fff463b52b1f42eb360c2a871ee18d12dbc93807adffafa5b8fc6dea0051857a9910160405180910390a1505050505050565b600080613b448360016140bf565b600080613b5085614178565b806020019051810190613b639190614ef9565b90969095509350505050565b6033546001600160401b03600160201b9091048116908216811115613bc65760405162461bcd60e51b815260206004820152600d60248201526c4e6f6e636520746f6f206c6f7760981b6044820152606401610885565b6001600160401b03821660009081526034602052604090205460ff1615613c2f5760405162461bcd60e51b815260206004820152601760248201527f4e6f6e636520616c72656164792070726f6365737365640000000000000000006044820152606401610885565b6001600160401b038216600081815260346020908152604091829020805460ff1916600117905590519182527f8aa30b3e46076ef0187550969c01982aeb9af5db2eada56ab253a53e4c9946e9910160405180910390a1806001600160401b0316826001600160401b03161461098857603380546bffffffffffffffff000000001916600160201b6001600160401b038516908102919091179091556040519081527fc328b88555c22b57c1f2678e88ad3d9982d056ca6b05be82546e7b6bc6fda2db9060200160405180910390a15050565b610988613273565b606082471015613d6b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610885565b843b613db95760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610885565b600080866001600160a01b03168587604051613dd59190614f27565b60006040518083038185875af1925050503d8060008114613e12576040519150601f19603f3d011682016040523d82523d6000602084013e613e17565b606091505b5091509150613e27828286614191565b979650505050505050565b600080613b448360026140bf565b6509184e72a000821115613e8e5760405162461bcd60e51b81526020600482015260156024820152740a8ded6cadc40c2dadeeadce840e8dede40d0d2ced605b1b6044820152606401610885565b613ee26001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000167f0000000000000000000000000000000000000000000000000000000000000000846141ca565b60335460009062010000900461ffff16613efd576000613f22565b60335461271090613f189062010000900461ffff1685614f43565b613f229190614f5a565b60335460405163779b432d60e01b81529192506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081169263779b432d92613feb9288927f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000909216917f00000000000000000000000000000000000000000000000000000000000000009183918a9161ffff909116908c90600401614f7c565b600060405180830381600087803b15801561400557600080fd5b505af1158015614019573d6000803e3d6000fd5b50506033546040517f149007d4a77eb98d041de59e6ca469bd27b351b74f16c4d0648978322a1b8a77935061276792507f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000917f0000000000000000000000000000000000000000000000000000000000000000918991889161ffff16908a90614fdd565b6103f26140cb836142df565b63ffffffff161461411e5760405162461bcd60e51b815260206004820152601e60248201527f496e76616c6964204f726967696e204d6573736167652056657273696f6e00006044820152606401610885565b8063ffffffff1661412e836135c1565b63ffffffff16146109885760405162461bcd60e51b8152602060048201526014602482015273496e76616c6964204d657373616765207479706560601b6044820152606401610885565b60606128bb60088351846128db9092919063ffffffff16565b606083156141a0575081612367565b8251156141b05782518084602001fd5b8160405162461bcd60e51b81526004016108859190614d7b565b8015806142445750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa15801561421e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906142429190614ad1565b155b6142af5760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610885565b6040516001600160a01b03831660248201526044810182905261227090849063095ea7b360e01b90606401612239565b60006128bb8282612899565b82805482825590600052602060002090810192821561433e579160200282015b8281111561433e5781546001600160a01b0319166001600160a01b0384351617825560209092019160019091019061430b565b5061434a9291506143a3565b5090565b82805482825590600052602060002090810192821561433e579160200282015b8281111561433e57825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061436e565b5b8082111561434a57600081556001016143a4565b6001600160a01b0381168114610dbe57600080fd5b600080604083850312156143e057600080fd5b82356143eb816143b8565b915060208301356143fb816143b8565b809150509250929050565b60006020828403121561441857600080fd5b8135612367816143b8565b6000806040838503121561443657600080fd5b8235614441816143b8565b946020939093013593505050565b803563ffffffff8116811461446357600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b03811182821017156144a3576144a3614468565b6040525050565b600082601f8301126144bb57600080fd5b81356001600160401b038111156144d4576144d4614468565b6040516144eb601f8301601f19166020018261447e565b81815284602083860101111561450057600080fd5b816020850160208301376000918101602001919091529392505050565b6000806000806080858703121561453357600080fd5b61453c8561444f565b9350602085013592506145516040860161444f565b915060608501356001600160401b0381111561456c57600080fd5b614578878288016144aa565b91505092959194509250565b60008083601f84011261459657600080fd5b5081356001600160401b038111156145ad57600080fd5b6020830191508360208260051b85010111156145c857600080fd5b9250929050565b600080600080606085870312156145e557600080fd5b84356145f0816143b8565b93506020850135925060408501356001600160401b0381111561461257600080fd5b61461e87828801614584565b95989497509550505050565b6001600160401b0381168114610dbe57600080fd5b60006020828403121561465157600080fd5b81356123678161462a565b803561ffff8116811461446357600080fd5b60006020828403121561468057600080fd5b6128b88261465c565b6000806040838503121561469c57600080fd5b82356001600160401b038111156146b257600080fd5b6146be858286016144aa565b92505060208301356001600160401b038111156146da57600080fd5b6146e6858286016144aa565b9150509250929050565b60006020828403121561470257600080fd5b5035919050565b6000806020838503121561471c57600080fd5b82356001600160401b0381111561473257600080fd5b613b6385828601614584565b60008060006060848603121561475357600080fd5b833561475e816143b8565b9250602084013561476e816143b8565b929592945050506040919091013590565b6000806000806080858703121561479557600080fd5b84356147a0816143b8565b935060208501356147b0816143b8565b92506147be6040860161465c565b91506147cc6060860161465c565b905092959194509250565b600081518084526020840193506020830160005b828110156148125781516001600160a01b03168652602095860195909101906001016147eb565b5093949350505050565b6020815260006128b860208301846147d7565b6020808252601a908201527f43616c6c6572206973206e6f742074686520476f7665726e6f72000000000000604082015260600190565b634e487b7160e01b600052603260045260246000fd5b60808152600061488f60808301876147d7565b82810360208401526148a181876147d7565b83810360408501528551808252602080880193509091019060005b818110156148da5783518352602093840193909201916001016148bc565b50508381036060850152845180825260208083019350600582901b8301810190870160005b8381101561495a57848303601f190186528151805180855260209182019185019060005b81811015614941578351835260209384019390920191600101614923565b50506020978801979094509290920191506001016148ff565b50909a9950505050505050505050565b60208082526028908201527f43616c6c6572206973206e6f74207468652053747261746567697374206f722060408201526723b7bb32b93737b960c11b606082015260800190565b6020808252600e908201526d1499595b9d1c985b9d0818d85b1b60921b604082015260600190565b60005b838110156149f55781810151838201526020016149dd565b50506000910152565b60008151808452614a168160208601602086016149da565b601f01601f19169290920160200192915050565b604081526000614a3d60408301856149fe565b8281036020840152610a6981856149fe565b600060208284031215614a6157600080fd5b8151801515811461236757600080fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156128bb576128bb614a71565b60208082526018908201527f556e657870656374656420617373657420616464726573730000000000000000604082015260600190565b600060208284031215614ae357600080fd5b5051919050565b808201808211156128bb576128bb614a71565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b6040808252845490820181905260008581526020812090916060840190835b81811015614b915783546001600160a01b0316835260019384019360209093019201614b6a565b50508381036020808601919091528582520190508460005b85811015614bda578135614bbc816143b8565b6001600160a01b031683526020928301929190910190600101614ba9565b50909695505050505050565b63ffffffff60e01b8460e01b16815263ffffffff60e01b8360e01b16600482015260008251614c1c8160088501602087016149da565b91909101600801949350505050565b63ffffffff8616815284602082015283604082015263ffffffff8316606082015260a060808201526000613e2760a08301846149fe565b63ffffffff85811682526001600160a01b038516602083015283166040820152608060608201819052600090614c9a908301846149fe565b9695505050505050565b600060033d1115614cbd5760046000803e5060005160e01c5b90565b600060443d1015614cce5790565b6040513d600319016004823e80513d60248201116001600160401b0382111715614cf757505090565b80820180516001600160401b03811115614d12575050505090565b3d8401600319018282016020011115614d2c575050505090565b614d3b6020828501018561447e565b509392505050565b6f02232b837b9b4ba103330b4b632b21d160851b815260008251614d6e8160108501602087016149da565b9190910160100192915050565b6020815260006128b860208301846149fe565b7f4465706f736974206661696c65643a206c6f772d6c6576656c2063616c6c206681526f030b4b632b2103bb4ba34103230ba30960851b602082015260008251614ddf8160308501602087016149da565b9190910160300192915050565b600060208284031215614dfe57600080fd5b8151612367816143b8565b7202bb4ba34323930bbb0b6103330b4b632b21d1606d1b815260008251614e378160138501602087016149da565b9190910160130192915050565b7f5769746864726177616c206661696c65643a206c6f772d6c6576656c2063616c815272036103330b4b632b2103bb4ba34103230ba309606d1b602082015260008251614e988160338501602087016149da565b9190910160330192915050565b602080825260139082015272092dcecc2d8d2c840c8c2e8c240d8cadccee8d606b1b604082015260600190565b80516020808301519190811015614ef3576000198160200360031b1b821691505b50919050565b60008060408385031215614f0c57600080fd5b8251614f178161462a565b6020939093015192949293505050565b60008251614f398184602087016149da565b9190910192915050565b80820281158282048414176128bb576128bb614a71565b600082614f7757634e487b7160e01b600052601260045260246000fd5b500490565b88815263ffffffff8816602082015286604082015260018060a01b03861660608201528460808201528360a082015263ffffffff831660c082015261010060e08201526000614fcf6101008301846149fe565b9a9950505050505050505050565b63ffffffff88811682526001600160a01b038881166020840152871660408301526060820186905260808201859052831660a082015260e060c0820181905260009061502b908301846149fe565b999850505050505050505056fe53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac45357bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4aa26469706673582212205efb2307624767aeb27588fe9404d68ff6927a3d5bce673b7daad0b21273912564736f6c634300081c0033", "libraries": {}, "devdoc": { "kind": "dev", @@ -1531,7 +1542,7 @@ "storageLayout": { "storage": [ { - "astId": 55299, + "astId": 8060, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "initialized", "offset": 0, @@ -1539,7 +1550,7 @@ "type": "t_bool" }, { - "astId": 55302, + "astId": 8063, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "initializing", "offset": 1, @@ -1547,7 +1558,7 @@ "type": "t_bool" }, { - "astId": 55342, + "astId": 8103, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "______gap", "offset": 0, @@ -1555,7 +1566,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 45196, + "astId": 4015, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "minFinalityThreshold", "offset": 0, @@ -1563,7 +1574,7 @@ "type": "t_uint16" }, { - "astId": 45199, + "astId": 4018, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "feePremiumBps", "offset": 2, @@ -1571,7 +1582,7 @@ "type": "t_uint16" }, { - "astId": 45202, + "astId": 4021, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "lastTransferNonce", "offset": 4, @@ -1579,7 +1590,7 @@ "type": "t_uint64" }, { - "astId": 45205, + "astId": 4024, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "operator", "offset": 12, @@ -1587,7 +1598,7 @@ "type": "t_address" }, { - "astId": 45210, + "astId": 4029, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "nonceProcessed", "offset": 0, @@ -1595,7 +1606,7 @@ "type": "t_mapping(t_uint64,t_bool)" }, { - "astId": 45214, + "astId": 4033, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "__gap", "offset": 0, @@ -1603,7 +1614,7 @@ "type": "t_array(t_uint256)48_storage" }, { - "astId": 55422, + "astId": 8183, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_deprecated_platformAddress", "offset": 0, @@ -1611,7 +1622,7 @@ "type": "t_address" }, { - "astId": 55425, + "astId": 8186, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_deprecated_vaultAddress", "offset": 0, @@ -1619,7 +1630,7 @@ "type": "t_address" }, { - "astId": 55430, + "astId": 8191, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "assetToPToken", "offset": 0, @@ -1627,7 +1638,7 @@ "type": "t_mapping(t_address,t_address)" }, { - "astId": 55434, + "astId": 8195, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "assetsMapped", "offset": 0, @@ -1635,7 +1646,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 55436, + "astId": 8197, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_deprecated_rewardTokenAddress", "offset": 0, @@ -1643,7 +1654,7 @@ "type": "t_address" }, { - "astId": 55438, + "astId": 8199, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_deprecated_rewardLiquidationThreshold", "offset": 0, @@ -1651,7 +1662,7 @@ "type": "t_uint256" }, { - "astId": 55441, + "astId": 8202, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "harvesterAddress", "offset": 0, @@ -1659,7 +1670,7 @@ "type": "t_address" }, { - "astId": 55445, + "astId": 8206, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "rewardTokenAddresses", "offset": 0, @@ -1667,7 +1678,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 55449, + "astId": 8210, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_reserved", "offset": 0, @@ -1675,7 +1686,7 @@ "type": "t_array(t_int256)98_storage" }, { - "astId": 33995, + "astId": 3130, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_deprecate_shareToken", "offset": 0, @@ -1683,7 +1694,7 @@ "type": "t_address" }, { - "astId": 33998, + "astId": 3133, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "_deprecate_assetToken", "offset": 0, @@ -1691,7 +1702,7 @@ "type": "t_address" }, { - "astId": 34008, + "astId": 3143, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "__gap", "offset": 0, @@ -1699,7 +1710,7 @@ "type": "t_array(t_uint256)50_storage" }, { - "astId": 9290, + "astId": 1882, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "strategistAddr", "offset": 0, @@ -1707,7 +1718,7 @@ "type": "t_address" }, { - "astId": 9294, + "astId": 1886, "contract": "contracts/strategies/crosschain/CrossChainRemoteStrategy.sol:CrossChainRemoteStrategy", "label": "__gap", "offset": 0, diff --git a/contracts/deployments/base/operations/046_crosschain_upgrade_remote.execute.json b/contracts/deployments/base/operations/046_crosschain_upgrade_remote.execute.json new file mode 100644 index 0000000000..011b601fd6 --- /dev/null +++ b/contracts/deployments/base/operations/046_crosschain_upgrade_remote.execute.json @@ -0,0 +1,52 @@ +{ + "version": "1.0", + "chainId": "8453", + "createdAt": 1772750064, + "meta": { + "name": "Transaction Batch", + "description": "", + "txBuilderVersion": "1.16.1", + "createdFromSafeAddress": "0x92A19381444A001d62cE67BaFF066fA1111d7202", + "createdFromOwnerAddress": "" + }, + "transactions": [ + { + "to": "0xf817cb3092179083c48c014688D98B72fB61464f", + "value": "0", + "data": null, + "contractMethod": { + "inputs": [ + { + "type": "address[]", + "name": "targets" + }, + { + "type": "uint256[]", + "name": "values" + }, + { + "type": "bytes[]", + "name": "payloads" + }, + { + "type": "bytes32", + "name": "predecessor" + }, + { + "type": "bytes32", + "name": "salt" + } + ], + "name": "executeBatch", + "payable": true + }, + "contractInputsValues": { + "targets": "[\"0xB1d624fc40824683e2bFBEfd19eB208DbBE00866\"]", + "values": "[\"0\"]", + "payloads": "[\"0x3659cfe6000000000000000000000000aa8af8db4b6a827b51786334d26349eb03569731\"]", + "predecessor": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "0x0811fe167193c4dfaf52eecbaca2778e070a89ff2d6ee22787dacec13347ce55" + } + } + ] +} \ No newline at end of file diff --git a/contracts/deployments/base/operations/046_crosschain_upgrade_remote.schedule.json b/contracts/deployments/base/operations/046_crosschain_upgrade_remote.schedule.json new file mode 100644 index 0000000000..7663a25c87 --- /dev/null +++ b/contracts/deployments/base/operations/046_crosschain_upgrade_remote.schedule.json @@ -0,0 +1,57 @@ +{ + "version": "1.0", + "chainId": "8453", + "createdAt": 1772750064, + "meta": { + "name": "Transaction Batch", + "description": "", + "txBuilderVersion": "1.16.1", + "createdFromSafeAddress": "0x92A19381444A001d62cE67BaFF066fA1111d7202", + "createdFromOwnerAddress": "" + }, + "transactions": [ + { + "to": "0xf817cb3092179083c48c014688D98B72fB61464f", + "value": "0", + "data": null, + "contractMethod": { + "inputs": [ + { + "type": "address[]", + "name": "targets" + }, + { + "type": "uint256[]", + "name": "values" + }, + { + "type": "bytes[]", + "name": "payloads" + }, + { + "type": "bytes32", + "name": "predecessor" + }, + { + "type": "bytes32", + "name": "salt" + }, + { + "type": "uint256", + "name": "delay" + } + ], + "name": "scheduleBatch", + "payable": false + }, + "contractInputsValues": { + "targets": "[\"0xB1d624fc40824683e2bFBEfd19eB208DbBE00866\"]", + "values": "[\"0\"]", + "payloads": "[\"0x3659cfe6000000000000000000000000aa8af8db4b6a827b51786334d26349eb03569731\"]", + "predecessor": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "0x0811fe167193c4dfaf52eecbaca2778e070a89ff2d6ee22787dacec13347ce55", + "delay": "172800" + } + } + ] +} \ No newline at end of file diff --git a/contracts/deployments/base/solcInputs/ca5c08626bc4341b9af4973050a80d7d.json b/contracts/deployments/base/solcInputs/ca5c08626bc4341b9af4973050a80d7d.json new file mode 100644 index 0000000000..3a376760b5 --- /dev/null +++ b/contracts/deployments/base/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/base/CrossChainRemoteStrategy.json b/contracts/storageLayout/base/CrossChainRemoteStrategy.json index 7bda8955cf..9749d48bfe 100644 --- a/contracts/storageLayout/base/CrossChainRemoteStrategy.json +++ b/contracts/storageLayout/base/CrossChainRemoteStrategy.json @@ -151,7 +151,7 @@ "slot": "207", "type": "t_address", "contract": "Generalized4626Strategy", - "src": "contracts/strategies/Generalized4626Strategy.sol:20" + "src": "contracts/strategies/Generalized4626Strategy.sol:23" }, { "label": "_deprecate_assetToken", @@ -159,7 +159,7 @@ "slot": "208", "type": "t_address", "contract": "Generalized4626Strategy", - "src": "contracts/strategies/Generalized4626Strategy.sol:23" + "src": "contracts/strategies/Generalized4626Strategy.sol:26" }, { "label": "__gap", @@ -167,7 +167,7 @@ "slot": "209", "type": "t_array(t_uint256)50_storage", "contract": "Generalized4626Strategy", - "src": "contracts/strategies/Generalized4626Strategy.sol:29" + "src": "contracts/strategies/Generalized4626Strategy.sol:32" }, { "label": "strategistAddr", From 2b8f981bd8f8abc257152dca2921a281c782d3af Mon Sep 17 00:00:00 2001 From: Domen Grabec Date: Fri, 6 Mar 2026 10:36:57 +0100 Subject: [PATCH 2/2] prettier --- .../contracts/strategies/Generalized4626Strategy.sol | 6 ++++-- contracts/contracts/strategies/MorphoV2Strategy.sol | 1 - contracts/contracts/strategies/MorphoV2VaultUtils.sol | 10 +++++----- .../strategies/crosschain/CrossChainRemoteStrategy.sol | 6 +----- .../mainnet/179_upgrade_ousd_morpho_v2_strategy.js | 2 +- .../test/strategies/crosschain/cross-chain-strategy.js | 7 +++---- contracts/utils/morpho.js | 9 ++++----- 7 files changed, 18 insertions(+), 23 deletions(-) diff --git a/contracts/contracts/strategies/Generalized4626Strategy.sol b/contracts/contracts/strategies/Generalized4626Strategy.sol index b4793db7de..d451ff672e 100644 --- a/contracts/contracts/strategies/Generalized4626Strategy.sol +++ b/contracts/contracts/strategies/Generalized4626Strategy.sol @@ -5,7 +5,7 @@ pragma solidity ^0.8.0; * @title Generalized 4626 Strategy * @notice Investment strategy for ERC-4626 Tokenized Vaults * @dev This strategy should not be used for the Morpho V2 Vaults as those are not - * completley ERC-4626 compliant - they don't implement the maxWithdraw() and + * completley ERC-4626 compliant - they don't implement the maxWithdraw() and * maxRedeem() functions and rather return 0 when any of them is called. * @author Origin Protocol Inc */ @@ -145,7 +145,9 @@ contract Generalized4626Strategy is InitializableAbstractStrategy { nonReentrant { // @dev Don't use for Morpho V2 Vaults as below line will return 0 - uint256 sharesToRedeem = IERC4626(platformAddress).maxRedeem(address(this)); + uint256 sharesToRedeem = IERC4626(platformAddress).maxRedeem( + address(this) + ); uint256 assetAmount = 0; if (sharesToRedeem > 0) { diff --git a/contracts/contracts/strategies/MorphoV2Strategy.sol b/contracts/contracts/strategies/MorphoV2Strategy.sol index a963398e53..a7291d9145 100644 --- a/contracts/contracts/strategies/MorphoV2Strategy.sol +++ b/contracts/contracts/strategies/MorphoV2Strategy.sol @@ -12,7 +12,6 @@ import { IVaultV2 } from "../interfaces/morpho/IVaultV2.sol"; import { Math } from "@openzeppelin/contracts/utils/math/Math.sol"; contract MorphoV2Strategy is Generalized4626Strategy { - /** * @param _baseConfig Base strategy config with Morpho V2 Vault and * vaultAddress (OToken Vault contract), eg VaultProxy or OETHVaultProxy diff --git a/contracts/contracts/strategies/MorphoV2VaultUtils.sol b/contracts/contracts/strategies/MorphoV2VaultUtils.sol index 02fcad5bd7..98ad5ce94f 100644 --- a/contracts/contracts/strategies/MorphoV2VaultUtils.sol +++ b/contracts/contracts/strategies/MorphoV2VaultUtils.sol @@ -16,10 +16,11 @@ library MorphoV2VaultUtils { * 2) additional liquidity from the active adapter if it resolves to a Morpho V1 vault * and, when provided, matches the expected adapter */ - function maxWithdrawableAssets( - address platformAddress, - address assetToken - ) internal view returns (uint256 availableAssetLiquidity) { + function maxWithdrawableAssets(address platformAddress, address assetToken) + internal + view + returns (uint256 availableAssetLiquidity) + { availableAssetLiquidity = IERC20(assetToken).balanceOf(platformAddress); address liquidityAdapter = IVaultV2(platformAddress).liquidityAdapter(); @@ -34,5 +35,4 @@ library MorphoV2VaultUtils { revert IncompatibleAdapter(liquidityAdapter); } } - } diff --git a/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol b/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol index aa1c10e224..5e1a0c667e 100644 --- a/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol +++ b/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol @@ -153,11 +153,7 @@ contract CrossChainRemoteStrategy is ); if (amountToWithdraw > 0) { - _withdraw( - address(this), - usdcToken, - amountToWithdraw - ); + _withdraw(address(this), usdcToken, amountToWithdraw); } } 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 810103568c..f0245f60dd 100644 --- a/contracts/deploy/mainnet/179_upgrade_ousd_morpho_v2_strategy.js +++ b/contracts/deploy/mainnet/179_upgrade_ousd_morpho_v2_strategy.js @@ -19,7 +19,7 @@ module.exports = deploymentWithGovernanceProposal( "MorphoV2Strategy", [ [addresses.mainnet.MorphoOUSDv2Vault, cVaultProxy.address], - addresses.mainnet.USDC + addresses.mainnet.USDC, ] ); diff --git a/contracts/test/strategies/crosschain/cross-chain-strategy.js b/contracts/test/strategies/crosschain/cross-chain-strategy.js index 4702d408bf..7f61f5d457 100644 --- a/contracts/test/strategies/crosschain/cross-chain-strategy.js +++ b/contracts/test/strategies/crosschain/cross-chain-strategy.js @@ -110,10 +110,9 @@ describe("ForkTest: CrossChainRemoteStrategy", function () { .connect(governor) .setLiquidityAdapter(morphoVault.address); - await expect(crossChainRemoteStrategy.connect(governor).withdrawAll()) - .to.be.revertedWithCustomError( - "IncompatibleAdapter(address)" - ); + await expect( + crossChainRemoteStrategy.connect(governor).withdrawAll() + ).to.be.revertedWithCustomError("IncompatibleAdapter(address)"); }); // Checks the diff in the total expected value in the vault diff --git a/contracts/utils/morpho.js b/contracts/utils/morpho.js index 2abb288a65..44b9a2db97 100644 --- a/contracts/utils/morpho.js +++ b/contracts/utils/morpho.js @@ -33,12 +33,11 @@ async function morphoWithdrawShortfall() { addresses.mainnet.USDC ); - const usdc = await ethers.getContractAt( - erc20Abi, - addresses.mainnet.USDC + const usdc = await ethers.getContractAt(erc20Abi, addresses.mainnet.USDC); + const vaultUSDCBalance = await usdc.balanceOf( + addresses.mainnet.MorphoOUSDv2Vault ); - const vaultUSDCBalance = await usdc.balanceOf(addresses.mainnet.MorphoOUSDv2Vault); - + maxWithdrawal = maxWithdrawal.add(vaultUSDCBalance); log( `Morpho OUSD v2 Strategy USDC balance: ${formatUnits(