文件 1 的 17:Address.sol
pragma solidity ^0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 17:Governable.sol
pragma solidity ^0.8.0;
contract Governable {
bytes32 private constant governorPosition =
0x7bea13895fa79d2831e0a9e28edede30099005a50d652d8957cf8a607ee6ca4a;
bytes32 private constant pendingGovernorPosition =
0x44c4d30b2eaad5130ad70c3ba6972730566f3e6359ab83e800d905c61b1c51db;
bytes32 private constant reentryStatusPosition =
0x53bf423e48ed90e97d02ab0ebab13b2a235a6bfbe9c321847d5c175333ac4535;
uint256 constant _NOT_ENTERED = 1;
uint256 constant _ENTERED = 2;
event PendingGovernorshipTransfer(
address indexed previousGovernor,
address indexed newGovernor
);
event GovernorshipTransferred(
address indexed previousGovernor,
address indexed newGovernor
);
constructor() {
_setGovernor(msg.sender);
emit GovernorshipTransferred(address(0), _governor());
}
function governor() public view returns (address) {
return _governor();
}
function _governor() internal view returns (address governorOut) {
bytes32 position = governorPosition;
assembly {
governorOut := sload(position)
}
}
function _pendingGovernor()
internal
view
returns (address pendingGovernor)
{
bytes32 position = pendingGovernorPosition;
assembly {
pendingGovernor := sload(position)
}
}
modifier onlyGovernor() {
require(isGovernor(), "Caller is not the Governor");
_;
}
function isGovernor() public view returns (bool) {
return msg.sender == _governor();
}
function _setGovernor(address newGovernor) internal {
bytes32 position = governorPosition;
assembly {
sstore(position, newGovernor)
}
}
modifier nonReentrant() {
bytes32 position = reentryStatusPosition;
uint256 _reentry_status;
assembly {
_reentry_status := sload(position)
}
require(_reentry_status != _ENTERED, "Reentrant call");
assembly {
sstore(position, _ENTERED)
}
_;
assembly {
sstore(position, _NOT_ENTERED)
}
}
function _setPendingGovernor(address newGovernor) internal {
bytes32 position = pendingGovernorPosition;
assembly {
sstore(position, newGovernor)
}
}
function transferGovernance(address _newGovernor) external onlyGovernor {
_setPendingGovernor(_newGovernor);
emit PendingGovernorshipTransfer(_governor(), _newGovernor);
}
function claimGovernance() external {
require(
msg.sender == _pendingGovernor(),
"Only the pending Governor can complete the claim"
);
_changeGovernor(msg.sender);
}
function _changeGovernor(address _newGovernor) internal {
require(_newGovernor != address(0), "New Governor is address(0)");
emit GovernorshipTransferred(_governor(), _newGovernor);
_setGovernor(_newGovernor);
}
}
文件 3 的 17:Helpers.sol
pragma solidity ^0.8.0;
import { IBasicToken } from "../interfaces/IBasicToken.sol";
library Helpers {
function getSymbol(address _token) internal view returns (string memory) {
string memory symbol = IBasicToken(_token).symbol();
return symbol;
}
function getDecimals(address _token) internal view returns (uint256) {
uint256 decimals = IBasicToken(_token).decimals();
require(
decimals >= 4 && decimals <= 18,
"Token must have sufficient decimal places"
);
return decimals;
}
}
文件 4 的 17:IBasicToken.sol
pragma solidity ^0.8.0;
interface IBasicToken {
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 5 的 17:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 6 的 17:IStrategy.sol
pragma solidity ^0.8.0;
interface IStrategy {
function deposit(address _asset, uint256 _amount) external;
function depositAll() external;
function withdraw(
address _recipient,
address _asset,
uint256 _amount
) external;
function withdrawAll() external;
function checkBalance(address _asset)
external
view
returns (uint256 balance);
function supportsAsset(address _asset) external view returns (bool);
function collectRewardTokens() external;
function getRewardTokenAddresses() external view returns (address[] memory);
}
文件 7 的 17:IVault.sol
pragma solidity ^0.8.0;
import { VaultStorage } from "../vault/VaultStorage.sol";
interface IVault {
event AssetSupported(address _asset);
event AssetDefaultStrategyUpdated(address _asset, address _strategy);
event AssetAllocated(address _asset, address _strategy, uint256 _amount);
event StrategyApproved(address _addr);
event StrategyRemoved(address _addr);
event Mint(address _addr, uint256 _value);
event Redeem(address _addr, uint256 _value);
event CapitalPaused();
event CapitalUnpaused();
event RebasePaused();
event RebaseUnpaused();
event VaultBufferUpdated(uint256 _vaultBuffer);
event RedeemFeeUpdated(uint256 _redeemFeeBps);
event PriceProviderUpdated(address _priceProvider);
event AllocateThresholdUpdated(uint256 _threshold);
event RebaseThresholdUpdated(uint256 _threshold);
event StrategistUpdated(address _address);
event MaxSupplyDiffChanged(uint256 maxSupplyDiff);
event YieldDistribution(address _to, uint256 _yield, uint256 _fee);
event TrusteeFeeBpsChanged(uint256 _basis);
event TrusteeAddressChanged(address _address);
event SwapperChanged(address _address);
event SwapAllowedUndervalueChanged(uint256 _basis);
event SwapSlippageChanged(address _asset, uint256 _basis);
event Swapped(
address indexed _fromAsset,
address indexed _toAsset,
uint256 _fromAssetAmount,
uint256 _toAssetAmount
);
function transferGovernance(address _newGovernor) external;
function claimGovernance() external;
function governor() external view returns (address);
function setPriceProvider(address _priceProvider) external;
function priceProvider() external view returns (address);
function setRedeemFeeBps(uint256 _redeemFeeBps) external;
function redeemFeeBps() external view returns (uint256);
function setVaultBuffer(uint256 _vaultBuffer) external;
function vaultBuffer() external view returns (uint256);
function setAutoAllocateThreshold(uint256 _threshold) external;
function autoAllocateThreshold() external view returns (uint256);
function setRebaseThreshold(uint256 _threshold) external;
function rebaseThreshold() external view returns (uint256);
function setStrategistAddr(address _address) external;
function strategistAddr() external view returns (address);
function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;
function maxSupplyDiff() external view returns (uint256);
function setTrusteeAddress(address _address) external;
function trusteeAddress() external view returns (address);
function setTrusteeFeeBps(uint256 _basis) external;
function trusteeFeeBps() external view returns (uint256);
function ousdMetaStrategy() external view returns (address);
function setSwapper(address _swapperAddr) external;
function setSwapAllowedUndervalue(uint16 _percentageBps) external;
function setOracleSlippage(address _asset, uint16 _allowedOracleSlippageBps)
external;
function supportAsset(address _asset, uint8 _supportsAsset) external;
function approveStrategy(address _addr) external;
function removeStrategy(address _addr) external;
function setAssetDefaultStrategy(address _asset, address _strategy)
external;
function assetDefaultStrategies(address _asset)
external
view
returns (address);
function pauseRebase() external;
function unpauseRebase() external;
function rebasePaused() external view returns (bool);
function pauseCapital() external;
function unpauseCapital() external;
function capitalPaused() external view returns (bool);
function transferToken(address _asset, uint256 _amount) external;
function priceUnitMint(address asset) external view returns (uint256);
function priceUnitRedeem(address asset) external view returns (uint256);
function withdrawAllFromStrategy(address _strategyAddr) external;
function withdrawAllFromStrategies() external;
function withdrawFromStrategy(
address _strategyFromAddress,
address[] calldata _assets,
uint256[] calldata _amounts
) external;
function depositToStrategy(
address _strategyToAddress,
address[] calldata _assets,
uint256[] calldata _amounts
) external;
function mint(
address _asset,
uint256 _amount,
uint256 _minimumOusdAmount
) external;
function mintForStrategy(uint256 _amount) external;
function redeem(uint256 _amount, uint256 _minimumUnitAmount) external;
function burnForStrategy(uint256 _amount) external;
function redeemAll(uint256 _minimumUnitAmount) external;
function allocate() external;
function rebase() external;
function swapCollateral(
address fromAsset,
address toAsset,
uint256 fromAssetAmount,
uint256 minToAssetAmount,
bytes calldata data
) external returns (uint256 toAssetAmount);
function totalValue() external view returns (uint256 value);
function checkBalance(address _asset) external view returns (uint256);
function calculateRedeemOutputs(uint256 _amount)
external
view
returns (uint256[] memory);
function getAssetCount() external view returns (uint256);
function getAssetConfig(address _asset)
external
view
returns (VaultStorage.Asset memory config);
function getAllAssets() external view returns (address[] memory);
function getStrategyCount() external view returns (uint256);
function swapper() external view returns (address);
function allowedSwapUndervalue() external view returns (uint256);
function getAllStrategies() external view returns (address[] memory);
function isSupportedAsset(address _asset) external view returns (bool);
function netOusdMintForStrategyThreshold() external view returns (uint256);
function setOusdMetaStrategy(address _ousdMetaStrategy) external;
function setNetOusdMintForStrategyThreshold(uint256 _threshold) external;
function netOusdMintedForStrategy() external view returns (int256);
function weth() external view returns (address);
function cacheWETHAssetIndex() external;
function wethAssetIndex() external view returns (uint256);
function initialize(address, address) external;
function setAdminImpl(address) external;
function removeAsset(address _asset) external;
}
文件 8 的 17:IWETH9.sol
pragma solidity ^0.8.0;
interface IWETH9 {
event Approval(address indexed src, address indexed guy, uint256 wad);
event Deposit(address indexed dst, uint256 wad);
event Transfer(address indexed src, address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
function allowance(address, address) external view returns (uint256);
function approve(address guy, uint256 wad) external returns (bool);
function balanceOf(address) external view returns (uint256);
function decimals() external view returns (uint8);
function deposit() external payable;
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address dst, uint256 wad) external returns (bool);
function transferFrom(
address src,
address dst,
uint256 wad
) external returns (bool);
function withdraw(uint256 wad) external;
}
文件 9 的 17:Initializable.sol
pragma solidity ^0.8.0;
abstract contract Initializable {
bool private initialized;
bool private initializing;
modifier initializer() {
require(
initializing || !initialized,
"Initializable: contract is already initialized"
);
bool isTopLevelCall = !initializing;
if (isTopLevelCall) {
initializing = true;
initialized = true;
}
_;
if (isTopLevelCall) {
initializing = false;
}
}
uint256[50] private ______gap;
}
文件 10 的 17:InitializableAbstractStrategy.sol
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Initializable } from "../utils/Initializable.sol";
import { Governable } from "../governance/Governable.sol";
import { IVault } from "../interfaces/IVault.sol";
abstract contract InitializableAbstractStrategy is Initializable, Governable {
using SafeERC20 for IERC20;
event PTokenAdded(address indexed _asset, address _pToken);
event PTokenRemoved(address indexed _asset, address _pToken);
event Deposit(address indexed _asset, address _pToken, uint256 _amount);
event Withdrawal(address indexed _asset, address _pToken, uint256 _amount);
event RewardTokenCollected(
address recipient,
address rewardToken,
uint256 amount
);
event RewardTokenAddressesUpdated(
address[] _oldAddresses,
address[] _newAddresses
);
event HarvesterAddressesUpdated(
address _oldHarvesterAddress,
address _newHarvesterAddress
);
address public immutable platformAddress;
address public immutable vaultAddress;
address private _deprecated_platformAddress;
address private _deprecated_vaultAddress;
mapping(address => address) public assetToPToken;
address[] internal assetsMapped;
address private _deprecated_rewardTokenAddress;
uint256 private _deprecated_rewardLiquidationThreshold;
address public harvesterAddress;
address[] public rewardTokenAddresses;
int256[98] private _reserved;
struct BaseStrategyConfig {
address platformAddress;
address vaultAddress;
}
constructor(BaseStrategyConfig memory _config) {
platformAddress = _config.platformAddress;
vaultAddress = _config.vaultAddress;
}
function _initialize(
address[] memory _rewardTokenAddresses,
address[] memory _assets,
address[] memory _pTokens
) internal {
rewardTokenAddresses = _rewardTokenAddresses;
uint256 assetCount = _assets.length;
require(assetCount == _pTokens.length, "Invalid input arrays");
for (uint256 i = 0; i < assetCount; ++i) {
_setPTokenAddress(_assets[i], _pTokens[i]);
}
}
function collectRewardTokens() external virtual onlyHarvester nonReentrant {
_collectRewardTokens();
}
function _collectRewardTokens() internal virtual {
uint256 rewardTokenCount = rewardTokenAddresses.length;
for (uint256 i = 0; i < rewardTokenCount; ++i) {
IERC20 rewardToken = IERC20(rewardTokenAddresses[i]);
uint256 balance = rewardToken.balanceOf(address(this));
if (balance > 0) {
emit RewardTokenCollected(
harvesterAddress,
address(rewardToken),
balance
);
rewardToken.safeTransfer(harvesterAddress, balance);
}
}
}
modifier onlyVault() {
require(msg.sender == vaultAddress, "Caller is not the Vault");
_;
}
modifier onlyHarvester() {
require(msg.sender == harvesterAddress, "Caller is not the Harvester");
_;
}
modifier onlyVaultOrGovernor() {
require(
msg.sender == vaultAddress || msg.sender == governor(),
"Caller is not the Vault or Governor"
);
_;
}
modifier onlyVaultOrGovernorOrStrategist() {
require(
msg.sender == vaultAddress ||
msg.sender == governor() ||
msg.sender == IVault(vaultAddress).strategistAddr(),
"Caller is not the Vault, Governor, or Strategist"
);
_;
}
function setRewardTokenAddresses(address[] calldata _rewardTokenAddresses)
external
onlyGovernor
{
uint256 rewardTokenCount = _rewardTokenAddresses.length;
for (uint256 i = 0; i < rewardTokenCount; ++i) {
require(
_rewardTokenAddresses[i] != address(0),
"Can not set an empty address as a reward token"
);
}
emit RewardTokenAddressesUpdated(
rewardTokenAddresses,
_rewardTokenAddresses
);
rewardTokenAddresses = _rewardTokenAddresses;
}
function getRewardTokenAddresses()
external
view
returns (address[] memory)
{
return rewardTokenAddresses;
}
function setPTokenAddress(address _asset, address _pToken)
external
virtual
onlyGovernor
{
_setPTokenAddress(_asset, _pToken);
}
function removePToken(uint256 _assetIndex) external virtual onlyGovernor {
require(_assetIndex < assetsMapped.length, "Invalid index");
address asset = assetsMapped[_assetIndex];
address pToken = assetToPToken[asset];
if (_assetIndex < assetsMapped.length - 1) {
assetsMapped[_assetIndex] = assetsMapped[assetsMapped.length - 1];
}
assetsMapped.pop();
assetToPToken[asset] = address(0);
emit PTokenRemoved(asset, pToken);
}
function _setPTokenAddress(address _asset, address _pToken) internal {
require(assetToPToken[_asset] == address(0), "pToken already set");
require(
_asset != address(0) && _pToken != address(0),
"Invalid addresses"
);
assetToPToken[_asset] = _pToken;
assetsMapped.push(_asset);
emit PTokenAdded(_asset, _pToken);
_abstractSetPToken(_asset, _pToken);
}
function transferToken(address _asset, uint256 _amount)
public
onlyGovernor
{
require(!supportsAsset(_asset), "Cannot transfer supported asset");
IERC20(_asset).safeTransfer(governor(), _amount);
}
function setHarvesterAddress(address _harvesterAddress)
external
onlyGovernor
{
emit HarvesterAddressesUpdated(harvesterAddress, _harvesterAddress);
harvesterAddress = _harvesterAddress;
}
function _abstractSetPToken(address _asset, address _pToken)
internal
virtual;
function safeApproveAllTokens() external virtual;
function deposit(address _asset, uint256 _amount) external virtual;
function depositAll() external virtual;
function withdraw(
address _recipient,
address _asset,
uint256 _amount
) external virtual;
function withdrawAll() external virtual;
function checkBalance(address _asset)
external
view
virtual
returns (uint256 balance);
function supportsAsset(address _asset) public view virtual returns (bool);
}
文件 11 的 17:InitializableERC20Detailed.sol
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
abstract contract InitializableERC20Detailed is IERC20 {
uint256[100] private _____gap;
string private _name;
string private _symbol;
uint8 private _decimals;
function _initialize(
string memory nameArg,
string memory symbolArg,
uint8 decimalsArg
) internal {
_name = nameArg;
_symbol = symbolArg;
_decimals = decimalsArg;
}
function name() public view returns (string memory) {
return _name;
}
function symbol() public view returns (string memory) {
return _symbol;
}
function decimals() public view returns (uint8) {
return _decimals;
}
}
文件 12 的 17:LidoWithdrawalStrategy.sol
pragma solidity ^0.8.0;
import { IERC20, InitializableAbstractStrategy } from "../utils/InitializableAbstractStrategy.sol";
import { IWETH9 } from "../interfaces/IWETH9.sol";
import { IVault } from "../interfaces/IVault.sol";
interface IStETHWithdrawal {
event WithdrawalRequested(
uint256 indexed requestId,
address indexed requestor,
address indexed owner,
uint256 amountOfStETH,
uint256 amountOfShares
);
event WithdrawalsFinalized(
uint256 indexed from,
uint256 indexed to,
uint256 amountOfETHLocked,
uint256 sharesToBurn,
uint256 timestamp
);
event WithdrawalClaimed(
uint256 indexed requestId,
address indexed owner,
address indexed receiver,
uint256 amountOfETH
);
struct WithdrawalRequestStatus {
uint256 amountOfStETH;
uint256 amountOfShares;
address owner;
uint256 timestamp;
bool isFinalized;
bool isClaimed;
}
function requestWithdrawals(uint256[] calldata _amounts, address _owner)
external
returns (uint256[] memory requestIds);
function getLastCheckpointIndex() external view returns (uint256);
function findCheckpointHints(
uint256[] calldata _requestIds,
uint256 _firstIndex,
uint256 _lastIndex
) external view returns (uint256[] memory hintIds);
function claimWithdrawals(
uint256[] calldata _requestIds,
uint256[] calldata _hints
) external;
function getWithdrawalStatus(uint256[] calldata _requestIds)
external
view
returns (WithdrawalRequestStatus[] memory statuses);
function getWithdrawalRequests(address _owner)
external
view
returns (uint256[] memory requestsIds);
function finalize(
uint256 _lastRequestIdToBeFinalized,
uint256 _maxShareRate
) external payable;
}
contract LidoWithdrawalStrategy is InitializableAbstractStrategy {
IWETH9 private constant weth =
IWETH9(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20 private constant stETH =
IERC20(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84);
IStETHWithdrawal private constant withdrawalQueue =
IStETHWithdrawal(0x889edC2eDab5f40e902b864aD4d7AdE8E412F9B1);
uint256 public constant MaxWithdrawalAmount = 1000 ether;
uint256 public outstandingWithdrawals;
event WithdrawalRequests(uint256[] requestIds, uint256[] amounts);
event WithdrawalClaims(uint256[] requestIds, uint256 amount);
constructor(BaseStrategyConfig memory _stratConfig)
InitializableAbstractStrategy(_stratConfig)
{}
function initialize(
address[] memory _rewardTokenAddresses,
address[] memory _assets,
address[] memory _pTokens
) external onlyGovernor initializer {
InitializableAbstractStrategy._initialize(
_rewardTokenAddresses,
_assets,
_pTokens
);
safeApproveAllTokens();
}
function deposit(address, uint256) public override onlyVault nonReentrant {
require(false, "use depositAll() instead");
}
function depositAll() external override onlyVault nonReentrant {
uint256 stETHStart = stETH.balanceOf(address(this));
require(stETHStart > 0, "No stETH to withdraw");
uint256 withdrawalLength = (stETHStart / MaxWithdrawalAmount) + 1;
uint256[] memory amounts = new uint256[](withdrawalLength);
uint256 stETHRemaining = stETHStart;
uint256 i = 0;
while (stETHRemaining > MaxWithdrawalAmount) {
amounts[i++] = MaxWithdrawalAmount;
stETHRemaining -= MaxWithdrawalAmount;
}
amounts[i] = stETHRemaining;
uint256[] memory requestIds = withdrawalQueue.requestWithdrawals(
amounts,
address(this)
);
emit WithdrawalRequests(requestIds, amounts);
uint256 stEthDust = stETH.balanceOf(address(this));
require(
stEthDust <= withdrawalLength,
"Not all stEth in withdraw queue"
);
outstandingWithdrawals += stETHStart;
uint256 wethBalance = weth.balanceOf(address(this));
if (wethBalance > 0) {
weth.transfer(vaultAddress, wethBalance);
}
emit Deposit(address(stETH), address(withdrawalQueue), stETHStart);
}
function withdraw(
address _recipient,
address _asset,
uint256 _amount
) external override onlyVault nonReentrant {
revert("use claimWithdrawals()");
}
function claimWithdrawals(
uint256[] memory _requestIds,
uint256 _expectedAmount
) external nonReentrant {
require(
msg.sender == IVault(vaultAddress).strategistAddr(),
"Caller is not the Strategist"
);
uint256 startingBalance = payable(address(this)).balance;
uint256 lastIndex = withdrawalQueue.getLastCheckpointIndex();
uint256[] memory hintIds = withdrawalQueue.findCheckpointHints(
_requestIds,
1,
lastIndex
);
withdrawalQueue.claimWithdrawals(_requestIds, hintIds);
uint256 currentBalance = payable(address(this)).balance;
uint256 withdrawalAmount = currentBalance - startingBalance;
require(
withdrawalAmount + 2 >= _expectedAmount &&
withdrawalAmount <= _expectedAmount,
"Withdrawal amount not expected"
);
emit WithdrawalClaims(_requestIds, withdrawalAmount);
outstandingWithdrawals -= withdrawalAmount;
weth.deposit{ value: currentBalance }();
weth.transfer(vaultAddress, currentBalance);
emit Withdrawal(
address(weth),
address(withdrawalQueue),
currentBalance
);
}
function withdrawAll() external override onlyVaultOrGovernor nonReentrant {
if (payable(address(this)).balance > 0) {
weth.deposit{ value: payable(address(this)).balance }();
}
uint256 wethBalance = weth.balanceOf(address(this));
if (wethBalance > 0) {
weth.transfer(vaultAddress, wethBalance);
emit Withdrawal(address(weth), address(0), wethBalance);
}
uint256 stEthBalance = stETH.balanceOf(address(this));
if (stEthBalance > 0) {
stETH.transfer(vaultAddress, stEthBalance);
emit Withdrawal(address(stETH), address(0), stEthBalance);
}
}
function checkBalance(address _asset)
external
view
override
returns (uint256 balance)
{
if (_asset == address(weth)) {
return outstandingWithdrawals;
} else if (_asset == address(stETH)) {
return 0;
} else {
revert("Unexpected asset address");
}
}
function safeApproveAllTokens() public override {
stETH.approve(address(withdrawalQueue), type(uint256).max);
}
function supportsAsset(address _asset) public pure override returns (bool) {
return _asset == address(stETH) || _asset == address(weth);
}
receive() external payable {}
function _abstractSetPToken(address, address) internal pure override {
revert("No pTokens are used");
}
}
文件 13 的 17:OUSD.sol
pragma solidity ^0.8.0;
import { SafeMath } from "@openzeppelin/contracts/utils/math/SafeMath.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { Initializable } from "../utils/Initializable.sol";
import { InitializableERC20Detailed } from "../utils/InitializableERC20Detailed.sol";
import { StableMath } from "../utils/StableMath.sol";
import { Governable } from "../governance/Governable.sol";
contract OUSD is Initializable, InitializableERC20Detailed, Governable {
using SafeMath for uint256;
using StableMath for uint256;
event TotalSupplyUpdatedHighres(
uint256 totalSupply,
uint256 rebasingCredits,
uint256 rebasingCreditsPerToken
);
event AccountRebasingEnabled(address account);
event AccountRebasingDisabled(address account);
enum RebaseOptions {
NotSet,
OptOut,
OptIn
}
uint256 private constant MAX_SUPPLY = ~uint128(0);
uint256 public _totalSupply;
mapping(address => mapping(address => uint256)) private _allowances;
address public vaultAddress = address(0);
mapping(address => uint256) private _creditBalances;
uint256 private _rebasingCredits;
uint256 private _rebasingCreditsPerToken;
uint256 public nonRebasingSupply;
mapping(address => uint256) public nonRebasingCreditsPerToken;
mapping(address => RebaseOptions) public rebaseState;
mapping(address => uint256) public isUpgraded;
uint256 private constant RESOLUTION_INCREASE = 1e9;
function initialize(
string calldata _nameArg,
string calldata _symbolArg,
address _vaultAddress,
uint256 _initialCreditsPerToken
) external onlyGovernor initializer {
InitializableERC20Detailed._initialize(_nameArg, _symbolArg, 18);
_rebasingCreditsPerToken = _initialCreditsPerToken;
vaultAddress = _vaultAddress;
}
modifier onlyVault() {
require(vaultAddress == msg.sender, "Caller is not the Vault");
_;
}
function totalSupply() public view override returns (uint256) {
return _totalSupply;
}
function rebasingCreditsPerToken() public view returns (uint256) {
return _rebasingCreditsPerToken / RESOLUTION_INCREASE;
}
function rebasingCredits() public view returns (uint256) {
return _rebasingCredits / RESOLUTION_INCREASE;
}
function rebasingCreditsPerTokenHighres() public view returns (uint256) {
return _rebasingCreditsPerToken;
}
function rebasingCreditsHighres() public view returns (uint256) {
return _rebasingCredits;
}
function balanceOf(address _account)
public
view
override
returns (uint256)
{
if (_creditBalances[_account] == 0) return 0;
return
_creditBalances[_account].divPrecisely(_creditsPerToken(_account));
}
function creditsBalanceOf(address _account)
public
view
returns (uint256, uint256)
{
uint256 cpt = _creditsPerToken(_account);
if (cpt == 1e27) {
return (_creditBalances[_account], cpt);
} else {
return (
_creditBalances[_account] / RESOLUTION_INCREASE,
cpt / RESOLUTION_INCREASE
);
}
}
function creditsBalanceOfHighres(address _account)
public
view
returns (
uint256,
uint256,
bool
)
{
return (
_creditBalances[_account],
_creditsPerToken(_account),
isUpgraded[_account] == 1
);
}
function transfer(address _to, uint256 _value)
public
override
returns (bool)
{
require(_to != address(0), "Transfer to zero address");
require(
_value <= balanceOf(msg.sender),
"Transfer greater than balance"
);
_executeTransfer(msg.sender, _to, _value);
emit Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(
address _from,
address _to,
uint256 _value
) public override returns (bool) {
require(_to != address(0), "Transfer to zero address");
require(_value <= balanceOf(_from), "Transfer greater than balance");
_allowances[_from][msg.sender] = _allowances[_from][msg.sender].sub(
_value
);
_executeTransfer(_from, _to, _value);
emit Transfer(_from, _to, _value);
return true;
}
function _executeTransfer(
address _from,
address _to,
uint256 _value
) internal {
bool isNonRebasingTo = _isNonRebasingAccount(_to);
bool isNonRebasingFrom = _isNonRebasingAccount(_from);
uint256 creditsCredited = _value.mulTruncate(_creditsPerToken(_to));
uint256 creditsDeducted = _value.mulTruncate(_creditsPerToken(_from));
_creditBalances[_from] = _creditBalances[_from].sub(
creditsDeducted,
"Transfer amount exceeds balance"
);
_creditBalances[_to] = _creditBalances[_to].add(creditsCredited);
if (isNonRebasingTo && !isNonRebasingFrom) {
nonRebasingSupply = nonRebasingSupply.add(_value);
_rebasingCredits = _rebasingCredits.sub(creditsDeducted);
} else if (!isNonRebasingTo && isNonRebasingFrom) {
nonRebasingSupply = nonRebasingSupply.sub(_value);
_rebasingCredits = _rebasingCredits.add(creditsCredited);
}
}
function allowance(address _owner, address _spender)
public
view
override
returns (uint256)
{
return _allowances[_owner][_spender];
}
function approve(address _spender, uint256 _value)
public
override
returns (bool)
{
_allowances[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function increaseAllowance(address _spender, uint256 _addedValue)
public
returns (bool)
{
_allowances[msg.sender][_spender] = _allowances[msg.sender][_spender]
.add(_addedValue);
emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);
return true;
}
function decreaseAllowance(address _spender, uint256 _subtractedValue)
public
returns (bool)
{
uint256 oldValue = _allowances[msg.sender][_spender];
if (_subtractedValue >= oldValue) {
_allowances[msg.sender][_spender] = 0;
} else {
_allowances[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
emit Approval(msg.sender, _spender, _allowances[msg.sender][_spender]);
return true;
}
function mint(address _account, uint256 _amount) external onlyVault {
_mint(_account, _amount);
}
function _mint(address _account, uint256 _amount) internal nonReentrant {
require(_account != address(0), "Mint to the zero address");
bool isNonRebasingAccount = _isNonRebasingAccount(_account);
uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));
_creditBalances[_account] = _creditBalances[_account].add(creditAmount);
if (isNonRebasingAccount) {
nonRebasingSupply = nonRebasingSupply.add(_amount);
} else {
_rebasingCredits = _rebasingCredits.add(creditAmount);
}
_totalSupply = _totalSupply.add(_amount);
require(_totalSupply < MAX_SUPPLY, "Max supply");
emit Transfer(address(0), _account, _amount);
}
function burn(address account, uint256 amount) external onlyVault {
_burn(account, amount);
}
function _burn(address _account, uint256 _amount) internal nonReentrant {
require(_account != address(0), "Burn from the zero address");
if (_amount == 0) {
return;
}
bool isNonRebasingAccount = _isNonRebasingAccount(_account);
uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));
uint256 currentCredits = _creditBalances[_account];
if (
currentCredits == creditAmount || currentCredits - 1 == creditAmount
) {
_creditBalances[_account] = 0;
} else if (currentCredits > creditAmount) {
_creditBalances[_account] = _creditBalances[_account].sub(
creditAmount
);
} else {
revert("Remove exceeds balance");
}
if (isNonRebasingAccount) {
nonRebasingSupply = nonRebasingSupply.sub(_amount);
} else {
_rebasingCredits = _rebasingCredits.sub(creditAmount);
}
_totalSupply = _totalSupply.sub(_amount);
emit Transfer(_account, address(0), _amount);
}
function _creditsPerToken(address _account)
internal
view
returns (uint256)
{
if (nonRebasingCreditsPerToken[_account] != 0) {
return nonRebasingCreditsPerToken[_account];
} else {
return _rebasingCreditsPerToken;
}
}
function _isNonRebasingAccount(address _account) internal returns (bool) {
bool isContract = Address.isContract(_account);
if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {
_ensureRebasingMigration(_account);
}
return nonRebasingCreditsPerToken[_account] > 0;
}
function _ensureRebasingMigration(address _account) internal {
if (nonRebasingCreditsPerToken[_account] == 0) {
emit AccountRebasingDisabled(_account);
if (_creditBalances[_account] == 0) {
nonRebasingCreditsPerToken[_account] = 1e27;
} else {
nonRebasingCreditsPerToken[_account] = _rebasingCreditsPerToken;
nonRebasingSupply = nonRebasingSupply.add(balanceOf(_account));
_rebasingCredits = _rebasingCredits.sub(
_creditBalances[_account]
);
}
}
}
function governanceRebaseOptIn(address _account)
public
nonReentrant
onlyGovernor
{
_rebaseOptIn(_account);
}
function rebaseOptIn() public nonReentrant {
_rebaseOptIn(msg.sender);
}
function _rebaseOptIn(address _account) internal {
require(_isNonRebasingAccount(_account), "Account has not opted out");
uint256 newCreditBalance = _creditBalances[_account]
.mul(_rebasingCreditsPerToken)
.div(_creditsPerToken(_account));
nonRebasingSupply = nonRebasingSupply.sub(balanceOf(_account));
_creditBalances[_account] = newCreditBalance;
_rebasingCredits = _rebasingCredits.add(_creditBalances[_account]);
rebaseState[_account] = RebaseOptions.OptIn;
delete nonRebasingCreditsPerToken[_account];
emit AccountRebasingEnabled(_account);
}
function rebaseOptOut() public nonReentrant {
require(!_isNonRebasingAccount(msg.sender), "Account has not opted in");
nonRebasingSupply = nonRebasingSupply.add(balanceOf(msg.sender));
nonRebasingCreditsPerToken[msg.sender] = _rebasingCreditsPerToken;
_rebasingCredits = _rebasingCredits.sub(_creditBalances[msg.sender]);
rebaseState[msg.sender] = RebaseOptions.OptOut;
emit AccountRebasingDisabled(msg.sender);
}
function changeSupply(uint256 _newTotalSupply)
external
onlyVault
nonReentrant
{
require(_totalSupply > 0, "Cannot increase 0 supply");
if (_totalSupply == _newTotalSupply) {
emit TotalSupplyUpdatedHighres(
_totalSupply,
_rebasingCredits,
_rebasingCreditsPerToken
);
return;
}
_totalSupply = _newTotalSupply > MAX_SUPPLY
? MAX_SUPPLY
: _newTotalSupply;
_rebasingCreditsPerToken = _rebasingCredits.divPrecisely(
_totalSupply.sub(nonRebasingSupply)
);
require(_rebasingCreditsPerToken > 0, "Invalid change in supply");
_totalSupply = _rebasingCredits
.divPrecisely(_rebasingCreditsPerToken)
.add(nonRebasingSupply);
emit TotalSupplyUpdatedHighres(
_totalSupply,
_rebasingCredits,
_rebasingCreditsPerToken
);
}
}
文件 14 的 17:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 15 的 17:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 16 的 17:StableMath.sol
pragma solidity ^0.8.0;
import { SafeMath } from "@openzeppelin/contracts/utils/math/SafeMath.sol";
library StableMath {
using SafeMath for uint256;
uint256 private constant FULL_SCALE = 1e18;
function scaleBy(
uint256 x,
uint256 to,
uint256 from
) internal pure returns (uint256) {
if (to > from) {
x = x.mul(10**(to - from));
} else if (to < from) {
x = x.div(10**(from - to));
}
return x;
}
function mulTruncate(uint256 x, uint256 y) internal pure returns (uint256) {
return mulTruncateScale(x, y, FULL_SCALE);
}
function mulTruncateScale(
uint256 x,
uint256 y,
uint256 scale
) internal pure returns (uint256) {
uint256 z = x.mul(y);
return z.div(scale);
}
function mulTruncateCeil(uint256 x, uint256 y)
internal
pure
returns (uint256)
{
uint256 scaled = x.mul(y);
uint256 ceil = scaled.add(FULL_SCALE.sub(1));
return ceil.div(FULL_SCALE);
}
function divPrecisely(uint256 x, uint256 y)
internal
pure
returns (uint256)
{
uint256 z = x.mul(FULL_SCALE);
return z.div(y);
}
}
文件 17 的 17:VaultStorage.sol
pragma solidity ^0.8.0;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { IStrategy } from "../interfaces/IStrategy.sol";
import { Governable } from "../governance/Governable.sol";
import { OUSD } from "../token/OUSD.sol";
import { Initializable } from "../utils/Initializable.sol";
import "../utils/Helpers.sol";
contract VaultStorage is Initializable, Governable {
using SafeERC20 for IERC20;
event AssetSupported(address _asset);
event AssetRemoved(address _asset);
event AssetDefaultStrategyUpdated(address _asset, address _strategy);
event AssetAllocated(address _asset, address _strategy, uint256 _amount);
event StrategyApproved(address _addr);
event StrategyRemoved(address _addr);
event Mint(address _addr, uint256 _value);
event Redeem(address _addr, uint256 _value);
event CapitalPaused();
event CapitalUnpaused();
event RebasePaused();
event RebaseUnpaused();
event VaultBufferUpdated(uint256 _vaultBuffer);
event OusdMetaStrategyUpdated(address _ousdMetaStrategy);
event RedeemFeeUpdated(uint256 _redeemFeeBps);
event PriceProviderUpdated(address _priceProvider);
event AllocateThresholdUpdated(uint256 _threshold);
event RebaseThresholdUpdated(uint256 _threshold);
event StrategistUpdated(address _address);
event MaxSupplyDiffChanged(uint256 maxSupplyDiff);
event YieldDistribution(address _to, uint256 _yield, uint256 _fee);
event TrusteeFeeBpsChanged(uint256 _basis);
event TrusteeAddressChanged(address _address);
event NetOusdMintForStrategyThresholdChanged(uint256 _threshold);
event SwapperChanged(address _address);
event SwapAllowedUndervalueChanged(uint256 _basis);
event SwapSlippageChanged(address _asset, uint256 _basis);
event Swapped(
address indexed _fromAsset,
address indexed _toAsset,
uint256 _fromAssetAmount,
uint256 _toAssetAmount
);
enum UnitConversion {
DECIMALS,
GETEXCHANGERATE
}
struct Asset {
bool isSupported;
UnitConversion unitConversion;
uint8 decimals;
uint16 allowedOracleSlippageBps;
}
mapping(address => Asset) internal assets;
address[] internal allAssets;
struct Strategy {
bool isSupported;
uint256 _deprecated;
}
mapping(address => Strategy) internal strategies;
address[] internal allStrategies;
address public priceProvider;
bool public rebasePaused = false;
bool public capitalPaused = true;
uint256 public redeemFeeBps;
uint256 public vaultBuffer;
uint256 public autoAllocateThreshold;
uint256 public rebaseThreshold;
OUSD internal oUSD;
bytes32 constant adminImplPosition =
0xa2bd3d3cf188a41358c8b401076eb59066b09dec5775650c0de4c55187d17bd9;
address private _deprecated_rebaseHooksAddr = address(0);
address private _deprecated_uniswapAddr = address(0);
address public strategistAddr = address(0);
mapping(address => address) public assetDefaultStrategies;
uint256 public maxSupplyDiff;
address public trusteeAddress;
uint256 public trusteeFeeBps;
address[] private _deprecated_swapTokens;
uint256 constant MINT_MINIMUM_UNIT_PRICE = 0.998e18;
address public ousdMetaStrategy = address(0);
int256 public netOusdMintedForStrategy = 0;
uint256 public netOusdMintForStrategyThreshold = 0;
uint256 constant MIN_UNIT_PRICE_DRIFT = 0.7e18;
uint256 constant MAX_UNIT_PRICE_DRIFT = 1.3e18;
struct SwapConfig {
address swapper;
uint16 allowedUndervalueBps;
}
SwapConfig internal swapConfig = SwapConfig(address(0), 0);
uint256[50] private __gap;
function setAdminImpl(address newImpl) external onlyGovernor {
require(
Address.isContract(newImpl),
"new implementation is not a contract"
);
bytes32 position = adminImplPosition;
assembly {
sstore(position, newImpl)
}
}
}
{
"compilationTarget": {
"contracts/strategies/LidoWithdrawalStrategy.sol": "LidoWithdrawalStrategy"
},
"evmVersion": "london",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"components":[{"internalType":"address","name":"platformAddress","type":"address"},{"internalType":"address","name":"vaultAddress","type":"address"}],"internalType":"struct InitializableAbstractStrategy.BaseStrategyConfig","name":"_stratConfig","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_pToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernor","type":"address"}],"name":"GovernorshipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_oldHarvesterAddress","type":"address"},{"indexed":false,"internalType":"address","name":"_newHarvesterAddress","type":"address"}],"name":"HarvesterAddressesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_pToken","type":"address"}],"name":"PTokenAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_pToken","type":"address"}],"name":"PTokenRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousGovernor","type":"address"},{"indexed":true,"internalType":"address","name":"newGovernor","type":"address"}],"name":"PendingGovernorshipTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_oldAddresses","type":"address[]"},{"indexed":false,"internalType":"address[]","name":"_newAddresses","type":"address[]"}],"name":"RewardTokenAddressesUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"rewardToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RewardTokenCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_asset","type":"address"},{"indexed":false,"internalType":"address","name":"_pToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"requestIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalClaims","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"requestIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"WithdrawalRequests","type":"event"},{"inputs":[],"name":"MaxWithdrawalAmount","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":[{"internalType":"address","name":"_asset","type":"address"}],"name":"checkBalance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_requestIds","type":"uint256[]"},{"internalType":"uint256","name":"_expectedAmount","type":"uint256"}],"name":"claimWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collectRewardTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"deposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"depositAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getRewardTokenAddresses","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"harvesterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_rewardTokenAddresses","type":"address[]"},{"internalType":"address[]","name":"_assets","type":"address[]"},{"internalType":"address[]","name":"_pTokens","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outstandingWithdrawals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"platformAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetIndex","type":"uint256"}],"name":"removePToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"rewardTokenAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"safeApproveAllTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_harvesterAddress","type":"address"}],"name":"setHarvesterAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"address","name":"_pToken","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":"_asset","type":"address"}],"name":"supportsAsset","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernor","type":"address"}],"name":"transferGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vaultAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_asset","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]