编译器
0.8.21+commit.d9974bed
文件 1 的 31:AccessControl.sol
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => 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 override returns (bool) {
return _roles[role].members[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(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
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 {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
文件 2 的 31:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 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 functionCallWithValue(target, data, 0, "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");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, 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) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 3 的 31:AggregatorV3Interface.sol
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(uint80 _roundId)
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
文件 4 的 31:BaseV2Vault.sol
pragma solidity ^0.8.19;
import {TokenOutNotAllowed} from "../errors/scErrors.sol";
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 {ProtocolNotSupported, ProtocolInUse, ZeroAddress} 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 {PriceConverter} from "./PriceConverter.sol";
import {Swapper} from "./Swapper.sol";
import {sc4626} from "../sc4626.sol";
abstract contract BaseV2Vault is sc4626, IFlashLoanRecipient {
using Address for address;
using EnumerableMap for EnumerableMap.UintToAddressMap;
event SwapperUpdated(address indexed admin, address newSwapper);
event ProtocolAdapterAdded(address indexed admin, uint256 adapterId, address adapter);
event ProtocolAdapterRemoved(address indexed admin, uint256 adapterId);
event RewardsClaimed(uint256 adapterId);
event TokenSwapped(address token, uint256 amount, uint256 amountReceived);
event TokenWhitelisted(address token, bool value);
IVault public constant balancerVault = IVault(C.BALANCER_VAULT);
PriceConverter public immutable priceConverter;
Swapper public swapper;
EnumerableMap.UintToAddressMap internal protocolAdapters;
mapping(ERC20 => bool) internal zeroExSwapWhitelist;
constructor(
address _admin,
address _keeper,
ERC20 _asset,
PriceConverter _priceConverter,
Swapper _swapper,
string memory _name,
string memory _symbol
) sc4626(_admin, _keeper, _asset, _name, _symbol) {
_zeroAddressCheck(address(_priceConverter));
_zeroAddressCheck(address(_swapper));
priceConverter = _priceConverter;
swapper = _swapper;
zeroExSwapWhitelist[_asset] = true;
}
function whiteListOutToken(ERC20 _token, bool _value) external {
_onlyAdmin();
if (address(_token) == address(0)) revert ZeroAddress();
zeroExSwapWhitelist[_token] = _value;
emit TokenWhitelisted(address(_token), _value);
}
function setSwapper(Swapper _newSwapper) external {
_onlyAdmin();
if (address(_newSwapper) == address(0)) revert ZeroAddress();
swapper = _newSwapper;
emit SwapperUpdated(msg.sender, address(_newSwapper));
}
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 isTokenWhitelisted(ERC20 _token) external view returns (bool) {
return zeroExSwapWhitelist[_token];
}
function claimRewards(uint256 _adapterId, bytes calldata _callData) external {
_onlyKeeperOrFlashLoan();
_isSupportedCheck(_adapterId);
_adapterDelegateCall(_adapterId, abi.encodeWithSelector(IAdapter.claimRewards.selector, _callData));
emit RewardsClaimed(_adapterId);
}
function zeroExSwap(
ERC20 _tokenIn,
ERC20 _tokenOut,
uint256 _amount,
bytes calldata _swapData,
uint256 _assetAmountOutMin
) external {
_onlyKeeperOrFlashLoan();
if (!zeroExSwapWhitelist[_tokenOut]) revert TokenOutNotAllowed(address(_tokenOut));
bytes memory result = address(swapper).functionDelegateCall(
abi.encodeWithSelector(
Swapper.zeroExSwap.selector, _tokenIn, _tokenOut, _amount, _assetAmountOutMin, _swapData
)
);
emit TokenSwapped(address(_tokenIn), _amount, abi.decode(result, (uint256)));
}
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 _isSupportedCheck(uint256 _adapterId) internal view {
if (!isSupported(_adapterId)) revert ProtocolNotSupported(_adapterId);
}
function _zeroAddressCheck(address _address) internal pure {
if (_address == address(0)) revert ZeroAddress();
}
}
文件 5 的 31:Constants.sol
pragma solidity ^0.8.13;
library Constants {
address public constant MULTISIG = 0x035F210e5d14054E8AE5A6CFA76d643aA200D56E;
uint256 public constant ONE = 1e18;
uint256 public constant WETH_USDC_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 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_AUSDC_TOKEN = 0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c;
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 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_STETH_ETH_PRICE_FEED = 0x86392dC19c0b719886221c78AB11eb8Cf5c52812;
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 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;
}
文件 6 的 31:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 7 的 31:ERC165.sol
pragma solidity ^0.8.0;
import "./IERC165.sol";
abstract contract ERC165 is IERC165 {
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
文件 8 的 31: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);
}
}
文件 9 的 31: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 {}
}
文件 10 的 31:EnumerableMap.sol
pragma solidity ^0.8.0;
import "./EnumerableSet.sol";
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
struct Bytes32ToBytes32Map {
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 => 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];
require(value != 0 || contains(map, key), "EnumerableMap: nonexistent key");
return value;
}
function get(
Bytes32ToBytes32Map storage map,
bytes32 key,
string memory errorMessage
) internal view returns (bytes32) {
bytes32 value = map._values[key];
require(value != 0 || contains(map, key), errorMessage);
return value;
}
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 get(
UintToUintMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key), errorMessage));
}
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 get(
UintToAddressMap storage map,
uint256 key,
string memory errorMessage
) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key), errorMessage))));
}
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 get(
AddressToUintMap storage map,
address key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key))), errorMessage));
}
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 get(
Bytes32ToUintMap storage map,
bytes32 key,
string memory errorMessage
) internal view returns (uint256) {
return uint256(get(map._inner, key, errorMessage));
}
}
文件 11 的 31:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[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;
}
}
文件 12 的 31: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 的 31:IAccessControl.sol
pragma solidity ^0.8.0;
interface IAccessControl {
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 account) external;
}
文件 14 的 31: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 的 31:ICurvePool.sol
pragma solidity ^0.8.10;
interface ICurvePool {
function exchange(int128 i, int128 j, uint256 dx, uint256 min_dy) external payable returns (uint256);
}
文件 16 的 31:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 17 的 31:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, 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 from,
address to,
uint256 amount
) external returns (bool);
}
文件 18 的 31:IFlashLoanRecipient.sol
pragma solidity ^0.8.0;
interface IFlashLoanRecipient {
function receiveFlashLoan(
address[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external;
}
文件 19 的 31:ILido.sol
pragma solidity ^0.8.10;
import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
interface ILido is IERC20 {
function submit(address _referral) external payable returns (uint256);
function getTotalPooledEther() external view returns (uint256);
}
文件 20 的 31:ISwapRouter.sol
pragma solidity ^0.8.13;
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
}
文件 21 的 31:IVault.sol
pragma solidity ^0.8.0;
interface IVault {
function flashLoan(address recipient, address[] memory tokens, uint256[] memory amounts, bytes memory userData)
external;
}
文件 22 的 31:IwstETH.sol
pragma solidity ^0.8.10;
import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol";
interface IwstETH is IERC20 {
function wrap(uint256 _stETHAmount) external returns (uint256);
function unwrap(uint256 _wstETHAmount) external returns (uint256);
function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);
function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);
function stEthPerToken() external view returns (uint256);
function tokensPerStEth() external view returns (uint256);
}
文件 23 的 31:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1);
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
文件 24 的 31:PriceConverter.sol
pragma solidity ^0.8.19;
import {FixedPointMathLib} from "solmate/utils/FixedPointMathLib.sol";
import {AccessControl} from "openzeppelin-contracts/access/AccessControl.sol";
import {ZeroAddress, CallerNotAdmin} from "../errors/scErrors.sol";
import {Constants as C} from "../lib/Constants.sol";
import {AggregatorV3Interface} from "../interfaces/chainlink/AggregatorV3Interface.sol";
import {IwstETH} from "../interfaces/lido/IwstETH.sol";
contract PriceConverter is AccessControl {
using FixedPointMathLib for uint256;
IwstETH constant wstETH = IwstETH(C.WSTETH);
event UsdcToEthPriceFeedUpdated(address indexed admin, address newPriceFeed);
event StEthToEthPriceFeedUpdated(address indexed admin, address newPriceFeed);
AggregatorV3Interface public usdcToEthPriceFeed = AggregatorV3Interface(C.CHAINLINK_USDC_ETH_PRICE_FEED);
AggregatorV3Interface public stEThToEthPriceFeed = AggregatorV3Interface(C.CHAINLINK_STETH_ETH_PRICE_FEED);
constructor(address _admin) {
_zeroAddressCheck(_admin);
_grantRole(DEFAULT_ADMIN_ROLE, _admin);
}
function _onlyAdmin() internal view {
if (!hasRole(DEFAULT_ADMIN_ROLE, msg.sender)) revert CallerNotAdmin();
}
function setUsdcToEthPriceFeed(address _newPriceFeed) external {
_onlyAdmin();
_zeroAddressCheck(_newPriceFeed);
usdcToEthPriceFeed = AggregatorV3Interface(_newPriceFeed);
emit UsdcToEthPriceFeedUpdated(msg.sender, address(_newPriceFeed));
}
function setStEThToEthPriceFeed(address _newPriceFeed) external {
_onlyAdmin();
_zeroAddressCheck(_newPriceFeed);
stEThToEthPriceFeed = AggregatorV3Interface(_newPriceFeed);
emit StEthToEthPriceFeedUpdated(msg.sender, address(_newPriceFeed));
}
function ethToUsdc(uint256 _ethAmount) public view returns (uint256) {
(, int256 usdcPriceInEth,,,) = usdcToEthPriceFeed.latestRoundData();
return _ethAmount.divWadDown(uint256(usdcPriceInEth) * C.WETH_USDC_DECIMALS_DIFF);
}
function usdcToEth(uint256 _usdcAmount) public view returns (uint256) {
(, int256 usdcPriceInEth,,,) = usdcToEthPriceFeed.latestRoundData();
return (_usdcAmount * C.WETH_USDC_DECIMALS_DIFF).mulWadDown(uint256(usdcPriceInEth));
}
function ethToWstEth(uint256 ethAmount) public view returns (uint256) {
(, int256 price,,,) = stEThToEthPriceFeed.latestRoundData();
uint256 stEthAmount = ethAmount.divWadDown(uint256(price));
return wstETH.getWstETHByStETH(stEthAmount);
}
function stEthToEth(uint256 _stEthAmount) public view returns (uint256) {
(, int256 price,,,) = stEThToEthPriceFeed.latestRoundData();
return _stEthAmount.mulWadDown(uint256(price));
}
function wstEthToEth(uint256 wstEthAmount) public view returns (uint256) {
uint256 stEthAmount = wstETH.getStETHByWstETH(wstEthAmount);
return stEthToEth(stEthAmount);
}
function _zeroAddressCheck(address _address) internal pure {
if (_address == address(0)) revert ZeroAddress();
}
}
文件 25 的 31: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");
}
}
文件 26 的 31:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
文件 27 的 31:Swapper.sol
pragma solidity ^0.8.19;
import {ERC20} from "solmate/tokens/ERC20.sol";
import {WETH} from "solmate/tokens/WETH.sol";
import {ILido} from "../interfaces/lido/ILido.sol";
import {IwstETH} from "../interfaces/lido/IwstETH.sol";
import {ICurvePool} from "../interfaces/curve/ICurvePool.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import {Address} from "openzeppelin-contracts/utils/Address.sol";
import {AmountReceivedBelowMin} from "../errors/scErrors.sol";
import {ISwapRouter} from "../interfaces/uniswap/ISwapRouter.sol";
import {Constants as C} from "../lib/Constants.sol";
contract Swapper {
using SafeTransferLib for ERC20;
using Address for address;
ISwapRouter public constant swapRouter = ISwapRouter(C.UNISWAP_V3_SWAP_ROUTER);
ICurvePool public constant curvePool = ICurvePool(C.CURVE_ETH_STETH_POOL);
WETH public constant weth = WETH(payable(C.WETH));
ILido public constant stEth = ILido(C.STETH);
IwstETH public constant wstETH = IwstETH(C.WSTETH);
function uniswapSwapExactInput(
ERC20 _tokenIn,
ERC20 _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
uint24 _poolFee
) external returns (uint256) {
ERC20(_tokenIn).safeApprove(address(swapRouter), _amountIn);
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
tokenIn: address(_tokenIn),
tokenOut: address(_tokenOut),
fee: _poolFee,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: _amountOutMin,
sqrtPriceLimitX96: 0
});
return swapRouter.exactInputSingle(params);
}
function uniswapSwapExactOutput(
ERC20 _tokenIn,
ERC20 _tokenOut,
uint256 _amountOut,
uint256 _amountInMaximum,
uint24 _poolFee
) external returns (uint256) {
ISwapRouter.ExactOutputSingleParams memory params = ISwapRouter.ExactOutputSingleParams({
tokenIn: address(_tokenIn),
tokenOut: address(_tokenOut),
fee: _poolFee,
recipient: address(this),
deadline: block.timestamp,
amountOut: _amountOut,
amountInMaximum: _amountInMaximum,
sqrtPriceLimitX96: 0
});
_tokenIn.safeApprove(address(swapRouter), _amountInMaximum);
uint256 amountIn = swapRouter.exactOutputSingle(params);
_tokenIn.safeApprove(address(swapRouter), 0);
return amountIn;
}
function zeroExSwap(
ERC20 _tokenIn,
ERC20 _tokenOut,
uint256 _amountIn,
uint256 _amountOutMin,
bytes calldata _swapData
) external returns (uint256) {
uint256 tokenOutInitialBalance = _tokenOut.balanceOf(address(this));
_tokenIn.safeApprove(C.ZERO_EX_ROUTER, _amountIn);
C.ZERO_EX_ROUTER.functionCall(_swapData);
uint256 amountReceived = _tokenOut.balanceOf(address(this)) - tokenOutInitialBalance;
if (amountReceived < _amountOutMin) revert AmountReceivedBelowMin();
_tokenIn.approve(C.ZERO_EX_ROUTER, 0);
return amountReceived;
}
function lidoSwapWethToWstEth(uint256 _wethAmount) external {
weth.withdraw(_wethAmount);
stEth.submit{value: _wethAmount}(address(0x00));
uint256 stEthBalance = stEth.balanceOf(address(this));
ERC20(address(stEth)).safeApprove(address(wstETH), stEthBalance);
wstETH.wrap(stEthBalance);
}
function curveSwapStEthToWeth(uint256 _stEthAmount, uint256 _wethAmountOutMin)
external
returns (uint256 wethReceived)
{
ERC20(address(stEth)).safeApprove(address(curvePool), _stEthAmount);
wethReceived = curvePool.exchange(1, 0, _stEthAmount, _wethAmountOutMin);
weth.deposit{value: address(this).balance}();
}
}
文件 28 的 31:WETH.sol
pragma solidity >=0.8.0;
import {ERC20} from "./ERC20.sol";
import {SafeTransferLib} from "../utils/SafeTransferLib.sol";
contract WETH is ERC20("Wrapped Ether", "WETH", 18) {
using SafeTransferLib for address;
event Deposit(address indexed from, uint256 amount);
event Withdrawal(address indexed to, uint256 amount);
function deposit() public payable virtual {
_mint(msg.sender, msg.value);
emit Deposit(msg.sender, msg.value);
}
function withdraw(uint256 amount) public virtual {
_burn(msg.sender, amount);
emit Withdrawal(msg.sender, amount);
msg.sender.safeTransferETH(amount);
}
receive() external payable virtual {
deposit();
}
}
文件 29 的 31: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();
}
}
文件 30 的 31: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 InsufficientDepositBalance();
error AmountReceivedBelowMin();
error FlashLoanAmountZero();
error ProtocolNotSupported(uint256 adapterId);
error ProtocolInUse(uint256 adapterId);
error FloatBalanceTooLow(uint256 actual, uint256 required);
error TokenOutNotAllowed(address token);
文件 31 的 31:scUSDCv2.sol
pragma solidity ^0.8.19;
import {NoProfitsToSell, FlashLoanAmountZero, EndUsdcBalanceTooLow, FloatBalanceTooLow} from "../errors/scErrors.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {WETH} from "solmate/tokens/WETH.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 {AggregatorV3Interface} from "../interfaces/chainlink/AggregatorV3Interface.sol";
import {IAdapter} from "./IAdapter.sol";
import {PriceConverter} from "./PriceConverter.sol";
import {Swapper} from "./Swapper.sol";
contract scUSDCv2 is BaseV2Vault {
using SafeTransferLib for ERC20;
using SafeTransferLib for WETH;
using FixedPointMathLib for uint256;
using Address for address;
using EnumerableMap for EnumerableMap.UintToAddressMap;
WETH public constant weth = WETH(payable(C.WETH));
ERC4626 public immutable scWETH;
enum FlashLoanType {
Reallocate,
ExitAllPositions
}
event EmergencyExitExecuted(
address indexed admin, uint256 wethWithdrawn, uint256 debtRepaid, uint256 collateralReleased
);
event Reallocated();
event Rebalanced(uint256 totalCollateral, uint256 totalDebt, uint256 floatBalance);
event ProfitSold(uint256 wethSold, uint256 usdcReceived);
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 wethAmount);
event Disinvested(uint256 wethAmount);
constructor(address _admin, address _keeper, ERC4626 _scWETH, PriceConverter _priceConverter, Swapper _swapper)
BaseV2Vault(_admin, _keeper, ERC20(C.USDC), _priceConverter, _swapper, "Sandclock Yield USDC", "scUSDC")
{
_zeroAddressCheck(address(_scWETH));
scWETH = _scWETH;
weth.safeApprove(address(scWETH), type(uint256).max);
}
function rebalance(bytes[] calldata _callData) external {
_onlyKeeper();
_multiCall(_callData);
_invest();
uint256 float = usdcBalance();
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(weth);
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 _usdcAmountOutMin) external {
_onlyKeeper();
uint256 profit = _calculateWethProfit(wethInvested(), totalDebt());
if (profit == 0) revert NoProfitsToSell();
uint256 withdrawn = _disinvest(profit);
uint256 usdcReceived = _swapWethForUsdc(withdrawn, _usdcAmountOutMin);
emit ProfitSold(withdrawn, usdcReceived);
}
function exitAllPositions(uint256 _endUsdcBalanceMin) external {
_onlyKeeper();
uint256 collateral = totalCollateral();
uint256 debt = totalDebt();
uint256 wethBalance = scWETH.redeem(scWETH.balanceOf(address(this)), address(this), address(this));
if (debt > wethBalance) {
address[] memory tokens = new address[](1);
tokens[0] = address(weth);
uint256[] memory amounts = new uint256[](1);
amounts[0] = debt - wethBalance;
_initiateFlashLoan();
balancerVault.flashLoan(address(this), tokens, amounts, abi.encode(FlashLoanType.ExitAllPositions));
_finalizeFlashLoan();
} else {
_repayAllDebtAndWithdrawCollateral();
uint256 wethLeft = _wethBalance();
if (wethLeft != 0) _swapWethForUsdc(wethLeft, 0);
}
if (usdcBalance() < _endUsdcBalanceMin) revert EndUsdcBalanceTooLow();
emit EmergencyExitExecuted(msg.sender, wethBalance, 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();
_swapUsdcForExactWeth(flashLoanAmount);
} else {
(, bytes[] memory callData) = abi.decode(_data, (FlashLoanType, bytes[]));
_multiCall(callData);
}
weth.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(usdcBalance(), totalCollateral(), wethInvested(), totalDebt());
}
function usdcBalance() 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 wethInvested() public view returns (uint256) {
return scWETH.convertToAssets(scWETH.balanceOf(address(this)));
}
function getProfit() public view returns (uint256) {
return _calculateWethProfit(wethInvested(), 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 wethBalance = _wethBalance();
_amount = _amount > wethBalance ? wethBalance : _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 wethBalance = _wethBalance();
if (wethBalance > 0) {
scWETH.deposit(wethBalance, address(this));
emit Invested(wethBalance);
}
}
function _disinvest(uint256 _wethAmount) internal returns (uint256) {
uint256 shares = scWETH.convertToShares(_wethAmount);
uint256 amount = scWETH.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 = usdcBalance();
if (initialBalance >= _assets) return;
uint256 collateral = totalCollateral();
uint256 debt = totalDebt();
uint256 invested = wethInvested();
uint256 total = _calculateTotalAssets(initialBalance, collateral, invested, debt);
uint256 profit = _calculateWethProfit(invested, debt);
uint256 floatRequired = total > _assets ? (total - _assets).mulWadUp(floatPercentage) : 0;
uint256 usdcNeeded = _assets + floatRequired - initialBalance;
if (profit != 0) {
uint256 withdrawn = _disinvest(profit);
uint256 usdcAmountOutMin = priceConverter.ethToUsdc(withdrawn).mulWadDown(slippageTolerance);
uint256 usdcReceived = _swapWethForUsdc(withdrawn, usdcAmountOutMin);
if (initialBalance + usdcReceived >= _assets) return;
usdcNeeded -= usdcReceived;
}
_repayDebtAndReleaseCollateral(debt, collateral, invested, usdcNeeded);
}
function _repayDebtAndReleaseCollateral(
uint256 _totalDebt,
uint256 _totalCollateral,
uint256 _invested,
uint256 _usdcNeeded
) internal {
_usdcNeeded = _usdcNeeded > _totalCollateral ? _totalCollateral : _usdcNeeded;
uint256 wethNeeded = _usdcNeeded.mulDivUp(_totalDebt, _totalCollateral);
wethNeeded = wethNeeded > _invested ? _invested : wethNeeded;
uint256 wethDisinvested = 0;
if (wethNeeded != 0) wethDisinvested = _disinvest(wethNeeded);
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 = _usdcNeeded.mulDivUp(collateral, _totalCollateral);
if (wethDisinvested != 0 && debt != 0) {
uint256 toRepay = toWithdraw.mulDivUp(debt, collateral);
if (toRepay > wethDisinvested) {
toRepay = wethDisinvested;
} else {
wethDisinvested -= 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 = _calculateWethProfit(_invested, _debt);
if (profit != 0) {
total += priceConverter.ethToUsdc(profit).mulWadDown(slippageTolerance);
} else {
total -= priceConverter.ethToUsdc(_debt - _invested);
}
}
function _calculateWethProfit(uint256 _invested, uint256 _debt) internal pure returns (uint256) {
return _invested > _debt ? _invested - _debt : 0;
}
function _wethBalance() internal view returns (uint256) {
return weth.balanceOf(address(this));
}
function _swapWethForUsdc(uint256 _wethAmount, uint256 _usdcAmountOutMin) internal returns (uint256) {
bytes memory result = address(swapper).functionDelegateCall(
abi.encodeWithSelector(
Swapper.uniswapSwapExactInput.selector, weth, asset, _wethAmount, _usdcAmountOutMin, 500
)
);
return abi.decode(result, (uint256));
}
function _swapUsdcForExactWeth(uint256 _wethAmountOut) internal {
address(swapper).functionDelegateCall(
abi.encodeWithSelector(
Swapper.uniswapSwapExactOutput.selector,
asset,
weth,
_wethAmountOut,
type(uint256).max,
500
)
);
}
}
{
"compilationTarget": {
"src/steth/scUSDCv2.sol": "scUSDCv2"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"remappings": [
":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/",
":euler-interfaces/=lib/euler-interfaces/contracts/",
":forge-std/=lib/forge-std/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":"_scWETH","type":"address"},{"internalType":"contract PriceConverter","name":"_priceConverter","type":"address"},{"internalType":"contract Swapper","name":"_swapper","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotAdmin","type":"error"},{"inputs":[],"name":"CallerNotKeeper","type":"error"},{"inputs":[],"name":"EndUsdcBalanceTooLow","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":"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":[{"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":"wethAmount","type":"uint256"}],"name":"Disinvested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"wethWithdrawn","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":"wethAmount","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":false,"internalType":"uint256","name":"wethSold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"usdcReceived","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":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountReceived","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":[{"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":"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":"_endUsdcBalanceMin","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":"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 PriceConverter","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":"account","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":[],"name":"scWETH","outputs":[{"internalType":"contract ERC4626","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_usdcAmountOutMin","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":"uint256","name":"_newSlippageTolerance","type":"uint256"}],"name":"setSlippageTolerance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract Swapper","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":[],"name":"swapper","outputs":[{"internalType":"contract Swapper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"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":[],"name":"usdcBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract WETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wethInvested","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ERC20","name":"_token","type":"address"},{"internalType":"bool","name":"_value","type":"bool"}],"name":"whiteListOutToken","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"},{"inputs":[{"internalType":"contract ERC20","name":"_tokenIn","type":"address"},{"internalType":"contract ERC20","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_swapData","type":"bytes"},{"internalType":"uint256","name":"_assetAmountOutMin","type":"uint256"}],"name":"zeroExSwap","outputs":[],"stateMutability":"nonpayable","type":"function"}]