编译器
0.8.21+commit.d9974bed
文件 1 的 26:AccessControl.sol
pragma solidity ^0.8.20;
import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address account => bool) hasRole;
bytes32 adminRole;
}
mapping(bytes32 role => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
function hasRole(bytes32 role, address account) public view virtual returns (bool) {
return _roles[role].hasRole[account];
}
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert AccessControlUnauthorizedAccount(account, role);
}
}
function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address callerConfirmation) public virtual {
if (callerConfirmation != _msgSender()) {
revert AccessControlBadConfirmation();
}
_revokeRole(role, callerConfirmation);
}
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
if (!hasRole(role, account)) {
_roles[role].hasRole[account] = true;
emit RoleGranted(role, account, _msgSender());
return true;
} else {
return false;
}
}
function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
if (hasRole(role, account)) {
_roles[role].hasRole[account] = false;
emit RoleRevoked(role, account, _msgSender());
return true;
} else {
return false;
}
}
}
文件 2 的 26:Address.sol
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
library Address {
error AddressEmptyCode(address target);
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert Errors.FailedCall();
}
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
function _revert(bytes memory returndata) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}
文件 3 的 26:BaseV2Vault.sol
pragma solidity ^0.8.19;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {Address} from "openzeppelin-contracts/utils/Address.sol";
import {EnumerableMap} from "openzeppelin-contracts/utils/structs/EnumerableMap.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {ProtocolNotSupported, ProtocolInUse, ZeroAddress, TokenOutNotAllowed} from "../errors/scErrors.sol";
import {Constants as C} from "../lib/Constants.sol";
import {IVault} from "../interfaces/balancer/IVault.sol";
import {IFlashLoanRecipient} from "../interfaces/balancer/IFlashLoanRecipient.sol";
import {IAdapter} from "./IAdapter.sol";
import {sc4626} from "../sc4626.sol";
import {IPriceConverter} from "./priceConverter/IPriceConverter.sol";
import {ISwapper} from "./swapper/ISwapper.sol";
abstract contract BaseV2Vault is sc4626, IFlashLoanRecipient {
using Address for address;
using SafeTransferLib for ERC20;
using EnumerableMap for EnumerableMap.UintToAddressMap;
event SwapperUpdated(address indexed admin, address newSwapper);
event PriceConverterUpdated(address indexed admin, address newPriceConverter);
event ProtocolAdapterAdded(address indexed admin, uint256 adapterId, address adapter);
event ProtocolAdapterRemoved(address indexed admin, uint256 adapterId);
event RewardsClaimed(uint256 adapterId);
event TokenSwapped(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOutReceived);
event TokenWhitelisted(address token, bool value);
IVault public constant balancerVault = IVault(C.BALANCER_VAULT);
IPriceConverter public priceConverter;
ISwapper public swapper;
EnumerableMap.UintToAddressMap internal protocolAdapters;
mapping(ERC20 => bool) internal swapWhitelist;
constructor(
address _admin,
address _keeper,
ERC20 _asset,
IPriceConverter _priceConverter,
ISwapper _swapper,
string memory _name,
string memory _symbol
) sc4626(_admin, _keeper, _asset, _name, _symbol) {
_setPriceConverter(_priceConverter);
_setSwapper(_swapper);
swapWhitelist[_asset] = true;
}
function whiteListToken(ERC20 _token, bool _value) external {
_onlyAdmin();
if (address(_token) == address(0)) revert ZeroAddress();
swapWhitelist[_token] = _value;
emit TokenWhitelisted(address(_token), _value);
}
function setSwapper(ISwapper _newSwapper) external {
_onlyAdmin();
_setSwapper(_newSwapper);
emit SwapperUpdated(msg.sender, address(_newSwapper));
}
function setPriceConverter(IPriceConverter _newPriceConverter) external {
_onlyAdmin();
_setPriceConverter(_newPriceConverter);
emit PriceConverterUpdated(msg.sender, address(_newPriceConverter));
}
function addAdapter(IAdapter _adapter) external {
_onlyAdmin();
uint256 id = _adapter.id();
if (isSupported(id)) revert ProtocolInUse(id);
protocolAdapters.set(id, address(_adapter));
address(_adapter).functionDelegateCall(abi.encodeWithSelector(IAdapter.setApprovals.selector));
emit ProtocolAdapterAdded(msg.sender, id, address(_adapter));
}
function removeAdapter(uint256 _adapterId, bool _force) external {
_onlyAdmin();
_isSupportedCheck(_adapterId);
if (!_force && IAdapter(protocolAdapters.get(_adapterId)).getCollateral(address(this)) > 0) {
revert ProtocolInUse(_adapterId);
}
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.revokeApprovals.selector));
protocolAdapters.remove(_adapterId);
emit ProtocolAdapterRemoved(msg.sender, _adapterId);
}
function isSupported(uint256 _adapterId) public view returns (bool) {
return protocolAdapters.contains(_adapterId);
}
function getAdapter(uint256 _adapterId) external view returns (address adapter) {
(, adapter) = protocolAdapters.tryGet(_adapterId);
}
function isTokenWhitelisted(ERC20 _token) external view returns (bool) {
return swapWhitelist[_token];
}
function claimRewards(uint256 _adapterId, bytes calldata _callData) external {
_onlyKeeperOrFlashLoan();
_isSupportedCheck(_adapterId);
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.claimRewards.selector, _callData));
emit RewardsClaimed(_adapterId);
}
function swapTokens(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
bytes calldata _swapData
) external {
_onlyKeeperOrFlashLoan();
if (!swapWhitelist[ERC20(_tokenOut)]) revert TokenOutNotAllowed(_tokenOut);
bytes memory result = address(swapper).functionDelegateCall(
abi.encodeWithSelector(
ISwapper.swapTokens.selector, _tokenIn, _tokenOut, _amountIn, _amountOutMin, _swapData
)
);
uint256 amountReceived = abi.decode(result, (uint256));
emit TokenSwapped(_tokenIn, _tokenOut, _amountIn, amountReceived);
}
function _multiCall(bytes[] memory _callData) internal {
for (uint256 i = 0; i < _callData.length; i++) {
if (_callData[i].length == 0) continue;
address(this).functionDelegateCall(_callData[i]);
}
}
function _adapterDelegateCall(uint256 _adapterId, bytes memory _data) internal {
protocolAdapters.get(_adapterId).functionDelegateCall(_data);
}
function _adapterDelegateCall(address _adapter, bytes memory _data) internal {
_adapter.functionDelegateCall(_data);
}
function _setSwapper(ISwapper _newSwapper) internal {
_zeroAddressCheck(address(_newSwapper));
swapper = _newSwapper;
}
function _setPriceConverter(IPriceConverter _newPriceConverter) internal {
_zeroAddressCheck(address(_newPriceConverter));
priceConverter = _newPriceConverter;
}
function _isSupportedCheck(uint256 _adapterId) internal view {
if (!isSupported(_adapterId)) revert ProtocolNotSupported(_adapterId);
}
function _zeroAddressCheck(address _address) internal pure {
if (_address == address(0)) revert ZeroAddress();
}
}
文件 4 的 26:Constants.sol
pragma solidity ^0.8.13;
library Constants {
uint256 public constant ONE = 1e18;
uint256 public constant WETH_USDC_DECIMALS_DIFF = 1e12;
uint256 public constant WETH_USDT_DECIMALS_DIFF = 1e12;
uint256 public constant AAVE_VAR_INTEREST_RATE_MODE = 2;
uint8 public constant AAVE_EMODE_ID = 1;
uint32 constant EULER_CONFIG_FACTOR_SCALE = 4_000_000_000;
address public constant USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
address public constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address public constant WSTETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;
address public constant STETH = 0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;
address public constant LUSD = 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0;
address public constant DAI = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
address public constant SDAI = 0x83F20F44975D03b1b09e64809B757c47f942BEeA;
address public constant USDS = 0xdC035D45d973E3EC169d2276DDab16f1e407384F;
address public constant SUSDS = 0xa3931d71877C0E7a3148CB7Eb4463524FEc27fbD;
address public constant USDT = 0xdAC17F958D2ee523a2206206994597C13D831ec7;
address public constant CURVE_ETH_STETH_POOL = 0xDC24316b9AE028F1497c275EB9192a3Ea0f67022;
address public constant UNISWAP_V3_SWAP_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
address public constant AAVE_V3_POOL = 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2;
address public constant AAVE_V3_POOL_DATA_PROVIDER = 0x7B4EB56E7CD4b454BA8ff71E4518426369a138a3;
address public constant AAVE_V3_REWARDS_CONTROLLER = 0x8164Cc65827dcFe994AB23944CBC90e0aa80bFcb;
address public constant AAVE_V3_AUSDC_TOKEN = 0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c;
address public constant AAVE_V3_AUSDS_TOKEN = 0x32a6268f9Ba3642Dda7892aDd74f1D34469A4259;
address public constant AAVE_V3_AUSDT_TOKEN = 0x23878914EFE38d27C4D67Ab83ed1b93A74D4086a;
address public constant AAVE_V3_AWSTETH_TOKEN = 0x0B925eD163218f6662a35e0f0371Ac234f9E9371;
address public constant AAVE_V3_VAR_DEBT_WETH_TOKEN = 0xeA51d7853EEFb32b6ee06b1C12E6dcCA88Be0fFE;
address public constant AAVE_V3_VAR_DEBT_IMPLEMENTATION_CONTRACT = 0xaC725CB59D16C81061BDeA61041a8A5e73DA9EC6;
address public constant SPARK_POOL = 0xC13e21B648A5Ee794902342038FF3aDAB66BE987;
address public constant SPARK_POOL_DATA_PROVIDER = 0xFc21d6d146E6086B8359705C8b28512a983db0cb;
address public constant SPARK_ADAI_TOKEN = 0x4DEDf26112B3Ec8eC46e7E31EA5e123490B05B8B;
address public constant SPARK_ASDAI_TOKEN = 0x78f897F0fE2d3B5690EbAe7f19862DEacedF10a7;
address public constant SPARK_VAR_DEBT_WETH_TOKEN = 0x2e7576042566f8D6990e07A1B61Ad1efd86Ae70d;
address public constant EULER = 0x27182842E098f60e3D576794A5bFFb0777E025d3;
address public constant EULER_MARKETS = 0x3520d5a913427E6F0D6A83E07ccD4A4da316e4d3;
address public constant EULER_ETOKEN_WSTETH = 0xbd1bd5C956684f7EB79DA40f582cbE1373A1D593;
address public constant EULER_ETOKEN_USDC = 0xEb91861f8A4e1C12333F42DCE8fB0Ecdc28dA716;
address public constant EULER_DTOKEN_WETH = 0x62e28f054efc24b26A794F5C1249B6349454352C;
address public constant EULER_REWARDS_TOKEN = 0xd9Fcd98c322942075A5C3860693e9f4f03AAE07b;
address public constant CHAINLINK_USDC_ETH_PRICE_FEED = 0x986b5E1e1755e3C2440e960477f25201B0a8bbD4;
address public constant CHAINLINK_DAI_ETH_PRICE_FEED = 0x773616E4d11A78F511299002da57A0a94577F1f4;
address public constant CHAINLINK_STETH_ETH_PRICE_FEED = 0x86392dC19c0b719886221c78AB11eb8Cf5c52812;
address public constant CHAINLINK_USDT_ETH_PRICE_FEED = 0xEe9F2375b4bdF6387aa8265dD4FB8F16512A1d46;
address public constant LIQUITY_USD_ETH_PRICE_FEED = 0x4c517D4e2C851CA76d7eC94B805269Df0f2201De;
address public constant BALANCER_VAULT = 0xBA12222222228d8Ba445958a75a0704d566BF2C8;
address public constant BALANCER_ADMIN = 0x97207B095e4D5C9a6e4cfbfcd2C3358E03B90c4A;
address public constant BALANCER_FEES_COLLECTOR = 0xce88686553686DA562CE7Cea497CE749DA109f9F;
address public constant ZERO_EX_ROUTER = 0xDef1C0ded9bec7F1a1670819833240f027b25EfF;
address public constant LIFI = 0x1231DEB6f5749EF6cE6943a275A1D3E7486F4EaE;
address public constant COMPOUND_V3_COMET_WETH = 0xA17581A9E3356d9A858b789D68B4d866e593aE94;
address public constant AAVE_V2_LENDING_POOL = 0x7d2768dE32b0b80b7a3454c06BdAc94A69DDc7A9;
address public constant AAVE_V2_PROTOCOL_DATA_PROVIDER = 0x057835Ad21a177dbdd3090bB1CAE03EaCF78Fc6d;
address public constant AAVE_V2_AUSDC_TOKEN = 0xBcca60bB61934080951369a648Fb03DF4F96263C;
address public constant AAVE_V2_VAR_DEBT_WETH_TOKEN = 0xF63B34710400CAd3e044cFfDcAb00a0f32E33eCf;
address public constant LIQUITY_STABILITY_POOL = 0x66017D22b0f8556afDd19FC67041899Eb65a21bb;
address public constant LIQUITY_LQTY_TOKEN = 0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D;
address public constant MORPHO = 0x33333aea097c193e66081E930c33020272b33333;
address public constant DAI_USDS_CONVERTER = 0x3225737a9Bbb6473CB4a45b7244ACa2BeFdB276A;
}
文件 5 的 26:Context.sol
pragma solidity ^0.8.20;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
文件 6 的 26:ERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 7 的 26:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 8 的 26:ERC4626.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "../utils/FixedPointMathLib.sol";
abstract contract ERC4626 is ERC20 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed caller,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
ERC20 public immutable asset;
constructor(
ERC20 _asset,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol, _asset.decimals()) {
asset = _asset;
}
function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {
assets = previewMint(shares);
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function withdraw(
uint256 assets,
address receiver,
address owner
) public virtual returns (uint256 shares) {
shares = previewWithdraw(assets);
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender];
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function redeem(
uint256 shares,
address receiver,
address owner
) public virtual returns (uint256 assets) {
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender];
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}
function previewDeposit(uint256 assets) public view virtual returns (uint256) {
return convertToShares(assets);
}
function previewMint(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
}
function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
}
function previewRedeem(uint256 shares) public view virtual returns (uint256) {
return convertToAssets(shares);
}
function maxDeposit(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxMint(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxWithdraw(address owner) public view virtual returns (uint256) {
return convertToAssets(balanceOf[owner]);
}
function maxRedeem(address owner) public view virtual returns (uint256) {
return balanceOf[owner];
}
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual {}
function afterDeposit(uint256 assets, uint256 shares) internal virtual {}
}
文件 9 的 26:EnumerableMap.sol
pragma solidity ^0.8.20;
import {EnumerableSet} from "./EnumerableSet.sol";
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
error EnumerableMapNonexistentKey(bytes32 key);
struct Bytes32ToBytes32Map {
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 key => bytes32) _values;
}
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) {
bytes32 key = map._keys.at(index);
return (key, map._values[key]);
}
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) {
bytes32 value = map._values[key];
if (value == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, value);
}
}
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
if (value == 0 && !contains(map, key)) {
revert EnumerableMapNonexistentKey(key);
}
return value;
}
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return map._keys.values();
}
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), uint256(value));
}
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, uint256(value));
}
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
function keys(UintToUintMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), address(uint160(uint256(value))));
}
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(value))));
}
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
struct UintToBytes32Map {
Bytes32ToBytes32Map _inner;
}
function set(UintToBytes32Map storage map, uint256 key, bytes32 value) internal returns (bool) {
return set(map._inner, bytes32(key), value);
}
function remove(UintToBytes32Map storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
function contains(UintToBytes32Map storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
function length(UintToBytes32Map storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(UintToBytes32Map storage map, uint256 index) internal view returns (uint256, bytes32) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (uint256(key), value);
}
function tryGet(UintToBytes32Map storage map, uint256 key) internal view returns (bool, bytes32) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(key));
return (success, value);
}
function get(UintToBytes32Map storage map, uint256 key) internal view returns (bytes32) {
return get(map._inner, bytes32(key));
}
function keys(UintToBytes32Map storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), uint256(value));
}
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(value));
}
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
function keys(AddressToUintMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct AddressToAddressMap {
Bytes32ToBytes32Map _inner;
}
function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value))));
}
function remove(AddressToAddressMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
function contains(AddressToAddressMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
function length(AddressToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(AddressToAddressMap storage map, uint256 index) internal view returns (address, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), address(uint160(uint256(value))));
}
function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, address(uint160(uint256(value))));
}
function get(AddressToAddressMap storage map, address key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(uint256(uint160(key)))))));
}
function keys(AddressToAddressMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct AddressToBytes32Map {
Bytes32ToBytes32Map _inner;
}
function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), value);
}
function remove(AddressToBytes32Map storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
function length(AddressToBytes32Map storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(AddressToBytes32Map storage map, uint256 index) internal view returns (address, bytes32) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (address(uint160(uint256(key))), value);
}
function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool, bytes32) {
(bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, value);
}
function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) {
return get(map._inner, bytes32(uint256(uint160(key))));
}
function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, uint256(value));
}
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, uint256(value));
}
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct Bytes32ToAddressMap {
Bytes32ToBytes32Map _inner;
}
function set(Bytes32ToAddressMap storage map, bytes32 key, address value) internal returns (bool) {
return set(map._inner, key, bytes32(uint256(uint160(value))));
}
function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
function length(Bytes32ToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
function at(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32, address) {
(bytes32 key, bytes32 value) = at(map._inner, index);
return (key, address(uint160(uint256(value))));
}
function tryGet(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool, address) {
(bool success, bytes32 value) = tryGet(map._inner, key);
return (success, address(uint160(uint256(value))));
}
function get(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, key))));
}
function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
}
文件 10 的 26:EnumerableSet.sol
pragma solidity ^0.8.20;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 value => uint256) _positions;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 position = set._positions[value];
if (position != 0) {
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[valueIndex] = lastValue;
set._positions[lastValue] = position;
}
set._values.pop();
delete set._positions[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 11 的 26:Errors.sol
pragma solidity ^0.8.20;
library Errors {
error InsufficientBalance(uint256 balance, uint256 needed);
error FailedCall();
error FailedDeployment();
}
文件 12 的 26:FixedPointMathLib.sol
pragma solidity >=0.8.0;
library FixedPointMathLib {
uint256 internal constant MAX_UINT256 = 2**256 - 1;
uint256 internal constant WAD = 1e18;
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD);
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD);
}
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y);
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y);
}
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := div(mul(x, y), denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
function rpow(
uint256 x,
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
assembly {
switch x
case 0 {
switch n
case 0 {
z := scalar
}
default {
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
z := scalar
}
default {
z := x
}
let half := shr(1, scalar)
for {
n := shr(1, n)
} n {
n := shr(1, n)
} {
if shr(128, x) {
revert(0, 0)
}
let xx := mul(x, x)
let xxRound := add(xx, half)
if lt(xxRound, xx) {
revert(0, 0)
}
x := div(xxRound, scalar)
if mod(n, 2) {
let zx := mul(z, x)
if iszero(eq(div(zx, x), z)) {
if iszero(iszero(x)) {
revert(0, 0)
}
}
let zxRound := add(zx, half)
if lt(zxRound, zx) {
revert(0, 0)
}
z := div(zxRound, scalar)
}
}
}
}
}
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly {
let y := x
z := 181
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
z := shr(18, mul(z, add(y, 65536)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := sub(z, lt(div(x, z), z))
}
}
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mod(x, y)
}
}
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly {
r := div(x, y)
}
}
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}
文件 13 的 26:IAccessControl.sol
pragma solidity ^0.8.20;
interface IAccessControl {
error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);
error AccessControlBadConfirmation();
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
function hasRole(bytes32 role, address account) external view returns (bool);
function getRoleAdmin(bytes32 role) external view returns (bytes32);
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function renounceRole(bytes32 role, address callerConfirmation) external;
}
文件 14 的 26:IAdapter.sol
pragma solidity ^0.8.19;
interface IAdapter {
function id() external view returns (uint256);
function setApprovals() external;
function revokeApprovals() external;
function supply(uint256 amount) external;
function borrow(uint256 amount) external;
function repay(uint256 amount) external;
function withdraw(uint256 amount) external;
function claimRewards(bytes calldata data) external;
function getCollateral(address account) external view returns (uint256);
function getDebt(address account) external view returns (uint256);
function getMaxLtv() external view returns (uint256);
}
文件 15 的 26:IERC165.sol
pragma solidity ^0.8.20;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 16 的 26:IFlashLoanRecipient.sol
pragma solidity ^0.8.0;
interface IFlashLoanRecipient {
function receiveFlashLoan(
address[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external;
}
文件 17 的 26:IPriceConverter.sol
pragma solidity ^0.8.19;
interface IPriceConverter {}
文件 18 的 26:ISinglePairPriceConverter.sol
pragma solidity ^0.8.19;
import {IPriceConverter} from "./IPriceConverter.sol";
interface ISinglePairPriceConverter is IPriceConverter {
function asset() external view returns (address);
function targetToken() external view returns (address);
function targetTokenToAsset(uint256 _tokenAmount) external view returns (uint256 assetAmount);
function assetToTargetToken(uint256 _assetAmount) external view returns (uint256 tokenAmount);
}
文件 19 的 26:ISinglePairSwapper.sol
pragma solidity ^0.8.19;
import "./ISwapper.sol";
interface ISinglePairSwapper is ISwapper {
function asset() external view returns (address);
function targetToken() external view returns (address);
function swapTargetTokenForAsset(uint256 _targetAmount, uint256 _assetAmountOutMin)
external
returns (uint256 amountReceived);
function swapAssetForExactTargetToken(uint256 _targetTokenAmountOut) external returns (uint256 amountSpent);
}
文件 20 的 26:ISwapper.sol
pragma solidity ^0.8.19;
interface ISwapper {
function swapRouter() external view returns (address);
function swapTokens(
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
bytes calldata _swapData
) external returns (uint256);
}
文件 21 的 26:IVault.sol
pragma solidity ^0.8.0;
interface IVault {
function flashLoan(address recipient, address[] memory tokens, uint256[] memory amounts, bytes memory userData)
external;
}
文件 22 的 26:SafeTransferLib.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), from)
mstore(add(freeMemoryPointer, 36), to)
mstore(add(freeMemoryPointer, 68), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to)
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), to)
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
文件 23 的 26:sc4626.sol
pragma solidity ^0.8.10;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {ERC4626} from "solmate/mixins/ERC4626.sol";
import {AccessControl} from "openzeppelin-contracts/access/AccessControl.sol";
import {Constants as C} from "./lib/Constants.sol";
import {
CallerNotAdmin,
CallerNotKeeper,
ZeroAddress,
InvalidFlashLoanCaller,
TreasuryCannotBeZero,
FeesTooHigh,
InvalidFloatPercentage,
InvalidSlippageTolerance
} from "./errors/scErrors.sol";
abstract contract sc4626 is ERC4626, AccessControl {
constructor(address _admin, address _keeper, ERC20 _asset, string memory _name, string memory _symbol)
ERC4626(_asset, _name, _symbol)
{
if (_admin == address(0)) revert ZeroAddress();
if (_keeper == address(0)) revert ZeroAddress();
_grantRole(DEFAULT_ADMIN_ROLE, _admin);
_grantRole(KEEPER_ROLE, _keeper);
}
event TreasuryUpdated(address indexed user, address newTreasury);
event PerformanceFeeUpdated(address indexed user, uint256 newPerformanceFee);
event FloatPercentageUpdated(address indexed user, uint256 newFloatPercentage);
event SlippageToleranceUpdated(address indexed admin, uint256 newSlippageTolerance);
bytes32 public constant KEEPER_ROLE = keccak256("KEEPER_ROLE");
bool public flashLoanInitiated;
address public treasury;
uint256 public performanceFee = 0.1e18;
uint256 public floatPercentage = 0.01e18;
uint256 public slippageTolerance = 0.99e18;
function setTreasury(address _newTreasury) external {
_onlyAdmin();
if (_newTreasury == address(0)) revert TreasuryCannotBeZero();
treasury = _newTreasury;
emit TreasuryUpdated(msg.sender, _newTreasury);
}
function setPerformanceFee(uint256 _newPerformanceFee) external {
_onlyAdmin();
if (_newPerformanceFee > 1e18) revert FeesTooHigh();
performanceFee = _newPerformanceFee;
emit PerformanceFeeUpdated(msg.sender, _newPerformanceFee);
}
function setFloatPercentage(uint256 _newFloatPercentage) external {
_onlyAdmin();
if (_newFloatPercentage > C.ONE) revert InvalidFloatPercentage();
floatPercentage = _newFloatPercentage;
emit FloatPercentageUpdated(msg.sender, _newFloatPercentage);
}
function setSlippageTolerance(uint256 _newSlippageTolerance) external {
_onlyAdmin();
if (_newSlippageTolerance > C.ONE) revert InvalidSlippageTolerance();
slippageTolerance = _newSlippageTolerance;
emit SlippageToleranceUpdated(msg.sender, _newSlippageTolerance);
}
function _onlyAdmin() internal view {
if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert CallerNotAdmin();
}
function _onlyKeeper() internal view {
if (!hasRole(KEEPER_ROLE, msg.sender)) revert CallerNotKeeper();
}
function _onlyKeeperOrFlashLoan() internal view {
if (!flashLoanInitiated) _onlyKeeper();
}
function _initiateFlashLoan() internal {
flashLoanInitiated = true;
}
function _finalizeFlashLoan() internal {
flashLoanInitiated = false;
}
function _isFlashLoanInitiated() internal view {
if (!flashLoanInitiated) revert InvalidFlashLoanCaller();
}
}
文件 24 的 26:scCrossAssetYieldVault.sol
pragma solidity ^0.8.19;
import {
NoProfitsToSell,
FlashLoanAmountZero,
EndAssetBalanceTooLow,
FloatBalanceTooLow,
TargetTokenMismatch,
InvestedAmountNotWithdrawn
} from "../errors/scErrors.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {ERC4626} from "solmate/mixins/ERC4626.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
import {Address} from "openzeppelin-contracts/utils/Address.sol";
import {EnumerableMap} from "openzeppelin-contracts/utils/structs/EnumerableMap.sol";
import {Constants as C} from "../lib/Constants.sol";
import {BaseV2Vault} from "./BaseV2Vault.sol";
import {IAdapter} from "./IAdapter.sol";
import {ISinglePairPriceConverter} from "./priceConverter/ISinglePairPriceConverter.sol";
import {ISinglePairSwapper} from "./swapper/ISinglePairSwapper.sol";
abstract contract scCrossAssetYieldVault is BaseV2Vault {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
using Address for address;
using EnumerableMap for EnumerableMap.UintToAddressMap;
enum FlashLoanType {
Reallocate,
ExitAllPositions
}
event EmergencyExitExecuted(
address indexed admin, uint256 targetTokenWithdrawn, uint256 debtRepaid, uint256 collateralReleased
);
event Reallocated();
event Rebalanced(uint256 totalCollateral, uint256 totalDebt, uint256 floatBalance);
event ProfitSold(uint256 targetTokenSold, uint256 assetReceived);
event Supplied(uint256 adapterId, uint256 amount);
event Borrowed(uint256 adapterId, uint256 amount);
event Repaid(uint256 adapterId, uint256 amount);
event Withdrawn(uint256 adapterId, uint256 amount);
event Invested(uint256 targetTokenAmount);
event Disinvested(uint256 targetTokenAmount);
event TargetVaultUpdated(address targetVault);
ERC20 public immutable targetToken;
ERC4626 public targetVault;
constructor(
address _admin,
address _keeper,
ERC20 _asset,
ERC4626 _targetVault,
ISinglePairPriceConverter _priceConverter,
ISinglePairSwapper _swapper,
string memory _name,
string memory _symbol
) BaseV2Vault(_admin, _keeper, _asset, _priceConverter, _swapper, _name, _symbol) {
_zeroAddressCheck(address(_targetVault));
targetVault = _targetVault;
targetToken = targetVault.asset();
targetToken.safeApprove(address(_targetVault), type(uint256).max);
}
function updateTargetVault(ERC4626 _newTargetVault) external {
_onlyAdmin();
if (_newTargetVault.asset() != targetToken) revert TargetTokenMismatch();
if (targetTokenInvestedAmount() != 0) revert InvestedAmountNotWithdrawn();
targetVault = _newTargetVault;
emit TargetVaultUpdated(address(_newTargetVault));
}
function rebalance(bytes[] calldata _callData) external {
_onlyKeeper();
_multiCall(_callData);
_invest();
uint256 float = assetBalance();
uint256 floatRequired = totalAssets().mulWadDown(floatPercentage);
if (float < floatRequired) {
revert FloatBalanceTooLow(float, floatRequired);
}
emit Rebalanced(totalCollateral(), totalDebt(), float);
}
function reallocate(uint256 _flashLoanAmount, bytes[] calldata _callData) external {
_onlyKeeper();
if (_flashLoanAmount == 0) revert FlashLoanAmountZero();
address[] memory tokens = new address[](1);
tokens[0] = address(targetToken);
uint256[] memory amounts = new uint256[](1);
amounts[0] = _flashLoanAmount;
_initiateFlashLoan();
balancerVault.flashLoan(address(this), tokens, amounts, abi.encode(FlashLoanType.Reallocate, _callData));
_finalizeFlashLoan();
emit Reallocated();
}
function sellProfit(uint256 _assetAmountOutMin) external {
_onlyKeeper();
uint256 profit = _calculateProfitInTargetToken(targetTokenInvestedAmount(), totalDebt());
if (profit == 0) revert NoProfitsToSell();
uint256 withdrawn = _disinvest(profit);
uint256 assetReceived = _swapTargetTokenForAsset(withdrawn, _assetAmountOutMin);
emit ProfitSold(withdrawn, assetReceived);
}
function exitAllPositions(uint256 _endAssetBalanceMin) external {
_onlyKeeper();
uint256 collateral = totalCollateral();
uint256 debt = totalDebt();
uint256 targetTokenBalance =
targetVault.redeem(targetVault.balanceOf(address(this)), address(this), address(this));
if (debt > targetTokenBalance) {
address[] memory tokens = new address[](1);
tokens[0] = address(targetToken);
uint256[] memory amounts = new uint256[](1);
amounts[0] = debt - targetTokenBalance;
_initiateFlashLoan();
balancerVault.flashLoan(address(this), tokens, amounts, abi.encode(FlashLoanType.ExitAllPositions));
_finalizeFlashLoan();
} else {
_repayAllDebtAndWithdrawCollateral();
uint256 targetTokenLeft = _targetTokenBalance();
if (targetTokenLeft != 0) _swapTargetTokenForAsset(targetTokenLeft, 0);
}
if (assetBalance() < _endAssetBalanceMin) revert EndAssetBalanceTooLow();
emit EmergencyExitExecuted(msg.sender, targetTokenBalance, debt, collateral);
}
function receiveFlashLoan(
address[] calldata,
uint256[] calldata _amounts,
uint256[] calldata _feeAmounts,
bytes calldata _data
) external {
_isFlashLoanInitiated();
uint256 flashLoanAmount = _amounts[0];
FlashLoanType flashLoanType = abi.decode(_data, (FlashLoanType));
if (flashLoanType == FlashLoanType.ExitAllPositions) {
_repayAllDebtAndWithdrawCollateral();
_swapAssetForExactTargetToken(flashLoanAmount);
} else {
(, bytes[] memory callData) = abi.decode(_data, (FlashLoanType, bytes[]));
_multiCall(callData);
}
targetToken.safeTransfer(address(balancerVault), flashLoanAmount + _feeAmounts[0]);
}
function supply(uint256 _adapterId, uint256 _amount) external {
_onlyKeeperOrFlashLoan();
_isSupportedCheck(_adapterId);
_supply(_adapterId, _amount);
}
function borrow(uint256 _adapterId, uint256 _amount) external {
_onlyKeeperOrFlashLoan();
_isSupportedCheck(_adapterId);
_borrow(_adapterId, _amount);
}
function repay(uint256 _adapterId, uint256 _amount) external {
_onlyKeeperOrFlashLoan();
_isSupportedCheck(_adapterId);
_repay(_adapterId, _amount);
}
function withdraw(uint256 _adapterId, uint256 _amount) external {
_onlyKeeperOrFlashLoan();
_isSupportedCheck(_adapterId);
_withdraw(_adapterId, _amount);
}
function disinvest(uint256 _amount) external {
_onlyKeeper();
_disinvest(_amount);
}
function totalAssets() public view override returns (uint256) {
return _calculateTotalAssets(assetBalance(), totalCollateral(), targetTokenInvestedAmount(), totalDebt());
}
function assetBalance() public view returns (uint256) {
return asset.balanceOf(address(this));
}
function getCollateral(uint256 _adapterId) external view returns (uint256) {
if (!isSupported(_adapterId)) return 0;
return IAdapter(protocolAdapters.get(_adapterId)).getCollateral(address(this));
}
function totalCollateral() public view returns (uint256 total) {
uint256 length = protocolAdapters.length();
for (uint256 i = 0; i < length; i++) {
(, address adapter) = protocolAdapters.at(i);
total += IAdapter(adapter).getCollateral(address(this));
}
}
function getDebt(uint256 _adapterId) external view returns (uint256) {
if (!isSupported(_adapterId)) return 0;
return IAdapter(protocolAdapters.get(_adapterId)).getDebt(address(this));
}
function totalDebt() public view returns (uint256 total) {
uint256 length = protocolAdapters.length();
for (uint256 i = 0; i < length; i++) {
(, address adapter) = protocolAdapters.at(i);
total += IAdapter(adapter).getDebt(address(this));
}
}
function targetTokenInvestedAmount() public view returns (uint256) {
return targetVault.convertToAssets(targetVault.balanceOf(address(this)));
}
function getProfit() public view returns (uint256) {
return _calculateProfitInTargetToken(targetTokenInvestedAmount(), totalDebt());
}
function _supply(uint256 _adapterId, uint256 _amount) internal {
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.supply.selector, _amount));
emit Supplied(_adapterId, _amount);
}
function _borrow(uint256 _adapterId, uint256 _amount) internal {
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.borrow.selector, _amount));
emit Borrowed(_adapterId, _amount);
}
function _repay(uint256 _adapterId, uint256 _amount) internal {
uint256 targetTokenBalance = _targetTokenBalance();
_amount = _amount > targetTokenBalance ? targetTokenBalance : _amount;
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.repay.selector, _amount));
emit Repaid(_adapterId, _amount);
}
function _withdraw(uint256 _adapterId, uint256 _amount) internal {
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.withdraw.selector, _amount));
emit Withdrawn(_adapterId, _amount);
}
function _invest() internal {
uint256 targetTokenBalance = _targetTokenBalance();
if (targetTokenBalance > 0) {
targetVault.deposit(targetTokenBalance, address(this));
emit Invested(targetTokenBalance);
}
}
function _disinvest(uint256 _targetTokenAmount) internal returns (uint256) {
uint256 shares = targetVault.convertToShares(_targetTokenAmount);
uint256 amount = targetVault.redeem(shares, address(this), address(this));
emit Disinvested(amount);
return amount;
}
function _repayAllDebtAndWithdrawCollateral() internal {
uint256 length = protocolAdapters.length();
for (uint256 i = 0; i < length; i++) {
(uint256 id, address adapter) = protocolAdapters.at(i);
uint256 debt = IAdapter(adapter).getDebt(address(this));
uint256 collateral = IAdapter(adapter).getCollateral(address(this));
if (debt > 0) _repay(id, debt);
if (collateral > 0) _withdraw(id, collateral);
}
}
function beforeWithdraw(uint256 _assets, uint256) internal override {
uint256 initialBalance = assetBalance();
if (initialBalance >= _assets) return;
uint256 collateral = totalCollateral();
uint256 debt = totalDebt();
uint256 invested = targetTokenInvestedAmount();
uint256 total = _calculateTotalAssets(initialBalance, collateral, invested, debt);
uint256 profit = _calculateProfitInTargetToken(invested, debt);
uint256 floatRequired = total > _assets ? (total - _assets).mulWadUp(floatPercentage) : 0;
uint256 assetNeeded = _assets + floatRequired - initialBalance;
if (profit != 0) {
uint256 withdrawn = _disinvest(profit);
uint256 assetAmountOutMin = converter().targetTokenToAsset(withdrawn).mulWadDown(slippageTolerance);
uint256 assetReceived = _swapTargetTokenForAsset(withdrawn, assetAmountOutMin);
if (initialBalance + assetReceived >= _assets) return;
assetNeeded -= assetReceived;
}
_repayDebtAndReleaseCollateral(debt, collateral, invested, assetNeeded);
}
function _repayDebtAndReleaseCollateral(
uint256 _totalDebt,
uint256 _totalCollateral,
uint256 _invested,
uint256 _assetNeeded
) internal {
_assetNeeded = _assetNeeded > _totalCollateral ? _totalCollateral : _assetNeeded;
uint256 targetTokenNeeded = _assetNeeded.mulDivUp(_totalDebt, _totalCollateral);
targetTokenNeeded = targetTokenNeeded > _invested ? _invested : targetTokenNeeded;
uint256 targetTokenDisinvested = 0;
if (targetTokenNeeded != 0) targetTokenDisinvested = _disinvest(targetTokenNeeded);
uint256 length = protocolAdapters.length();
for (uint256 i = 0; i < length; i++) {
(uint256 id, address adapter) = protocolAdapters.at(i);
uint256 collateral = IAdapter(adapter).getCollateral(address(this));
if (collateral == 0) continue;
uint256 debt = IAdapter(adapter).getDebt(address(this));
uint256 toWithdraw = _assetNeeded.mulDivUp(collateral, _totalCollateral);
if (targetTokenDisinvested != 0 && debt != 0) {
uint256 toRepay = toWithdraw.mulDivUp(debt, collateral);
if (toRepay > targetTokenDisinvested) {
toRepay = targetTokenDisinvested;
} else {
targetTokenDisinvested -= toRepay;
}
_repay(id, toRepay);
}
_withdraw(id, toWithdraw);
}
}
function _calculateTotalAssets(uint256 _float, uint256 _collateral, uint256 _invested, uint256 _debt)
internal
view
returns (uint256 total)
{
total = _float + _collateral;
uint256 profit = _calculateProfitInTargetToken(_invested, _debt);
if (profit != 0) {
total += converter().targetTokenToAsset(profit).mulWadDown(slippageTolerance);
} else {
total -= converter().targetTokenToAsset(_debt - _invested);
}
}
function _calculateProfitInTargetToken(uint256 _invested, uint256 _debt) internal pure returns (uint256) {
return _invested > _debt ? _invested - _debt : 0;
}
function _targetTokenBalance() internal view returns (uint256) {
return targetToken.balanceOf(address(this));
}
function converter() public view returns (ISinglePairPriceConverter) {
return ISinglePairPriceConverter(address(priceConverter));
}
function _swapTargetTokenForAsset(uint256 _targetTokenAmount, uint256 _assetAmountOutMin)
internal
virtual
returns (uint256)
{
bytes memory result = address(swapper).functionDelegateCall(
abi.encodeCall(ISinglePairSwapper.swapTargetTokenForAsset, (_targetTokenAmount, _assetAmountOutMin))
);
return abi.decode(result, (uint256));
}
function _swapAssetForExactTargetToken(uint256 _targetTokenAmountOut) internal virtual {
address(swapper).functionDelegateCall(
abi.encodeCall(ISinglePairSwapper.swapAssetForExactTargetToken, (_targetTokenAmountOut))
);
}
}
文件 25 的 26:scErrors.sol
pragma solidity ^0.8.10;
error InvalidTargetLtv();
error InvalidMaxLtv();
error InvalidFlashLoanCaller();
error InvalidSlippageTolerance();
error InvalidFloatPercentage();
error ZeroAddress();
error PleaseUseRedeemMethod();
error FeesTooHigh();
error TreasuryCannotBeZero();
error VaultNotUnderwater();
error CallerNotAdmin();
error CallerNotKeeper();
error NoProfitsToSell();
error EndUsdcBalanceTooLow();
error EndDaiBalanceTooLow();
error EndAssetBalanceTooLow();
error InsufficientDepositBalance();
error AmountReceivedBelowMin();
error FlashLoanAmountZero();
error ProtocolNotSupported(uint256 adapterId);
error ProtocolInUse(uint256 adapterId);
error FloatBalanceTooLow(uint256 actual, uint256 required);
error TokenOutNotAllowed(address token);
error TargetTokenMismatch();
error InvestedAmountNotWithdrawn();
library Check {
function isZeroAddress(address _address) internal pure {
if (_address == address(0)) revert ZeroAddress();
}
}
文件 26 的 26:scUSDSv2.sol
pragma solidity ^0.8.19;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {ERC4626} from "solmate/mixins/ERC4626.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {scCrossAssetYieldVault} from "./scCrossAssetYieldVault.sol";
import {Constants as C} from "../lib/Constants.sol";
import {ISinglePairPriceConverter} from "./priceConverter/ISinglePairPriceConverter.sol";
import {ISinglePairSwapper} from "./swapper/ISinglePairSwapper.sol";
contract scUSDSv2 is scCrossAssetYieldVault {
using SafeTransferLib for ERC20;
constructor(
address _admin,
address _keeper,
ERC4626 _targetVault,
ISinglePairPriceConverter _priceConverter,
ISinglePairSwapper _swapper
)
scCrossAssetYieldVault(
_admin,
_keeper,
ERC20(C.USDS),
_targetVault,
_priceConverter,
_swapper,
"Sandclock USDS Real Yield Vault",
"scUSDSv2"
)
{
ERC20(C.DAI).safeApprove(C.DAI_USDS_CONVERTER, type(uint256).max);
ERC20(C.USDS).safeApprove(C.DAI_USDS_CONVERTER, type(uint256).max);
}
}
{
"compilationTarget": {
"src/steth/scUSDSv2.sol": "scUSDSv2"
},
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":aave-v3-core/=lib/aave-v3-core/",
":aave-v3/=lib/aave-v3-core/contracts/",
":create3-factory/=lib/create3-factory/src/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
":solidity-stringutils/=lib/surl/lib/solidity-stringutils/",
":solmate/=lib/solmate/src/",
":surl/=lib/surl/src/"
]
}
[{"inputs":[{"internalType":"address","name":"_admin","type":"address"},{"internalType":"address","name":"_keeper","type":"address"},{"internalType":"contract ERC4626","name":"_targetVault","type":"address"},{"internalType":"contract ISinglePairPriceConverter","name":"_priceConverter","type":"address"},{"internalType":"contract ISinglePairSwapper","name":"_swapper","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[],"name":"CallerNotAdmin","type":"error"},{"inputs":[],"name":"CallerNotKeeper","type":"error"},{"inputs":[],"name":"EndAssetBalanceTooLow","type":"error"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"EnumerableMapNonexistentKey","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"FeesTooHigh","type":"error"},{"inputs":[],"name":"FlashLoanAmountZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"actual","type":"uint256"},{"internalType":"uint256","name":"required","type":"uint256"}],"name":"FloatBalanceTooLow","type":"error"},{"inputs":[],"name":"InvalidFlashLoanCaller","type":"error"},{"inputs":[],"name":"InvalidFloatPercentage","type":"error"},{"inputs":[],"name":"InvalidSlippageTolerance","type":"error"},{"inputs":[],"name":"InvestedAmountNotWithdrawn","type":"error"},{"inputs":[],"name":"NoProfitsToSell","type":"error"},{"inputs":[{"internalType":"uint256","name":"adapterId","type":"uint256"}],"name":"ProtocolInUse","type":"error"},{"inputs":[{"internalType":"uint256","name":"adapterId","type":"uint256"}],"name":"ProtocolNotSupported","type":"error"},{"inputs":[],"name":"TargetTokenMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"TokenOutNotAllowed","type":"error"},{"inputs":[],"name":"TreasuryCannotBeZero","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Borrowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetTokenAmount","type":"uint256"}],"name":"Disinvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"targetTokenWithdrawn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtRepaid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralReleased","type":"uint256"}],"name":"EmergencyExitExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newFloatPercentage","type":"uint256"}],"name":"FloatPercentageUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetTokenAmount","type":"uint256"}],"name":"Invested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"newPerformanceFee","type":"uint256"}],"name":"PerformanceFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"address","name":"newPriceConverter","type":"address"}],"name":"PriceConverterUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"targetTokenSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"assetReceived","type":"uint256"}],"name":"ProfitSold","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"},{"indexed":false,"internalType":"address","name":"adapter","type":"address"}],"name":"ProtocolAdapterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"}],"name":"ProtocolAdapterRemoved","type":"event"},{"anonymous":false,"inputs":[],"name":"Reallocated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"totalCollateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalDebt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"floatBalance","type":"uint256"}],"name":"Rebalanced","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Repaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"newSlippageTolerance","type":"uint256"}],"name":"SlippageToleranceUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Supplied","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"address","name":"newSwapper","type":"address"}],"name":"SwapperUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"targetVault","type":"address"}],"name":"TargetVaultUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOutReceived","type":"uint256"}],"name":"TokenSwapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"value","type":"bool"}],"name":"TokenWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"address","name":"newTreasury","type":"address"}],"name":"TreasuryUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"adapterId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"KEEPER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IAdapter","name":"_adapter","type":"address"}],"name":"addAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"assetBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"balancerVault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"borrow","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"},{"internalType":"bytes","name":"_callData","type":"bytes"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"converter","outputs":[{"internalType":"contract ISinglePairPriceConverter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"disinvest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_endAssetBalanceMin","type":"uint256"}],"name":"exitAllPositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"flashLoanInitiated","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"floatPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"}],"name":"getAdapter","outputs":[{"internalType":"address","name":"adapter","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"}],"name":"getCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"}],"name":"getDebt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProfit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"}],"name":"isSupported","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"_token","type":"address"}],"name":"isTokenWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performanceFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"priceConverter","outputs":[{"internalType":"contract IPriceConverter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_flashLoanAmount","type":"uint256"},{"internalType":"bytes[]","name":"_callData","type":"bytes[]"}],"name":"reallocate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_callData","type":"bytes[]"}],"name":"rebalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"_feeAmounts","type":"uint256[]"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"receiveFlashLoan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"},{"internalType":"bool","name":"_force","type":"bool"}],"name":"removeAdapter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"repay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetAmountOutMin","type":"uint256"}],"name":"sellProfit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newFloatPercentage","type":"uint256"}],"name":"setFloatPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newPerformanceFee","type":"uint256"}],"name":"setPerformanceFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPriceConverter","name":"_newPriceConverter","type":"address"}],"name":"setPriceConverter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newSlippageTolerance","type":"uint256"}],"name":"setSlippageTolerance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISwapper","name":"_newSwapper","type":"address"}],"name":"setSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newTreasury","type":"address"}],"name":"setTreasury","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"slippageTolerance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"supply","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"uint256","name":"_amountOutMin","type":"uint256"},{"internalType":"bytes","name":"_swapData","type":"bytes"}],"name":"swapTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapper","outputs":[{"internalType":"contract ISwapper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetToken","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetTokenInvestedAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"targetVault","outputs":[{"internalType":"contract ERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalCollateral","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalDebt","outputs":[{"internalType":"uint256","name":"total","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasury","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC4626","name":"_newTargetVault","type":"address"}],"name":"updateTargetVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"_token","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"whiteListToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_adapterId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]