Feature Tip: Add private address tag to any address under My Name Tag !
Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x61127e61 | 22174723 | 355 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CurveV2FactoryCryptoAdapter
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import { ICurveStableSwapNG } from "src/interfaces/external/curve/ICurveStableSwapNG.sol";
import { ICryptoSwapPool, IPool } from "src/interfaces/external/curve/ICryptoSwapPool.sol";
import { IWETH9 } from "src/interfaces/utils/IWETH9.sol";
import { LibAdapter } from "src/libs/LibAdapter.sol";
import { Errors } from "src/utils/Errors.sol";
//slither-disable-start similar-names
library CurveV2FactoryCryptoAdapter {
event WithdrawLiquidity(
uint256[] amountsWithdrawn,
address[] tokens,
// 0 - lpBurnAmount
// 1 - lpShare
// 2 - lpTotalSupply
uint256[3] lpAmounts,
address poolAddress
);
function removeLiquidity(
uint256[] memory amounts,
uint256 maxLpBurnAmount,
address poolAddress,
address lpTokenAddress,
IWETH9 weth
) public returns (address[] memory, uint256[] memory) {
return removeLiquidity(amounts, maxLpBurnAmount, poolAddress, lpTokenAddress, weth, false);
}
/**
* @notice Withdraw liquidity from Curve pool
* @dev Calls to external contract
* @dev We trust sender to send a true Curve poolAddress.
* If it's not the case it will fail in the remove_liquidity_one_coin part
* @param amounts Minimum amounts of coin to receive
* @param maxLpBurnAmount Amount of LP tokens to burn in the withdrawal
* @param poolAddress Curve pool address
* @param lpTokenAddress LP token of the pool to burn
* @param weth WETH address on the operating chain
* @param isNg is a newer ng pool with dynamic arrays
* @return tokens Addresses of the withdrawn tokens
* @return actualAmounts Amounts of the withdrawn tokens
*/
function removeLiquidity(
uint256[] memory amounts,
uint256 maxLpBurnAmount,
address poolAddress,
address lpTokenAddress,
IWETH9 weth,
bool isNg
) public returns (address[] memory tokens, uint256[] memory actualAmounts) {
//slither-disable-start reentrancy-events
if (amounts.length > 4) {
revert Errors.InvalidParam("amounts");
}
Errors.verifyNotZero(maxLpBurnAmount, "maxLpBurnAmount");
Errors.verifyNotZero(poolAddress, "poolAddress");
Errors.verifyNotZero(lpTokenAddress, "lpTokenAddress");
Errors.verifyNotZero(address(weth), "weth");
uint256[] memory coinsBalancesBefore = new uint256[](amounts.length);
tokens = new address[](amounts.length);
uint256 ethIndex = 999;
for (uint256 i = 0; i < amounts.length; ++i) {
address coin = IPool(poolAddress).coins(i);
tokens[i] = coin;
if (coin == LibAdapter.CURVE_REGISTRY_ETH_ADDRESS_POINTER) {
coinsBalancesBefore[i] = address(this).balance;
ethIndex = i;
} else {
tokens[i] = coin;
coinsBalancesBefore[i] = IERC20(coin).balanceOf(address(this));
}
}
uint256 lpTokenBalanceBefore = IERC20(lpTokenAddress).balanceOf(address(this));
_runWithdrawal(poolAddress, amounts, maxLpBurnAmount, isNg);
uint256 lpTokenBalanceAfter = IERC20(lpTokenAddress).balanceOf(address(this));
uint256 lpTokenAmount = lpTokenBalanceBefore - lpTokenBalanceAfter;
if (lpTokenAmount > maxLpBurnAmount) {
revert LibAdapter.LpTokenAmountMismatch();
}
actualAmounts = _compareCoinsBalances(
coinsBalancesBefore, _getCoinsBalances(tokens, weth, ethIndex != 999 ? true : false), amounts, false
);
if (ethIndex != 999) {
// Wrapping up received ETH as system operates with WETH
// slither-disable-next-line arbitrary-send-eth
weth.deposit{ value: actualAmounts[ethIndex] }();
}
_updateWethAddress(tokens, address(weth));
emit WithdrawLiquidity(
actualAmounts,
tokens,
[lpTokenAmount, lpTokenBalanceAfter, IERC20(lpTokenAddress).totalSupply()],
poolAddress
);
//slither-disable-end reentrancy-events
}
/**
* @dev This is a helper function to replace Curve's Registry pointer
* to ETH with WETH address to be compatible with the rest of the system
*/
function _updateWethAddress(address[] memory tokens, address weth) private pure {
for (uint256 i = 0; i < tokens.length; ++i) {
if (tokens[i] == LibAdapter.CURVE_REGISTRY_ETH_ADDRESS_POINTER) {
tokens[i] = weth;
}
}
}
/// @dev Gets balances of pool's ERC-20 tokens or ETH
function _getCoinsBalances(
address[] memory tokens,
IWETH9 weth,
bool useEth
) private view returns (uint256[] memory coinsBalances) {
uint256 nTokens = tokens.length;
coinsBalances = new uint256[](nTokens);
for (uint256 i = 0; i < nTokens; ++i) {
address coin = tokens[i];
if (coin == LibAdapter.CURVE_REGISTRY_ETH_ADDRESS_POINTER) {
coinsBalances[i] = useEth ? address(this).balance : weth.balanceOf(address(this));
} else {
coinsBalances[i] = IERC20(coin).balanceOf(address(this));
}
}
}
/// @dev Validate to have a valid balance change
function _compareCoinsBalances(
uint256[] memory balancesBefore,
uint256[] memory balancesAfter,
uint256[] memory amounts,
bool isLiqDeployment
) private pure returns (uint256[] memory balanceChange) {
uint256 nTokens = amounts.length;
balanceChange = new uint256[](nTokens);
for (uint256 i = 0; i < nTokens; ++i) {
uint256 balanceDiff =
isLiqDeployment ? balancesBefore[i] - balancesAfter[i] : balancesAfter[i] - balancesBefore[i];
if (balanceDiff < amounts[i]) {
revert LibAdapter.InvalidBalanceChange();
}
balanceChange[i] = balanceDiff;
}
}
function _runWithdrawal(
address poolAddress,
uint256[] memory amounts,
uint256 maxLpBurnAmount,
bool isNg
) private {
if (isNg) {
ICurveStableSwapNG pool = ICurveStableSwapNG(poolAddress);
// slither-disable-next-line unused-return
pool.remove_liquidity(maxLpBurnAmount, amounts);
} else {
uint256 nTokens = amounts.length;
ICryptoSwapPool pool = ICryptoSwapPool(poolAddress);
if (nTokens == 2) {
uint256[2] memory staticParamArray = [amounts[0], amounts[1]];
pool.remove_liquidity(maxLpBurnAmount, staticParamArray);
} else if (nTokens == 3) {
uint256[3] memory staticParamArray = [amounts[0], amounts[1], amounts[2]];
pool.remove_liquidity(maxLpBurnAmount, staticParamArray);
} else if (nTokens == 4) {
uint256[4] memory staticParamArray = [amounts[0], amounts[1], amounts[2], amounts[3]];
pool.remove_liquidity(maxLpBurnAmount, staticParamArray);
}
}
}
//slither-disable-end similar-names
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @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 amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
// solhint-disable var-name-mixedcase,func-name-mixedcase
/// @notice Interface for next generation Curve pool oracle functionality.
interface ICurveStableSwapNG {
/// @notice Returns current price in pool.
function price_oracle() external view returns (uint256);
function add_liquidity(uint256[] memory amounts, uint256 min_mint_amount) external payable returns (uint256);
function remove_liquidity(uint256 amount, uint256[] memory min_amounts) external returns (uint256[] memory);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IPool } from "src/interfaces/external/curve/IPool.sol";
/* solhint-disable func-name-mixedcase, var-name-mixedcase */
interface ICryptoSwapPool is IPool {
function token() external returns (address);
// slither-disable-start naming-convention
function add_liquidity(uint256[2] memory amounts, uint256 min_mint_amount) external payable returns (uint256);
function add_liquidity(uint256[3] memory amounts, uint256 min_mint_amount) external payable returns (uint256);
function add_liquidity(uint256[4] memory amounts, uint256 min_mint_amount) external payable returns (uint256);
function remove_liquidity(uint256 amount, uint256[2] memory min_amounts) external;
function remove_liquidity(uint256 amount, uint256[3] memory min_amounts) external;
function remove_liquidity(uint256 amount, uint256[4] memory min_amounts) external;
function remove_liquidity_one_coin(uint256 token_amount, uint256 i, uint256 min_amount) external;
// slither-disable-end naming-convention
function get_virtual_price() external returns (uint256);
function claim_admin_fees() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol";
interface IWETH9 is IERC20 {
function symbol() external view returns (string memory);
function deposit() external payable;
function withdraw(
uint256 amount
) external;
}// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { IERC20 } from "openzeppelin-contracts/token/ERC20/IERC20.sol";
import { SafeERC20 } from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
library LibAdapter {
using SafeERC20 for IERC20;
address public constant CURVE_REGISTRY_ETH_ADDRESS_POINTER = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
error MinLpAmountNotReached();
error LpTokenAmountMismatch();
error NoNonZeroAmountProvided();
error InvalidBalanceChange();
// Utils
function _approve(IERC20 token, address spender, uint256 amount) internal {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance > 0) {
token.safeDecreaseAllowance(spender, currentAllowance);
}
token.safeIncreaseAllowance(spender, amount);
}
}// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
import { Address } from "openzeppelin-contracts/utils/Address.sol";
import { ISystemComponent } from "src/interfaces/ISystemComponent.sol";
// solhint-disable max-line-length
library Errors {
using Address for address;
///////////////////////////////////////////////////////////////////
// Set errors
///////////////////////////////////////////////////////////////////
error AccessDenied();
error ZeroAddress(string paramName);
error ZeroAmount();
error InsufficientBalance(address token);
error AssetNotAllowed(address token);
error NotImplemented();
error InvalidAddress(address addr);
error InvalidParam(string paramName);
error InvalidParams();
error UnsafePrice(address token, uint256 spotPrice, uint256 safePrice);
error AlreadySet(string param);
error AlreadyRegistered(address param);
error SlippageExceeded(uint256 expected, uint256 actual);
error ArrayLengthMismatch(uint256 length1, uint256 length2, string details);
error ItemNotFound();
error ItemExists();
error MissingRole(bytes32 role, address user);
error RegistryItemMissing(string item);
error NotRegistered();
// Used to check storage slot is empty before setting.
error MustBeZero();
// Used to check storage slot set before deleting.
error MustBeSet();
error ApprovalFailed(address token);
error FlashLoanFailed(address token, uint256 amount);
error SystemMismatch(address source1, address source2);
error InvalidToken(address token);
error UnreachableError();
error InvalidSigner(address signer);
error InvalidChainId(uint256 chainId);
error SenderMismatch(address recipient, address sender);
error UnsupportedMessage(bytes32 messageType, bytes message);
error NotSupported();
error InvalidConfiguration();
error InvalidDataReturned();
function verifyNotZero(address addr, string memory paramName) internal pure {
if (addr == address(0)) {
revert ZeroAddress(paramName);
}
}
function verifyNotZero(bytes32 key, string memory paramName) internal pure {
if (key == bytes32(0)) {
revert InvalidParam(paramName);
}
}
function verifyNotEmpty(string memory val, string memory paramName) internal pure {
if (bytes(val).length == 0) {
revert InvalidParam(paramName);
}
}
function verifyNotZero(uint256 num, string memory paramName) internal pure {
if (num == 0) {
revert InvalidParam(paramName);
}
}
function verifySystemsMatch(address component1, address component2) internal view {
address registry1 =
abi.decode(component1.functionStaticCall(abi.encodeCall(ISystemComponent.getSystemRegistry, ())), (address));
address registry2 =
abi.decode(component2.functionStaticCall(abi.encodeCall(ISystemComponent.getSystemRegistry, ())), (address));
if (registry1 != registry2) {
revert SystemMismatch(component1, component2);
}
}
function verifyArrayLengths(uint256 length1, uint256 length2, string memory details) internal pure {
if (length1 != length2) {
revert ArrayLengthMismatch(length1, length2, details);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
//slither-disable-next-line name-reused
interface IPool {
function coins(
uint256 i
) external view returns (address);
function balances(
uint256 i
) external view returns (uint256);
// These method used for cases when Pool is a LP token at the same time
function balanceOf(
address account
) external returns (uint256);
// These method used for cases when Pool is a LP token at the same time
function totalSupply() external returns (uint256);
// solhint-disable func-name-mixedcase
function lp_token() external returns (address);
function token() external returns (address);
function gamma() external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../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;
function safeTransfer(
IERC20 token,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value
) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(
IERC20 token,
address spender,
uint256 value
) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
uint256 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
function safeDecreaseAllowance(
IERC20 token,
address spender,
uint256 value
) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @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, "SafeERC20: low-level call failed");
if (returndata.length > 0) {
// Return data is optional
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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, it is bubbled up by this
* function (like regular Solidity function calls).
*
* 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.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @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`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// 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(errorMessage);
}
}
}// SPDX-License-Identifier: UNLICENSED
// Copyright (c) 2023 Tokemak Foundation. All rights reserved.
pragma solidity ^0.8.24;
/// @notice Stores a reference to the registry for this system
interface ISystemComponent {
/// @notice The system instance this contract is tied to
function getSystemRegistry() external view returns (address registry);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @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.
*/
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].
*/
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);
}{
"remappings": [
"forge-std/=lib/forge-std/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"src/=src/",
"test/=test/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"erc4626-tests/=lib/erc4626-tests/",
"prb-math/=lib/prb-math/",
"crytic/properties/=lib/properties/",
"redstone-finance/=lib/redstone-evm-connector/packages/evm-connector/contracts/",
"ERC4626/=lib/properties/lib/ERC4626/contracts/",
"properties/=lib/properties/contracts/",
"redstone-evm-connector/=lib/redstone-evm-connector/",
"solmate/=lib/properties/lib/solmate/src/",
"usingtellor/=lib/usingtellor/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false,
"libraries": {
"src/destinations/adapters/BalancerBeethovenAdapter.sol": {
"BalancerBeethovenAdapter": "0x70B8181DfD58218578f8005Fc900d04B9F34BeEd"
},
"src/destinations/adapters/BalancerV3Adapter.sol": {
"BalancerV3Adapter": "0x3e5e2EB6cd218A6c0d60585928C7fF06b120b684"
},
"src/destinations/adapters/CurveV2FactoryCryptoAdapter.sol": {
"CurveV2FactoryCryptoAdapter": "0xC795A503140A4A2e73696bcdeba7b0CC3Fe3bf1e"
},
"src/destinations/adapters/rewards/AuraRewardsAdapter.sol": {
"AuraRewards": "0x0bBF2D0AC8e7b1c3bea6E9E3A07C5033FbfC25BE"
},
"src/destinations/adapters/rewards/ConvexRewardsAdapter.sol": {
"ConvexRewards": "0x31B16977409A1a386429D8de4692D51e4f815FE5"
},
"src/destinations/adapters/rewards/CurveRewardsAdapter.sol": {
"CurveRewardsAdapter": "0xb01b7CED7CeC09b8fC9eb7Bfcb631460e181Fdde"
},
"src/destinations/adapters/staking/AuraAdapter.sol": {
"AuraStaking": "0x09bd39525A60C9460Aad8602Bd50d9D31EFb39B0"
},
"src/destinations/adapters/staking/ConvexAdapter.sol": {
"ConvexStaking": "0xeA31d2Ae0E9f68f26343EDe51Afda312ff4B2620"
},
"src/destinations/adapters/staking/CurveGaugeAdapter.sol": {
"CurveGaugeStaking": "0xc66e319e82987382162D75f6Fd163Ca95a639f6f"
},
"src/libs/BalancerUtilities.sol": {
"BalancerUtilities": "0x58570c8501360179A22bFe862e1fCde471693950"
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"InvalidBalanceChange","type":"error"},{"inputs":[{"internalType":"string","name":"paramName","type":"string"}],"name":"InvalidParam","type":"error"},{"inputs":[],"name":"LpTokenAmountMismatch","type":"error"},{"inputs":[{"internalType":"string","name":"paramName","type":"string"}],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256[]","name":"amountsWithdrawn","type":"uint256[]"},{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"},{"indexed":false,"internalType":"uint256[3]","name":"lpAmounts","type":"uint256[3]"},{"indexed":false,"internalType":"address","name":"poolAddress","type":"address"}],"name":"WithdrawLiquidity","type":"event"}]Contract Creation Code
61127e610035600b8282823980515f1a60731461002957634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061003f575f3560e01c8063a60ca28f14610043578063c0dba33d14610079575b5f80fd5b81801561004e575f80fd5b5061006261005d366004610dfc565b610098565b604051610070929190610e8d565b60405180910390f35b818015610084575f80fd5b50610062610093366004610f0f565b61062e565b6060806004885111156100dd57604051634389d5ab60e01b8152602060048201526007602482015266616d6f756e747360c81b60448201526064015b60405180910390fd5b61010e876040518060400160405280600f81526020016e1b585e131c109d5c9b905b5bdd5b9d608a1b81525061064d565b61013b866040518060400160405280600b81526020016a706f6f6c4164647265737360a81b815250610673565b61016b856040518060400160405280600e81526020016d6c70546f6b656e4164647265737360901b815250610673565b61019184604051806040016040528060048152602001630eecae8d60e31b815250610673565b5f885167ffffffffffffffff8111156101ac576101ac610d11565b6040519080825280602002602001820160405280156101d5578160200160208202803683370190505b509050885167ffffffffffffffff8111156101f2576101f2610d11565b60405190808252806020026020018201604052801561021b578160200160208202803683370190505b5092506103e75f5b8a518110156103b45760405163c661065760e01b8152600481018290525f906001600160a01b038b169063c661065790602401602060405180830381865afa158015610271573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102959190610f8b565b9050808683815181106102aa576102aa610fad565b6001600160a01b039283166020918202929092010152811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed190161030457478483815181106102f0576102f0610fad565b6020026020010181815250508192506103ab565b8086838151811061031757610317610fad565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b8152306004820152908216906370a0823190602401602060405180830381865afa158015610368573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038c9190610fc1565b84838151811061039e5761039e610fad565b6020026020010181815250505b50600101610223565b506040516370a0823160e01b81523060048201525f906001600160a01b038916906370a0823190602401602060405180830381865afa1580156103f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041d9190610fc1565b905061042b898c8c8961069c565b6040516370a0823160e01b81523060048201525f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561046f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104939190610fc1565b90505f6104a08284610fd8565b90508b8111156104c3576040516317a3bae160e01b815260040160405180910390fd5b6104e9856104e2898c886103e7036104db575f61096d565b600161096d565b8f5f610b37565b9550836103e71461055e57886001600160a01b031663d0e30db087868151811061051557610515610fad565b60200260200101516040518263ffffffff1660e01b81526004015f604051808303818588803b158015610546575f80fd5b505af1158015610558573d5f803e3d5ffd5b50505050505b610568878a610c7f565b7f07b152336751ce779bdbb95a34344ac86aa8c4505d996446a3ea19e15193fb01868860405180606001604052808581526020018681526020018e6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106029190610fc1565b8152508e6040516106169493929190611059565b60405180910390a15050505050965096945050505050565b60608061063f87878787875f610098565b915091509550959350505050565b815f0361066f5780604051634389d5ab60e01b81526004016100d491906110d9565b5050565b6001600160a01b03821661066f578060405163eac0d38960e01b81526004016100d491906110d9565b801561071b5760405163350376e360e21b815284906001600160a01b0382169063d40ddb8c906106d29086908890600401611125565b5f604051808303815f875af11580156106ed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107149190810190611145565b5050610967565b82518460028290036107d3575f6040518060400160405280875f8151811061074557610745610fad565b602002602001015181526020018760018151811061076557610765610fad565b60200260200101518152509050816001600160a01b0316635b36389c86836040518363ffffffff1660e01b81526004016107a09291906111d1565b5f604051808303815f87803b1580156107b7575f80fd5b505af11580156107c9573d5f803e3d5ffd5b5050505050610964565b81600303610874575f6040518060600160405280875f815181106107f9576107f9610fad565b602002602001015181526020018760018151811061081957610819610fad565b602002602001015181526020018760028151811061083957610839610fad565b60200260200101518152509050816001600160a01b031663ecb586a586836040518363ffffffff1660e01b81526004016107a0929190611208565b81600403610964575f6040518060800160405280875f8151811061089a5761089a610fad565b60200260200101518152602001876001815181106108ba576108ba610fad565b60200260200101518152602001876002815181106108da576108da610fad565b60200260200101518152602001876003815181106108fa576108fa610fad565b60200260200101518152509050816001600160a01b0316637d49d87586836040518363ffffffff1660e01b815260040161093592919061121c565b5f604051808303815f87803b15801561094c575f80fd5b505af115801561095e573d5f803e3d5ffd5b50505050505b50505b50505050565b82516060908067ffffffffffffffff81111561098b5761098b610d11565b6040519080825280602002602001820160405280156109b4578160200160208202803683370190505b5091505f5b81811015610b2e575f8682815181106109d4576109d4610fad565b6020026020010151905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316816001600160a01b031603610aa05784610a7b576040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa158015610a52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a769190610fc1565b610a7d565b475b848381518110610a8f57610a8f610fad565b602002602001018181525050610b25565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa158015610ae2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b069190610fc1565b848381518110610b1857610b18610fad565b6020026020010181815250505b506001016109b9565b50509392505050565b81516060908067ffffffffffffffff811115610b5557610b55610d11565b604051908082528060200260200182016040528015610b7e578160200160208202803683370190505b5091505f5b81811015610c75575f84610bd457878281518110610ba357610ba3610fad565b6020026020010151878381518110610bbd57610bbd610fad565b6020026020010151610bcf9190610fd8565b610c12565b868281518110610be657610be6610fad565b6020026020010151888381518110610c0057610c00610fad565b6020026020010151610c129190610fd8565b9050858281518110610c2657610c26610fad565b6020026020010151811015610c4e57604051634f83730b60e01b815260040160405180910390fd5b80848381518110610c6157610c61610fad565b602090810291909101015250600101610b83565b5050949350505050565b5f5b8251811015610d0c5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316838281518110610cba57610cba610fad565b60200260200101516001600160a01b031603610d045781838281518110610ce357610ce3610fad565b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101610c81565b505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610d4e57610d4e610d11565b604052919050565b5f67ffffffffffffffff821115610d6f57610d6f610d11565b5060051b60200190565b5f82601f830112610d88575f80fd5b81356020610d9d610d9883610d56565b610d25565b8083825260208201915060208460051b870101935086841115610dbe575f80fd5b602086015b84811015610dda5780358352918301918301610dc3565b509695505050505050565b6001600160a01b0381168114610df9575f80fd5b50565b5f805f805f8060c08789031215610e11575f80fd5b863567ffffffffffffffff811115610e27575f80fd5b610e3389828a01610d79565b965050602087013594506040870135610e4b81610de5565b93506060870135610e5b81610de5565b92506080870135610e6b81610de5565b915060a08701358015158114610e7f575f80fd5b809150509295509295509295565b604080825283519082018190525f906020906060840190828701845b82811015610ece5781516001600160a01b031684529284019290840190600101610ea9565b505050838103828501528451808252858301918301905f5b81811015610f0257835183529284019291840191600101610ee6565b5090979650505050505050565b5f805f805f60a08688031215610f23575f80fd5b853567ffffffffffffffff811115610f39575f80fd5b610f4588828901610d79565b955050602086013593506040860135610f5d81610de5565b92506060860135610f6d81610de5565b91506080860135610f7d81610de5565b809150509295509295909350565b5f60208284031215610f9b575f80fd5b8151610fa681610de5565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610fd1575f80fd5b5051919050565b81810381811115610ff757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f815180845260208085019450602084015f5b8381101561102c57815187529582019590820190600101611010565b509495945050505050565b805f5b600381101561096757815184526020938401939091019060010161103a565b60c081525f61106b60c0830187610ffd565b8281036020848101919091528651808352878201928201905f5b818110156110aa5784516001600160a01b031683529383019391830191600101611085565b50508093505050506110bf6040830185611037565b6001600160a01b039290921660a091909101529392505050565b5f602080835283518060208501525f5b81811015611105578581018301518582016040015282016110e9565b505f604082860101526040601f19601f8301168501019250505092915050565b828152604060208201525f61113d6040830184610ffd565b949350505050565b5f6020808385031215611156575f80fd5b825167ffffffffffffffff81111561116c575f80fd5b8301601f8101851361117c575f80fd5b805161118a610d9882610d56565b81815260059190911b820183019083810190878311156111a8575f80fd5b928401925b828410156111c6578351825292840192908401906111ad565b979650505050505050565b828152606081016020808301845f5b60028110156111fd578151835291830191908301906001016111e0565b505050509392505050565b82815260808101610fa66020830184611037565b82815260a081016020808301845f5b60048110156111fd5781518352918301919083019060010161122b56fea26469706673582212201057d4d1627b4a9f1ea94ccecd64f2fbaa13925c787ecb4a95eca1d67c255e5e64736f6c63430008180033
Deployed Bytecode
0x73c795a503140a4a2e73696bcdeba7b0cc3fe3bf1e301460806040526004361061003f575f3560e01c8063a60ca28f14610043578063c0dba33d14610079575b5f80fd5b81801561004e575f80fd5b5061006261005d366004610dfc565b610098565b604051610070929190610e8d565b60405180910390f35b818015610084575f80fd5b50610062610093366004610f0f565b61062e565b6060806004885111156100dd57604051634389d5ab60e01b8152602060048201526007602482015266616d6f756e747360c81b60448201526064015b60405180910390fd5b61010e876040518060400160405280600f81526020016e1b585e131c109d5c9b905b5bdd5b9d608a1b81525061064d565b61013b866040518060400160405280600b81526020016a706f6f6c4164647265737360a81b815250610673565b61016b856040518060400160405280600e81526020016d6c70546f6b656e4164647265737360901b815250610673565b61019184604051806040016040528060048152602001630eecae8d60e31b815250610673565b5f885167ffffffffffffffff8111156101ac576101ac610d11565b6040519080825280602002602001820160405280156101d5578160200160208202803683370190505b509050885167ffffffffffffffff8111156101f2576101f2610d11565b60405190808252806020026020018201604052801561021b578160200160208202803683370190505b5092506103e75f5b8a518110156103b45760405163c661065760e01b8152600481018290525f906001600160a01b038b169063c661065790602401602060405180830381865afa158015610271573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102959190610f8b565b9050808683815181106102aa576102aa610fad565b6001600160a01b039283166020918202929092010152811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed190161030457478483815181106102f0576102f0610fad565b6020026020010181815250508192506103ab565b8086838151811061031757610317610fad565b6001600160a01b0392831660209182029290920101526040516370a0823160e01b8152306004820152908216906370a0823190602401602060405180830381865afa158015610368573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061038c9190610fc1565b84838151811061039e5761039e610fad565b6020026020010181815250505b50600101610223565b506040516370a0823160e01b81523060048201525f906001600160a01b038916906370a0823190602401602060405180830381865afa1580156103f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061041d9190610fc1565b905061042b898c8c8961069c565b6040516370a0823160e01b81523060048201525f906001600160a01b038a16906370a0823190602401602060405180830381865afa15801561046f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104939190610fc1565b90505f6104a08284610fd8565b90508b8111156104c3576040516317a3bae160e01b815260040160405180910390fd5b6104e9856104e2898c886103e7036104db575f61096d565b600161096d565b8f5f610b37565b9550836103e71461055e57886001600160a01b031663d0e30db087868151811061051557610515610fad565b60200260200101516040518263ffffffff1660e01b81526004015f604051808303818588803b158015610546575f80fd5b505af1158015610558573d5f803e3d5ffd5b50505050505b610568878a610c7f565b7f07b152336751ce779bdbb95a34344ac86aa8c4505d996446a3ea19e15193fb01868860405180606001604052808581526020018681526020018e6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156105de573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106029190610fc1565b8152508e6040516106169493929190611059565b60405180910390a15050505050965096945050505050565b60608061063f87878787875f610098565b915091509550959350505050565b815f0361066f5780604051634389d5ab60e01b81526004016100d491906110d9565b5050565b6001600160a01b03821661066f578060405163eac0d38960e01b81526004016100d491906110d9565b801561071b5760405163350376e360e21b815284906001600160a01b0382169063d40ddb8c906106d29086908890600401611125565b5f604051808303815f875af11580156106ed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526107149190810190611145565b5050610967565b82518460028290036107d3575f6040518060400160405280875f8151811061074557610745610fad565b602002602001015181526020018760018151811061076557610765610fad565b60200260200101518152509050816001600160a01b0316635b36389c86836040518363ffffffff1660e01b81526004016107a09291906111d1565b5f604051808303815f87803b1580156107b7575f80fd5b505af11580156107c9573d5f803e3d5ffd5b5050505050610964565b81600303610874575f6040518060600160405280875f815181106107f9576107f9610fad565b602002602001015181526020018760018151811061081957610819610fad565b602002602001015181526020018760028151811061083957610839610fad565b60200260200101518152509050816001600160a01b031663ecb586a586836040518363ffffffff1660e01b81526004016107a0929190611208565b81600403610964575f6040518060800160405280875f8151811061089a5761089a610fad565b60200260200101518152602001876001815181106108ba576108ba610fad565b60200260200101518152602001876002815181106108da576108da610fad565b60200260200101518152602001876003815181106108fa576108fa610fad565b60200260200101518152509050816001600160a01b0316637d49d87586836040518363ffffffff1660e01b815260040161093592919061121c565b5f604051808303815f87803b15801561094c575f80fd5b505af115801561095e573d5f803e3d5ffd5b50505050505b50505b50505050565b82516060908067ffffffffffffffff81111561098b5761098b610d11565b6040519080825280602002602001820160405280156109b4578160200160208202803683370190505b5091505f5b81811015610b2e575f8682815181106109d4576109d4610fad565b6020026020010151905073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316816001600160a01b031603610aa05784610a7b576040516370a0823160e01b81523060048201526001600160a01b038716906370a0823190602401602060405180830381865afa158015610a52573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a769190610fc1565b610a7d565b475b848381518110610a8f57610a8f610fad565b602002602001018181525050610b25565b6040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa158015610ae2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b069190610fc1565b848381518110610b1857610b18610fad565b6020026020010181815250505b506001016109b9565b50509392505050565b81516060908067ffffffffffffffff811115610b5557610b55610d11565b604051908082528060200260200182016040528015610b7e578160200160208202803683370190505b5091505f5b81811015610c75575f84610bd457878281518110610ba357610ba3610fad565b6020026020010151878381518110610bbd57610bbd610fad565b6020026020010151610bcf9190610fd8565b610c12565b868281518110610be657610be6610fad565b6020026020010151888381518110610c0057610c00610fad565b6020026020010151610c129190610fd8565b9050858281518110610c2657610c26610fad565b6020026020010151811015610c4e57604051634f83730b60e01b815260040160405180910390fd5b80848381518110610c6157610c61610fad565b602090810291909101015250600101610b83565b5050949350505050565b5f5b8251811015610d0c5773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6001600160a01b0316838281518110610cba57610cba610fad565b60200260200101516001600160a01b031603610d045781838281518110610ce357610ce3610fad565b60200260200101906001600160a01b031690816001600160a01b0316815250505b600101610c81565b505050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610d4e57610d4e610d11565b604052919050565b5f67ffffffffffffffff821115610d6f57610d6f610d11565b5060051b60200190565b5f82601f830112610d88575f80fd5b81356020610d9d610d9883610d56565b610d25565b8083825260208201915060208460051b870101935086841115610dbe575f80fd5b602086015b84811015610dda5780358352918301918301610dc3565b509695505050505050565b6001600160a01b0381168114610df9575f80fd5b50565b5f805f805f8060c08789031215610e11575f80fd5b863567ffffffffffffffff811115610e27575f80fd5b610e3389828a01610d79565b965050602087013594506040870135610e4b81610de5565b93506060870135610e5b81610de5565b92506080870135610e6b81610de5565b915060a08701358015158114610e7f575f80fd5b809150509295509295509295565b604080825283519082018190525f906020906060840190828701845b82811015610ece5781516001600160a01b031684529284019290840190600101610ea9565b505050838103828501528451808252858301918301905f5b81811015610f0257835183529284019291840191600101610ee6565b5090979650505050505050565b5f805f805f60a08688031215610f23575f80fd5b853567ffffffffffffffff811115610f39575f80fd5b610f4588828901610d79565b955050602086013593506040860135610f5d81610de5565b92506060860135610f6d81610de5565b91506080860135610f7d81610de5565b809150509295509295909350565b5f60208284031215610f9b575f80fd5b8151610fa681610de5565b9392505050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215610fd1575f80fd5b5051919050565b81810381811115610ff757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f815180845260208085019450602084015f5b8381101561102c57815187529582019590820190600101611010565b509495945050505050565b805f5b600381101561096757815184526020938401939091019060010161103a565b60c081525f61106b60c0830187610ffd565b8281036020848101919091528651808352878201928201905f5b818110156110aa5784516001600160a01b031683529383019391830191600101611085565b50508093505050506110bf6040830185611037565b6001600160a01b039290921660a091909101529392505050565b5f602080835283518060208501525f5b81811015611105578581018301518582016040015282016110e9565b505f604082860101526040601f19601f8301168501019250505092915050565b828152604060208201525f61113d6040830184610ffd565b949350505050565b5f6020808385031215611156575f80fd5b825167ffffffffffffffff81111561116c575f80fd5b8301601f8101851361117c575f80fd5b805161118a610d9882610d56565b81815260059190911b820183019083810190878311156111a8575f80fd5b928401925b828410156111c6578351825292840192908401906111ad565b979650505050505050565b828152606081016020808301845f5b60028110156111fd578151835291830191908301906001016111e0565b505050509392505050565b82815260808101610fa66020830184611037565b82815260a081016020808301845f5b60048110156111fd5781518352918301919083019060010161122b56fea26469706673582212201057d4d1627b4a9f1ea94ccecd64f2fbaa13925c787ecb4a95eca1d67c255e5e64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
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.