Overview
ETH Balance
ETH Value
$0.00Latest 1 from a total of 1 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Components | 27524839 | 129 days ago | IN | 0 ETH | 0 |
View more zero value Internal Transactions in Advanced View mode
Cross-Chain Transactions
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x05E93f70...88C8fbcCE The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
// ** euler imports
import {IEVault as IEulerVault} from "@euler-interfaces/IEulerVault.sol";
import {IEVC as EVCLib, IEthereumVaultConnector as IEVC} from "@euler-interfaces/IEVC.sol";
import {IRewardToken as IrEUL} from "@euler-interfaces/IRewardToken.sol";
// ** external imports
import {IMerklDistributor} from "@merkl-contracts/IMerklDistributor.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// ** contracts
import {LendingBase} from "../lendingAdapters/LendingBase.sol";
/// @title Euler Lending Adapter
/// @notice Implementation of the lending adapter using Euler V2.
contract EulerLendingAdapter is LendingBase {
using SafeERC20 for IERC20;
IEVC immutable evc;
IrEUL public immutable rEUL;
IEulerVault public immutable vault0;
IEulerVault public immutable vault1;
address public immutable subAccount0 = getSubAccountAddress(1);
address public immutable subAccount1 = getSubAccountAddress(2);
constructor(
IERC20 _base,
IERC20 _quote,
IEVC _evc,
IEulerVault _vault0,
IEulerVault _vault1,
IMerklDistributor _merklRewardsDistributor,
IrEUL _rEUL
) LendingBase(_merklRewardsDistributor, _base, _quote) {
evc = _evc;
vault0 = _vault0;
vault1 = _vault1;
rEUL = _rEUL;
evc.enableController(subAccount0, address(vault0));
evc.enableCollateral(subAccount0, address(vault1));
evc.enableController(subAccount1, address(vault1));
evc.enableCollateral(subAccount1, address(vault0));
BASE.forceApprove(address(vault0), type(uint256).max);
QUOTE.forceApprove(address(vault0), type(uint256).max);
BASE.forceApprove(address(vault1), type(uint256).max);
QUOTE.forceApprove(address(vault1), type(uint256).max);
}
function getSubAccountAddress(uint8 accountId) internal view returns (address) {
return address(uint160(address(this)) ^ uint160(accountId));
}
// ** rEUL unlocking support
function unlockRewardEUL(address to, uint256 lockTimestamp) external onlyOwner {
rEUL.withdrawToByLockTimestamp(to, lockTimestamp, true);
}
// ** Long market
function getBorrowedLong() public view override returns (uint256) {
return vault0.debtOf(subAccount0);
}
function getCollateralLong() public view override returns (uint256) {
return vault1.convertToAssets(vault1.balanceOf(subAccount0));
}
function borrowLong(uint256 amount) public override onlyModule onlyActive {
EVCLib.BatchItem[] memory items = new EVCLib.BatchItem[](1);
items[0] = EVCLib.BatchItem({
targetContract: address(vault0),
onBehalfOfAccount: subAccount0,
value: 0,
data: abi.encodeCall(IEulerVault.borrow, (amount, msg.sender))
});
evc.batch(items);
}
function repayLong(uint256 amount) public override onlyModule notPaused {
BASE.safeTransferFrom(msg.sender, address(this), amount);
vault0.repay(amount, subAccount0);
}
function removeCollateralLong(uint256 amount) public override onlyModule notPaused {
EVCLib.BatchItem[] memory items = new EVCLib.BatchItem[](1);
items[0] = EVCLib.BatchItem({
targetContract: address(vault1),
onBehalfOfAccount: subAccount0,
value: 0,
data: abi.encodeCall(IEulerVault.withdraw, (amount, msg.sender, subAccount0))
});
evc.batch(items);
}
function addCollateralLong(uint256 amount) public override onlyModule onlyActive {
QUOTE.safeTransferFrom(msg.sender, address(this), amount);
vault1.mint(vault1.convertToShares(amount), subAccount0);
}
// ** Short market
function getBorrowedShort() public view override returns (uint256) {
return vault1.debtOf(subAccount1);
}
function getCollateralShort() public view override returns (uint256) {
return vault0.convertToAssets(vault0.balanceOf(subAccount1));
}
function borrowShort(uint256 amount) public override onlyModule onlyActive {
EVCLib.BatchItem[] memory items = new EVCLib.BatchItem[](1);
items[0] = EVCLib.BatchItem({
targetContract: address(vault1),
onBehalfOfAccount: subAccount1,
value: 0,
data: abi.encodeCall(IEulerVault.borrow, (amount, msg.sender))
});
evc.batch(items);
}
function repayShort(uint256 amount) public override onlyModule notPaused {
QUOTE.safeTransferFrom(msg.sender, address(this), amount);
vault1.repay(amount, subAccount1);
}
function removeCollateralShort(uint256 amount) public override onlyModule notPaused {
EVCLib.BatchItem[] memory items = new EVCLib.BatchItem[](1);
items[0] = EVCLib.BatchItem({
targetContract: address(vault0),
onBehalfOfAccount: subAccount1,
value: 0,
data: abi.encodeCall(IEulerVault.withdraw, (amount, msg.sender, subAccount1))
});
evc.batch(items);
}
function addCollateralShort(uint256 amount) public override onlyModule onlyActive {
BASE.safeTransferFrom(msg.sender, address(this), amount);
vault0.mint(vault0.convertToShares(amount), subAccount1);
}
// ** Helpers
function syncPositions() external {
// Intentionally empty as no synchronization is needed for Euler positions.
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library Base {
struct Integrations {
address evc;
address protocolConfig;
address sequenceRegistry;
address balanceTracker;
address permit2;
}
}
library Dispatch {
struct DeployedModules {
address initialize;
address token;
address vault;
address borrowing;
address liquidation;
address riskManager;
address balanceForwarder;
address governance;
}
}
interface IEVault {
error E_AccountLiquidity();
error E_AmountTooLargeToEncode();
error E_BadAddress();
error E_BadAssetReceiver();
error E_BadBorrowCap();
error E_BadCollateral();
error E_BadFee();
error E_BadMaxLiquidationDiscount();
error E_BadSharesOwner();
error E_BadSharesReceiver();
error E_BadSupplyCap();
error E_BorrowCapExceeded();
error E_CheckUnauthorized();
error E_CollateralDisabled();
error E_ConfigAmountTooLargeToEncode();
error E_ControllerDisabled();
error E_DebtAmountTooLargeToEncode();
error E_EmptyError();
error E_ExcessiveRepayAmount();
error E_FlashLoanNotRepaid();
error E_Initialized();
error E_InsufficientAllowance();
error E_InsufficientAssets();
error E_InsufficientBalance();
error E_InsufficientCash();
error E_InsufficientDebt();
error E_InvalidLTVAsset();
error E_LTVBorrow();
error E_LTVLiquidation();
error E_LiquidationCoolOff();
error E_MinYield();
error E_NoLiability();
error E_NoPriceOracle();
error E_NotController();
error E_NotHookTarget();
error E_NotSupported();
error E_OperationDisabled();
error E_OutstandingDebt();
error E_ProxyMetadata();
error E_Reentrancy();
error E_RepayTooMuch();
error E_SelfLiquidation();
error E_SelfTransfer();
error E_SupplyCapExceeded();
error E_TransientState();
error E_Unauthorized();
error E_ViolatorLiquidityDeferred();
error E_ZeroAssets();
error E_ZeroShares();
event Approval(address indexed owner, address indexed spender, uint256 value);
event BalanceForwarderStatus(address indexed account, bool status);
event Borrow(address indexed account, uint256 assets);
event ConvertFees(
address indexed sender,
address indexed protocolReceiver,
address indexed governorReceiver,
uint256 protocolShares,
uint256 governorShares
);
event DebtSocialized(address indexed account, uint256 assets);
event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);
event EVaultCreated(address indexed creator, address indexed asset, address dToken);
event GovSetCaps(uint16 newSupplyCap, uint16 newBorrowCap);
event GovSetConfigFlags(uint32 newConfigFlags);
event GovSetFeeReceiver(address indexed newFeeReceiver);
event GovSetGovernorAdmin(address indexed newGovernorAdmin);
event GovSetHookConfig(address indexed newHookTarget, uint32 newHookedOps);
event GovSetInterestFee(uint16 newFee);
event GovSetInterestRateModel(address newInterestRateModel);
event GovSetLTV(
address indexed collateral,
uint16 borrowLTV,
uint16 liquidationLTV,
uint16 initialLiquidationLTV,
uint48 targetTimestamp,
uint32 rampDuration
);
event GovSetLiquidationCoolOffTime(uint16 newCoolOffTime);
event GovSetMaxLiquidationDiscount(uint16 newDiscount);
event InterestAccrued(address indexed account, uint256 assets);
event Liquidate(
address indexed liquidator,
address indexed violator,
address collateral,
uint256 repayAssets,
uint256 yieldBalance
);
event PullDebt(address indexed from, address indexed to, uint256 assets);
event Repay(address indexed account, uint256 assets);
event Transfer(address indexed from, address indexed to, uint256 value);
event VaultStatus(
uint256 totalShares,
uint256 totalBorrows,
uint256 accumulatedFees,
uint256 cash,
uint256 interestAccumulator,
uint256 interestRate,
uint256 timestamp
);
event Withdraw(
address indexed sender,
address indexed receiver,
address indexed owner,
uint256 assets,
uint256 shares
);
function EVC() external view returns (address);
function LTVBorrow(address collateral) external view returns (uint16);
function LTVFull(
address collateral
)
external
view
returns (
uint16 borrowLTV,
uint16 liquidationLTV,
uint16 initialLiquidationLTV,
uint48 targetTimestamp,
uint32 rampDuration
);
function LTVLiquidation(address collateral) external view returns (uint16);
function LTVList() external view returns (address[] memory);
function MODULE_BALANCE_FORWARDER() external view returns (address);
function MODULE_BORROWING() external view returns (address);
function MODULE_GOVERNANCE() external view returns (address);
function MODULE_INITIALIZE() external view returns (address);
function MODULE_LIQUIDATION() external view returns (address);
function MODULE_RISKMANAGER() external view returns (address);
function MODULE_TOKEN() external view returns (address);
function MODULE_VAULT() external view returns (address);
function accountLiquidity(
address account,
bool liquidation
) external view returns (uint256 collateralValue, uint256 liabilityValue);
function accountLiquidityFull(
address account,
bool liquidation
) external view returns (address[] memory collaterals, uint256[] memory collateralValues, uint256 liabilityValue);
function accumulatedFees() external view returns (uint256);
function accumulatedFeesAssets() external view returns (uint256);
function allowance(address holder, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function asset() external view returns (address);
function balanceForwarderEnabled(address account) external view returns (bool);
function balanceOf(address account) external view returns (uint256);
function balanceTrackerAddress() external view returns (address);
function borrow(uint256 amount, address receiver) external returns (uint256);
function caps() external view returns (uint16 supplyCap, uint16 borrowCap);
function cash() external view returns (uint256);
function checkAccountStatus(address account, address[] memory collaterals) external view returns (bytes4);
function checkLiquidation(
address liquidator,
address violator,
address collateral
) external view returns (uint256 maxRepay, uint256 maxYield);
function checkVaultStatus() external returns (bytes4);
function configFlags() external view returns (uint32);
function convertFees() external;
function convertToAssets(uint256 shares) external view returns (uint256);
function convertToShares(uint256 assets) external view returns (uint256);
function creator() external view returns (address);
function dToken() external view returns (address);
function debtOf(address account) external view returns (uint256);
function debtOfExact(address account) external view returns (uint256);
function decimals() external view returns (uint8);
function deposit(uint256 amount, address receiver) external returns (uint256);
function disableBalanceForwarder() external;
function disableController() external;
function enableBalanceForwarder() external;
function feeReceiver() external view returns (address);
function flashLoan(uint256 amount, bytes memory data) external;
function governorAdmin() external view returns (address);
function hookConfig() external view returns (address, uint32);
function initialize(address proxyCreator) external;
function interestAccumulator() external view returns (uint256);
function interestFee() external view returns (uint16);
function interestRate() external view returns (uint256);
function interestRateModel() external view returns (address);
function liquidate(address violator, address collateral, uint256 repayAssets, uint256 minYieldBalance) external;
function liquidationCoolOffTime() external view returns (uint16);
function maxDeposit(address account) external view returns (uint256);
function maxLiquidationDiscount() external view returns (uint16);
function maxMint(address account) external view returns (uint256);
function maxRedeem(address owner) external view returns (uint256);
function maxWithdraw(address owner) external view returns (uint256);
function mint(uint256 amount, address receiver) external returns (uint256);
function name() external view returns (string memory);
function oracle() external view returns (address);
function permit2Address() external view returns (address);
function previewDeposit(uint256 assets) external view returns (uint256);
function previewMint(uint256 shares) external view returns (uint256);
function previewRedeem(uint256 shares) external view returns (uint256);
function previewWithdraw(uint256 assets) external view returns (uint256);
function protocolConfigAddress() external view returns (address);
function protocolFeeReceiver() external view returns (address);
function protocolFeeShare() external view returns (uint256);
function pullDebt(uint256 amount, address from) external;
function redeem(uint256 amount, address receiver, address owner) external returns (uint256);
function repay(uint256 amount, address receiver) external returns (uint256);
function repayWithShares(uint256 amount, address receiver) external returns (uint256 shares, uint256 debt);
function setCaps(uint16 supplyCap, uint16 borrowCap) external;
function setConfigFlags(uint32 newConfigFlags) external;
function setFeeReceiver(address newFeeReceiver) external;
function setGovernorAdmin(address newGovernorAdmin) external;
function setHookConfig(address newHookTarget, uint32 newHookedOps) external;
function setInterestFee(uint16 newFee) external;
function setInterestRateModel(address newModel) external;
function setLTV(address collateral, uint16 borrowLTV, uint16 liquidationLTV, uint32 rampDuration) external;
function setLiquidationCoolOffTime(uint16 newCoolOffTime) external;
function setMaxLiquidationDiscount(uint16 newDiscount) external;
function skim(uint256 amount, address receiver) external returns (uint256);
function symbol() external view returns (string memory);
function totalAssets() external view returns (uint256);
function totalBorrows() external view returns (uint256);
function totalBorrowsExact() external view returns (uint256);
function totalSupply() external view returns (uint256);
function touch() external;
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function transferFromMax(address from, address to) external returns (bool);
function unitOfAccount() external view returns (address);
function viewDelegate() external payable;
function withdraw(uint256 amount, address receiver, address owner) external returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
library IEVC {
struct BatchItem {
address targetContract;
address onBehalfOfAccount;
uint256 value;
bytes data;
}
struct BatchItemResult {
bool success;
bytes result;
}
struct StatusCheckResult {
address checkedAddress;
bool isValid;
bytes result;
}
}
interface IEthereumVaultConnector {
error EVC_BatchPanic();
error EVC_ChecksReentrancy();
error EVC_ControlCollateralReentrancy();
error EVC_ControllerViolation();
error EVC_EmptyError();
error EVC_InvalidAddress();
error EVC_InvalidData();
error EVC_InvalidNonce();
error EVC_InvalidOperatorStatus();
error EVC_InvalidTimestamp();
error EVC_InvalidValue();
error EVC_LockdownMode();
error EVC_NotAuthorized();
error EVC_OnBehalfOfAccountNotAuthenticated();
error EVC_PermitDisabledMode();
error EVC_RevertedBatchResult(
IEVC.BatchItemResult[] batchItemsResult,
IEVC.StatusCheckResult[] accountsStatusResult,
IEVC.StatusCheckResult[] vaultsStatusResult
);
error EVC_SimulationBatchNested();
error InvalidIndex();
error TooManyElements();
event AccountStatusCheck(address indexed account, address indexed controller);
event CallWithContext(
address indexed caller,
bytes19 indexed onBehalfOfAddressPrefix,
address onBehalfOfAccount,
address indexed targetContract,
bytes4 selector
);
event CollateralStatus(address indexed account, address indexed collateral, bool enabled);
event ControllerStatus(address indexed account, address indexed controller, bool enabled);
event LockdownModeStatus(bytes19 indexed addressPrefix, bool enabled);
event NonceStatus(
bytes19 indexed addressPrefix,
uint256 indexed nonceNamespace,
uint256 oldNonce,
uint256 newNonce
);
event NonceUsed(bytes19 indexed addressPrefix, uint256 indexed nonceNamespace, uint256 nonce);
event OperatorStatus(bytes19 indexed addressPrefix, address indexed operator, uint256 accountOperatorAuthorized);
event OwnerRegistered(bytes19 indexed addressPrefix, address indexed owner);
event PermitDisabledModeStatus(bytes19 indexed addressPrefix, bool enabled);
event VaultStatusCheck(address indexed vault);
receive() external payable;
function areChecksDeferred() external view returns (bool);
function areChecksInProgress() external view returns (bool);
function batch(IEVC.BatchItem[] memory items) external payable;
function batchRevert(IEVC.BatchItem[] memory items) external payable;
function batchSimulation(
IEVC.BatchItem[] memory items
)
external
payable
returns (
IEVC.BatchItemResult[] memory batchItemsResult,
IEVC.StatusCheckResult[] memory accountsStatusCheckResult,
IEVC.StatusCheckResult[] memory vaultsStatusCheckResult
);
function call(
address targetContract,
address onBehalfOfAccount,
uint256 value,
bytes memory data
) external payable returns (bytes memory result);
function controlCollateral(
address targetCollateral,
address onBehalfOfAccount,
uint256 value,
bytes memory data
) external payable returns (bytes memory result);
function disableCollateral(address account, address vault) external payable;
function disableController(address account) external payable;
function enableCollateral(address account, address vault) external payable;
function enableController(address account, address vault) external payable;
function forgiveAccountStatusCheck(address account) external payable;
function forgiveVaultStatusCheck() external payable;
function getAccountOwner(address account) external view returns (address);
function getAddressPrefix(address account) external pure returns (bytes19);
function getCollaterals(address account) external view returns (address[] memory);
function getControllers(address account) external view returns (address[] memory);
function getCurrentOnBehalfOfAccount(
address controllerToCheck
) external view returns (address onBehalfOfAccount, bool controllerEnabled);
function getLastAccountStatusCheckTimestamp(address account) external view returns (uint256);
function getNonce(bytes19 addressPrefix, uint256 nonceNamespace) external view returns (uint256);
function getOperator(bytes19 addressPrefix, address operator) external view returns (uint256);
function getRawExecutionContext() external view returns (uint256 context);
function haveCommonOwner(address account, address otherAccount) external pure returns (bool);
function isAccountOperatorAuthorized(address account, address operator) external view returns (bool);
function isAccountStatusCheckDeferred(address account) external view returns (bool);
function isCollateralEnabled(address account, address vault) external view returns (bool);
function isControlCollateralInProgress() external view returns (bool);
function isControllerEnabled(address account, address vault) external view returns (bool);
function isLockdownMode(bytes19 addressPrefix) external view returns (bool);
function isOperatorAuthenticated() external view returns (bool);
function isPermitDisabledMode(bytes19 addressPrefix) external view returns (bool);
function isSimulationInProgress() external view returns (bool);
function isVaultStatusCheckDeferred(address vault) external view returns (bool);
function name() external view returns (string memory);
function permit(
address signer,
address sender,
uint256 nonceNamespace,
uint256 nonce,
uint256 deadline,
uint256 value,
bytes memory data,
bytes memory signature
) external payable;
function reorderCollaterals(address account, uint8 index1, uint8 index2) external payable;
function requireAccountAndVaultStatusCheck(address account) external payable;
function requireAccountStatusCheck(address account) external payable;
function requireVaultStatusCheck() external payable;
function setAccountOperator(address account, address operator, bool authorized) external payable;
function setLockdownMode(bytes19 addressPrefix, bool enabled) external payable;
function setNonce(bytes19 addressPrefix, uint256 nonceNamespace, uint256 nonce) external payable;
function setOperator(bytes19 addressPrefix, address operator, uint256 operatorBitField) external payable;
function setPermitDisabledMode(bytes19 addressPrefix, bool enabled) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IRewardToken {
error ControllerDisabled();
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
error ERC20InvalidApprover(address approver);
error ERC20InvalidReceiver(address receiver);
error ERC20InvalidSender(address sender);
error ERC20InvalidSpender(address spender);
error ERC20InvalidUnderlying(address token);
error EVC_InvalidAddress();
error EnumerableMapNonexistentKey(bytes32 key);
error InvalidWhitelistStatus();
error NotAuthorized();
error OwnableInvalidOwner(address owner);
error OwnableUnauthorizedAccount(address account);
error RemainderLossNotAllowed();
error SafeERC20FailedOperation(address token);
event Approval(address indexed owner, address indexed spender, uint256 value);
event LockCreated(address indexed account, uint256 lockTimestamp);
event LockRemoved(address indexed account, uint256 lockTimestamp);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
event RemainderReceiverSet(address indexed remainderReceiver);
event Transfer(address indexed from, address indexed to, uint256 value);
event WhitelistStatusSet(address indexed account, uint256 status);
function EVC() external view returns (address);
function WHITELIST_STATUS_ADMIN() external view returns (uint256);
function WHITELIST_STATUS_DISTRIBUTOR() external view returns (uint256);
function WHITELIST_STATUS_NONE() external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function balanceOf(address account) external view returns (uint256);
function decimals() external view returns (uint8);
function depositFor(address account, uint256 amount) external returns (bool);
function getLockedAmountByLockTimestamp(address account, uint256 lockTimestamp) external view returns (uint256);
function getLockedAmounts(address account) external view returns (uint256[] memory, uint256[] memory);
function getLockedAmountsLength(address account) external view returns (uint256);
function getLockedAmountsLockTimestamps(address account) external view returns (uint256[] memory);
function getWithdrawAmountsByLockTimestamp(
address account,
uint256 lockTimestamp
) external view returns (uint256, uint256);
function name() external view returns (string memory);
function owner() external view returns (address);
function remainderReceiver() external view returns (address);
function renounceOwnership() external pure;
function setRemainderReceiver(address _remainderReceiver) external;
function setWhitelistStatus(address account, uint256 status) external;
function setWhitelistStatus(uint256 status) external;
function symbol() external view returns (string memory);
function totalSupply() external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
function transferOwnership(address newOwner) external;
function underlying() external view returns (address);
function whitelistStatus(address) external view returns (uint256);
function withdrawTo(address account, uint256 amount) external returns (bool);
function withdrawToByLockTimestamp(
address account,
uint256 lockTimestamp,
bool allowRemainderLoss
) external returns (bool);
function withdrawToByLockTimestamps(
address account,
uint256[] memory lockTimestamps,
bool allowRemainderLoss
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IMerklDistributor {
/// @notice Claims rewards for a given set of users
/// @dev Unless another address has been approved for claiming, only an address can claim for itself
/// @param users Addresses for which claiming is taking place
/// @param tokens ERC20 token claimed
/// @param amounts Amount of tokens that will be sent to the corresponding users
/// @param proofs Array of hashes bridging from a leaf `(hash of user | token | amount)` to the Merkle root
function claim(
address[] calldata users,
address[] calldata tokens,
uint256[] calldata amounts,
bytes32[][] calldata proofs
) external;
/// @notice Returns the Merkle root that is currently live for the contract
function getMerkleRoot() external view returns (bytes32);
/// @notice Updates the Merkle tree
function updateTree(MerkleTree calldata _tree) external;
/// @notice When the current tree becomes valid
function endOfDisputePeriod() external view returns (uint48);
}
struct MerkleTree {
// Root of a Merkle tree which leaves are `(address user, address token, uint amount)`
// representing an amount of tokens accumulated by `user`.
// The Merkle tree is assumed to have only increasing amounts: that is to say if a user can claim 1,
// then after the amount associated in the Merkle tree for this token should be x > 1
bytes32 merkleRoot;
// Ipfs hash of the tree data
bytes32 ipfsHash;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
// ** external imports
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IMerklDistributor} from "@merkl-contracts/IMerklDistributor.sol";
// ** contracts
import {Base} from "../base/Base.sol";
// ** interfaces
import {ILendingAdapter} from "../../interfaces/ILendingAdapter.sol";
/// @title Lending Base
/// @notice Abstract contract that serves as the base for all lending adapters.
/// @dev Implements the updatePosition flow and the claim rewards functionality using Merkl.
abstract contract LendingBase is Base, ILendingAdapter {
using SafeERC20 for IERC20;
IMerklDistributor public immutable merklRewardsDistributor;
constructor(
IMerklDistributor _merklRewardsDistributor,
IERC20 _base,
IERC20 _quote
) Base(ComponentType.EXTERNAL_ADAPTER, msg.sender, _base, _quote) {
merklRewardsDistributor = _merklRewardsDistributor;
}
// ** Merkl rewards support
/// @notice Claims rewards from Merkl.
/// @param to The address where the tokens will be sent.
/// @param rewardToken The address of the reward token.
/// @param claimable The overall claimable amount of token rewards.
/// @param proof Array of hashes bridging from a leaf to the Merkle root.
function claimMerklRewards(
address to,
IERC20 rewardToken,
uint256 claimable,
bytes32[] calldata proof
) external onlyOwner {
address[] memory users = new address[](1);
address[] memory tokens = new address[](1);
uint256[] memory amounts = new uint256[](1);
bytes32[][] memory proofs = new bytes32[][](1);
users[0] = address(this);
tokens[0] = address(rewardToken);
amounts[0] = claimable;
proofs[0] = proof;
merklRewardsDistributor.claim(users, tokens, amounts, proofs);
// The `balanceOf` is necessary because amount received is not always equal `claimable`.
// The `to != address(this)` check is necessary to skip transfer for tokens like rEUL, which are locked.
if (to != address(this)) rewardToken.safeTransfer(to, rewardToken.balanceOf(address(this)));
}
// ** Position management
function getPosition() external view returns (uint256, uint256, uint256, uint256) {
return (getCollateralLong(), getCollateralShort(), getBorrowedLong(), getBorrowedShort());
}
/// @notice Updates the position by adjusting collateral and debt for both long and short sides.
/// @dev The order of operations is critical to avoid `phantom under-collateralization`:
/// - Collateral is added and debt is repaid first, to ensure the account is not temporarily under-collateralized.
/// - Now, collateral is removed and debt is borrowed if needed.
function updatePosition(
int256 deltaCL,
int256 deltaCS,
int256 deltaDL,
int256 deltaDS
) external onlyModule notPaused {
if (deltaCL < 0) addCollateralLong(uint256(-deltaCL));
if (deltaCS < 0) addCollateralShort(uint256(-deltaCS));
if (deltaDL < 0) repayLong(uint256(-deltaDL));
if (deltaDS < 0) repayShort(uint256(-deltaDS));
if (deltaCL > 0) removeCollateralLong(uint256(deltaCL));
if (deltaCS > 0) removeCollateralShort(uint256(deltaCS));
if (deltaDL > 0) borrowLong(uint256(deltaDL));
if (deltaDS > 0) borrowShort(uint256(deltaDS));
}
// ** Long and short market functions to be implemented by derived contracts
function addCollateralLong(uint256 amount) public virtual;
function addCollateralShort(uint256 amount) public virtual;
function repayLong(uint256 amount) public virtual;
function repayShort(uint256 amount) public virtual;
function removeCollateralLong(uint256 amount) public virtual;
function removeCollateralShort(uint256 amount) public virtual;
function borrowLong(uint256 amount) public virtual;
function borrowShort(uint256 amount) public virtual;
function getCollateralLong() public view virtual returns (uint256);
function getCollateralShort() public view virtual returns (uint256);
function getBorrowedLong() public view virtual returns (uint256);
function getBorrowedShort() public view virtual returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// ** external imports
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
// ** interfaces
import {IALM} from "../../interfaces/IALM.sol";
import {IBaseStrategyHook} from "../../interfaces/IBaseStrategyHook.sol";
import {ILendingAdapter} from "../../interfaces/ILendingAdapter.sol";
import {IFlashLoanAdapter} from "../../interfaces/IFlashLoanAdapter.sol";
import {IPositionManager} from "../../interfaces/IPositionManager.sol";
import {IOracle} from "../../interfaces/IOracle.sol";
import {IRebalanceAdapter} from "../../interfaces/IRebalanceAdapter.sol";
import {ISwapAdapter} from "../../interfaces/ISwapAdapter.sol";
import {IBase} from "../../interfaces/IBase.sol";
/// @title Base
/// @notice Abstract contract that serves as the base for all modules and adapters.
abstract contract Base is IBase {
using SafeERC20 for IERC20;
enum ComponentType {
ALM,
HOOK,
REBALANCE_ADAPTER,
POSITION_MANAGER,
EXTERNAL_ADAPTER
}
ComponentType public immutable componentType;
address public owner;
IERC20 public immutable BASE;
IERC20 public immutable QUOTE;
IALM public alm;
IBaseStrategyHook public hook;
ILendingAdapter public lendingAdapter;
IFlashLoanAdapter public flashLoanAdapter;
IPositionManager public positionManager;
IOracle public oracle;
IRebalanceAdapter public rebalanceAdapter;
ISwapAdapter public swapAdapter;
constructor(ComponentType _componentType, address initialOwner, IERC20 _base, IERC20 _quote) {
componentType = _componentType;
BASE = _base;
QUOTE = _quote;
owner = initialOwner;
emit OwnershipTransferred(address(0), initialOwner);
}
function setComponents(
IALM _alm,
IBaseStrategyHook _hook,
ILendingAdapter _lendingAdapter,
IFlashLoanAdapter _flashLoanAdapter,
IPositionManager _positionManager,
IOracle _oracle,
IRebalanceAdapter _rebalanceAdapter,
ISwapAdapter _swapAdapter
) external onlyOwner {
alm = _alm;
hook = _hook;
oracle = _oracle;
rebalanceAdapter = _rebalanceAdapter;
if (componentType == ComponentType.POSITION_MANAGER) {
switchApproval(address(lendingAdapter), address(_lendingAdapter));
} else if (componentType == ComponentType.HOOK) {
switchApproval(address(lendingAdapter), address(_lendingAdapter));
switchApproval(address(positionManager), address(_positionManager));
} else if (componentType == ComponentType.ALM || componentType == ComponentType.REBALANCE_ADAPTER) {
switchApproval(address(lendingAdapter), address(_lendingAdapter));
switchApproval(address(flashLoanAdapter), address(_flashLoanAdapter));
switchApproval(address(swapAdapter), address(_swapAdapter));
}
lendingAdapter = _lendingAdapter;
flashLoanAdapter = _flashLoanAdapter;
swapAdapter = _swapAdapter;
positionManager = _positionManager;
}
function switchApproval(address moduleOld, address moduleNew) internal {
if (moduleOld == moduleNew) return;
if (moduleOld != address(0)) {
BASE.forceApprove(moduleOld, 0);
QUOTE.forceApprove(moduleOld, 0);
}
BASE.forceApprove(moduleNew, type(uint256).max);
QUOTE.forceApprove(moduleNew, type(uint256).max);
}
function transferOwnership(address newOwner) external onlyOwner {
if (owner == newOwner) return;
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
// ** Modifiers
modifier onlyOwner() {
if (owner != msg.sender) {
revert OwnableUnauthorizedAccount(msg.sender);
}
_;
}
/// @dev Only the ALM may call this function.
modifier onlyALM() {
if (msg.sender != address(alm)) revert NotALM(msg.sender);
_;
}
modifier onlyHook() {
if (msg.sender != address(hook)) revert NotHook(msg.sender);
_;
}
/// @dev Only the rebalance adapter may call this function.
modifier onlyRebalanceAdapter() {
if (msg.sender != address(rebalanceAdapter)) revert NotRebalanceAdapter(msg.sender);
_;
}
/// @dev Only the flash loan adapter may call this function.
modifier onlyFlashLoanAdapter() {
if (msg.sender != address(flashLoanAdapter)) revert NotFlashLoanAdapter(msg.sender);
_;
}
/// @dev Only modules may call this function.
modifier onlyModule() {
if (
msg.sender != address(alm) &&
msg.sender != address(hook) &&
msg.sender != address(rebalanceAdapter) &&
msg.sender != address(positionManager)
) revert NotModule(msg.sender);
_;
}
/// @notice Restricts function execution when contract is paused.
/// @dev Allows execution when status is active (0) or shutdown (2).
/// @dev Reverts with ContractPaused when status equals 1 (paused).
modifier notPaused() {
if (alm.status() == 1) revert ContractPaused();
_;
}
/// @notice Restricts function execution when contract is not active.
/// @dev Allows execution when status equals 0 (active).
/// @dev Reverts with ContractNotActive when status is paused (1) or shutdown (2).
modifier onlyActive() {
if (alm.status() != 0) revert ContractNotActive();
_;
}
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
/// @notice Defines the interface for a Lending Adapter.
interface ILendingAdapter {
// ** Position management
function getPosition() external view returns (uint256, uint256, uint256, uint256);
function updatePosition(int256 deltaCL, int256 deltaCS, int256 deltaDL, int256 deltaDS) external;
// ** Long market
function getBorrowedLong() external view returns (uint256);
function borrowLong(uint256 amountUSDC) external;
function repayLong(uint256 amountUSDC) external;
function getCollateralLong() external view returns (uint256);
function removeCollateralLong(uint256 amountWETH) external;
function addCollateralLong(uint256 amountWETH) external;
// ** Short market
function getBorrowedShort() external view returns (uint256);
function borrowShort(uint256 amountWETH) external;
function repayShort(uint256 amountWETH) external;
function getCollateralShort() external view returns (uint256);
function removeCollateralShort(uint256 amountUSDC) external;
function addCollateralShort(uint256 amountUSDC) external;
// ** Helpers
function syncPositions() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Defines the interface for an Automated Liquidity Manager.
interface IALM {
error ZeroLiquidity();
error NotZeroShares();
error NotMinOutWithdrawBase();
error NotMinOutWithdrawQuote();
error NotALiquidityOperator();
error TVLCapExceeded();
error NotAValidPositionState();
error NotMinShares();
event StatusSet(uint8 indexed status);
event OperatorSet(address indexed liquidityOperator);
event TVLCapSet(uint256 tvlCap);
event Deposit(address indexed to, uint256 amount, uint256 delShares, uint256 TVL, uint256 totalSupply);
event Withdraw(
address indexed to,
uint256 delShares,
uint256 baseOut,
uint256 quoteOut,
uint256 totalSupply,
uint256 liquidity
);
function status() external view returns (uint8);
function TVL(uint256 price) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Defines the interface for a Base Strategy Hook.
interface IBaseStrategyHook {
error AddLiquidityThroughHook();
error UnauthorizedPool();
error SwapPriceChangeTooHigh();
error NotASwapOperator();
error OnlyOnePoolPerHook();
error MustUseDynamicFee();
error ProtocolFeeNotValid();
error LiquidityMultiplierNotValid();
error TicksMisordered(int24 tickLower, int24 tickUpper);
error TickLowerOutOfBounds(int24 tick);
error TickUpperOutOfBounds(int24 tick);
error TickDeltasNotValid();
error LPFeeTooLarge(uint24 fee);
error NativeTokenUnsupported();
event OperatorSet(address indexed swapOperator);
event TreasurySet(address indexed treasury);
event ProtocolParamsSet(
uint256 liquidityMultiplier,
uint256 protocolFee,
uint256 swapPriceThreshold,
int24 tickLowerDelta,
int24 tickUpperDelta
);
event LiquidityUpdated(uint128 newLiquidity);
event SqrtPriceUpdated(uint160 newSqrtPrice);
event BoundariesUpdated(int24 newTickLower, int24 newTickUpper);
event LPFeeSet(uint24 fee);
event HookFee(bytes32 indexed id, address indexed sender, uint128 feeAmount0, uint128 feeAmount1);
struct Ticks {
int24 lower;
int24 upper;
}
function activeTicks() external view returns (int24 lower, int24 upper);
function tickDeltas() external view returns (int24 lower, int24 upper);
function refreshReservesAndTransferFees() external;
function updateLiquidityAndBoundariesToOracle() external;
function updateLiquidityAndBoundaries(uint160 sqrtPrice) external returns (uint128 newLiquidity);
function updateLiquidity() external returns (uint128 newLiquidity);
function isInvertedPool() external view returns (bool);
function protocolFee() external view returns (uint256);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
/// @notice Defines the interface for a Flash Loan Adapter.
interface IFlashLoanAdapter {
function flashLoanSingle(bool isBase, uint256 amount, bytes calldata data) external;
function flashLoanTwoTokens(uint256 amountBase, uint256 amountQuote, bytes calldata data) external;
}
/// @notice Defines the interface for a Flash Loan Receiver.
interface IFlashLoanReceiver {
function onFlashLoanSingle(bool isBase, uint256 amount, bytes calldata data) external;
function onFlashLoanTwoTokens(uint256 amountBase, uint256 amountQuote, bytes calldata data) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
/// @notice Defines the interface for a Position Manager.
interface IPositionManager {
function positionAdjustmentPriceUp(uint256 deltaUSDC, uint256 deltaWETH, uint160 sqrtPrice) external;
function positionAdjustmentPriceDown(uint256 deltaUSDC, uint256 deltaWETH, uint160 sqrtPrice) external;
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
/// @notice Defines the interface for an Oracle.
interface IOracle {
error TotalDecimalsDeltaNotValid();
error PriceZero();
error SqrtPriceNotValid();
function price() external view returns (uint256);
function poolPrice() external view returns (uint256, uint160);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @notice Defines the interface for a Rebalance Adapter.
interface IRebalanceAdapter {
function sqrtPriceAtLastRebalance() external view returns (uint160);
}// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
/// @notice Defines the interface for a Swap Adapter.
interface ISwapAdapter {
function swapExactOutput(bool isBaseToQuote, uint256 amountOut) external returns (uint256 amountIn);
function swapExactInput(bool isBaseToQuote, uint256 amountIn) external returns (uint256 amountOut);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// ** interfaces
import {IALM} from "./IALM.sol";
import {IBaseStrategyHook} from "./IBaseStrategyHook.sol";
import {ILendingAdapter} from "./ILendingAdapter.sol";
import {IFlashLoanAdapter} from "./IFlashLoanAdapter.sol";
import {IPositionManager} from "./IPositionManager.sol";
import {IOracle} from "./IOracle.sol";
import {IRebalanceAdapter} from "./IRebalanceAdapter.sol";
import {ISwapAdapter} from "./ISwapAdapter.sol";
/// @notice Defines the interface for a Base contract.
interface IBase {
error OwnableUnauthorizedAccount(address account);
error NotALM(address account);
error NotHook(address account);
error NotRebalanceAdapter(address account);
error NotModule(address account);
error NotFlashLoanAdapter(address account);
error ContractPaused();
error ContractNotActive();
error InvalidNativeTokenSender();
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function setComponents(
IALM _alm,
IBaseStrategyHook _hook,
ILendingAdapter _lendingAdapter,
IFlashLoanAdapter _flashLoanAdapter,
IPositionManager _positionManager,
IOracle _oracle,
IRebalanceAdapter _rebalanceAdapter,
ISwapAdapter _swapAdapter
) external;
}{
"remappings": [
"@forks/=test/forks/",
"@src/=src/",
"@test/=test/",
"forge-std/=lib/forge-std/src/",
"v4-core/=lib/v4-periphery/lib/v4-core/src/",
"v4-core-test/=lib/v4-periphery/lib/v4-core/test/",
"v4-periphery/=lib/v4-periphery/",
"@v3-periphery/=external/v3-periphery/",
"@openzeppelin/contracts/=lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/token/=lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/contracts/token/",
"@openzeppelin/=lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/contracts/",
"@morpho-blue/=lib/morpho-blue/src/",
"@chainlink/=lib/chainlink-brownie-contracts/contracts/src/v0.8/",
"@prb-math/=lib/prb-math/src/",
"@morpho-oracles/=external/morpho-oracles/",
"@v3-core/=external/v3-core/",
"@v2-core/=external/v2-core/",
"@universal-router/=external/universal-router/",
"@euler-interfaces/=external/euler-interfaces/",
"@merkl-contracts/=external/merkl-contracts/",
"@permit2/=external/permit2/",
"@universal-rewards-distributor/=external/universal-rewards-distributor/",
"@solmate/=lib/v4-periphery/lib/v4-core/lib/solmate/",
"@ensdomains/=lib/v4-periphery/lib/v4-core/node_modules/@ensdomains/",
"@uniswap/v4-core/=lib/v4-periphery/lib/v4-core/",
"chainlink-brownie-contracts/=lib/chainlink-brownie-contracts/",
"ds-test/=lib/morpho-blue/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-gas-snapshot/=lib/v4-periphery/lib/permit2/lib/forge-gas-snapshot/src/",
"halmos-cheatcodes/=lib/morpho-blue/lib/halmos-cheatcodes/src/",
"hardhat/=lib/v4-periphery/lib/v4-core/node_modules/hardhat/",
"morpho-blue/=lib/morpho-blue/",
"openzeppelin-contracts/=lib/v4-periphery/lib/v4-core/lib/openzeppelin-contracts/",
"permit2/=lib/v4-periphery/lib/permit2/",
"prb-math/=lib/prb-math/src/",
"solmate/=lib/v4-periphery/lib/v4-core/lib/solmate/"
],
"optimizer": {
"enabled": true,
"runs": 800
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"contract IERC20","name":"_base","type":"address"},{"internalType":"contract IERC20","name":"_quote","type":"address"},{"internalType":"contract IEthereumVaultConnector","name":"_evc","type":"address"},{"internalType":"contract IEVault","name":"_vault0","type":"address"},{"internalType":"contract IEVault","name":"_vault1","type":"address"},{"internalType":"contract IMerklDistributor","name":"_merklRewardsDistributor","type":"address"},{"internalType":"contract IRewardToken","name":"_rEUL","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ContractNotActive","type":"error"},{"inputs":[],"name":"ContractPaused","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidNativeTokenSender","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotALM","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotFlashLoanAdapter","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotHook","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotModule","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NotRebalanceAdapter","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"BASE","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"QUOTE","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addCollateralLong","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addCollateralShort","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"alm","outputs":[{"internalType":"contract IALM","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrowLong","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"borrowShort","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"contract IERC20","name":"rewardToken","type":"address"},{"internalType":"uint256","name":"claimable","type":"uint256"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"}],"name":"claimMerklRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"componentType","outputs":[{"internalType":"enum Base.ComponentType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flashLoanAdapter","outputs":[{"internalType":"contract IFlashLoanAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBorrowedLong","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getBorrowedShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralLong","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCollateralShort","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPosition","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hook","outputs":[{"internalType":"contract IBaseStrategyHook","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lendingAdapter","outputs":[{"internalType":"contract ILendingAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merklRewardsDistributor","outputs":[{"internalType":"contract IMerklDistributor","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract IOracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"positionManager","outputs":[{"internalType":"contract IPositionManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rEUL","outputs":[{"internalType":"contract IRewardToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rebalanceAdapter","outputs":[{"internalType":"contract IRebalanceAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"removeCollateralLong","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"removeCollateralShort","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayLong","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"repayShort","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IALM","name":"_alm","type":"address"},{"internalType":"contract IBaseStrategyHook","name":"_hook","type":"address"},{"internalType":"contract ILendingAdapter","name":"_lendingAdapter","type":"address"},{"internalType":"contract IFlashLoanAdapter","name":"_flashLoanAdapter","type":"address"},{"internalType":"contract IPositionManager","name":"_positionManager","type":"address"},{"internalType":"contract IOracle","name":"_oracle","type":"address"},{"internalType":"contract IRebalanceAdapter","name":"_rebalanceAdapter","type":"address"},{"internalType":"contract ISwapAdapter","name":"_swapAdapter","type":"address"}],"name":"setComponents","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"subAccount0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"subAccount1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapAdapter","outputs":[{"internalType":"contract ISwapAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"syncPositions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"lockTimestamp","type":"uint256"}],"name":"unlockRewardEUL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int256","name":"deltaCL","type":"int256"},{"internalType":"int256","name":"deltaCS","type":"int256"},{"internalType":"int256","name":"deltaDL","type":"int256"},{"internalType":"int256","name":"deltaDS","type":"int256"}],"name":"updatePosition","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault0","outputs":[{"internalType":"contract IEVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vault1","outputs":[{"internalType":"contract IEVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
0x6101c0604052306001186001600160a01b031661018052306002186001600160a01b03166101a052348015610032575f80fd5b5060405161328738038061328783398101604081905261005191610613565b8187876004338383836080819052506001600160a01b0382811660a05281811660c0525f80546001600160a01b03191691851691821781556040517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3505050506001600160a01b0392831660e05250508581166101008190528582166101408190528583166101605283831661012052610180516040516330da145b60e21b81529316600484015260248301529063c368516c906044015f604051808303815f87803b158015610123575f80fd5b505af1158015610135573d5f803e3d5ffd5b5050610100516101805161016051604051636a27f72d60e11b81526001600160a01b03928316600482015290821660248201529116925063d44fee5a91506044015f604051808303815f87803b15801561018d575f80fd5b505af115801561019f573d5f803e3d5ffd5b5050610100516101a051610160516040516330da145b60e21b81526001600160a01b03928316600482015290821660248201529116925063c368516c91506044015f604051808303815f87803b1580156101f7575f80fd5b505af1158015610209573d5f803e3d5ffd5b5050610100516101a05161014051604051636a27f72d60e11b81526001600160a01b03928316600482015290821660248201529116925063d44fee5a91506044015f604051808303815f87803b158015610261575f80fd5b505af1158015610273573d5f803e3d5ffd5b50506101405160a05161029393506001600160a01b031691505f196102f9565b6101405160c0516102b1916001600160a01b03909116905f196102f9565b6101605160a0516102cf916001600160a01b03909116905f196102f9565b6101605160c0516102ed916001600160a01b03909116905f196102f9565b505050505050506106df565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b1790915261035190859083906103bd16565b6103b757604080516001600160a01b03851660248201525f6044808301919091528251808303909101815260649091019091526020810180516001600160e01b0390811663095ea7b360e01b179091526103ad91869161045e16565b6103b7848261045e565b50505050565b5f805f846001600160a01b0316846040516103d891906106aa565b5f604051808303815f865af19150503d805f8114610411576040519150601f19603f3d011682016040523d82523d5f602084013e610416565b606091505b509150915081801561044057508051158061044057508080602001905181019061044091906106c0565b801561045557505f856001600160a01b03163b115b95945050505050565b5f6104726001600160a01b038416836104c9565b905080515f1415801561049657508080602001905181019061049491906106c0565b155b156104c457604051635274afe760e01b81526001600160a01b03841660048201526024015b60405180910390fd5b505050565b60606104d683835f6104dd565b9392505050565b6060814710156105025760405163cd78605960e01b81523060048201526024016104bb565b5f80856001600160a01b0316848660405161051d91906106aa565b5f6040518083038185875af1925050503d805f8114610557576040519150601f19603f3d011682016040523d82523d5f602084013e61055c565b606091505b50909250905061056d868383610577565b9695505050505050565b60608261058c57610587826105d3565b6104d6565b81511580156105a357506001600160a01b0384163b155b156105cc57604051639996b31560e01b81526001600160a01b03851660048201526024016104bb565b50806104d6565b8051156105e35780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b6001600160a01b03811681146105fc575f80fd5b5f805f805f805f60e0888a031215610629575f80fd5b8751610634816105ff565b6020890151909750610645816105ff565b6040890151909650610656816105ff565b6060890151909550610667816105ff565b6080890151909450610678816105ff565b60a0890151909350610689816105ff565b60c089015190925061069a816105ff565b8091505092959891949750929550565b5f82518060208501845e5f920191825250919050565b5f602082840312156106d0575f80fd5b815180151581146104d6575f80fd5b60805160a05160c05160e05161010051610120516101405161016051610180516101a051612a2f6108585f395f81816104df01528181610b5c01528181610bce0152818161100f015281816112a701528181611c590152611fb601525f81816105520152818161077d015281816108a00152818161177d015281816119db01528181611e0101526120c701525f8181610443015281816108ca01528181610b86015281816117580152818161192401528181611c340152611fde01525f81816104910152818161075801528181610bf801528181610fea015281816111f001528181611e2901526120f101525f81816104b80152611a6101525f61082301525f818161034a01526114c001525f818161046a015281816118e601528181611f700152818161218f01526121f801525f818161059f015281816111b201528181611dbb0152818161215b01526121c301525f81816102bd01528181610cb801528181610d0c01528181610d700152610dab0152612a2f5ff3fe608060405234801561000f575f80fd5b5060043610610269575f3560e01c80637f5a7c7b11610157578063b8f6eb8a116100d2578063e6c5f94b11610088578063f2fde38b1161006e578063f2fde38b146105c1578063fc8cdb4b146105d4578063fe472631146105dc575f80fd5b8063e6c5f94b14610587578063ec342ad01461059a575f80fd5b8063d8379d52116100b8578063d8379d521461053a578063e03e9ffd1461054d578063e227999714610574575f80fd5b8063b8f6eb8a14610514578063cc87079914610527575f80fd5b80639c57983911610127578063a7c60f8c1161010d578063a7c60f8c146104b3578063a82a841d146104da578063b03214e114610501575f80fd5b80639c57983914610465578063a1512a2b1461048c575f80fd5b80637f5a7c7b1461040657806383388b32146104195780638da5cb5b1461042c5780639bec62c91461043e575f80fd5b80634d6ee82f116101e7578063713a3ec9116101b757806377bb1eb91161019d57806377bb1eb9146103cd578063791b98bc146103e05780637dc0d1d0146103f3575f80fd5b8063713a3ec9146103925780637398ab18146103a5575f80fd5b80634d6ee82f1461033257806352bcbed81461034557806354ffbf441461036c5780635dea21e71461037f575f80fd5b80632a942db71161023c5780633c47f86e116102225780633c47f86e14610317578063491748341461031f57806349c0e0ba14610280575f80fd5b80632a942db7146102b857806330811b29146102ec575f80fd5b806310d10fac1461026d5780631919f1f8146102825780631fdb1a061461029d57806328286358146102b0575b5f80fd5b61028061027b366004612577565b6105ef565b005b61028a610889565b6040519081526020015b60405180910390f35b6102806102ab36600461258e565b6109a0565b61028a610b45565b6102df7f000000000000000000000000000000000000000000000000000000000000000081565b60405161029491906125d1565b6007546102ff906001600160a01b031681565b6040516001600160a01b039091168152602001610294565b61028a610bb7565b6003546102ff906001600160a01b031681565b61028061034036600461260b565b610c31565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b61028061037a366004612577565b610e84565b61028061038d366004612577565b61109c565b6102806103a03660046126af565b611314565b6103ad6115c0565b604080519485526020850193909352918301526060820152608001610294565b6008546102ff906001600160a01b031681565b6005546102ff906001600160a01b031681565b6006546102ff906001600160a01b031681565b6002546102ff906001600160a01b031681565b610280610427366004612577565b6115f2565b5f546102ff906001600160a01b031681565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b61028061050f366004612577565b6117d0565b6001546102ff906001600160a01b031681565b61028061053536600461274b565b611a08565b610280610548366004612577565b611ad0565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b610280610582366004612577565b611ca3565b610280610595366004612577565b611e58565b6102ff7f000000000000000000000000000000000000000000000000000000000000000081565b6102806105cf366004612775565b61200d565b61028a6120b0565b6004546102ff906001600160a01b031681565b6001546001600160a01b0316331480159061061557506002546001600160a01b03163314155b801561062c57506007546001600160a01b03163314155b801561064357506005546001600160a01b03163314155b156106685760405163cb11855160e01b81523360048201526024015b60405180910390fd5b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106dc9190612790565b60ff16156106fd57604051634e00e51360e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f1990920191018161071357905050604080516080810182526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f00000000000000000000000000000000000000000000000000000000000000001660208201525f818301529051602481018590523360448201529192509060608201906064015b60408051601f198184030181529190526020810180516001600160e01b0316630967fa2960e31b1790529052815182905f90610801576108016127b0565b602090810291909101015260405163305ab9e960e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063c16ae7a4906108589084906004016127c4565b5f604051808303815f87803b15801561086f575f80fd5b505af1158015610881573d5f803e3d5ffd5b505050505050565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f917f0000000000000000000000000000000000000000000000000000000000000000909116906307a2d13a9082906370a08231906024015b602060405180830381865afa15801561091a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061093e9190612883565b6040518263ffffffff1660e01b815260040161095c91815260200190565b602060405180830381865afa158015610977573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099b9190612883565b905090565b6001546001600160a01b031633148015906109c657506002546001600160a01b03163314155b80156109dd57506007546001600160a01b03163314155b80156109f457506005546001600160a01b03163314155b15610a145760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a64573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a889190612790565b60ff16600103610aab5760405163ab35696f60e01b815260040160405180910390fd5b5f841215610abf57610abf61050f8561289a565b5f831215610ad357610ad361038d8461289a565b5f821215610ae757610ae76105828361289a565b5f811215610afb57610afb6105958261289a565b5f841315610b0c57610b0c846115f2565b5f831315610b1d57610b1d83610e84565b5f821315610b2e57610b2e826105ef565b5f811315610b3f57610b3f81611ad0565b50505050565b60405163d283e75f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063d283e75f9060240161095c565b6040516370a0823160e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f917f0000000000000000000000000000000000000000000000000000000000000000909116906307a2d13a9082906370a08231906024016108ff565b5f546001600160a01b03163314610c5d5760405163118cdaa760e01b815233600482015260240161065f565b600180546001600160a01b03808b1673ffffffffffffffffffffffffffffffffffffffff1992831617909255600280548a841690831617905560068054868416908316179055600780549285169290911691909117905560037f00000000000000000000000000000000000000000000000000000000000000006004811115610ce857610ce86125bd565b03610d0857600354610d03906001600160a01b031687612122565b610e24565b60017f00000000000000000000000000000000000000000000000000000000000000006004811115610d3c57610d3c6125bd565b03610d6d57600354610d57906001600160a01b031687612122565b600554610d03906001600160a01b031685612122565b5f7f00000000000000000000000000000000000000000000000000000000000000006004811115610da057610da06125bd565b1480610ddd575060027f00000000000000000000000000000000000000000000000000000000000000006004811115610ddb57610ddb6125bd565b145b15610e2457600354610df8906001600160a01b031687612122565b600454610e0e906001600160a01b031686612122565b600854610e24906001600160a01b031682612122565b600380546001600160a01b0397881673ffffffffffffffffffffffffffffffffffffffff19918216179091556004805496881696821696909617909555600880549187169186169190911790555050600580549190931691161790555050565b6001546001600160a01b03163314801590610eaa57506002546001600160a01b03163314155b8015610ec157506007546001600160a01b03163314155b8015610ed857506005546001600160a01b03163314155b15610ef85760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6c9190612790565b60ff16600103610f8f5760405163ab35696f60e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f19909201910181610fa557905050604080516080810182526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f000000000000000000000000000000000000000000000000000000000000000016602082018190525f82840152915160248101869052336044820152606481019290925291925060608201906084015b60408051601f198184030181529190526020810180516001600160e01b0316632d182be560e21b1790529052815182905f90610801576108016127b0565b6001546001600160a01b031633148015906110c257506002546001600160a01b03163314155b80156110d957506007546001600160a01b03163314155b80156110f057506005546001600160a01b03163314155b156111105760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611160573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111849190612790565b60ff16156111a557604051634e00e51360e01b815260040160405180910390fd5b6111da6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084612220565b6040516363737ac960e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906394bf804d90829063c6e6f59290602401602060405180830381865afa158015611245573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112699190612883565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201526044015b6020604051808303815f875af11580156112ec573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113109190612883565b5050565b5f546001600160a01b031633146113405760405163118cdaa760e01b815233600482015260240161065f565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f929150602082015b60608152602001906001900390816113bc57905050905030845f815181106113e6576113e66127b0565b60200260200101906001600160a01b031690816001600160a01b03168152505087835f81518110611419576114196127b0565b60200260200101906001600160a01b031690816001600160a01b03168152505086825f8151811061144c5761144c6127b0565b6020026020010181815250508585808060200260200160405190810160405280939291908181526020018383602002808284375f92018290525085518694509092501515905061149e5761149e6127b0565b60209081029190910101526040516301c7ba5760e61b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906371ee95c0906114fb908790879087908790600401612903565b5f604051808303815f87803b158015611512575f80fd5b505af1158015611524573d5f803e3d5ffd5b505050506001600160a01b03891630146115b5576040516370a0823160e01b81523060048201526115b5908a906001600160a01b038b16906370a0823190602401602060405180830381865afa158015611580573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115a49190612883565b6001600160a01b038b169190612287565b505050505050505050565b5f805f806115cc610889565b6115d4610bb7565b6115dc6120b0565b6115e4610b45565b935093509350935090919293565b6001546001600160a01b0316331480159061161857506002546001600160a01b03163314155b801561162f57506007546001600160a01b03163314155b801561164657506005546001600160a01b03163314155b156116665760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116da9190612790565b60ff166001036116fd5760405163ab35696f60e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f1990920191018161171357905050604080516080810182526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f000000000000000000000000000000000000000000000000000000000000000016602082018190525f828401529151602481018690523360448201526064810192909252919250606082019060840161105e565b6001546001600160a01b031633148015906117f657506002546001600160a01b03163314155b801561180d57506007546001600160a01b03163314155b801561182457506005546001600160a01b03163314155b156118445760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611894573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b89190612790565b60ff16156118d957604051634e00e51360e01b815260040160405180910390fd5b61190e6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084612220565b6040516363737ac960e11b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906394bf804d90829063c6e6f59290602401602060405180830381865afa158015611979573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199d9190612883565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660248201526044016112d0565b5f546001600160a01b03163314611a345760405163118cdaa760e01b815233600482015260240161065f565b604051631ab27b9560e01b81526001600160a01b03838116600483015260248201839052600160448301527f00000000000000000000000000000000000000000000000000000000000000001690631ab27b95906064016020604051808303815f875af1158015611aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611acb91906129ed565b505050565b6001546001600160a01b03163314801590611af657506002546001600160a01b03163314155b8015611b0d57506007546001600160a01b03163314155b8015611b2457506005546001600160a01b03163314155b15611b445760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bb89190612790565b60ff1615611bd957604051634e00e51360e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f19909201910181611bef57905050604080516080810182526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811682527f00000000000000000000000000000000000000000000000000000000000000001660208201525f818301529051602481018590523360448201529192509060608201906064016107c3565b6001546001600160a01b03163314801590611cc957506002546001600160a01b03163314155b8015611ce057506007546001600160a01b03163314155b8015611cf757506005546001600160a01b03163314155b15611d175760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d8b9190612790565b60ff16600103611dae5760405163ab35696f60e01b815260040160405180910390fd5b611de36001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084612220565b60405163acb7081560e01b8152600481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063acb70815906044016112d0565b6001546001600160a01b03163314801590611e7e57506002546001600160a01b03163314155b8015611e9557506007546001600160a01b03163314155b8015611eac57506005546001600160a01b03163314155b15611ecc5760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f1c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f409190612790565b60ff16600103611f635760405163ab35696f60e01b815260040160405180910390fd5b611f986001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016333084612220565b60405163acb7081560e01b8152600481018290526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660248301527f0000000000000000000000000000000000000000000000000000000000000000169063acb70815906044016112d0565b5f546001600160a01b031633146120395760405163118cdaa760e01b815233600482015260240161065f565b5f546001600160a01b038281169116146120ad575f80546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790555b50565b60405163d283e75f60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000811660048301525f917f00000000000000000000000000000000000000000000000000000000000000009091169063d283e75f9060240161095c565b806001600160a01b0316826001600160a01b03160361213f575050565b6001600160a01b038216156121b6576121826001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016835f6122b8565b6121b66001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016835f6122b8565b6121eb6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016825f196122b8565b6113106001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016825f196122b8565b6040516001600160a01b038481166024830152838116604483015260648201839052610b3f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612343565b6040516001600160a01b03838116602483015260448201839052611acb91859182169063a9059cbb90606401612255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261230984826123a4565b610b3f576040516001600160a01b0384811660248301525f604483015261233d91869182169063095ea7b390606401612255565b610b3f84825b5f6123576001600160a01b03841683612445565b905080515f1415801561237b57508080602001905181019061237991906129ed565b155b15611acb57604051635274afe760e01b81526001600160a01b038416600482015260240161065f565b5f805f846001600160a01b0316846040516123bf9190612a0c565b5f604051808303815f865af19150503d805f81146123f8576040519150601f19603f3d011682016040523d82523d5f602084013e6123fd565b606091505b509150915081801561242757508051158061242757508080602001905181019061242791906129ed565b801561243c57505f856001600160a01b03163b115b95945050505050565b606061245283835f612459565b9392505050565b60608147101561247e5760405163cd78605960e01b815230600482015260240161065f565b5f80856001600160a01b031684866040516124999190612a0c565b5f6040518083038185875af1925050503d805f81146124d3576040519150601f19603f3d011682016040523d82523d5f602084013e6124d8565b606091505b50915091506124e88683836124f2565b9695505050505050565b606082612507576125028261254e565b612452565b815115801561251e57506001600160a01b0384163b155b1561254757604051639996b31560e01b81526001600160a01b038516600482015260240161065f565b5080612452565b80511561255e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f60208284031215612587575f80fd5b5035919050565b5f805f80608085870312156125a1575f80fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b5f52602160045260245ffd5b60208101600583106125f157634e487b7160e01b5f52602160045260245ffd5b91905290565b6001600160a01b03811681146120ad575f80fd5b5f805f805f805f80610100898b031215612623575f80fd5b883561262e816125f7565b9750602089013561263e816125f7565b9650604089013561264e816125f7565b9550606089013561265e816125f7565b9450608089013561266e816125f7565b935060a089013561267e816125f7565b925060c089013561268e816125f7565b915060e089013561269e816125f7565b809150509295985092959890939650565b5f805f805f608086880312156126c3575f80fd5b85356126ce816125f7565b945060208601356126de816125f7565b935060408601359250606086013567ffffffffffffffff811115612700575f80fd5b8601601f81018813612710575f80fd5b803567ffffffffffffffff811115612726575f80fd5b8860208260051b840101111561273a575f80fd5b959894975092955050506020019190565b5f806040838503121561275c575f80fd5b8235612767816125f7565b946020939093013593505050565b5f60208284031215612785575f80fd5b8135612452816125f7565b5f602082840312156127a0575f80fd5b815160ff81168114612452575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561287757603f1987860301845281516001600160a01b0381511686526001600160a01b0360208201511660208701526040810151604087015260608101519050608060608701528051806080880152806020830160a089015e5f60a0828901015260a0601f19601f830116880101965050506020820191506020840193506001810190506127ea565b50929695505050505050565b5f60208284031215612893575f80fd5b5051919050565b5f600160ff1b82016128ba57634e487b7160e01b5f52601160045260245ffd5b505f0390565b5f8151808452602084019350602083015f5b828110156128f95781516001600160a01b03168652602095860195909101906001016128d2565b5093949350505050565b608081525f61291560808301876128c0565b828103602084015261292781876128c0565b8381036040850152855180825260208088019350909101905f5b8181101561295f578351835260209384019390920191600101612941565b50508381036060850152845180825260208083019350600582901b830181019087015f5b838110156129dd57848303601f19018652815180518085526020918201918501905f5b818110156129c45783518352602093840193909201916001016129a6565b5050602097880197909450929092019150600101612983565b50909a9950505050505050505050565b5f602082840312156129fd575f80fd5b81518015158114612452575f80fd5b5f82518060208501845e5f92019182525091905056fea164736f6c634300081a000a000000000000000000000000078d782b760474a361dda0af3839290b0ef57ad600000000000000000000000042000000000000000000000000000000000000060000000000000000000000002a1176964f5d7cae5406b627bf6166664fe83c600000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae0000000000000000000000001b0e3da51b2517e09ae74cd31b708e46b9158e8b
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610269575f3560e01c80637f5a7c7b11610157578063b8f6eb8a116100d2578063e6c5f94b11610088578063f2fde38b1161006e578063f2fde38b146105c1578063fc8cdb4b146105d4578063fe472631146105dc575f80fd5b8063e6c5f94b14610587578063ec342ad01461059a575f80fd5b8063d8379d52116100b8578063d8379d521461053a578063e03e9ffd1461054d578063e227999714610574575f80fd5b8063b8f6eb8a14610514578063cc87079914610527575f80fd5b80639c57983911610127578063a7c60f8c1161010d578063a7c60f8c146104b3578063a82a841d146104da578063b03214e114610501575f80fd5b80639c57983914610465578063a1512a2b1461048c575f80fd5b80637f5a7c7b1461040657806383388b32146104195780638da5cb5b1461042c5780639bec62c91461043e575f80fd5b80634d6ee82f116101e7578063713a3ec9116101b757806377bb1eb91161019d57806377bb1eb9146103cd578063791b98bc146103e05780637dc0d1d0146103f3575f80fd5b8063713a3ec9146103925780637398ab18146103a5575f80fd5b80634d6ee82f1461033257806352bcbed81461034557806354ffbf441461036c5780635dea21e71461037f575f80fd5b80632a942db71161023c5780633c47f86e116102225780633c47f86e14610317578063491748341461031f57806349c0e0ba14610280575f80fd5b80632a942db7146102b857806330811b29146102ec575f80fd5b806310d10fac1461026d5780631919f1f8146102825780631fdb1a061461029d57806328286358146102b0575b5f80fd5b61028061027b366004612577565b6105ef565b005b61028a610889565b6040519081526020015b60405180910390f35b6102806102ab36600461258e565b6109a0565b61028a610b45565b6102df7f000000000000000000000000000000000000000000000000000000000000000481565b60405161029491906125d1565b6007546102ff906001600160a01b031681565b6040516001600160a01b039091168152602001610294565b61028a610bb7565b6003546102ff906001600160a01b031681565b61028061034036600461260b565b610c31565b6102ff7f0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b61028061037a366004612577565b610e84565b61028061038d366004612577565b61109c565b6102806103a03660046126af565b611314565b6103ad6115c0565b604080519485526020850193909352918301526060820152608001610294565b6008546102ff906001600160a01b031681565b6005546102ff906001600160a01b031681565b6006546102ff906001600160a01b031681565b6002546102ff906001600160a01b031681565b610280610427366004612577565b6115f2565b5f546102ff906001600160a01b031681565b6102ff7f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc81565b6102ff7f000000000000000000000000420000000000000000000000000000000000000681565b6102ff7f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba81565b6102ff7f0000000000000000000000001b0e3da51b2517e09ae74cd31b708e46b9158e8b81565b6102ff7f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db381565b61028061050f366004612577565b6117d0565b6001546102ff906001600160a01b031681565b61028061053536600461274b565b611a08565b610280610548366004612577565b611ad0565b6102ff7f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db081565b610280610582366004612577565b611ca3565b610280610595366004612577565b611e58565b6102ff7f000000000000000000000000078d782b760474a361dda0af3839290b0ef57ad681565b6102806105cf366004612775565b61200d565b61028a6120b0565b6004546102ff906001600160a01b031681565b6001546001600160a01b0316331480159061061557506002546001600160a01b03163314155b801561062c57506007546001600160a01b03163314155b801561064357506005546001600160a01b03163314155b156106685760405163cb11855160e01b81523360048201526024015b60405180910390fd5b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106b8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106dc9190612790565b60ff16156106fd57604051634e00e51360e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f1990920191018161071357905050604080516080810182526001600160a01b037f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba811682527f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db01660208201525f818301529051602481018590523360448201529192509060608201906064015b60408051601f198184030181529190526020810180516001600160e01b0316630967fa2960e31b1790529052815182905f90610801576108016127b0565b602090810291909101015260405163305ab9e960e21b81526001600160a01b037f0000000000000000000000002a1176964f5d7cae5406b627bf6166664fe83c60169063c16ae7a4906108589084906004016127c4565b5f604051808303815f87803b15801561086f575f80fd5b505af1158015610881573d5f803e3d5ffd5b505050505050565b6040516370a0823160e01b81526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db0811660048301525f917f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc909116906307a2d13a9082906370a08231906024015b602060405180830381865afa15801561091a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061093e9190612883565b6040518263ffffffff1660e01b815260040161095c91815260200190565b602060405180830381865afa158015610977573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061099b9190612883565b905090565b6001546001600160a01b031633148015906109c657506002546001600160a01b03163314155b80156109dd57506007546001600160a01b03163314155b80156109f457506005546001600160a01b03163314155b15610a145760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a64573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a889190612790565b60ff16600103610aab5760405163ab35696f60e01b815260040160405180910390fd5b5f841215610abf57610abf61050f8561289a565b5f831215610ad357610ad361038d8461289a565b5f821215610ae757610ae76105828361289a565b5f811215610afb57610afb6105958261289a565b5f841315610b0c57610b0c846115f2565b5f831315610b1d57610b1d83610e84565b5f821315610b2e57610b2e826105ef565b5f811315610b3f57610b3f81611ad0565b50505050565b60405163d283e75f60e01b81526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db3811660048301525f917f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc9091169063d283e75f9060240161095c565b6040516370a0823160e01b81526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db3811660048301525f917f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba909116906307a2d13a9082906370a08231906024016108ff565b5f546001600160a01b03163314610c5d5760405163118cdaa760e01b815233600482015260240161065f565b600180546001600160a01b03808b1673ffffffffffffffffffffffffffffffffffffffff1992831617909255600280548a841690831617905560068054868416908316179055600780549285169290911691909117905560037f00000000000000000000000000000000000000000000000000000000000000046004811115610ce857610ce86125bd565b03610d0857600354610d03906001600160a01b031687612122565b610e24565b60017f00000000000000000000000000000000000000000000000000000000000000046004811115610d3c57610d3c6125bd565b03610d6d57600354610d57906001600160a01b031687612122565b600554610d03906001600160a01b031685612122565b5f7f00000000000000000000000000000000000000000000000000000000000000046004811115610da057610da06125bd565b1480610ddd575060027f00000000000000000000000000000000000000000000000000000000000000046004811115610ddb57610ddb6125bd565b145b15610e2457600354610df8906001600160a01b031687612122565b600454610e0e906001600160a01b031686612122565b600854610e24906001600160a01b031682612122565b600380546001600160a01b0397881673ffffffffffffffffffffffffffffffffffffffff19918216179091556004805496881696821696909617909555600880549187169186169190911790555050600580549190931691161790555050565b6001546001600160a01b03163314801590610eaa57506002546001600160a01b03163314155b8015610ec157506007546001600160a01b03163314155b8015610ed857506005546001600160a01b03163314155b15610ef85760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015610f48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f6c9190612790565b60ff16600103610f8f5760405163ab35696f60e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f19909201910181610fa557905050604080516080810182526001600160a01b037f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba811682527f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db316602082018190525f82840152915160248101869052336044820152606481019290925291925060608201906084015b60408051601f198184030181529190526020810180516001600160e01b0316632d182be560e21b1790529052815182905f90610801576108016127b0565b6001546001600160a01b031633148015906110c257506002546001600160a01b03163314155b80156110d957506007546001600160a01b03163314155b80156110f057506005546001600160a01b03163314155b156111105760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611160573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111849190612790565b60ff16156111a557604051634e00e51360e01b815260040160405180910390fd5b6111da6001600160a01b037f000000000000000000000000078d782b760474a361dda0af3839290b0ef57ad616333084612220565b6040516363737ac960e11b8152600481018290527f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba6001600160a01b0316906394bf804d90829063c6e6f59290602401602060405180830381865afa158015611245573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112699190612883565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db31660248201526044015b6020604051808303815f875af11580156112ec573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113109190612883565b5050565b5f546001600160a01b031633146113405760405163118cdaa760e01b815233600482015260240161065f565b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833750506040805160018082528183019092529293505f929150602082015b60608152602001906001900390816113bc57905050905030845f815181106113e6576113e66127b0565b60200260200101906001600160a01b031690816001600160a01b03168152505087835f81518110611419576114196127b0565b60200260200101906001600160a01b031690816001600160a01b03168152505086825f8151811061144c5761144c6127b0565b6020026020010181815250508585808060200260200160405190810160405280939291908181526020018383602002808284375f92018290525085518694509092501515905061149e5761149e6127b0565b60209081029190910101526040516301c7ba5760e61b81526001600160a01b037f0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae16906371ee95c0906114fb908790879087908790600401612903565b5f604051808303815f87803b158015611512575f80fd5b505af1158015611524573d5f803e3d5ffd5b505050506001600160a01b03891630146115b5576040516370a0823160e01b81523060048201526115b5908a906001600160a01b038b16906370a0823190602401602060405180830381865afa158015611580573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115a49190612883565b6001600160a01b038b169190612287565b505050505050505050565b5f805f806115cc610889565b6115d4610bb7565b6115dc6120b0565b6115e4610b45565b935093509350935090919293565b6001546001600160a01b0316331480159061161857506002546001600160a01b03163314155b801561162f57506007546001600160a01b03163314155b801561164657506005546001600160a01b03163314155b156116665760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116b6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116da9190612790565b60ff166001036116fd5760405163ab35696f60e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f1990920191018161171357905050604080516080810182526001600160a01b037f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc811682527f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db016602082018190525f828401529151602481018690523360448201526064810192909252919250606082019060840161105e565b6001546001600160a01b031633148015906117f657506002546001600160a01b03163314155b801561180d57506007546001600160a01b03163314155b801561182457506005546001600160a01b03163314155b156118445760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611894573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b89190612790565b60ff16156118d957604051634e00e51360e01b815260040160405180910390fd5b61190e6001600160a01b037f000000000000000000000000420000000000000000000000000000000000000616333084612220565b6040516363737ac960e11b8152600481018290527f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc6001600160a01b0316906394bf804d90829063c6e6f59290602401602060405180830381865afa158015611979573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061199d9190612883565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815260048101919091526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db01660248201526044016112d0565b5f546001600160a01b03163314611a345760405163118cdaa760e01b815233600482015260240161065f565b604051631ab27b9560e01b81526001600160a01b03838116600483015260248201839052600160448301527f0000000000000000000000001b0e3da51b2517e09ae74cd31b708e46b9158e8b1690631ab27b95906064016020604051808303815f875af1158015611aa7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611acb91906129ed565b505050565b6001546001600160a01b03163314801590611af657506002546001600160a01b03163314155b8015611b0d57506007546001600160a01b03163314155b8015611b2457506005546001600160a01b03163314155b15611b445760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611b94573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611bb89190612790565b60ff1615611bd957604051634e00e51360e01b815260040160405180910390fd5b6040805160018082528183019092525f91816020015b604080516080810182525f80825260208083018290529282015260608082015282525f19909201910181611bef57905050604080516080810182526001600160a01b037f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc811682527f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db31660208201525f818301529051602481018590523360448201529192509060608201906064016107c3565b6001546001600160a01b03163314801590611cc957506002546001600160a01b03163314155b8015611ce057506007546001600160a01b03163314155b8015611cf757506005546001600160a01b03163314155b15611d175760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d8b9190612790565b60ff16600103611dae5760405163ab35696f60e01b815260040160405180910390fd5b611de36001600160a01b037f000000000000000000000000078d782b760474a361dda0af3839290b0ef57ad616333084612220565b60405163acb7081560e01b8152600481018290526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db0811660248301527f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba169063acb70815906044016112d0565b6001546001600160a01b03163314801590611e7e57506002546001600160a01b03163314155b8015611e9557506007546001600160a01b03163314155b8015611eac57506005546001600160a01b03163314155b15611ecc5760405163cb11855160e01b815233600482015260240161065f565b60015f9054906101000a90046001600160a01b03166001600160a01b031663200d2ed26040518163ffffffff1660e01b8152600401602060405180830381865afa158015611f1c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f409190612790565b60ff16600103611f635760405163ab35696f60e01b815260040160405180910390fd5b611f986001600160a01b037f000000000000000000000000420000000000000000000000000000000000000616333084612220565b60405163acb7081560e01b8152600481018290526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db3811660248301527f0000000000000000000000001f3134c3f3f8add904b9635acbefc0ea0d0e1ffc169063acb70815906044016112d0565b5f546001600160a01b031633146120395760405163118cdaa760e01b815233600482015260240161065f565b5f546001600160a01b038281169116146120ad575f80546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a35f805473ffffffffffffffffffffffffffffffffffffffff19166001600160a01b0383161790555b50565b60405163d283e75f60e01b81526001600160a01b037f00000000000000000000000098bef40722b21382c3389b72f16f9b79ceda8db0811660048301525f917f0000000000000000000000006eae95ee783e4d862867c4e0e4c3f4b95aa682ba9091169063d283e75f9060240161095c565b806001600160a01b0316826001600160a01b03160361213f575050565b6001600160a01b038216156121b6576121826001600160a01b037f000000000000000000000000078d782b760474a361dda0af3839290b0ef57ad616835f6122b8565b6121b66001600160a01b037f000000000000000000000000420000000000000000000000000000000000000616835f6122b8565b6121eb6001600160a01b037f000000000000000000000000078d782b760474a361dda0af3839290b0ef57ad616825f196122b8565b6113106001600160a01b037f000000000000000000000000420000000000000000000000000000000000000616825f196122b8565b6040516001600160a01b038481166024830152838116604483015260648201839052610b3f9186918216906323b872dd906084015b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050612343565b6040516001600160a01b03838116602483015260448201839052611acb91859182169063a9059cbb90606401612255565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261230984826123a4565b610b3f576040516001600160a01b0384811660248301525f604483015261233d91869182169063095ea7b390606401612255565b610b3f84825b5f6123576001600160a01b03841683612445565b905080515f1415801561237b57508080602001905181019061237991906129ed565b155b15611acb57604051635274afe760e01b81526001600160a01b038416600482015260240161065f565b5f805f846001600160a01b0316846040516123bf9190612a0c565b5f604051808303815f865af19150503d805f81146123f8576040519150601f19603f3d011682016040523d82523d5f602084013e6123fd565b606091505b509150915081801561242757508051158061242757508080602001905181019061242791906129ed565b801561243c57505f856001600160a01b03163b115b95945050505050565b606061245283835f612459565b9392505050565b60608147101561247e5760405163cd78605960e01b815230600482015260240161065f565b5f80856001600160a01b031684866040516124999190612a0c565b5f6040518083038185875af1925050503d805f81146124d3576040519150601f19603f3d011682016040523d82523d5f602084013e6124d8565b606091505b50915091506124e88683836124f2565b9695505050505050565b606082612507576125028261254e565b612452565b815115801561251e57506001600160a01b0384163b155b1561254757604051639996b31560e01b81526001600160a01b038516600482015260240161065f565b5080612452565b80511561255e5780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f60208284031215612587575f80fd5b5035919050565b5f805f80608085870312156125a1575f80fd5b5050823594602084013594506040840135936060013592509050565b634e487b7160e01b5f52602160045260245ffd5b60208101600583106125f157634e487b7160e01b5f52602160045260245ffd5b91905290565b6001600160a01b03811681146120ad575f80fd5b5f805f805f805f80610100898b031215612623575f80fd5b883561262e816125f7565b9750602089013561263e816125f7565b9650604089013561264e816125f7565b9550606089013561265e816125f7565b9450608089013561266e816125f7565b935060a089013561267e816125f7565b925060c089013561268e816125f7565b915060e089013561269e816125f7565b809150509295985092959890939650565b5f805f805f608086880312156126c3575f80fd5b85356126ce816125f7565b945060208601356126de816125f7565b935060408601359250606086013567ffffffffffffffff811115612700575f80fd5b8601601f81018813612710575f80fd5b803567ffffffffffffffff811115612726575f80fd5b8860208260051b840101111561273a575f80fd5b959894975092955050506020019190565b5f806040838503121561275c575f80fd5b8235612767816125f7565b946020939093013593505050565b5f60208284031215612785575f80fd5b8135612452816125f7565b5f602082840312156127a0575f80fd5b815160ff81168114612452575f80fd5b634e487b7160e01b5f52603260045260245ffd5b5f602082016020835280845180835260408501915060408160051b8601019250602086015f5b8281101561287757603f1987860301845281516001600160a01b0381511686526001600160a01b0360208201511660208701526040810151604087015260608101519050608060608701528051806080880152806020830160a089015e5f60a0828901015260a0601f19601f830116880101965050506020820191506020840193506001810190506127ea565b50929695505050505050565b5f60208284031215612893575f80fd5b5051919050565b5f600160ff1b82016128ba57634e487b7160e01b5f52601160045260245ffd5b505f0390565b5f8151808452602084019350602083015f5b828110156128f95781516001600160a01b03168652602095860195909101906001016128d2565b5093949350505050565b608081525f61291560808301876128c0565b828103602084015261292781876128c0565b8381036040850152855180825260208088019350909101905f5b8181101561295f578351835260209384019390920191600101612941565b50508381036060850152845180825260208083019350600582901b830181019087015f5b838110156129dd57848303601f19018652815180518085526020918201918501905f5b818110156129c45783518352602093840193909201916001016129a6565b5050602097880197909450929092019150600101612983565b50909a9950505050505050505050565b5f602082840312156129fd575f80fd5b81518015158114612452575f80fd5b5f82518060208501845e5f92019182525091905056fea164736f6c634300081a000a
Net Worth in USD
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.