Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 132789377 | 335 days ago | 0.000449859754435 ETH | ||||
| 132789377 | 335 days ago | 0.000449859754435 ETH | ||||
| 132745209 | 336 days ago | 0.0001 ETH | ||||
| 132745209 | 336 days ago | 0.0001 ETH | ||||
| 132745187 | 336 days ago | 0.001 ETH | ||||
| 132745187 | 336 days ago | 0.001 ETH | ||||
| 132291040 | 347 days ago | 0.000393319422946 ETH | ||||
| 132291040 | 347 days ago | 0.000393319422946 ETH | ||||
| 132291040 | 347 days ago | 0.000400194358722 ETH | ||||
| 132291040 | 347 days ago | 0.000400194358722 ETH | ||||
| 132145290 | 350 days ago | 0.000396506396454 ETH | ||||
| 132145290 | 350 days ago | 0.000396506396454 ETH | ||||
| 132145280 | 350 days ago | 0.000388030985764 ETH | ||||
| 132145280 | 350 days ago | 0.000388030985764 ETH | ||||
| 131847127 | 357 days ago | 0.000397274977326 ETH | ||||
| 131847127 | 357 days ago | 0.000397274977326 ETH | ||||
| 131846900 | 357 days ago | 0.000396663819662 ETH | ||||
| 131846900 | 357 days ago | 0.000396663819662 ETH | ||||
| 131846892 | 357 days ago | 0.000398049295859 ETH | ||||
| 131846892 | 357 days ago | 0.000398049295859 ETH | ||||
| 131846884 | 357 days ago | 0.00039409973953 ETH | ||||
| 131846884 | 357 days ago | 0.00039409973953 ETH | ||||
| 131846385 | 357 days ago | 0.000397863661128 ETH | ||||
| 131846385 | 357 days ago | 0.000397863661128 ETH | ||||
| 131846209 | 357 days ago | 0.000397740947872 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TokenZapV1
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;
// ════════════════════════════════════════════════ INTERFACES ═════════════════════════════════════════════════════
import {IZapRecipient} from "../interfaces/IZapRecipient.sol";
// ═════════════════════════════════════════════ INTERNAL IMPORTS ══════════════════════════════════════════════════
import {ZapDataV1} from "../libs/ZapDataV1.sol";
// ═════════════════════════════════════════════ EXTERNAL IMPORTS ══════════════════════════════════════════════════
import {IERC20, SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
/// @title TokenZapV1
/// @notice Facilitates atomic token operations known as "Zaps", allowing the execution of predefined actions
/// on behalf of users, such as deposits or swaps. Supports ERC20 tokens and native gas tokens (e.g., ETH).
/// @dev Tokens must be transferred to the contract before execution, native tokens could be provided as `msg.value`.
/// This contract is stateless and does not hold assets between Zaps; leftover tokens can be claimed by anyone.
/// Ensure that Zaps fully utilize tokens or revert to prevent the loss of funds.
contract TokenZapV1 is IZapRecipient {
using SafeERC20 for IERC20;
using ZapDataV1 for bytes;
address public constant NATIVE_GAS_TOKEN = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
error TokenZapV1__FinalBalanceBelowMin();
error TokenZapV1__FinalTokenNotSpecified();
error TokenZapV1__PayloadLengthAboveMax();
error TokenZapV1__TargetZeroAddress();
error TokenZapV1__TokenZeroAddress();
/// @notice Allows the contract to receive ETH.
/// @dev Leftover ETH can be claimed by anyone. Ensure the full balance is spent during Zaps.
receive() external payable {}
/// @notice Performs a Zap action using the specified token and amount. This amount must have previously been
/// transferred to this contract (could also be supplied as msg.value if the token is a native gas token).
/// Zap action will be performed forwarding full `msg.value` for ERC20s or `amount` for native gas tokens.
/// Note: all funds remaining after the Zap action is performed can be claimed by anyone.
/// Make sure to spend the full balance during the Zaps and avoid sending extra funds if a single Zap is performed.
/// @dev The provided ZapData contains the target address and calldata for the Zap action, and must be
/// encoded using the encodeZapData function. Native gas token transfers could be done by using empty `payload`,
/// this is the only case where target could be an EOA.
/// @param token Address of the token to be used for the Zap action.
/// @param amount Amount of the token to be used for the Zap action.
/// @param zapData Encoded Zap Data containing the target address and calldata for the Zap action.
/// @return selector Selector of this function to signal the caller about the success of the Zap action.
function zap(address token, uint256 amount, bytes calldata zapData) external payable returns (bytes4) {
if (token == address(0)) revert TokenZapV1__TokenZeroAddress();
// Validate the ZapData format and extract the target address.
zapData.validateV1();
address target = zapData.target();
if (target == address(0)) revert TokenZapV1__TargetZeroAddress();
// Note: we don't check the amount that was transferred to TokenZapV1 (or msg.value for native gas tokens).
// Transferring more than `amount` will lead to remaining funds in TokenZapV1, which can be claimed by anyone.
// Ensure that you send the exact amount for a single Zap or spend the full balance for multiple `zap()` calls.
uint256 msgValue = msg.value;
if (token == NATIVE_GAS_TOKEN) {
// For native gas tokens, we forward the requested amount to the target contract during the Zap action.
// Similar to ERC20s, we allow using pre-transferred native tokens for the Zap.
msgValue = amount;
// No approval is needed since native tokens don't use allowances.
// Note: balance check is performed within `Address.sendValue` or `Address.functionCallWithValue` below.
} else {
// For ERC20 tokens, grant unlimited approval to the target if the current allowance is insufficient.
// This is safe since the contract doesn't custody tokens between zaps.
if (IERC20(token).allowance(address(this), target) < amount) {
IERC20(token).forceApprove(target, type(uint256).max);
}
// Note: balance check is omitted as the target contract will revert if there are insufficient funds.
}
// Construct the payload for the target contract call with the Zap action.
// The payload is modified to replace the placeholder amount with the actual amount.
bytes memory payload = zapData.payload(amount);
if (payload.length == 0 && token == NATIVE_GAS_TOKEN) {
// Zap Action in a form of native gas token transfer to the target is requested.
// Note: we avoid using `functionCallWithValue` because the target might be an EOA. This will
// revert with a generic custom error should the target contract revert on incoming transfer.
Address.sendValue({recipient: payable(target), amount: msgValue});
} else {
// Perform the Zap action, forwarding the requested native value to the target contract.
// Note: this will bubble up any revert from the target contract, and revert if target is EOA.
Address.functionCallWithValue({target: target, data: payload, value: msgValue});
}
// Forward the final token to the specified recipient, if required.
_checkBalanceAndForward({
token: zapData.finalToken(),
forwardTo: zapData.forwardTo(),
minFinalBalance: zapData.minFinalBalance()
});
// Return function selector to indicate successful execution
return this.zap.selector;
}
/// @notice Encodes the ZapData for a Zap action.
/// @dev At the time of encoding, we don't know the exact amount of tokens that will be used for the Zap,
/// as we don't have a quote for performing a Zap. Therefore, a placeholder value for the amount must be used
/// when ABI-encoding the payload. A reference index where the actual amount is encoded within the payload
/// must be provided in order to replace the placeholder with the actual amount when the Zap is performed.
/// @param target Address of the target contract.
/// @param payload ABI-encoded calldata to be used for the `target` contract call.
/// If the target function has the token amount as an argument, any placeholder amount value
/// can be used for the original ABI encoding of `payload`. The placeholder amount will
/// be replaced with the actual amount when the Zap Data is decoded.
/// @param amountPosition Position (start index) where the token amount is encoded within `payload`.
/// This will usually be `4 + 32 * n`, where `n` is the position of the token amount in
/// the list of parameters of the target function (starting from 0).
/// Any value greater than or equal to `payload.length` can be used if the token amount is
/// not an argument of the target function.
/// @param finalToken The token produced as a result of the Zap action (ERC20 or native gas token).
/// A zero address value signals that the Zap action doesn't result in any asset per se,
/// like bridging or depositing into a vault without an LP token.
/// Note: this parameter must be set to a non-zero value if the `forwardTo` parameter is
/// set to a non-zero value.
/// @param forwardTo The address to which `finalToken` should be forwarded. This parameter is required only
/// if the Zap action does not automatically transfer the token to the intended recipient.
/// Otherwise, it must be set to address(0).
/// @param minFinalBalance The minimum balance of `finalToken` to have after performing the Zap action.
/// This parameter could be used to implement slippage protection for a Zap action that does
/// not automatically transfer the token to the intended recipient. Otherwise, it must be
/// set to 0.
function encodeZapData(
address target,
bytes memory payload,
uint256 amountPosition,
address finalToken,
address forwardTo,
uint256 minFinalBalance
)
external
pure
returns (bytes memory)
{
// External integrations do not need to understand the specific `AMOUNT_NOT_PRESENT` semantics.
// Therefore, they can specify any value greater than or equal to `payload.length` to indicate
// that the amount is not present in the payload.
if (amountPosition >= payload.length) {
amountPosition = ZapDataV1.AMOUNT_NOT_PRESENT;
}
// At this point, we have checked that `amountPosition` fits in uint16, so we can safely cast it.
return ZapDataV1.encodeV1({
amountPosition_: uint16(amountPosition),
finalToken_: finalToken,
forwardTo_: forwardTo,
minFinalBalance_: minFinalBalance,
target_: target,
payload_: payload
});
}
/// @notice Decodes the ZapData for a Zap action. Replaces the placeholder amount with the actual amount,
/// if it was present in the original `payload`. Otherwise, returns the original `payload` as is.
/// @param zapData Encoded Zap Data containing the target address and calldata for the Zap action.
/// @param amount Actual amount of the token to be used for the Zap action.
function decodeZapData(
bytes calldata zapData,
uint256 amount
)
public
pure
returns (address target, bytes memory payload)
{
zapData.validateV1();
target = zapData.target();
payload = zapData.payload(amount);
}
/// @notice Forwards the proceeds of the Zap action to the specified non-zero recipient.
function _checkBalanceAndForward(address token, address forwardTo, uint256 minFinalBalance) internal {
// Do nothing if both forwarding and minimum balance checks are not required.
if (forwardTo == address(0) && minFinalBalance == 0) {
return;
}
// Check the token address and its balance to be safely forwarded.
if (token == address(0)) revert TokenZapV1__FinalTokenNotSpecified();
// Perform the balance check before forwarding.
uint256 amount = token == NATIVE_GAS_TOKEN ? address(this).balance : IERC20(token).balanceOf(address(this));
if (amount == 0 || amount < minFinalBalance) revert TokenZapV1__FinalBalanceBelowMin();
// Forward the full balance of the final token to the specified recipient, if required.
if (forwardTo == address(0)) return;
if (token == NATIVE_GAS_TOKEN) {
Address.sendValue({recipient: payable(forwardTo), amount: amount});
} else {
IERC20(token).safeTransfer(forwardTo, amount);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Interface for contracts that can perform Zap operations. Such contracts could be used as Recipients
/// in a FastBridge transaction that includes a Zap operation. The Zap Data should include instructions on how
/// exactly the Zap operation should be executed, which would typically include the target address and calldata
/// to use. The exact implementation of the Zap Data encoding is up to the Recipient contract.
interface IZapRecipient {
/// @notice Performs a Zap operation with the given token and amount according to the provided Zap data.
/// @param token The address of the token being used for the Zap operation.
/// @param amount The amount of tokens to be used.
/// @param zapData The encoded data specifying how the Zap operation should be executed.
/// @return The function selector to indicate successful execution.
function zap(address token, uint256 amount, bytes memory zapData) external payable returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
// solhint-disable no-inline-assembly
library ZapDataV1 {
/// @notice Version of the Zap Data struct.
uint16 internal constant VERSION = 1;
/// @notice Value that indicates the amount is not present in the target function's payload.
uint16 internal constant AMOUNT_NOT_PRESENT = 0xFFFF;
// Offsets of the fields in the packed ZapData struct
// uint16 version [000 .. 002)
// uint16 amountPosition [002 .. 004)
// address finalToken [004 .. 024)
// address forwardTo [024 .. 044)
// uint256 minFinalBalance [044 .. 076)
// address target [076 .. 096)
// bytes payload [096 .. ***)
// forgefmt: disable-start
uint256 private constant OFFSET_AMOUNT_POSITION = 2;
uint256 private constant OFFSET_FINAL_TOKEN = 4;
uint256 private constant OFFSET_FORWARD_TO = 24;
uint256 private constant OFFSET_MIN_FINAL_BALANCE = 44;
uint256 private constant OFFSET_TARGET = 76;
uint256 private constant OFFSET_PAYLOAD = 96;
// forgefmt: disable-end
error ZapDataV1__InvalidEncoding();
error ZapDataV1__FinalTokenNotSpecified();
error ZapDataV1__PayloadLengthAboveMax();
error ZapDataV1__TargetZeroAddress();
error ZapDataV1__UnsupportedVersion(uint16 version);
/// @notice Validates that encodedZapData is a tightly packed encoded payload for ZapData struct.
/// @dev Checks that all the required fields are present and the version is correct.
function validateV1(bytes calldata encodedZapData) internal pure {
// Check the minimum length: must at least include all static fields.
if (encodedZapData.length < OFFSET_PAYLOAD) revert ZapDataV1__InvalidEncoding();
// Once we validated the length, we can be sure that the version field is present.
uint16 version_ = version(encodedZapData);
if (version_ != VERSION) revert ZapDataV1__UnsupportedVersion(version_);
}
/// @notice Encodes the ZapData struct by tightly packing the fields.
/// Note: we don't know the exact amount of tokens that will be used for the Zap at the time of encoding,
/// so we provide the reference index where the token amount is encoded within `payload_`. This allows us to
/// hot-swap the token amount in the payload, when the Zap is performed.
/// @dev `abi.decode` will not work as a result of the tightly packed fields. Use `decodeZapData` instead.
/// @param amountPosition_ Position (start index) where the token amount is encoded within `payload_`.
/// This will usually be `4 + 32 * n`, where `n` is the position of the token amount in
/// the list of parameters of the target function (starting from 0).
/// Or `AMOUNT_NOT_PRESENT` if the token amount is not encoded within `payload_`.
/// @param finalToken_ The token produced as a result of the Zap action (ERC20 or native gas token).
/// A zero address value signals that the Zap action doesn't result in any asset per se,
/// like bridging or depositing into a vault without an LP token.
/// Note: this parameter must be set to a non-zero value if either `forwardTo_` or
/// `minFinalBalance_` is set to a non-zero value.
/// @param forwardTo_ The address to which `finalToken` should be forwarded. This parameter is required only
/// if the Zap action does not automatically transfer the token to the intended recipient.
/// Otherwise, it must be set to address(0).
/// @param minFinalBalance_ The minimum balance of `finalToken` to have after performing the Zap action.
/// This parameter could be used to implement slippage protection for a Zap action that does
/// not automatically transfer the token to the intended recipient. Otherwise, it must be
/// set to 0.
/// @param target_ Address of the target contract.
/// @param payload_ ABI-encoded calldata to be used for the `target_` contract call.
/// If the target function has the token amount as an argument, any placeholder amount value
/// can be used for the original ABI encoding of `payload_`. The placeholder amount will
/// be replaced with the actual amount, when the Zap Data is decoded.
function encodeV1(
uint16 amountPosition_,
address finalToken_,
address forwardTo_,
uint256 minFinalBalance_,
address target_,
bytes memory payload_
)
internal
pure
returns (bytes memory encodedZapData)
{
if (target_ == address(0)) revert ZapDataV1__TargetZeroAddress();
// We use uint16 to represent the amount position within the payload, so its length must fit in uint16.
if (payload_.length > AMOUNT_NOT_PRESENT) revert ZapDataV1__PayloadLengthAboveMax();
// Amount is encoded in [amountPosition_ .. amountPosition_ + 32), which should be within the payload.
if (amountPosition_ != AMOUNT_NOT_PRESENT && (uint256(amountPosition_) + 32 > payload_.length)) {
revert ZapDataV1__InvalidEncoding();
}
// Final token needs to be specified if forwarding is required.
if (forwardTo_ != address(0) && finalToken_ == address(0)) {
revert ZapDataV1__FinalTokenNotSpecified();
}
// Final token needs to be specified if minimum balance check is required.
if (minFinalBalance_ != 0 && finalToken_ == address(0)) {
revert ZapDataV1__FinalTokenNotSpecified();
}
return abi.encodePacked(VERSION, amountPosition_, finalToken_, forwardTo_, minFinalBalance_, target_, payload_);
}
/// @notice Extracts the version from the encoded Zap Data.
function version(bytes calldata encodedZapData) internal pure returns (uint16 version_) {
// Load 32 bytes from the start and shift it 240 bits to the right to get the highest 16 bits.
assembly {
version_ := shr(240, calldataload(encodedZapData.offset))
}
}
/// @notice Extracts the finalToken address from the encoded Zap Data.
function finalToken(bytes calldata encodedZapData) internal pure returns (address finalToken_) {
// Load 32 bytes from the offset and shift it 96 bits to the right to get the highest 160 bits.
assembly {
finalToken_ := shr(96, calldataload(add(encodedZapData.offset, OFFSET_FINAL_TOKEN)))
}
}
/// @notice Extracts the forwardTo address from the encoded Zap Data.
function forwardTo(bytes calldata encodedZapData) internal pure returns (address forwardTo_) {
// Load 32 bytes from the offset and shift it 96 bits to the right to get the highest 160 bits.
assembly {
forwardTo_ := shr(96, calldataload(add(encodedZapData.offset, OFFSET_FORWARD_TO)))
}
}
/// @notice Extracts the minimum final balance from the encoded Zap Data.
function minFinalBalance(bytes calldata encodedZapData) internal pure returns (uint256 minFinalBalance_) {
// Load 32 bytes from the offset. No shift is applied, as we need the full 256 bits.
assembly {
minFinalBalance_ := calldataload(add(encodedZapData.offset, OFFSET_MIN_FINAL_BALANCE))
}
}
/// @notice Extracts the target address from the encoded Zap Data.
function target(bytes calldata encodedZapData) internal pure returns (address target_) {
// Load 32 bytes from the offset and shift it 96 bits to the right to get the highest 160 bits.
assembly {
target_ := shr(96, calldataload(add(encodedZapData.offset, OFFSET_TARGET)))
}
}
/// @notice Extracts the payload from the encoded Zap Data. Replaces the token amount with the provided value,
/// if it was present in the original data (if amountPosition is not AMOUNT_NOT_PRESENT).
/// @dev This payload will be used as a calldata for the target contract.
function payload(bytes calldata encodedZapData, uint256 amount) internal pure returns (bytes memory) {
// The original payload is located at encodedZapData[OFFSET_PAYLOAD:].
uint16 amountPosition = _amountPosition(encodedZapData);
// If the amount was not present in the original payload, return the payload as is.
if (amountPosition == AMOUNT_NOT_PRESENT) {
return encodedZapData[OFFSET_PAYLOAD:];
}
// Calculate the start and end indexes of the amount in ZapData from its position within the payload.
// Note: we use inclusive start and exclusive end indexes for easier slicing of the ZapData.
uint256 amountStartIndexIncl = OFFSET_PAYLOAD + amountPosition;
uint256 amountEndIndexExcl = amountStartIndexIncl + 32;
// Check that the amount is within the ZapData.
if (amountEndIndexExcl > encodedZapData.length) revert ZapDataV1__InvalidEncoding();
// Otherwise we need to replace the amount in the payload with the provided value.
return abi.encodePacked(
// Copy the original payload up to the amount
encodedZapData[OFFSET_PAYLOAD:amountStartIndexIncl],
// Replace the originally encoded amount with the provided value
amount,
// Copy the rest of the payload after the amount
encodedZapData[amountEndIndexExcl:]
);
}
/// @notice Extracts the amount position from the encoded Zap Data.
function _amountPosition(bytes calldata encodedZapData) private pure returns (uint16 amountPosition) {
// Load 32 bytes from the offset and shift it 240 bits to the right to get the highest 16 bits.
assembly {
amountPosition := shr(240, calldataload(add(encodedZapData.offset, OFFSET_AMOUNT_POSITION)))
}
}
}// 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) (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
// 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: 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);
}{
"remappings": [
"@openzeppelin/=node_modules/@openzeppelin/",
"@synapsecns/=node_modules/@synapsecns/",
"forge-std/=node_modules/forge-std/src/"
],
"optimizer": {
"enabled": true,
"runs": 1000000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TokenZapV1__FinalBalanceBelowMin","type":"error"},{"inputs":[],"name":"TokenZapV1__FinalTokenNotSpecified","type":"error"},{"inputs":[],"name":"TokenZapV1__PayloadLengthAboveMax","type":"error"},{"inputs":[],"name":"TokenZapV1__TargetZeroAddress","type":"error"},{"inputs":[],"name":"TokenZapV1__TokenZeroAddress","type":"error"},{"inputs":[],"name":"ZapDataV1__FinalTokenNotSpecified","type":"error"},{"inputs":[],"name":"ZapDataV1__InvalidEncoding","type":"error"},{"inputs":[],"name":"ZapDataV1__PayloadLengthAboveMax","type":"error"},{"inputs":[],"name":"ZapDataV1__TargetZeroAddress","type":"error"},{"inputs":[{"internalType":"uint16","name":"version","type":"uint16"}],"name":"ZapDataV1__UnsupportedVersion","type":"error"},{"inputs":[],"name":"NATIVE_GAS_TOKEN","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"zapData","type":"bytes"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"decodeZapData","outputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint256","name":"amountPosition","type":"uint256"},{"internalType":"address","name":"finalToken","type":"address"},{"internalType":"address","name":"forwardTo","type":"address"},{"internalType":"uint256","name":"minFinalBalance","type":"uint256"}],"name":"encodeZapData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes","name":"zapData","type":"bytes"}],"name":"zap","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b506113b1806100206000396000f3fe6080604052600436106100435760003560e01c80630f862f1e1461004f578063240a530a146100a1578063bdbe5169146100ce578063e85e13dd146100fc57600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b5061007773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100ad57600080fd5b506100c16100bc366004610f38565b610140565b60405161009891906110b9565b3480156100da57600080fd5b506100ee6100e9366004611115565b610169565b604051610098929190611161565b61010f61010a366004611198565b610196565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610098565b6060855185106101505761ffff94505b61015e858585858b8b610407565b979650505050505050565b6000606061017785856105ef565b604c85013560601c915061018c858585610679565b9050935093915050565b600073ffffffffffffffffffffffffffffffffffffffff85166101e5576040517fa620451f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101ef83836105ef565b604c83013560601c8061022e576040517fa921c0cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b347fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff881601610273575084610353565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015287919089169063dd62ed3e90604401602060405180830381865afa1580156102e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030c91906111f2565b10156103535761035373ffffffffffffffffffffffffffffffffffffffff8816837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61079b565b6000610360868689610679565b90508051600014801561039c575073ffffffffffffffffffffffffffffffffffffffff881673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b156103b0576103ab83836108bc565b6103bd565b6103bb838284610992565b505b6103da600487013560601c601888013560601c602c890135610a55565b507fe85e13dd00000000000000000000000000000000000000000000000000000000979650505050505050565b606073ffffffffffffffffffffffffffffffffffffffff8316610456576040517f2503727b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815161ffff1015610493576040517f4fc7c83b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61ffff878116148015906104b5575081516104b361ffff8916602061120b565b115b156104ec576040517f49a0c73b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff851615801590610525575073ffffffffffffffffffffffffffffffffffffffff8616155b1561055c576040517f3b2efc8e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b831580159061057f575073ffffffffffffffffffffffffffffffffffffffff8616155b156105b6576040517f3b2efc8e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018787878787876040516020016105d49796959493929190611245565b60405160208183030381529060405290509695505050505050565b606081101561062a576040517f49a0c73b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813560f01c60018114610674576040517f3a565e1600000000000000000000000000000000000000000000000000000000815261ffff821660048201526024015b60405180910390fd5b505050565b6060600284013560f01c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000181016106f5576106b784606081886112eb565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294506107949350505050565b600061070661ffff8316606061120b565b9050600061071582602061120b565b905085811115610751576040517f49a0c73b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61075e826060888a6112eb565b8661076b8985818d6112eb565b60405160200161077f959493929190611315565b60405160208183030381529060405293505050505b9392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526108278482610c69565b6108b65760405173ffffffffffffffffffffffffffffffffffffffff8481166024830152600060448301526108ac91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610d2d565b6108b68482610d2d565b50505050565b804710156108f8576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161066b565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610952576040519150601f19603f3d011682016040523d82523d6000602084013e610957565b606091505b5050905080610674576040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060814710156109d0576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161066b565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516109f9919061133d565b60006040518083038185875af1925050503d8060008114610a36576040519150601f19603f3d011682016040523d82523d6000602084013e610a3b565b606091505b5091509150610a4b868383610dc3565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216158015610a77575080155b15610a8157505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ace576040517f82ff5b2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610b94576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8f91906111f2565b610b96565b475b9050801580610ba457508181105b15610bdb576040517f92f25fe300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316610bfc5750505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff851601610c4857610c4383826108bc565b6108b6565b6108b673ffffffffffffffffffffffffffffffffffffffff85168483610e52565b60008060008473ffffffffffffffffffffffffffffffffffffffff1684604051610c93919061133d565b6000604051808303816000865af19150503d8060008114610cd0576040519150601f19603f3d011682016040523d82523d6000602084013e610cd5565b606091505b5091509150818015610cff575080511580610cff575080806020019051810190610cff9190611359565b8015610d22575060008573ffffffffffffffffffffffffffffffffffffffff163b115b925050505b92915050565b6000610d4f73ffffffffffffffffffffffffffffffffffffffff841683610e90565b90508051600014158015610d74575080806020019051810190610d729190611359565b155b15610674576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161066b565b606082610dd857610dd382610e9e565b610794565b8151158015610dfc575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610e4b576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161066b565b5080610794565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261067491859182169063a9059cbb90606401610865565b606061079483836000610992565b805115610eae5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610f0457600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060008060008060c08789031215610f5157600080fd5b610f5a87610ee0565b9550602087013567ffffffffffffffff80821115610f7757600080fd5b818901915089601f830112610f8b57600080fd5b813581811115610f9d57610f9d610f09565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610fe357610fe3610f09565b816040528281528c6020848701011115610ffc57600080fd5b8260208601602083013760006020848301015280995050505050506040870135935061102a60608801610ee0565b925061103860808801610ee0565b915060a087013590509295509295509295565b60005b8381101561106657818101518382015260200161104e565b50506000910152565b6000815180845261108781602086016020860161104b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610794602083018461106f565b60008083601f8401126110de57600080fd5b50813567ffffffffffffffff8111156110f657600080fd5b60208301915083602082850101111561110e57600080fd5b9250929050565b60008060006040848603121561112a57600080fd5b833567ffffffffffffffff81111561114157600080fd5b61114d868287016110cc565b909790965060209590950135949350505050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000611190604083018461106f565b949350505050565b600080600080606085870312156111ae57600080fd5b6111b785610ee0565b935060208501359250604085013567ffffffffffffffff8111156111da57600080fd5b6111e6878288016110cc565b95989497509550505050565b60006020828403121561120457600080fd5b5051919050565b80820180821115610d27577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffff000000000000000000000000000000000000000000000000000000000000808a60f01b168352808960f01b166002840152507fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808860601b166004840152808760601b16601884015285602c840152808560601b16604c8401525082516112d881606085016020870161104b565b9190910160600198975050505050505050565b600080858511156112fb57600080fd5b8386111561130857600080fd5b5050820193919092039150565b8486823760008582018581528385602083013760009301602001928352509095945050505050565b6000825161134f81846020870161104b565b9190910192915050565b60006020828403121561136b57600080fd5b8151801515811461079457600080fdfea2646970667358221220a7f03f1e40d3221e638a9f335b771884b9dcd7135c71b5a25aa731561348a33e64736f6c63430008180033
Deployed Bytecode
0x6080604052600436106100435760003560e01c80630f862f1e1461004f578063240a530a146100a1578063bdbe5169146100ce578063e85e13dd146100fc57600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b5061007773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156100ad57600080fd5b506100c16100bc366004610f38565b610140565b60405161009891906110b9565b3480156100da57600080fd5b506100ee6100e9366004611115565b610169565b604051610098929190611161565b61010f61010a366004611198565b610196565b6040517fffffffff000000000000000000000000000000000000000000000000000000009091168152602001610098565b6060855185106101505761ffff94505b61015e858585858b8b610407565b979650505050505050565b6000606061017785856105ef565b604c85013560601c915061018c858585610679565b9050935093915050565b600073ffffffffffffffffffffffffffffffffffffffff85166101e5576040517fa620451f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6101ef83836105ef565b604c83013560601c8061022e576040517fa921c0cb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b347fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff881601610273575084610353565b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff838116602483015287919089169063dd62ed3e90604401602060405180830381865afa1580156102e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061030c91906111f2565b10156103535761035373ffffffffffffffffffffffffffffffffffffffff8816837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61079b565b6000610360868689610679565b90508051600014801561039c575073ffffffffffffffffffffffffffffffffffffffff881673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b156103b0576103ab83836108bc565b6103bd565b6103bb838284610992565b505b6103da600487013560601c601888013560601c602c890135610a55565b507fe85e13dd00000000000000000000000000000000000000000000000000000000979650505050505050565b606073ffffffffffffffffffffffffffffffffffffffff8316610456576040517f2503727b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815161ffff1015610493576040517f4fc7c83b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61ffff878116148015906104b5575081516104b361ffff8916602061120b565b115b156104ec576040517f49a0c73b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff851615801590610525575073ffffffffffffffffffffffffffffffffffffffff8616155b1561055c576040517f3b2efc8e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b831580159061057f575073ffffffffffffffffffffffffffffffffffffffff8616155b156105b6576040517f3b2efc8e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018787878787876040516020016105d49796959493929190611245565b60405160208183030381529060405290509695505050505050565b606081101561062a576040517f49a0c73b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b813560f01c60018114610674576040517f3a565e1600000000000000000000000000000000000000000000000000000000815261ffff821660048201526024015b60405180910390fd5b505050565b6060600284013560f01c7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000181016106f5576106b784606081886112eb565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509294506107949350505050565b600061070661ffff8316606061120b565b9050600061071582602061120b565b905085811115610751576040517f49a0c73b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61075e826060888a6112eb565b8661076b8985818d6112eb565b60405160200161077f959493929190611315565b60405160208183030381529060405293505050505b9392505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790526108278482610c69565b6108b65760405173ffffffffffffffffffffffffffffffffffffffff8481166024830152600060448301526108ac91869182169063095ea7b3906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610d2d565b6108b68482610d2d565b50505050565b804710156108f8576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161066b565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114610952576040519150601f19603f3d011682016040523d82523d6000602084013e610957565b606091505b5050905080610674576040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6060814710156109d0576040517fcd78605900000000000000000000000000000000000000000000000000000000815230600482015260240161066b565b6000808573ffffffffffffffffffffffffffffffffffffffff1684866040516109f9919061133d565b60006040518083038185875af1925050503d8060008114610a36576040519150601f19603f3d011682016040523d82523d6000602084013e610a3b565b606091505b5091509150610a4b868383610dc3565b9695505050505050565b73ffffffffffffffffffffffffffffffffffffffff8216158015610a77575080155b15610a8157505050565b73ffffffffffffffffffffffffffffffffffffffff8316610ace576040517f82ff5b2800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14610b94576040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015610b6b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b8f91906111f2565b610b96565b475b9050801580610ba457508181105b15610bdb576040517f92f25fe300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8316610bfc5750505050565b7fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff851601610c4857610c4383826108bc565b6108b6565b6108b673ffffffffffffffffffffffffffffffffffffffff85168483610e52565b60008060008473ffffffffffffffffffffffffffffffffffffffff1684604051610c93919061133d565b6000604051808303816000865af19150503d8060008114610cd0576040519150601f19603f3d011682016040523d82523d6000602084013e610cd5565b606091505b5091509150818015610cff575080511580610cff575080806020019051810190610cff9190611359565b8015610d22575060008573ffffffffffffffffffffffffffffffffffffffff163b115b925050505b92915050565b6000610d4f73ffffffffffffffffffffffffffffffffffffffff841683610e90565b90508051600014158015610d74575080806020019051810190610d729190611359565b155b15610674576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8416600482015260240161066b565b606082610dd857610dd382610e9e565b610794565b8151158015610dfc575073ffffffffffffffffffffffffffffffffffffffff84163b155b15610e4b576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015260240161066b565b5080610794565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261067491859182169063a9059cbb90606401610865565b606061079483836000610992565b805115610eae5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff81168114610f0457600080fd5b919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60008060008060008060c08789031215610f5157600080fd5b610f5a87610ee0565b9550602087013567ffffffffffffffff80821115610f7757600080fd5b818901915089601f830112610f8b57600080fd5b813581811115610f9d57610f9d610f09565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610fe357610fe3610f09565b816040528281528c6020848701011115610ffc57600080fd5b8260208601602083013760006020848301015280995050505050506040870135935061102a60608801610ee0565b925061103860808801610ee0565b915060a087013590509295509295509295565b60005b8381101561106657818101518382015260200161104e565b50506000910152565b6000815180845261108781602086016020860161104b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b602081526000610794602083018461106f565b60008083601f8401126110de57600080fd5b50813567ffffffffffffffff8111156110f657600080fd5b60208301915083602082850101111561110e57600080fd5b9250929050565b60008060006040848603121561112a57600080fd5b833567ffffffffffffffff81111561114157600080fd5b61114d868287016110cc565b909790965060209590950135949350505050565b73ffffffffffffffffffffffffffffffffffffffff83168152604060208201526000611190604083018461106f565b949350505050565b600080600080606085870312156111ae57600080fd5b6111b785610ee0565b935060208501359250604085013567ffffffffffffffff8111156111da57600080fd5b6111e6878288016110cc565b95989497509550505050565b60006020828403121561120457600080fd5b5051919050565b80820180821115610d27577f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffff000000000000000000000000000000000000000000000000000000000000808a60f01b168352808960f01b166002840152507fffffffffffffffffffffffffffffffffffffffff000000000000000000000000808860601b166004840152808760601b16601884015285602c840152808560601b16604c8401525082516112d881606085016020870161104b565b9190910160600198975050505050505050565b600080858511156112fb57600080fd5b8386111561130857600080fd5b5050820193919092039150565b8486823760008582018581528385602083013760009301602001928352509095945050505050565b6000825161134f81846020870161104b565b9190910192915050565b60006020828403121561136b57600080fd5b8151801515811461079457600080fdfea2646970667358221220a7f03f1e40d3221e638a9f335b771884b9dcd7135c71b5a25aa731561348a33e64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 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.