编译器
0.8.18+commit.87f61d96
文件 1 的 58: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 的 58: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 的 58:BalancerFlashloanBase.sol
pragma solidity >=0.8.18;
import { IVault, IFlashLoanRecipient } from "./Interfaces.sol";
import { DefinitiveAssets, IERC20 } from "../../core/libraries/DefinitiveAssets.sol";
import { UnauthenticatedFlashloan, UntrustedFlashLoanSender } from "../../core/libraries/DefinitiveErrors.sol";
abstract contract BalancerFlashloanBase {
using DefinitiveAssets for IERC20;
address private FLASHLOAN_PROVIDER_ADDRESS;
bool private isAuthenticated;
constructor(address _flashloanProvider) {
FLASHLOAN_PROVIDER_ADDRESS = _flashloanProvider;
}
function initiateFlashLoan(address borrowToken, uint256 amount, bytes memory userData) internal {
(IERC20[] memory tokens, uint256[] memory amounts) = (new IERC20[](1), new uint256[](1));
tokens[0] = IERC20(borrowToken);
amounts[0] = amount;
isAuthenticated = true;
IVault(FLASHLOAN_PROVIDER_ADDRESS).flashLoan(IFlashLoanRecipient(address(this)), tokens, amounts, userData);
}
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external {
if (msg.sender != FLASHLOAN_PROVIDER_ADDRESS) {
revert UntrustedFlashLoanSender(msg.sender);
}
if (!isAuthenticated) {
revert UnauthenticatedFlashloan();
}
isAuthenticated = false;
onFlashLoanReceived(address(tokens[0]), amounts[0], feeAmounts[0], userData);
tokens[0].safeTransfer(FLASHLOAN_PROVIDER_ADDRESS, amounts[0] + feeAmounts[0]);
}
function onFlashLoanReceived(
address token,
uint256 amount,
uint256 feeAmount,
bytes memory userData
) internal virtual;
function setFlashloanProvider(address newProvider) external virtual;
function _setFlashloanProvider(address newProvider) internal {
FLASHLOAN_PROVIDER_ADDRESS = newProvider;
}
}
文件 4 的 58:BaseAccessControl.sol
pragma solidity >=0.8.18;
import { CoreAccessControl, CoreAccessControlConfig } from "../core/CoreAccessControl/v1/CoreAccessControl.sol";
import { CoreStopGuardian } from "../core/CoreStopGuardian/v1/CoreStopGuardian.sol";
abstract contract BaseAccessControl is CoreAccessControl, CoreStopGuardian {
constructor(CoreAccessControlConfig memory coreAccessControlConfig) CoreAccessControl(coreAccessControlConfig) {}
function enableStopGuardian() public override onlyAdmins {
return _enableStopGuardian();
}
function disableStopGuardian() public override onlyClientAdmin {
return _disableStopGuardian();
}
}
文件 5 的 58:BaseFees.sol
pragma solidity >=0.8.18;
import { BaseAccessControl } from "./BaseAccessControl.sol";
import { CoreFees, CoreFeesConfig } from "../core/CoreFees/v1/CoreFees.sol";
import { DefinitiveAssets, IERC20 } from "../core/libraries/DefinitiveAssets.sol";
import { DefinitiveConstants } from "../core/libraries/DefinitiveConstants.sol";
import { InvalidFeePercent } from "../core/libraries/DefinitiveErrors.sol";
abstract contract BaseFees is BaseAccessControl, CoreFees {
using DefinitiveAssets for IERC20;
constructor(CoreFeesConfig memory coreFeesConfig) CoreFees(coreFeesConfig) {}
function updateFeeAccount(address payable _feeAccount) public override onlyDefinitiveAdmin {
_updateFeeAccount(_feeAccount);
}
function _handleFeesOnAmount(address token, uint256 amount, uint256 feePct) internal returns (uint256 feeAmount) {
uint256 mMaxFeePCT = DefinitiveConstants.MAX_FEE_PCT;
if (feePct > mMaxFeePCT) {
revert InvalidFeePercent();
}
feeAmount = (amount * feePct) / mMaxFeePCT;
if (feeAmount > 0) {
if (token == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
DefinitiveAssets.safeTransferETH(FEE_ACCOUNT, feeAmount);
} else {
IERC20(token).safeTransfer(FEE_ACCOUNT, feeAmount);
}
}
}
}
文件 6 的 58:BaseNativeWrapper.sol
pragma solidity >=0.8.18;
import { BaseAccessControl } from "../../BaseAccessControl.sol";
import { IBaseNativeWrapperV1 } from "./IBaseNativeWrapperV1.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { DefinitiveAssets, IERC20 } from "../../../core/libraries/DefinitiveAssets.sol";
struct BaseNativeWrapperConfig {
address payable wrappedNativeAssetAddress;
}
abstract contract BaseNativeWrapper is IBaseNativeWrapperV1, BaseAccessControl, ReentrancyGuard {
using DefinitiveAssets for IERC20;
address payable public immutable WRAPPED_NATIVE_ASSET_ADDRESS;
constructor(BaseNativeWrapperConfig memory baseNativeWrapperConfig) {
WRAPPED_NATIVE_ASSET_ADDRESS = baseNativeWrapperConfig.wrappedNativeAssetAddress;
}
function wrap(uint256 amount) public onlyWhitelisted nonReentrant {
_wrap(amount);
emit NativeAssetWrap(_msgSender(), amount, true );
}
function unwrap(uint256 amount) public onlyWhitelisted nonReentrant {
_unwrap(amount);
emit NativeAssetWrap(_msgSender(), amount, false );
}
function unwrapAll() external onlyWhitelisted {
return unwrap(DefinitiveAssets.getBalance(WRAPPED_NATIVE_ASSET_ADDRESS));
}
function _wrap(uint256 amount) internal virtual;
function _unwrap(uint256 amount) internal virtual;
}
文件 7 的 58:BasePermissionedExecution.sol
pragma solidity >=0.8.18;
import { BaseAccessControl } from "../BaseAccessControl.sol";
import { CallUtils } from "../../tools/BubbleReverts/BubbleReverts.sol";
import { IBasePermissionedExecution } from "./IBasePermissionedExecution.sol";
abstract contract BasePermissionedExecution is BaseAccessControl, IBasePermissionedExecution {
function executeOperation(address target, bytes calldata payload) external payable override onlyClientAdmin {
(bool _success, bytes memory _returnedData) = payable(target).call{ value: msg.value }(payload);
if (!_success) {
CallUtils.revertFromReturnedData(_returnedData);
}
}
}
文件 8 的 58:BaseRewards.sol
pragma solidity >=0.8.18;
import { BaseFees } from "./BaseFees.sol";
import { CoreRewards } from "../core/CoreRewards/v1/CoreRewards.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { DefinitiveAssets, IERC20 } from "../core/libraries/DefinitiveAssets.sol";
abstract contract BaseRewards is BaseFees, CoreRewards, ReentrancyGuard {
using DefinitiveAssets for IERC20;
function claimAllRewards(
uint256 feePct
)
external
override
onlyWhitelisted
nonReentrant
stopGuarded
returns (IERC20[] memory rewardTokens, uint256[] memory earnedAmounts)
{
(rewardTokens, earnedAmounts) = _claimAllRewards();
uint256 rewardTokensLength = rewardTokens.length;
uint256[] memory feeAmounts = new uint256[](rewardTokensLength);
if (FEE_ACCOUNT != address(0) && feePct > 0) {
for (uint256 i; i < rewardTokensLength; ) {
if (earnedAmounts[i] == 0) {
unchecked {
++i;
}
continue;
}
feeAmounts[i] = _handleFeesOnAmount(address(rewardTokens[i]), earnedAmounts[i], feePct);
unchecked {
++i;
}
}
}
emit RewardsClaimed(rewardTokens, earnedAmounts, feeAmounts);
}
}
文件 9 的 58:BaseSafeHarborMode.sol
pragma solidity >=0.8.18;
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { BaseAccessControl } from "../../base/BaseAccessControl.sol";
import { IBaseSafeHarborMode } from "./IBaseSafeHarborMode.sol";
abstract contract BaseSafeHarborMode is Context, IBaseSafeHarborMode, BaseAccessControl {
bool public SAFE_HARBOR_MODE_ENABLED;
function disableSafeHarborMode() external onlyAdmins {
_setSafeHarborMode(false);
}
function enableSafeHarborMode() external onlyWhitelisted {
_setSafeHarborMode(true);
}
function _setSafeHarborMode(bool _enabled) internal {
SAFE_HARBOR_MODE_ENABLED = _enabled;
emit SafeHarborModeUpdate(_msgSender(), _enabled);
}
}
文件 10 的 58:BaseSwap.sol
pragma solidity >=0.8.18;
import { BaseFees } from "./BaseFees.sol";
import { CoreSwap, CoreSwapConfig, SwapPayload } from "../core/CoreSwap/v1/CoreSwap.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import { DefinitiveConstants } from "../core/libraries/DefinitiveConstants.sol";
import { InvalidFeePercent, InvalidSwapPayload, SlippageExceeded } from "../core/libraries/DefinitiveErrors.sol";
import { ICoreSwapHandlerV1 } from "../core/CoreSwapHandler/ICoreSwapHandlerV1.sol";
abstract contract BaseSwap is BaseFees, CoreSwap, ReentrancyGuard {
constructor(CoreSwapConfig memory coreSwapConfig) CoreSwap(coreSwapConfig) {}
function enableSwapTokens(address[] memory swapTokens) public override onlyClientAdmin stopGuarded {
return _updateSwapTokens(swapTokens, true);
}
function disableSwapTokens(address[] memory swapTokens) public override onlyAdmins {
return _updateSwapTokens(swapTokens, false);
}
function enableSwapOutputTokens(address[] memory swapOutputTokens) public override onlyClientAdmin stopGuarded {
return _updateSwapOutputTokens(swapOutputTokens, true);
}
function disableSwapOutputTokens(address[] memory swapOutputTokens) public override onlyAdmins {
return _updateSwapOutputTokens(swapOutputTokens, false);
}
function enableSwapHandlers(address[] memory swapHandlers) public override onlyClientAdmin stopGuarded {
_updateSwapHandlers(swapHandlers, true);
}
function disableSwapHandlers(address[] memory swapHandlers) public override onlyAdmins {
_updateSwapHandlers(swapHandlers, false);
}
function swap(
SwapPayload[] memory payloads,
address outputToken,
uint256 amountOutMin,
uint256 feePct
) external override onlyWhitelisted nonReentrant stopGuarded returns (uint256) {
if (feePct > DefinitiveConstants.MAX_FEE_PCT) {
revert InvalidFeePercent();
}
(uint256[] memory inputAmounts, uint256 outputAmount) = _swap(payloads, outputToken);
if (outputAmount < amountOutMin) {
revert SlippageExceeded(outputAmount, amountOutMin);
}
address[] memory swapTokens = new address[](payloads.length);
uint256 swapTokensLength = swapTokens.length;
for (uint256 i; i < swapTokensLength; ) {
swapTokens[i] = payloads[i].swapToken;
unchecked {
++i;
}
}
uint256 feeAmount;
if (FEE_ACCOUNT != address(0) && outputAmount > 0 && feePct > 0) {
feeAmount = _handleFeesOnAmount(outputToken, outputAmount, feePct);
}
emit SwapHandled(swapTokens, inputAmounts, outputToken, outputAmount, feeAmount);
return outputAmount;
}
function _getEncodedSwapHandlerCalldata(
SwapPayload memory payload,
address expectedOutputToken,
bool isPrincipalAssetSwap,
bool isDelegateCall
) internal pure override returns (bytes memory) {
if (isPrincipalAssetSwap && isDelegateCall) {
revert InvalidSwapPayload();
}
bytes4 selector;
if (isPrincipalAssetSwap) {
selector = ICoreSwapHandlerV1.swapUsingValidatedPathCall.selector;
} else {
selector = isDelegateCall ? ICoreSwapHandlerV1.swapDelegate.selector : ICoreSwapHandlerV1.swapCall.selector;
}
ICoreSwapHandlerV1.SwapParams memory _params = ICoreSwapHandlerV1.SwapParams({
inputAssetAddress: payload.swapToken,
inputAmount: payload.amount,
outputAssetAddress: expectedOutputToken,
minOutputAmount: payload.amountOutMin,
data: payload.handlerCalldata,
signature: payload.signature
});
return abi.encodeWithSelector(selector, _params);
}
}
文件 11 的 58:BaseTransfers.sol
pragma solidity >=0.8.18;
import { CoreDeposit } from "../../../core/CoreDeposit/v1/CoreDeposit.sol";
import { CoreWithdraw } from "../../../core/CoreWithdraw/v1/CoreWithdraw.sol";
import { BaseAccessControl } from "../../BaseAccessControl.sol";
import { ReentrancyGuard } from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
abstract contract BaseTransfers is CoreDeposit, CoreWithdraw, BaseAccessControl, ReentrancyGuard {
function deposit(
uint256[] calldata amounts,
address[] calldata erc20Tokens
) external payable virtual override onlyClients nonReentrant stopGuarded {
return _deposit(amounts, erc20Tokens);
}
function withdraw(
uint256 amount,
address erc20Token
) public virtual override onlyClients nonReentrant stopGuarded returns (bool) {
return _withdraw(amount, erc20Token);
}
function withdrawTo(
uint256 amount,
address erc20Token,
address to
) public virtual override onlyWhitelisted nonReentrant stopGuarded returns (bool) {
_checkRole(ROLE_CLIENT, to);
return _withdrawTo(amount, erc20Token, to);
}
function withdrawAll(
address[] calldata tokens
) public virtual override onlyClients nonReentrant stopGuarded returns (bool) {
return _withdrawAll(tokens);
}
function withdrawAllTo(
address[] calldata tokens,
address to
) public virtual override onlyWhitelisted stopGuarded returns (bool) {
_checkRole(ROLE_CLIENT, to);
return _withdrawAllTo(tokens, to);
}
function supportsNativeAssets() public pure virtual override returns (bool) {
return false;
}
}
文件 12 的 58:BaseTransfersNative.sol
pragma solidity >=0.8.18;
import { IBaseNativeWrapperV1 } from "../../BaseNativeWrapper/v1/IBaseNativeWrapperV1.sol";
import { BaseTransfers } from "../../BaseTransfers/v1/BaseTransfers.sol";
import { CoreTransfersNative } from "../../../core/CoreTransfersNative/v1/CoreTransfersNative.sol";
abstract contract BaseTransfersNative is IBaseNativeWrapperV1, CoreTransfersNative, BaseTransfers {
function deposit(
uint256[] calldata amounts,
address[] calldata assetAddresses
) external payable override onlyClients nonReentrant stopGuarded {
_depositNativeAndERC20(amounts, assetAddresses);
emit Deposit(_msgSender(), assetAddresses, amounts);
}
function supportsNativeAssets() public pure override returns (bool) {
return true;
}
}
文件 13 的 58:BubbleReverts.sol
pragma solidity >=0.8.18;
import { InvalidCalldata } from "../../core/libraries/DefinitiveErrors.sol";
library CallUtils {
function revertFromReturnedData(bytes memory returnedData) internal pure {
if (returnedData.length < 4) {
revert("CallUtils: target revert()");
} else {
bytes4 errorSelector;
assembly {
errorSelector := mload(add(returnedData, 0x20))
}
if (errorSelector == bytes4(0x4e487b71) ) {
string memory reason = "CallUtils: target panicked: 0x__";
uint256 errorCode;
assembly {
errorCode := mload(add(returnedData, 0x24))
let reasonWord := mload(add(reason, 0x20))
let e1 := add(and(errorCode, 0xf), 0x30)
let e2 := shl(8, add(shr(4, and(errorCode, 0xf0)), 0x30))
reasonWord := or(
and(reasonWord, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000),
or(e2, e1)
)
mstore(add(reason, 0x20), reasonWord)
}
revert(reason);
} else {
uint256 len = returnedData.length;
assembly {
revert(add(returnedData, 32), len)
}
}
}
}
function parseSelector(bytes memory callData) internal pure returns (bytes4 selector) {
if (callData.length < 4) {
revert InvalidCalldata();
}
assembly {
selector := mload(add(callData, 0x20))
}
}
function padLength32(uint256 len) internal pure returns (uint256 paddedLen) {
return ((len / 32) + (((len & 31) > 0) ? 1 : 0)) * 32;
}
function isValidAbiEncodedBytes(bytes memory data) internal pure returns (bool) {
if (data.length < 64) return false;
uint256 bytesOffset;
uint256 bytesLen;
assembly {
bytesOffset := mload(add(data, 32))
}
if (bytesOffset != 32) return false;
assembly {
bytesLen := mload(add(data, 64))
}
return data.length == 64 + padLength32(bytesLen);
}
}
文件 14 的 58:CompoundV3.sol
pragma solidity >=0.8.18;
import { IComet } from "../../../protocols/compound/Interfaces.sol";
import { DefinitiveAssets, IERC20 } from "../../../core/libraries/DefinitiveAssets.sol";
abstract contract CompoundV3 {
using DefinitiveAssets for IERC20;
address public immutable COMET_ADDRESS;
constructor(address _cometAddress) {
COMET_ADDRESS = _cometAddress;
}
function supply(address asset, uint256 amount) internal {
if (amount > 0) {
IERC20(asset).resetAndSafeIncreaseAllowance(address(this), COMET_ADDRESS, amount);
IComet(COMET_ADDRESS).supply(asset, amount);
}
}
function borrow(address asset, uint256 amount) internal {
if (amount > 0) {
IComet(COMET_ADDRESS).withdraw(asset, amount);
}
}
function repay(address asset, uint256 amount) internal {
uint256 debtAmount = _getTotalVariableDebt();
if (amount > debtAmount) {
return supply(asset, debtAmount);
}
return supply(asset, amount);
}
function decollateralize(address asset, uint256 amount) internal {
uint256 collateralAmount = _getTotalCollateral(asset);
if (amount > collateralAmount) {
return borrow(asset, collateralAmount);
}
return borrow(asset, amount);
}
function _getTotalCollateral(address asset) internal view returns (uint256) {
return IComet(COMET_ADDRESS).collateralBalanceOf(address(this), asset);
}
function _getLTV(address asset) internal view returns (uint256) {
IComet comet = IComet(COMET_ADDRESS);
(uint256 borrowAmount, uint256 collateralAmount) = (
comet.borrowBalanceOf(address(this)),
comet.collateralBalanceOf(address(this), asset)
);
(uint256 price, uint256 precision) = _getOraclePrice(asset);
return collateralAmount * price == 0 ? 0 : (borrowAmount * 1e4 * precision) / (collateralAmount * price);
}
function _getTotalVariableDebt() internal view returns (uint256) {
return IComet(COMET_ADDRESS).borrowBalanceOf(address(this));
}
function _getOraclePrice(address tokenAddress) internal view returns (uint256 price, uint256 precision) {
(, , address tokenPriceFeed, , , , , ) = IComet(COMET_ADDRESS).getAssetInfoByAddress(tokenAddress);
return (
IComet(COMET_ADDRESS).getPrice(tokenPriceFeed),
1e8
);
}
}
文件 15 的 58: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;
}
}
文件 16 的 58:CoreAccessControl.sol
pragma solidity >=0.8.18;
import { AccessControl as OZAccessControl } from "@openzeppelin/contracts/access/AccessControl.sol";
import { ICoreAccessControlV1 } from "./ICoreAccessControlV1.sol";
import { AccountNotAdmin, AccountNotWhitelisted, AccountMissingRole } from "../../libraries/DefinitiveErrors.sol";
struct CoreAccessControlConfig {
address admin;
address definitiveAdmin;
address[] definitive;
address[] client;
}
abstract contract CoreAccessControl is ICoreAccessControlV1, OZAccessControl {
bytes32 public constant ROLE_DEFINITIVE = keccak256("DEFINITIVE");
bytes32 public constant ROLE_DEFINITIVE_ADMIN = keccak256("DEFINITIVE_ADMIN");
bytes32 public constant ROLE_CLIENT = keccak256("CLIENT");
modifier onlyDefinitive() {
_checkRole(ROLE_DEFINITIVE);
_;
}
modifier onlyDefinitiveAdmin() {
_checkRole(ROLE_DEFINITIVE_ADMIN);
_;
}
modifier onlyClients() {
_checkRole(ROLE_CLIENT);
_;
}
modifier onlyClientAdmin() {
_checkRole(DEFAULT_ADMIN_ROLE);
_;
}
modifier onlyAdmins() {
bool isAdmins = (hasRole(DEFAULT_ADMIN_ROLE, _msgSender()) || hasRole(ROLE_DEFINITIVE_ADMIN, _msgSender()));
if (!isAdmins) {
revert AccountNotAdmin(_msgSender());
}
_;
}
modifier onlyWhitelisted() {
bool isWhitelisted = (hasRole(ROLE_CLIENT, _msgSender()) || hasRole(ROLE_DEFINITIVE, _msgSender()));
if (!isWhitelisted) {
revert AccountNotWhitelisted(_msgSender());
}
_;
}
constructor(CoreAccessControlConfig memory cfg) {
_setupRole(DEFAULT_ADMIN_ROLE, cfg.admin);
_setupRole(ROLE_DEFINITIVE_ADMIN, cfg.definitiveAdmin);
_setRoleAdmin(ROLE_DEFINITIVE_ADMIN, ROLE_DEFINITIVE_ADMIN);
uint256 cfgDefinitiveLength = cfg.definitive.length;
for (uint256 i; i < cfgDefinitiveLength; ) {
_setupRole(ROLE_DEFINITIVE, cfg.definitive[i]);
unchecked {
++i;
}
}
_setRoleAdmin(ROLE_DEFINITIVE, ROLE_DEFINITIVE_ADMIN);
uint256 cfgClientLength = cfg.client.length;
for (uint256 i; i < cfgClientLength; ) {
_setupRole(ROLE_CLIENT, cfg.client[i]);
unchecked {
++i;
}
}
}
function _checkRole(bytes32 role, address account) internal view virtual override {
if (!hasRole(role, account)) {
revert AccountMissingRole(account, role);
}
}
}
文件 17 的 58:CoreDeposit.sol
pragma solidity >=0.8.18;
import { ICoreDepositV1 } from "./ICoreDepositV1.sol";
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { DefinitiveAssets, IERC20 } from "../../libraries/DefinitiveAssets.sol";
import { InvalidInputs } from "../../libraries/DefinitiveErrors.sol";
abstract contract CoreDeposit is ICoreDepositV1, Context {
using DefinitiveAssets for IERC20;
function deposit(uint256[] calldata amounts, address[] calldata assetAddresses) external payable virtual;
function _deposit(uint256[] calldata amounts, address[] calldata erc20Tokens) internal virtual {
_depositERC20(amounts, erc20Tokens);
emit Deposit(_msgSender(), erc20Tokens, amounts);
}
function _depositERC20(uint256[] calldata amounts, address[] calldata erc20Tokens) internal {
uint256 amountsLength = amounts.length;
if (amountsLength != erc20Tokens.length) {
revert InvalidInputs();
}
for (uint256 i; i < amountsLength; ) {
IERC20(erc20Tokens[i]).safeTransferFrom(_msgSender(), address(this), amounts[i]);
unchecked {
++i;
}
}
}
}
文件 18 的 58:CoreFees.sol
pragma solidity >=0.8.18;
import { ICoreFeesV1 } from "./ICoreFeesV1.sol";
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
struct CoreFeesConfig {
address payable feeAccount;
}
abstract contract CoreFees is ICoreFeesV1, Context {
address payable public FEE_ACCOUNT;
constructor(CoreFeesConfig memory coreFeesConfig) {
FEE_ACCOUNT = coreFeesConfig.feeAccount;
}
function _updateFeeAccount(address payable feeAccount) internal {
FEE_ACCOUNT = feeAccount;
emit FeeAccountUpdated(_msgSender(), feeAccount);
}
}
文件 19 的 58:CoreMulticall.sol
pragma solidity >=0.8.18;
import { ICoreMulticallV1 } from "./ICoreMulticallV1.sol";
import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { DefinitiveAssets } from "../../libraries/DefinitiveAssets.sol";
abstract contract CoreMulticall is ICoreMulticallV1 {
function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
uint256 dataLength = data.length;
results = new bytes[](dataLength);
for (uint256 i; i < dataLength; ) {
results[i] = Address.functionDelegateCall(address(this), data[i]);
unchecked {
++i;
}
}
}
function getBalance(address assetAddress) public view returns (uint256) {
return DefinitiveAssets.getBalance(assetAddress);
}
}
文件 20 的 58:CoreRewards.sol
pragma solidity >=0.8.18;
import { ICoreRewardsV1 } from "./ICoreRewardsV1.sol";
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { IERC20 } from "../../libraries/DefinitiveAssets.sol";
abstract contract CoreRewards is ICoreRewardsV1, Context {
function unclaimedRewards() public view virtual returns (IERC20[] memory, uint256[] memory);
function claimAllRewards(uint256 feePct) external virtual returns (IERC20[] memory, uint256[] memory);
function _claimAllRewards() internal virtual returns (IERC20[] memory, uint256[] memory);
}
文件 21 的 58:CoreStopGuardian.sol
pragma solidity >=0.8.18;
import { ICoreStopGuardianV1 } from "./ICoreStopGuardianV1.sol";
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { StopGuardianEnabled } from "../../libraries/DefinitiveErrors.sol";
abstract contract CoreStopGuardian is ICoreStopGuardianV1, Context {
bool public STOP_GUARDIAN_ENABLED;
modifier stopGuarded() {
if (STOP_GUARDIAN_ENABLED) {
revert StopGuardianEnabled();
}
_;
}
function enableStopGuardian() public virtual;
function disableStopGuardian() public virtual;
function _enableStopGuardian() internal {
STOP_GUARDIAN_ENABLED = true;
emit StopGuardianUpdate(_msgSender(), true);
}
function _disableStopGuardian() internal {
STOP_GUARDIAN_ENABLED = false;
emit StopGuardianUpdate(_msgSender(), false);
}
}
文件 22 的 58:CoreSwap.sol
pragma solidity >=0.8.18;
import { ICoreSwapV1 } from "./ICoreSwapV1.sol";
import { DefinitiveAssets, IERC20 } from "../../libraries/DefinitiveAssets.sol";
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { CallUtils } from "../../../tools/BubbleReverts/BubbleReverts.sol";
import { DefinitiveConstants } from "../../libraries/DefinitiveConstants.sol";
import {
InvalidSwapOutputToken,
InvalidSwapHandler,
InsufficientSwapTokenBalance,
SwapTokenIsOutputToken,
InvalidOutputToken,
InvalidReportedOutputAmount,
InvalidExecutedOutputAmount,
SwapLimitExceeded
} from "../../libraries/DefinitiveErrors.sol";
struct CoreSwapConfig {
address[] swapTokens;
address[] swapOutputTokens;
address[] swapHandlers;
}
struct SwapPayload {
address handler;
uint256 amount;
address swapToken;
uint256 amountOutMin;
bool isDelegate;
bytes handlerCalldata;
bytes signature;
}
abstract contract CoreSwap is ICoreSwapV1, Context {
using DefinitiveAssets for IERC20;
uint256 internal swapsThisBlock;
uint256 internal latestBlockNumber;
uint256 public immutable MAX_SWAPS_PER_BLOCK;
mapping(address => bool) public _swapTokens;
mapping(address => bool) public _swapOutputTokens;
mapping(address => bool) public _swapHandlers;
modifier enforceSwapLimit(SwapPayload[] memory payloads) {
if (block.number != latestBlockNumber) {
latestBlockNumber = block.number;
delete swapsThisBlock;
}
swapsThisBlock += payloads.length;
if (swapsThisBlock > MAX_SWAPS_PER_BLOCK) {
revert SwapLimitExceeded();
}
_;
}
constructor(CoreSwapConfig memory coreSwapConfig) {
uint256 coreswapConfigSwapTokensLength = coreSwapConfig.swapTokens.length;
MAX_SWAPS_PER_BLOCK = DefinitiveConstants.MAX_SWAPS_PER_BLOCK;
for (uint256 i; i < coreswapConfigSwapTokensLength; ) {
_swapTokens[coreSwapConfig.swapTokens[i]] = true;
unchecked {
++i;
}
}
uint256 coreSwapConfigSwapOutputTokensLength = coreSwapConfig.swapOutputTokens.length;
for (uint256 i; i < coreSwapConfigSwapOutputTokensLength; ) {
_swapOutputTokens[coreSwapConfig.swapOutputTokens[i]] = true;
unchecked {
++i;
}
}
uint256 coreSwapConfigSwapHandlersLength = coreSwapConfig.swapHandlers.length;
for (uint256 i; i < coreSwapConfigSwapHandlersLength; ) {
_swapHandlers[coreSwapConfig.swapHandlers[i]] = true;
unchecked {
++i;
}
}
}
function enableSwapTokens(address[] memory swapTokens) public virtual;
function disableSwapTokens(address[] memory swapTokens) public virtual;
function _updateSwapTokens(address[] memory swapTokens, bool enabled) internal {
uint256 swapTokensLength = swapTokens.length;
for (uint256 i; i < swapTokensLength; ) {
_swapTokens[swapTokens[i]] = enabled;
emit SwapTokenUpdate(_msgSender(), swapTokens[i], enabled);
unchecked {
++i;
}
}
}
function enableSwapOutputTokens(address[] memory swapOutputTokens) public virtual;
function disableSwapOutputTokens(address[] memory swapOutputTokens) public virtual;
function _updateSwapOutputTokens(address[] memory swapOutputTokens, bool enabled) internal {
uint256 swapOutputTokensLength = swapOutputTokens.length;
for (uint256 i; i < swapOutputTokensLength; ) {
_swapOutputTokens[swapOutputTokens[i]] = enabled;
emit SwapOutputTokenUpdate(_msgSender(), swapOutputTokens[i], enabled);
unchecked {
++i;
}
}
}
function enableSwapHandlers(address[] memory swapHandlers) public virtual;
function disableSwapHandlers(address[] memory swapHandlers) public virtual;
function _updateSwapHandlers(address[] memory swapHandlers, bool enabled) internal {
uint256 swapHandlersLength = swapHandlers.length;
for (uint256 i; i < swapHandlersLength; ) {
_swapHandlers[swapHandlers[i]] = enabled;
emit SwapHandlerUpdate(_msgSender(), swapHandlers[i], enabled);
unchecked {
++i;
}
}
}
function swap(
SwapPayload[] memory payloads,
address outputToken,
uint256 amountOutMin,
uint256 feePct
) external virtual returns (uint256 outputAmount);
function _swap(
SwapPayload[] memory payloads,
address expectedOutputToken
) internal enforceSwapLimit(payloads) returns (uint256[] memory inputTokenAmounts, uint256 outputTokenAmount) {
if (!_swapOutputTokens[expectedOutputToken]) {
revert InvalidSwapOutputToken();
}
uint256 payloadsLength = payloads.length;
inputTokenAmounts = new uint256[](payloadsLength);
uint256 outputTokenBalanceStart = DefinitiveAssets.getBalance(expectedOutputToken);
for (uint256 i; i < payloadsLength; ) {
SwapPayload memory payload = payloads[i];
if (!_swapHandlers[payload.handler]) {
revert InvalidSwapHandler();
}
if (expectedOutputToken == payload.swapToken) {
revert SwapTokenIsOutputToken();
}
uint256 outputTokenBalanceBefore = DefinitiveAssets.getBalance(expectedOutputToken);
inputTokenAmounts[i] = DefinitiveAssets.getBalance(payload.swapToken);
(uint256 _outputAmount, address _outputToken) = _processSwap(payload, expectedOutputToken);
if (_outputToken != expectedOutputToken) {
revert InvalidOutputToken();
}
if (_outputAmount < payload.amountOutMin) {
revert InvalidReportedOutputAmount();
}
uint256 outputTokenBalanceAfter = DefinitiveAssets.getBalance(expectedOutputToken);
if ((outputTokenBalanceAfter - outputTokenBalanceBefore) < payload.amountOutMin) {
revert InvalidExecutedOutputAmount();
}
inputTokenAmounts[i] -= DefinitiveAssets.getBalance(payload.swapToken);
unchecked {
++i;
}
}
outputTokenAmount = DefinitiveAssets.getBalance(expectedOutputToken) - outputTokenBalanceStart;
}
function _processSwap(SwapPayload memory payload, address expectedOutputToken) private returns (uint256, address) {
payload.amount = _getValidatedPayloadAmount(payload);
bool isPrincipalAssetSwap = !_swapTokens[payload.swapToken];
bytes memory _calldata = _getEncodedSwapHandlerCalldata(
payload,
expectedOutputToken,
isPrincipalAssetSwap,
payload.isDelegate
);
bool _success;
bytes memory _returnBytes;
if (payload.isDelegate) {
(_success, _returnBytes) = payload.handler.delegatecall(_calldata);
} else {
_prepareAssetsForNonDelegateHandlerCall(payload, payload.amount);
(_success, _returnBytes) = payload.handler.call(_calldata);
}
if (!_success) {
CallUtils.revertFromReturnedData(_returnBytes);
}
return abi.decode(_returnBytes, (uint256, address));
}
function _getEncodedSwapHandlerCalldata(
SwapPayload memory payload,
address expectedOutputToken,
bool isPrincipalAssetSwap,
bool isDelegateCall
) internal pure virtual returns (bytes memory);
function _getValidatedPayloadAmount(SwapPayload memory payload) private view returns (uint256 amount) {
uint256 balance = DefinitiveAssets.getBalance(payload.swapToken);
DefinitiveAssets.validateAmount(balance);
amount = payload.amount;
if (amount != 0 && balance < amount) {
revert InsufficientSwapTokenBalance();
}
if (amount == 0) {
return balance;
}
}
function _prepareAssetsForNonDelegateHandlerCall(SwapPayload memory payload, uint256 amount) private {
if (payload.swapToken == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
DefinitiveAssets.safeTransferETH(payable(payload.handler), amount);
} else {
IERC20(payload.swapToken).resetAndSafeIncreaseAllowance(address(this), payload.handler, amount);
}
}
}
文件 23 的 58:CoreTransfersNative.sol
pragma solidity >=0.8.18;
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { ICoreTransfersNativeV1 } from "./ICoreTransfersNativeV1.sol";
import { DefinitiveAssets, IERC20 } from "../../libraries/DefinitiveAssets.sol";
import { DefinitiveConstants } from "../../libraries/DefinitiveConstants.sol";
import { InvalidInputs, InvalidMsgValue } from "../../libraries/DefinitiveErrors.sol";
abstract contract CoreTransfersNative is ICoreTransfersNativeV1, Context {
using DefinitiveAssets for IERC20;
receive() external payable virtual {}
fallback(bytes calldata) external payable virtual returns (bytes memory) {}
function _depositNativeAndERC20(uint256[] calldata amounts, address[] calldata assetAddresses) internal virtual {
uint256 assetAddressesLength = assetAddresses.length;
if (amounts.length != assetAddressesLength) {
revert InvalidInputs();
}
bool hasNativeAsset;
uint256 nativeAssetIndex;
for (uint256 i; i < assetAddressesLength; ) {
if (assetAddresses[i] == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
nativeAssetIndex = i;
hasNativeAsset = true;
unchecked {
++i;
}
continue;
}
IERC20(assetAddresses[i]).safeTransferFrom(_msgSender(), address(this), amounts[i]);
unchecked {
++i;
}
}
if (!hasNativeAsset && msg.value != 0) {
revert InvalidMsgValue();
}
if (hasNativeAsset && msg.value != amounts[nativeAssetIndex]) {
revert InvalidMsgValue();
}
}
}
文件 24 的 58:CoreWithdraw.sol
pragma solidity >=0.8.18;
import { ICoreWithdrawV1 } from "./ICoreWithdrawV1.sol";
import { DefinitiveAssets, IERC20 } from "../../libraries/DefinitiveAssets.sol";
import { Context } from "@openzeppelin/contracts/utils/Context.sol";
import { DefinitiveConstants } from "../../libraries/DefinitiveConstants.sol";
abstract contract CoreWithdraw is ICoreWithdrawV1, Context {
using DefinitiveAssets for IERC20;
function supportsNativeAssets() public pure virtual returns (bool);
function withdraw(uint256 amount, address erc20Token) public virtual returns (bool);
function withdrawTo(uint256 amount, address erc20Token, address to) public virtual returns (bool);
function _withdraw(uint256 amount, address erc20Token) internal returns (bool) {
return _withdrawTo(amount, erc20Token, _msgSender());
}
function _withdrawTo(uint256 amount, address erc20Token, address to) internal returns (bool success) {
if (erc20Token == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
DefinitiveAssets.safeTransferETH(payable(to), amount);
} else {
IERC20(erc20Token).safeTransfer(to, amount);
}
emit Withdrawal(erc20Token, amount, to);
success = true;
}
function withdrawAll(address[] calldata tokens) public virtual returns (bool);
function withdrawAllTo(address[] calldata tokens, address to) public virtual returns (bool);
function _withdrawAll(address[] calldata tokens) internal returns (bool) {
return _withdrawAllTo(tokens, _msgSender());
}
function _withdrawAllTo(address[] calldata tokens, address to) internal returns (bool success) {
uint256 tokenLength = tokens.length;
for (uint256 i; i < tokenLength; ) {
uint256 tokenBalance = DefinitiveAssets.getBalance(tokens[i]);
if (tokenBalance > 0) {
_withdrawTo(tokenBalance, tokens[i], to);
}
unchecked {
++i;
}
}
return true;
}
}
文件 25 的 58:DefinitiveAssets.sol
pragma solidity >=0.8.18;
import { IERC20, SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { SafeTransferLib } from "solmate/src/utils/SafeTransferLib.sol";
import { DefinitiveConstants } from "./DefinitiveConstants.sol";
import { InsufficientBalance, InvalidAmount, InvalidAmounts, InvalidERC20Address } from "./DefinitiveErrors.sol";
library DefinitiveAssets {
modifier onlyValidERC20(address erc20Token) {
if (address(erc20Token) == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
revert InvalidERC20Address();
}
_;
}
function getBalance(address assetAddress) internal view returns (uint256) {
if (assetAddress == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
return address(this).balance;
} else {
return IERC20(assetAddress).balanceOf(address(this));
}
}
function validateBalance(address token, uint256 amount) internal view {
if (token == DefinitiveConstants.NATIVE_ASSET_ADDRESS) {
validateNativeBalance(amount);
} else {
validateERC20Balance(token, amount);
}
}
function safeTransferETH(address recipient, uint256 amount) internal {
if (amount > 0) {
SafeTransferLib.safeTransferETH(payable(recipient), amount);
}
}
function resetAndSafeIncreaseAllowance(
IERC20 token,
address owner,
address spender,
uint256 amount
) internal onlyValidERC20(address(token)) {
if (token.allowance(owner, spender) > 0) {
SafeERC20.safeApprove(token, spender, 0);
}
return SafeERC20.safeIncreaseAllowance(token, spender, amount);
}
function safeTransfer(IERC20 token, address to, uint256 amount) internal onlyValidERC20(address(token)) {
if (amount > 0) {
SafeERC20.safeTransfer(token, to, amount);
}
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 amount
) internal onlyValidERC20(address(token)) {
if (amount > 0) {
SafeERC20.safeTransferFrom(token, from, to, amount);
}
}
function validateAmounts(uint256[] calldata amounts) internal pure {
bool hasValidAmounts;
uint256 amountsLength = amounts.length;
for (uint256 i; i < amountsLength; ) {
if (amounts[i] > 0) {
hasValidAmounts = true;
break;
}
unchecked {
++i;
}
}
if (!hasValidAmounts) {
revert InvalidAmounts();
}
}
function validateNativeBalance(uint256 amount) internal view {
if (getBalance(DefinitiveConstants.NATIVE_ASSET_ADDRESS) < amount) {
revert InsufficientBalance();
}
}
function validateERC20Balance(address token, uint256 amount) internal view onlyValidERC20(token) {
if (getBalance(token) < amount) {
revert InsufficientBalance();
}
}
function validateAmount(uint256 _amount) internal pure {
if (_amount == 0) {
revert InvalidAmount();
}
}
}
文件 26 的 58:DefinitiveConstants.sol
pragma solidity >=0.8.18;
library DefinitiveConstants {
uint256 internal constant MAX_FEE_PCT = 10000;
address internal constant NATIVE_ASSET_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
uint8 internal constant MAX_SWAPS_PER_BLOCK = 25;
struct Assets {
uint256[] amounts;
address[] addresses;
}
}
文件 27 的 58:DefinitiveErrors.sol
pragma solidity >=0.8.18;
error AccountMissingRole(address _account, bytes32 _role);
error AccountNotAdmin(address);
error AccountNotWhitelisted(address);
error AddLiquidityFailed();
error DeadlineExceeded();
error BorrowFailed(uint256 errorCode);
error DecollateralizeFailed(uint256 errorCode);
error DepositMoreThanMax();
error EnterAllFailed();
error EnforcedSafeLTV(uint256 invalidLTV);
error ExceededMaxDelta();
error ExceededMaxLTV();
error ExceededShareToAssetRatioDeltaThreshold();
error ExitAllFailed();
error ExitOneCoinFailed();
error InitializeMarketsFailed();
error InputGreaterThanStaked();
error InsufficientBalance();
error InsufficientSwapTokenBalance();
error InvalidAddress();
error InvalidAmount();
error InvalidAmounts();
error InvalidCalldata();
error InvalidDestinationSwapper();
error InvalidERC20Address();
error InvalidExecutedOutputAmount();
error InvalidFeePercent();
error InvalidHandler();
error InvalidInputs();
error InvalidMsgValue();
error InvalidSingleHopSwap();
error InvalidMultiHopSwap();
error InvalidOutputToken();
error InvalidRedemptionRecipient();
error InvalidReportedOutputAmount();
error InvalidRewardsClaim();
error InvalidSignature();
error InvalidSignatureLength();
error InvalidSwapHandler();
error InvalidSwapInputAmount();
error InvalidSwapOutputToken();
error InvalidSwapPath();
error InvalidSwapPayload();
error InvalidSwapToken();
error MintMoreThanMax();
error NativeAssetWrapFailed(bool wrappingToNative);
error NoSignatureVerificationSignerSet();
error RedeemMoreThanMax();
error RemoveLiquidityFailed();
error RepayDebtFailed();
error SafeHarborModeEnabled();
error SafeHarborRedemptionDisabled();
error SlippageExceeded(uint256 _outputAmount, uint256 _outputAmountMin);
error StakeFailed();
error SupplyFailed();
error StopGuardianEnabled();
error SwapDeadlineExceeded();
error SwapLimitExceeded();
error SwapTokenIsOutputToken();
error TransfersLimitExceeded();
error UnstakeFailed();
error UnauthenticatedFlashloan();
error UntrustedFlashLoanSender(address);
error WithdrawMoreThanMax();
error ZeroShares();
文件 28 的 58: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;
}
}
文件 29 的 58: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);
}
}
文件 30 的 58: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;
}
文件 31 的 58:IBaseNativeWrapperV1.sol
pragma solidity >=0.8.18;
interface IBaseNativeWrapperV1 {
event NativeAssetWrap(address actor, uint256 amount, bool indexed wrappingToNative);
function wrap(uint256 amount) external;
function unwrap(uint256 amount) external;
function unwrapAll() external;
}
文件 32 的 58:IBasePermissionedExecution.sol
pragma solidity >=0.8.18;
import { ICoreAccessControlV1 } from "../../core/CoreAccessControl/v1/ICoreAccessControlV1.sol";
interface IBasePermissionedExecution is ICoreAccessControlV1 {
function executeOperation(address target, bytes calldata payload) external payable;
}
文件 33 的 58:IBaseSafeHarborMode.sol
pragma solidity >=0.8.18;
interface IBaseSafeHarborMode {
event SafeHarborModeUpdate(address indexed actor, bool indexed isEnabled);
function SAFE_HARBOR_MODE_ENABLED() external view returns (bool);
function enableSafeHarborMode() external;
function disableSafeHarborMode() external;
}
文件 34 的 58:ICoreAccessControlV1.sol
pragma solidity >=0.8.18;
import { IAccessControl } from "@openzeppelin/contracts/access/IAccessControl.sol";
interface ICoreAccessControlV1 is IAccessControl {
function ROLE_CLIENT() external returns (bytes32);
function ROLE_DEFINITIVE() external returns (bytes32);
function ROLE_DEFINITIVE_ADMIN() external returns (bytes32);
}
文件 35 的 58:ICoreDepositV1.sol
pragma solidity >=0.8.18;
interface ICoreDepositV1 {
event Deposit(address indexed actor, address[] assetAddresses, uint256[] amounts);
function deposit(uint256[] calldata amounts, address[] calldata assetAddresses) external payable;
}
文件 36 的 58:ICoreFeesV1.sol
pragma solidity >=0.8.18;
interface ICoreFeesV1 {
event FeeAccountUpdated(address actor, address feeAccount);
function FEE_ACCOUNT() external returns (address payable);
function updateFeeAccount(address payable feeAccount) external;
}
文件 37 的 58:ICoreMulticallV1.sol
pragma solidity >=0.8.18;
interface ICoreMulticallV1 {
function multicall(bytes[] calldata data) external returns (bytes[] memory results);
function getBalance(address assetAddress) external view returns (uint256);
}
文件 38 的 58:ICoreRewardsV1.sol
pragma solidity >=0.8.18;
import { IERC20 } from "../../../core/libraries/DefinitiveAssets.sol";
interface ICoreRewardsV1 {
event RewardsClaimed(IERC20[] rewardTokens, uint256[] rewardAmounts, uint256[] feeAmounts);
function unclaimedRewards() external view returns (IERC20[] memory, uint256[] memory);
function claimAllRewards(uint256 feePct) external returns (IERC20[] memory, uint256[] memory);
}
文件 39 的 58:ICoreStopGuardianV1.sol
pragma solidity >=0.8.18;
interface ICoreStopGuardianV1 {
event StopGuardianUpdate(address indexed actor, bool indexed isEnabled);
function STOP_GUARDIAN_ENABLED() external view returns (bool);
function enableStopGuardian() external;
function disableStopGuardian() external;
}
文件 40 的 58:ICoreSwapHandlerV1.sol
pragma solidity >=0.8.18;
interface ICoreSwapHandlerV1 {
event Swap(
address indexed actor,
address indexed inputToken,
uint256 inputAmount,
address indexed outputToken,
uint256 outputAmount
);
struct SwapParams {
address inputAssetAddress;
uint256 inputAmount;
address outputAssetAddress;
uint256 minOutputAmount;
bytes data;
bytes signature;
}
function swapCall(SwapParams calldata params) external payable returns (uint256 amountOut, address outputAsset);
function swapDelegate(SwapParams calldata params) external payable returns (uint256 amountOut, address outputAsset);
function swapUsingValidatedPathCall(
SwapParams calldata params
) external payable returns (uint256 amountOut, address outputAsset);
}
文件 41 的 58:ICoreSwapV1.sol
pragma solidity >=0.8.18;
import { SwapPayload } from "./CoreSwap.sol";
interface ICoreSwapV1 {
event SwapHandlerUpdate(address actor, address swapHandler, bool isEnabled);
event SwapTokenUpdate(address actor, address swapToken, bool isEnabled);
event SwapOutputTokenUpdate(address actor, address swapOutputToken, bool isEnabled);
event SwapHandled(
address[] swapTokens,
uint256[] swapAmounts,
address outputToken,
uint256 outputAmount,
uint256 feeAmount
);
function enableSwapTokens(address[] memory swapTokens) external;
function disableSwapTokens(address[] memory swapTokens) external;
function enableSwapOutputTokens(address[] memory swapOutputTokens) external;
function disableSwapOutputTokens(address[] memory swapOutputTokens) external;
function enableSwapHandlers(address[] memory swapHandlers) external;
function disableSwapHandlers(address[] memory swapHandlers) external;
function swap(
SwapPayload[] memory payloads,
address outputToken,
uint256 amountOutMin,
uint256 feePct
) external returns (uint256 outputAmount);
}
文件 42 的 58:ICoreTransfersNativeV1.sol
pragma solidity >=0.8.18;
interface ICoreTransfersNativeV1 {
receive() external payable;
fallback(bytes calldata) external payable returns (bytes memory);
}
文件 43 的 58:ICoreWithdrawV1.sol
pragma solidity >=0.8.18;
interface ICoreWithdrawV1 {
event Withdrawal(address indexed erc20Token, uint256 amount, address indexed recipient);
function withdrawAll(address[] calldata tokens) external returns (bool);
function withdrawAllTo(address[] calldata tokens, address to) external returns (bool);
function supportsNativeAssets() external pure returns (bool);
function withdraw(uint256 amount, address erc20Token) external returns (bool);
}
文件 44 的 58:IERC165.sol
pragma solidity ^0.8.0;
interface IERC165 {
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
文件 45 的 58: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);
}
文件 46 的 58:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 47 的 58:ILLSDStrategyV1.sol
pragma solidity >=0.8.18;
import { ICoreMulticallV1 } from "../../../core/CoreMulticall/v1/ICoreMulticallV1.sol";
import { SwapPayload } from "../../../base/BaseSwap.sol";
import { IBasePermissionedExecution } from "../../../base/BasePermissionedExecution/IBasePermissionedExecution.sol";
interface ILLSDStrategyV1 is ICoreMulticallV1, IBasePermissionedExecution {
event Enter(
uint256 collateral,
uint256 collateralDelta,
uint256 debt,
uint256 debtDelta,
address[] dryAssets,
int256[] dryBalanceDeltas,
uint256 ltv
);
event Exit(
uint256 collateral,
uint256 collateralDelta,
uint256 debt,
uint256 debtDelta,
address[] dryAssets,
int256[] dryBalanceDeltas,
uint256 ltv
);
event SweepDust(uint256 collateral, uint256 collateralDelta, uint256 debt, uint256 debtDelta, uint256 ltv);
struct EnterContext {
uint256 flashloanAmount;
SwapPayload swapPayload;
uint256 maxLTV;
}
struct ExitContext {
uint256 flashloanAmount;
uint256 repayAmount;
uint256 decollateralizeAmount;
SwapPayload swapPayload;
uint256 maxLTV;
}
enum FlashLoanContextType {
ENTER,
EXIT
}
function STAKED_TOKEN() external view returns (address);
function STAKING_TOKEN() external view returns (address);
function enter(uint256 flashloanAmount, SwapPayload calldata swapPayload, uint256 maxLTV) external;
function enterMulticall(uint256 borrowAmount, SwapPayload calldata swapPayload, uint256 maxLTV) external;
function exit(
uint256 flashloanAmount,
uint256 repayAmount,
uint256 decollateralizeAmount,
SwapPayload calldata swapPayload,
uint256 maxLTV
) external;
function exitMulticall(
uint256 decollateralizeAmount,
SwapPayload calldata swapPayload,
bool repayDebt,
uint256 maxLTV
) external;
function sweepDust() external;
function getDebtAmount() external view returns (uint256);
function getCollateralAmount() external view returns (uint256);
function getCollateralToDebtPrice() external view returns (uint256 price, uint256 precision);
function getLTV() external view returns (uint256);
}
文件 48 的 58:IWETH9.sol
pragma solidity >=0.8.18;
interface IWETH9 {
function balanceOf(address) external view returns (uint256);
function deposit() external payable;
function withdraw(uint256 wad) external;
}
文件 49 的 58:Interfaces.sol
pragma solidity >=0.8.18;
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
interface IFlashLoanRecipient {
function receiveFlashLoan(
IERC20[] memory tokens,
uint256[] memory amounts,
uint256[] memory feeAmounts,
bytes memory userData
) external;
}
interface IVault {
event FlashLoan(IFlashLoanRecipient indexed recipient, IERC20 indexed token, uint256 amount, uint256 feeAmount);
struct JoinPoolRequest {
address[] assets;
uint256[] maxAmountsIn;
bytes userData;
bool fromInternalBalance;
}
struct ExitPoolRequest {
address[] assets;
uint256[] minAmountsOut;
bytes userData;
bool toInternalBalance;
}
enum JoinKind {
INIT,
EXACT_TOKENS_IN_FOR_BPT_OUT,
TOKEN_IN_FOR_EXACT_BPT_OUT,
ALL_TOKENS_IN_FOR_EXACT_BPT_OUT
}
enum ExitKind {
EXACT_BPT_IN_FOR_ONE_TOKEN_OUT,
EXACT_BPT_IN_FOR_TOKENS_OUT,
BPT_IN_FOR_EXACT_TOKENS_OUT,
MANAGEMENT_FEE_TOKENS_OUT
}
enum StableExitKind {
EXACT_BPT_IN_FOR_ONE_TOKEN_OUT,
BPT_IN_FOR_EXACT_TOKENS_OUT,
EXACT_BPT_IN_FOR_ALL_TOKENS_OUT
}
function joinPool(
bytes32 poolId,
address sender,
address recipient,
JoinPoolRequest memory request
) external payable;
function exitPool(
bytes32 poolId,
address sender,
address payable recipient,
ExitPoolRequest memory request
) external;
function flashLoan(
IFlashLoanRecipient recipient,
IERC20[] memory tokens,
uint256[] memory amounts,
bytes memory userData
) external;
}
interface IRewardsGauge {
function deposit(uint256 _value) external;
function withdraw(uint256 _value) external;
function balanceOf(address _account) external view returns (uint256);
function totalSupply() external view returns (uint256);
function reward_tokens(uint256 _index) external view returns (address);
function reward_balances(address token) external view returns (uint256);
function reward_integral(address token) external view returns (uint256);
function reward_integral_for(address token, address user) external view returns (uint256);
function reward_contract() external view returns (IRewardsContract);
function claimable_reward(address _addr, address _token) external view returns (uint256);
}
interface IRewardsContract {
struct RewardToken {
address distributor;
uint256 period_finish;
uint256 rate;
uint256 duration;
uint256 received;
uint256 paid;
}
function get_reward() external;
function reward_data(address _token) external view returns (RewardToken memory);
function reward_tokens(uint256 index) external view returns (address);
function last_update_time() external view returns (uint256);
}
interface IChildChainGaugeRewardHelper {
function claimRewardsFromGauge(address gauge, address user) external;
}
文件 50 的 58:LLSDStrategy.sol
pragma solidity >=0.8.18;
import { ILLSDStrategyV1 } from "./ILLSDStrategyV1.sol";
import { BaseSwap, CoreSwapConfig, SwapPayload } from "../../../base/BaseSwap.sol";
import { CoreMulticall } from "../../../core/CoreMulticall/v1/CoreMulticall.sol";
import { BaseAccessControl, CoreAccessControlConfig } from "../../../base/BaseAccessControl.sol";
import { DefinitiveAssets, IERC20 } from "../../../core/libraries/DefinitiveAssets.sol";
import { ExceededMaxLTV, InvalidRewardsClaim } from "../../../core/libraries/DefinitiveErrors.sol";
import { BaseFees, CoreFeesConfig } from "../../../base/BaseFees.sol";
import { BasePermissionedExecution } from "../../../base/BasePermissionedExecution/BasePermissionedExecution.sol";
import { BaseSafeHarborMode } from "../../../base/BaseSafeHarborMode/BaseSafeHarborMode.sol";
import { BaseRewards } from "../../../base/BaseRewards.sol";
import { BalancerFlashloanBase } from "../../../protocols/balancer/BalancerFlashloanBase.sol";
struct LLSDStrategyConfig {
address stakingToken;
address stakedToken;
}
abstract contract LLSDStrategy is
ILLSDStrategyV1,
BaseSwap,
CoreMulticall,
BasePermissionedExecution,
BaseSafeHarborMode,
BaseRewards,
BalancerFlashloanBase
{
address[] internal DRY_TOKENS;
constructor(
CoreAccessControlConfig memory coreAccessControlConfig,
CoreSwapConfig memory coreSwapConfig,
CoreFeesConfig memory coreFeesConfig,
LLSDStrategyConfig memory llsdConfig,
address flashloanProviderAddress
)
BaseAccessControl(coreAccessControlConfig)
BaseSwap(coreSwapConfig)
BaseFees(coreFeesConfig)
BalancerFlashloanBase(flashloanProviderAddress)
{
DRY_TOKENS = new address[](2);
DRY_TOKENS[0] = llsdConfig.stakedToken;
DRY_TOKENS[1] = llsdConfig.stakingToken;
}
function STAKED_TOKEN() public view returns (address) {
return DRY_TOKENS[0];
}
function STAKING_TOKEN() public view returns (address) {
return DRY_TOKENS[1];
}
modifier emitEvent(FlashLoanContextType _type) {
(uint256 collateralBefore, uint256 debtBefore, int256[] memory dryBalanceDeltas) = (
getCollateralAmount(),
getDebtAmount(),
_getBalanceDeltas(new int256[](2))
);
_;
emitEnterOrExitEvent(collateralBefore, debtBefore, dryBalanceDeltas, _type);
}
modifier enforceMaxLTV(uint256 maxLTV) {
_;
if (getLTV() > maxLTV) {
revert ExceededMaxLTV();
}
}
function setFlashloanProvider(address newProvider) external override onlyDefinitiveAdmin {
_setFlashloanProvider(newProvider);
}
function emitEnterOrExitEvent(
uint256 collateralBefore,
uint256 debtBefore,
int256[] memory dryBalancesBefore,
FlashLoanContextType _type
) internal {
(uint256 collateralAfter, uint256 debtAfter, int256[] memory dryBalanceDeltas, uint256 ltv) = (
getCollateralAmount(),
getDebtAmount(),
_getBalanceDeltas(dryBalancesBefore),
getLTV()
);
if (_type == FlashLoanContextType.ENTER) {
emit Enter(
collateralAfter,
collateralAfter - collateralBefore,
debtAfter,
debtAfter - debtBefore,
DRY_TOKENS,
dryBalanceDeltas,
ltv
);
} else if (_type == FlashLoanContextType.EXIT) {
emit Exit(
collateralAfter,
collateralBefore - collateralAfter,
debtAfter,
debtBefore - debtAfter,
DRY_TOKENS,
dryBalanceDeltas,
ltv
);
}
}
function enterMulticall(
uint256 borrowAmount,
SwapPayload calldata swapPayload,
uint256 maxLTV
)
external
virtual
onlyWhitelisted
stopGuarded
nonReentrant
enforceMaxLTV(maxLTV)
emitEvent(FlashLoanContextType.ENTER)
{
address mSTAKED_TOKEN = STAKED_TOKEN();
_supply(DefinitiveAssets.getBalance(mSTAKED_TOKEN));
_borrow(borrowAmount);
if (swapPayload.amount > 0) {
SwapPayload[] memory swapPayloads = new SwapPayload[](1);
swapPayloads[0] = swapPayload;
_swap(swapPayloads, mSTAKED_TOKEN);
}
}
function exitMulticall(
uint256 decollateralizeAmount,
SwapPayload calldata swapPayload,
bool repayDebt,
uint256 maxLTV
) external onlyWhitelisted stopGuarded nonReentrant enforceMaxLTV(maxLTV) emitEvent(FlashLoanContextType.EXIT) {
_decollateralize(decollateralizeAmount);
address mSTAKING_TOKEN = STAKING_TOKEN();
uint256 swapOutput = DefinitiveAssets.getBalance(mSTAKING_TOKEN);
if (swapPayload.amount > 0) {
SwapPayload[] memory swapPayloads = new SwapPayload[](1);
swapPayloads[0] = swapPayload;
_swap(swapPayloads, mSTAKING_TOKEN);
swapOutput = DefinitiveAssets.getBalance(mSTAKING_TOKEN) - swapOutput;
}
if (repayDebt) {
uint256 debtAmount = getDebtAmount();
uint256 repayAmount = swapOutput < debtAmount ? swapOutput : debtAmount;
_repay(repayAmount);
}
}
function sweepDust() external onlyWhitelisted stopGuarded nonReentrant {
(uint256 collateralBefore, uint256 debtBefore) = (getCollateralAmount(), getDebtAmount());
if (collateralBefore > 0 && debtBefore > 0) {
_repay(DefinitiveAssets.getBalance(STAKING_TOKEN()));
}
_supply(DefinitiveAssets.getBalance(STAKED_TOKEN()));
(uint256 collateralAfter, uint256 debtAfter) = (getCollateralAmount(), getDebtAmount());
emit SweepDust(
collateralAfter,
collateralAfter - collateralBefore,
debtAfter,
debtBefore - debtAfter,
getLTV()
);
}
function getCollateralAmount() public view virtual returns (uint256);
function getDebtAmount() public view virtual returns (uint256);
function getLTV() public view virtual returns (uint256);
function unclaimedRewards()
public
view
virtual
override
returns (IERC20[] memory rewardTokens, uint256[] memory earnedAmounts)
{}
function _borrow(uint256 amount) internal virtual;
function _decollateralize(uint256 amount) internal virtual;
function _repay(uint256 amount) internal virtual;
function _supply(uint256 amount) internal virtual;
function _claimAllRewards() internal virtual override returns (IERC20[] memory, uint256[] memory) {
revert InvalidRewardsClaim();
}
function _getBalanceDeltas(
int256[] memory previousDryBalances
) internal view returns (int256[] memory dryBalanceDeltas) {
address[] memory mDryAssets = DRY_TOKENS;
dryBalanceDeltas = new int256[](mDryAssets.length);
uint256 length = mDryAssets.length;
uint256 i = 0;
while (i < length) {
dryBalanceDeltas[i] = int256(DefinitiveAssets.getBalance(mDryAssets[i])) - previousDryBalances[i];
unchecked {
++i;
}
}
}
}
文件 51 的 58:LLSD_EthereumCompoundV3Balancer_wstETH_WETH.sol
pragma solidity >=0.8.18;
import { BaseTransfersNative } from "../../../base/BaseTransfersNative/v1/BaseTransfersNative.sol";
import {
WETH9NativeWrapper,
BaseNativeWrapperConfig
} from "../../../modules/native-asset-wrappers/WETH9NativeWrapper.sol";
import { SwapPayload } from "../../../base/BaseSwap.sol";
import { DefinitiveAssets, IERC20 } from "../../../core/libraries/DefinitiveAssets.sol";
import {
CoreAccessControlConfig,
CoreSwapConfig,
CoreFeesConfig,
LLSDStrategy,
LLSDStrategyConfig
} from "../../../modules/LLSDStrategy/v1/LLSDStrategy.sol";
import { CompoundV3 } from "../Compound/CompoundV3.sol";
contract LLSD_EthereumCompoundV3Balancer_wstETH_WETH is
LLSDStrategy,
BaseTransfersNative,
WETH9NativeWrapper,
CompoundV3
{
using DefinitiveAssets for IERC20;
address public constant COMPOUND_POOL = 0xA17581A9E3356d9A858b789D68B4d866e593aE94;
constructor(
BaseNativeWrapperConfig memory baseNativeWrapperConfig,
CoreAccessControlConfig memory coreAccessControlConfig,
CoreSwapConfig memory coreSwapConfig,
CoreFeesConfig memory coreFeesConfig,
address flashloanProviderAddress
)
CompoundV3(COMPOUND_POOL)
LLSDStrategy(
coreAccessControlConfig,
coreSwapConfig,
coreFeesConfig,
LLSDStrategyConfig(
0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2,
0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0
),
flashloanProviderAddress
)
WETH9NativeWrapper(baseNativeWrapperConfig)
{}
function enter(
uint256 flashloanAmount,
SwapPayload calldata swapPayload,
uint256 maxLTV
) external onlyWhitelisted stopGuarded nonReentrant enforceMaxLTV(maxLTV) emitEvent(FlashLoanContextType.ENTER) {
EnterContext memory ctx = EnterContext(flashloanAmount, swapPayload, maxLTV);
return
flashloanAmount == 0
? _enterContinue(abi.encode(ctx))
: initiateFlashLoan(
STAKING_TOKEN(),
flashloanAmount,
abi.encode(FlashLoanContextType.ENTER, abi.encode(ctx))
);
}
function exit(
uint256 flashloanAmount,
uint256 repayAmount,
uint256 decollateralizeAmount,
SwapPayload calldata swapPayload,
uint256 maxLTV
) external onlyWhitelisted stopGuarded nonReentrant enforceMaxLTV(maxLTV) emitEvent(FlashLoanContextType.EXIT) {
ExitContext memory ctx = ExitContext(flashloanAmount, repayAmount, decollateralizeAmount, swapPayload, maxLTV);
return
flashloanAmount == 0
? _exitContinue(abi.encode(ctx))
: initiateFlashLoan(
STAKING_TOKEN(),
flashloanAmount,
abi.encode(FlashLoanContextType.EXIT, abi.encode(ctx))
);
}
function getCollateralToDebtPrice() external view returns (uint256, uint256) {
(uint256 stakedAssetPriceETH, uint256 stakedAssetPricePrecision) = _getOraclePrice(STAKED_TOKEN());
return (1e18 / stakedAssetPriceETH, 1e18 / stakedAssetPricePrecision);
}
function getDebtAmount() public view override returns (uint256) {
return _getTotalVariableDebt();
}
function getCollateralAmount() public view override returns (uint256) {
return _getTotalCollateral(STAKED_TOKEN());
}
function getLTV() public view override returns (uint256) {
return _getLTV(STAKED_TOKEN());
}
function onFlashLoanReceived(
address,
uint256,
uint256,
bytes memory userData
) internal override {
(FlashLoanContextType ctxType, bytes memory data) = abi.decode(userData, (FlashLoanContextType, bytes));
if (ctxType == FlashLoanContextType.ENTER) {
return _enterContinue(data);
}
if (ctxType == FlashLoanContextType.EXIT) {
return _exitContinue(data);
}
}
function _enterContinue(bytes memory contextData) internal {
EnterContext memory context = abi.decode(contextData, (EnterContext));
address mSTAKED_TOKEN = STAKED_TOKEN();
if (context.swapPayload.amount > 0) {
SwapPayload[] memory swapPayloads = new SwapPayload[](1);
swapPayloads[0] = context.swapPayload;
_swap(swapPayloads, mSTAKED_TOKEN);
}
_supply(DefinitiveAssets.getBalance(mSTAKED_TOKEN));
_borrow(context.flashloanAmount);
}
function _exitContinue(bytes memory contextData) internal {
ExitContext memory context = abi.decode(contextData, (ExitContext));
_repay(context.repayAmount);
_decollateralize(context.decollateralizeAmount);
if (context.swapPayload.amount > 0) {
SwapPayload[] memory swapPayloads = new SwapPayload[](1);
swapPayloads[0] = context.swapPayload;
_swap(swapPayloads, STAKING_TOKEN());
}
}
function _borrow(uint256 amount) internal override {
borrow(STAKING_TOKEN(), amount);
}
function _decollateralize(uint256 amount) internal override {
decollateralize(STAKED_TOKEN(), amount);
}
function _repay(uint256 amount) internal override {
uint256 debtAmount = getDebtAmount();
repay(STAKING_TOKEN(), amount > debtAmount ? debtAmount : amount);
}
function _supply(uint256 amount) internal override {
supply(STAKED_TOKEN(), amount);
}
}
文件 52 的 58: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, "Math: mulDiv overflow");
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 << 3) < value ? 1 : 0);
}
}
}
文件 53 的 58:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 54 的 58:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 55 的 58: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");
}
}
文件 56 的 58:SignedMath.sol
pragma solidity ^0.8.0;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 57 的 58:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.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 toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
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);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
文件 58 的 58:WETH9NativeWrapper.sol
pragma solidity >=0.8.18;
import { BaseNativeWrapper, BaseNativeWrapperConfig } from "../../base/BaseNativeWrapper/v1/BaseNativeWrapper.sol";
import { IWETH9 } from "../../vendor/interfaces/IWETH9.sol";
abstract contract WETH9NativeWrapper is BaseNativeWrapper {
constructor(BaseNativeWrapperConfig memory config) BaseNativeWrapper(config) {}
function _wrap(uint256 amount) internal override {
IWETH9(WRAPPED_NATIVE_ASSET_ADDRESS).deposit{ value: amount }();
}
function _unwrap(uint256 amount) internal override {
IWETH9(WRAPPED_NATIVE_ASSET_ADDRESS).withdraw(amount);
}
}
{
"compilationTarget": {
"contracts/strategies/LLSD/wstETH/LLSD_EthereumCompoundV3Balancer_wstETH_WETH.sol": "LLSD_EthereumCompoundV3Balancer_wstETH_WETH"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "none"
},
"optimizer": {
"enabled": true,
"runs": 850
},
"remappings": []
}
[{"inputs":[{"components":[{"internalType":"address payable","name":"wrappedNativeAssetAddress","type":"address"}],"internalType":"struct BaseNativeWrapperConfig","name":"baseNativeWrapperConfig","type":"tuple"},{"components":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"definitiveAdmin","type":"address"},{"internalType":"address[]","name":"definitive","type":"address[]"},{"internalType":"address[]","name":"client","type":"address[]"}],"internalType":"struct CoreAccessControlConfig","name":"coreAccessControlConfig","type":"tuple"},{"components":[{"internalType":"address[]","name":"swapTokens","type":"address[]"},{"internalType":"address[]","name":"swapOutputTokens","type":"address[]"},{"internalType":"address[]","name":"swapHandlers","type":"address[]"}],"internalType":"struct CoreSwapConfig","name":"coreSwapConfig","type":"tuple"},{"components":[{"internalType":"address payable","name":"feeAccount","type":"address"}],"internalType":"struct CoreFeesConfig","name":"coreFeesConfig","type":"tuple"},{"internalType":"address","name":"flashloanProviderAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_account","type":"address"},{"internalType":"bytes32","name":"_role","type":"bytes32"}],"name":"AccountMissingRole","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AccountNotAdmin","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"AccountNotWhitelisted","type":"error"},{"inputs":[],"name":"ExceededMaxLTV","type":"error"},{"inputs":[],"name":"InsufficientSwapTokenBalance","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidERC20Address","type":"error"},{"inputs":[],"name":"InvalidExecutedOutputAmount","type":"error"},{"inputs":[],"name":"InvalidFeePercent","type":"error"},{"inputs":[],"name":"InvalidInputs","type":"error"},{"inputs":[],"name":"InvalidMsgValue","type":"error"},{"inputs":[],"name":"InvalidOutputToken","type":"error"},{"inputs":[],"name":"InvalidReportedOutputAmount","type":"error"},{"inputs":[],"name":"InvalidRewardsClaim","type":"error"},{"inputs":[],"name":"InvalidSwapHandler","type":"error"},{"inputs":[],"name":"InvalidSwapOutputToken","type":"error"},{"inputs":[],"name":"InvalidSwapPayload","type":"error"},{"inputs":[{"internalType":"uint256","name":"_outputAmount","type":"uint256"},{"internalType":"uint256","name":"_outputAmountMin","type":"uint256"}],"name":"SlippageExceeded","type":"error"},{"inputs":[],"name":"StopGuardianEnabled","type":"error"},{"inputs":[],"name":"SwapLimitExceeded","type":"error"},{"inputs":[],"name":"SwapTokenIsOutputToken","type":"error"},{"inputs":[],"name":"UnauthenticatedFlashloan","type":"error"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"UntrustedFlashLoanSender","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"address[]","name":"assetAddresses","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtDelta","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"dryAssets","type":"address[]"},{"indexed":false,"internalType":"int256[]","name":"dryBalanceDeltas","type":"int256[]"},{"indexed":false,"internalType":"uint256","name":"ltv","type":"uint256"}],"name":"Enter","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtDelta","type":"uint256"},{"indexed":false,"internalType":"address[]","name":"dryAssets","type":"address[]"},{"indexed":false,"internalType":"int256[]","name":"dryBalanceDeltas","type":"int256[]"},{"indexed":false,"internalType":"uint256","name":"ltv","type":"uint256"}],"name":"Exit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"address","name":"feeAccount","type":"address"}],"name":"FeeAccountUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"bool","name":"wrappingToNative","type":"bool"}],"name":"NativeAssetWrap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IERC20[]","name":"rewardTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"rewardAmounts","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"feeAmounts","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":"actor","type":"address"},{"indexed":true,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"SafeHarborModeUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"actor","type":"address"},{"indexed":true,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"StopGuardianUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"swapTokens","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"swapAmounts","type":"uint256[]"},{"indexed":false,"internalType":"address","name":"outputToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"outputAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"feeAmount","type":"uint256"}],"name":"SwapHandled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"address","name":"swapHandler","type":"address"},{"indexed":false,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"SwapHandlerUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"address","name":"swapOutputToken","type":"address"},{"indexed":false,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"SwapOutputTokenUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"actor","type":"address"},{"indexed":false,"internalType":"address","name":"swapToken","type":"address"},{"indexed":false,"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"SwapTokenUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"collateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"collateralDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debt","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"debtDelta","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ltv","type":"uint256"}],"name":"SweepDust","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"erc20Token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"}],"name":"Withdrawal","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"COMET_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"COMPOUND_POOL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_ACCOUNT","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_SWAPS_PER_BLOCK","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_CLIENT","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_DEFINITIVE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLE_DEFINITIVE_ADMIN","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"SAFE_HARBOR_MODE_ENABLED","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKED_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STAKING_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STOP_GUARDIAN_ENABLED","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WRAPPED_NATIVE_ASSET_ADDRESS","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_swapHandlers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_swapOutputTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_swapTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"feePct","type":"uint256"}],"name":"claimAllRewards","outputs":[{"internalType":"contract IERC20[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"earnedAmounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"address[]","name":"assetAddresses","type":"address[]"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"disableSafeHarborMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disableStopGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"swapHandlers","type":"address[]"}],"name":"disableSwapHandlers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"swapOutputTokens","type":"address[]"}],"name":"disableSwapOutputTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"swapTokens","type":"address[]"}],"name":"disableSwapTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableSafeHarborMode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"enableStopGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"swapHandlers","type":"address[]"}],"name":"enableSwapHandlers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"swapOutputTokens","type":"address[]"}],"name":"enableSwapOutputTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"swapTokens","type":"address[]"}],"name":"enableSwapTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"flashloanAmount","type":"uint256"},{"components":[{"internalType":"address","name":"handler","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapToken","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"isDelegate","type":"bool"},{"internalType":"bytes","name":"handlerCalldata","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SwapPayload","name":"swapPayload","type":"tuple"},{"internalType":"uint256","name":"maxLTV","type":"uint256"}],"name":"enter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"borrowAmount","type":"uint256"},{"components":[{"internalType":"address","name":"handler","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapToken","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"isDelegate","type":"bool"},{"internalType":"bytes","name":"handlerCalldata","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SwapPayload","name":"swapPayload","type":"tuple"},{"internalType":"uint256","name":"maxLTV","type":"uint256"}],"name":"enterMulticall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"executeOperation","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"flashloanAmount","type":"uint256"},{"internalType":"uint256","name":"repayAmount","type":"uint256"},{"internalType":"uint256","name":"decollateralizeAmount","type":"uint256"},{"components":[{"internalType":"address","name":"handler","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapToken","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"isDelegate","type":"bool"},{"internalType":"bytes","name":"handlerCalldata","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SwapPayload","name":"swapPayload","type":"tuple"},{"internalType":"uint256","name":"maxLTV","type":"uint256"}],"name":"exit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"decollateralizeAmount","type":"uint256"},{"components":[{"internalType":"address","name":"handler","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapToken","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"isDelegate","type":"bool"},{"internalType":"bytes","name":"handlerCalldata","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SwapPayload","name":"swapPayload","type":"tuple"},{"internalType":"bool","name":"repayDebt","type":"bool"},{"internalType":"uint256","name":"maxLTV","type":"uint256"}],"name":"exitMulticall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetAddress","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralToDebtPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDebtAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLTV","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":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"feeAmounts","type":"uint256[]"},{"internalType":"bytes","name":"userData","type":"bytes"}],"name":"receiveFlashLoan","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":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newProvider","type":"address"}],"name":"setFlashloanProvider","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":"supportsNativeAssets","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"handler","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"swapToken","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"bool","name":"isDelegate","type":"bool"},{"internalType":"bytes","name":"handlerCalldata","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct SwapPayload[]","name":"payloads","type":"tuple[]"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"feePct","type":"uint256"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sweepDust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unclaimedRewards","outputs":[{"internalType":"contract IERC20[]","name":"rewardTokens","type":"address[]"},{"internalType":"uint256[]","name":"earnedAmounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unwrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unwrapAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_feeAccount","type":"address"}],"name":"updateFeeAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"erc20Token","type":"address"}],"name":"withdraw","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"withdrawAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawAllTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"erc20Token","type":"address"},{"internalType":"address","name":"to","type":"address"}],"name":"withdrawTo","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"wrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]