Overview
MNT Balance
MNT Value
$0.00Latest 25 from a total of 24,104 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap Meta | 75951201 | 342 days ago | IN | 0 MNT | 0.03033325 | ||||
| Swap Meta | 75951073 | 342 days ago | IN | 0 MNT | 0.01497735 | ||||
| Swap Meta | 75950827 | 342 days ago | IN | 0 MNT | 0.10676125 | ||||
| Swap Meta | 75822584 | 345 days ago | IN | 0 MNT | 0.26560032 | ||||
| Swap Meta | 75582399 | 351 days ago | IN | 0 MNT | 0.01727717 | ||||
| Swap Meta | 75419452 | 354 days ago | IN | 0 MNT | 0.03360879 | ||||
| Swap Meta | 75418964 | 354 days ago | IN | 0 MNT | 0.04471498 | ||||
| Swap Meta | 75329344 | 356 days ago | IN | 0 MNT | 0.01537014 | ||||
| Swap Meta | 75105821 | 362 days ago | IN | 0 MNT | 0.12318691 | ||||
| Swap Meta | 75105806 | 362 days ago | IN | 0 MNT | 0.17162509 | ||||
| Swap Meta | 75105787 | 362 days ago | IN | 0 MNT | 0.06676962 | ||||
| Swap Meta | 75102762 | 362 days ago | IN | 5 MNT | 0.05473369 | ||||
| Swap Meta | 75099479 | 362 days ago | IN | 0 MNT | 0.01919264 | ||||
| Swap Meta | 75090347 | 362 days ago | IN | 0 MNT | 0.0229688 | ||||
| Swap Meta | 75076132 | 362 days ago | IN | 0 MNT | 0.12616661 | ||||
| Swap Meta | 75076058 | 362 days ago | IN | 0 MNT | 0.11720293 | ||||
| Swap Meta | 75076001 | 362 days ago | IN | 0 MNT | 0.02879851 | ||||
| Swap Meta | 75070976 | 362 days ago | IN | 0 MNT | 0.35275764 | ||||
| Swap Meta | 75070899 | 362 days ago | IN | 0 MNT | 0.35556381 | ||||
| Swap Meta | 75070685 | 362 days ago | IN | 0 MNT | 0.24788966 | ||||
| Swap Meta | 75050756 | 363 days ago | IN | 0 MNT | 0.15440044 | ||||
| Swap Meta | 75050731 | 363 days ago | IN | 0 MNT | 0.1371906 | ||||
| Swap Meta | 75050587 | 363 days ago | IN | 0 MNT | 0.22592902 | ||||
| Swap Meta | 75041762 | 363 days ago | IN | 0 MNT | 0.02924469 | ||||
| Swap Meta | 75015928 | 364 days ago | IN | 0 MNT | 0.24715719 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 75102762 | 362 days ago | 5 MNT | ||||
| 74970796 | 365 days ago | 0.1 MNT | ||||
| 74953971 | 365 days ago | 20 MNT | ||||
| 74934315 | 366 days ago | 8 MNT | ||||
| 74934292 | 366 days ago | 105 MNT | ||||
| 74902480 | 366 days ago | 100 MNT | ||||
| 74787022 | 369 days ago | 50 MNT | ||||
| 74777433 | 369 days ago | 16.9 MNT | ||||
| 74749134 | 370 days ago | 1 MNT | ||||
| 74712892 | 371 days ago | 45 MNT | ||||
| 74682674 | 371 days ago | 209 MNT | ||||
| 74615018 | 373 days ago | 60 MNT | ||||
| 74588929 | 374 days ago | 55 MNT | ||||
| 74580323 | 374 days ago | 14.4 MNT | ||||
| 74580292 | 374 days ago | 18 MNT | ||||
| 74580245 | 374 days ago | 36.2 MNT | ||||
| 74580203 | 374 days ago | 35.5 MNT | ||||
| 74503484 | 376 days ago | 25 MNT | ||||
| 74500089 | 376 days ago | 1 MNT | ||||
| 74497793 | 376 days ago | 1 MNT | ||||
| 74486633 | 376 days ago | 671 MNT | ||||
| 74486622 | 376 days ago | 671 MNT | ||||
| 74480068 | 376 days ago | 13 MNT | ||||
| 74480004 | 376 days ago | 3.41 MNT | ||||
| 74446122 | 377 days ago | 0.1 MNT |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {PermitUtilsSlim} from "./permit/PermitUtilsSlim.sol";
////////////////////////////////////////////////////
// Minimal meta swap aggregation contract
// - Allows simulation to validate receiver amount
// - Supports permits, exact in & out swaps
// - Swap aggregation calls are assumed to already
// check for slippage and send funds directly to the
// user-defined receiver
////////////////////////////////////////////////////
contract DeltaMetaAggregator is PermitUtilsSlim {
////////////////////////////////////////////////////
// Errors
////////////////////////////////////////////////////
error SimulationResults(uint256 amountPaid, uint256 amountReceived, bytes errorData);
error InvalidSwapCall();
error NativeTransferFailed();
error HasNoMsgValue();
// NativeTransferFailed()
bytes4 private constant NATIVE_TRANSFER_FAILED = 0xf4b3b1bc;
// InvalidSwapCall()
bytes4 private constant INVALID_SWAP_CALL = 0xee68db59;
// HasNoMsgValue()
bytes4 private constant HAS_NO_MSG_VALUE = 0x07270ad5;
////////////////////////////////////////////////////
// State
////////////////////////////////////////////////////
/// @notice maps token to approvalTarget to bool
mapping(address => mapping(address => bool)) private _approvedTargets;
////////////////////////////////////////////////////
// Constants
////////////////////////////////////////////////////
/// @dev maximum uint256 - used for approvals
uint256 private constant MAX_UINT_256 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
/// @dev mask for selector in calldata
bytes32 private constant SELECTOR_MASK = 0xffffffff00000000000000000000000000000000000000000000000000000000;
/// @dev mask for address in encoded input data
uint256 private constant ADDRESS_MASK = 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff;
/// @dev high bit for sweep flag
uint256 private constant SWEEP_MASK = 1 << 255;
////////////////////////////////////////////////////
// Constructor
////////////////////////////////////////////////////
constructor() {}
////////////////////////////////////////////////////
// Receive function for native swaps
////////////////////////////////////////////////////
receive() external payable {}
////////////////////////////////////////////////////
// Swap functions
////////////////////////////////////////////////////
/**
* Executes meta aggregation swap.
* Can only be executed any address but Permit2.
* Calldata is validated to prevent illegitimate `transferFrom`
* Note that the receiver address must be manually set in
* the aggregation call, otherwise, the funds will remain in this contract
* Ideally this function is executed after an simulation via `simSwapMeta`
* @param permitData permit calldata (use empty data for plai transfers)
* @param swapData swap calldata
* @param assetInData token input address, use zero address for native - high bit signals that we have to sweep
* @param assetOutData token output address, use zero address for native - high bit signals that we have to sweep, the address is ignored if sweep flag is not set
* @param amountIn input amount, ignored for native transfer
* @param approvalTarget contract approves this target when swapping (only if allowance too low)
* @param swapTarget swap aggregation executor
* @param receiver of assetOut - ignored if assetOut sweep flag is set to false
*/
function swapMeta(
bytes calldata permitData,
bytes calldata swapData,
bytes32 assetInData,
bytes32 assetOutData,
uint256 amountIn,
address approvalTarget,
address swapTarget,
address receiver
) external payable {
(address asset, bool sweep) = _decodeAssetData(assetInData);
// zero address assumes native transfer
if (asset != address(0)) {
// permit and pull - checks that no native is attached
_permitAndPull(asset, amountIn, permitData);
// approve if no allowance
// we actually do not care what we approve as this
// contract is not supposed to hold balances
_approveIfNot(asset, approvalTarget);
} else {
// if native is the input asset,
// we enforce that msg.value is attached
_requireHasMsgValue();
}
// validate swap call
_validateCalldata(swapData, swapTarget);
// execute external call
_executeExternalCall(swapData, swapTarget);
// execute sweep of input asset if desired
_sweepTokenIfNeeded(sweep, asset);
// execute sweep of output asset if desired
_handleOutputAsset(assetOutData, receiver);
}
struct SimAmounts {
address payAsset;
address receiveAsset;
uint256 amountReceived;
uint256 amountPaid;
}
/**
* Simulates the swap aggregation. Should be called before `swapMeta`
* Always reverts with simulation results in custom error.
* Ideally called via staticcall, the return object contains
* the balance change of the `receiver` address.
* Parameters are otherwise identical to `swapMeta`.
*/
function simSwapMeta(
bytes calldata permitData,
bytes calldata swapData,
bytes32 assetInData,
bytes32 assetOutData,
uint256 amountIn,
address approvalTarget,
address swapTarget,
address receiver
) external payable {
// we use a struct to avoid stack too deep
SimAmounts memory simAmounts;
// read asset data
(simAmounts.payAsset, ) = _decodeAssetData(assetInData);
(simAmounts.receiveAsset, ) = _decodeAssetData(assetOutData);
// get initial balances of receiver
simAmounts.amountReceived = _balanceOf(simAmounts.receiveAsset, receiver);
simAmounts.amountPaid = _balanceOf(simAmounts.payAsset, msg.sender);
// narrow scope for stack too deep
{
(bool success, bytes memory returnData) = address(this).delegatecall(
abi.encodeWithSelector(
DeltaMetaAggregator.swapMeta.selector, // call swap meta on sel
permitData,
swapData,
assetInData,
assetOutData,
amountIn,
approvalTarget,
swapTarget,
receiver
)
);
if (!success) {
revert SimulationResults(0, 0, returnData);
}
}
// get post swap balances
simAmounts.amountReceived = _balanceOf(simAmounts.receiveAsset, receiver) - simAmounts.amountReceived;
simAmounts.amountPaid = simAmounts.amountPaid - _balanceOf(simAmounts.payAsset, msg.sender);
revert SimulationResults(simAmounts.amountPaid, simAmounts.amountReceived, "");
}
////////////////////////////////////////////////////
// Internals
////////////////////////////////////////////////////
/// @dev executes call on target with data
/// -> MUST validate the selector and target first
/// @param data calldata
/// @param target target address
function _executeExternalCall(bytes calldata data, address target) private {
assembly {
let ptr := mload(0x40)
calldatacopy(ptr, data.offset, data.length) // copy permit calldata
if iszero(
call(
gas(),
target,
callvalue(),
ptr, //
data.length, // the length must be correct or the call will fail
0x0, // output = empty
0x0 // output size = zero
)
) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
/// @dev checks that
/// - Permit2 cannot be called
/// - the selector cannot be IERC20.transferFrom
function _validateCalldata(bytes calldata data, address swapTarget) private pure {
assembly {
// extract the selector from the calldata
let selector := and(SELECTOR_MASK, calldataload(data.offset))
// check if it is `transferFrom`
if eq(selector, ERC20_TRANSFER_FROM) {
mstore(0x0, INVALID_SWAP_CALL)
revert(0x0, 0x4)
}
// check if the target is permit2
if eq(swapTarget, PERMIT2) {
mstore(0x0, INVALID_SWAP_CALL)
revert(0x0, 0x4)
}
}
}
/// @dev enforce that msg.value is provided
function _requireHasMsgValue() private view {
assembly {
if iszero(callvalue()) {
mstore(0x0, HAS_NO_MSG_VALUE)
revert(0x0, 0x4)
}
}
}
/// @dev decode asset data to asset address and sweep flag
function _decodeAssetData(bytes32 data) private pure returns (address asset, bool sweep) {
assembly {
asset := and(ADDRESS_MASK, data)
sweep := and(SWEEP_MASK, data)
}
}
/// @dev Checks approvals in storage and sets the allowance to the
/// maximum if the current approval is not already >= an amount.
/// Reverts if the return data is invalid or the call reverts.
/// @param token The address of the token contract.
/// @param spender The address that receives an allowance.
function _approveIfNot(address token, address spender) private {
// approve if necessary
if (!_approvedTargets[token][spender]) {
assembly {
let ptr := mload(0x40)
////////////////////////////////////////////////////
// Approve, at this point it is clear that the target is nonzero
////////////////////////////////////////////////////
// selector for approve(address,uint256)
mstore(ptr, ERC20_APPROVE)
mstore(add(ptr, 0x04), spender)
mstore(add(ptr, 0x24), MAX_UINT_256)
if iszero(call(gas(), token, 0x0, ptr, 0x44, ptr, 32)) {
revert(0x0, 0x0)
}
}
_approvedTargets[token][spender] = true;
}
}
/// @dev balanceOf call in assembly, compatible for both native (use address zero for underlying) and ERC20
function _balanceOf(address underlying, address entity) private view returns (uint256 entityBalance) {
assembly {
switch iszero(underlying)
case 1 {
entityBalance := balance(entity)
}
default {
////////////////////////////////////////////////////
// get token balance in assembly usingn scrap space (64 bytes)
////////////////////////////////////////////////////
// selector for balanceOf(address)
mstore(0x0, ERC20_BALANCE_OF)
// add this address as parameter
mstore(0x4, entity)
// call to underlying
if iszero(staticcall(gas(), underlying, 0x0, 0x24, 0x0, 0x20)) {
revert(0x0, 0x0)
}
entityBalance := mload(0x0)
}
}
}
/// @dev sweep asset to caller if sweep=true
function _sweepTokenIfNeeded(bool sweep, address token) private {
assembly {
if sweep {
// initialize transferAmount
switch iszero(token)
case 1 {
let transferAmount := selfbalance()
if gt(transferAmount, 0) {
if iszero(
call(
gas(),
caller(),
transferAmount,
0x0, // input = empty for fallback/receive
0x0, // input size = zero
0x0, // output = empty
0x0 // output size = zero
)
) {
mstore(0, NATIVE_TRANSFER_FAILED)
revert(0, 0x4) // revert when native transfer fails
}
}
}
default {
// selector for balanceOf(address)
mstore(0, ERC20_BALANCE_OF)
// add this address as parameter
mstore(0x04, address())
// call to token
pop(
staticcall(
gas(),
token,
0x0,
0x24,
0x0,
0x20 //
)
)
// load the retrieved balance
let transferAmount := mload(0x0)
if gt(transferAmount, 0) {
let ptr := mload(0x40) // free memory pointer
// selector for transfer(address,uint256)
mstore(ptr, ERC20_TRANSFER)
mstore(add(ptr, 0x04), caller())
mstore(add(ptr, 0x24), transferAmount)
let success := call(gas(), token, 0, ptr, 0x44, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0, rdsize)
revert(ptr, rdsize)
}
}
}
}
}
}
/// @dev sweep asset to receiver if sweep=true
function _handleOutputAsset(bytes32 data, address receiver) private {
assembly {
if and(SWEEP_MASK, data) {
let token := and(ADDRESS_MASK, data)
// initialize transferAmount
switch iszero(token)
case 1 {
let transferAmount := selfbalance()
if gt(transferAmount, 0) {
if iszero(
call(
gas(),
receiver,
transferAmount,
0x0, // input = empty for fallback/receive
0x0, // input size = zero
0x0, // output = empty
0x0 // output size = zero
)
) {
mstore(0, NATIVE_TRANSFER_FAILED)
revert(0, 0x4) // revert when native transfer fails
}
}
}
default {
// selector for balanceOf(address)
mstore(0, ERC20_BALANCE_OF)
// add this address as parameter
mstore(0x04, address())
// call to token
pop(
staticcall(
gas(),
token,
0x0,
0x24,
0x0,
0x20 //
)
)
// load the retrieved balance
let transferAmount := mload(0x0)
if gt(transferAmount, 0) {
let ptr := mload(0x40) // free memory pointer
// selector for transfer(address,uint256)
mstore(ptr, ERC20_TRANSFER)
mstore(add(ptr, 0x04), receiver)
mstore(add(ptr, 0x24), transferAmount)
let success := call(gas(), token, 0, ptr, 0x44, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0, rdsize)
revert(ptr, rdsize)
}
}
}
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
/// @title PermitConstants
/// @notice A contract containing constants used for Permit2 & ERC20 type permits
abstract contract PermitConstants {
/*//////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////*/
/// @dev default Permit2 address
address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; // solhint-disable-line var-name-mixedcase
bytes32 internal constant ERC20_PERMIT = 0xd505accf00000000000000000000000000000000000000000000000000000000;
bytes32 internal constant DAI_PERMIT = 0x8fcbaf0c00000000000000000000000000000000000000000000000000000000;
bytes32 internal constant PERMIT2_PERMIT = 0x2b67b57000000000000000000000000000000000000000000000000000000000;
bytes32 internal constant CREDIT_PERMIT = 0x0b52d55800000000000000000000000000000000000000000000000000000000;
bytes32 internal constant PERMIT2_TRANSFER_FROM = 0x36c7851600000000000000000000000000000000000000000000000000000000;
bytes4 internal constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;
import {PermitConstants} from "./PermitConstants.sol";
import {ERC20Selectors} from "../selectors/ERC20Selectors.sol";
/// @title PermitUtilsSlim
/// @notice A contract containing utilities for Permits
abstract contract PermitUtilsSlim is PermitConstants, ERC20Selectors {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error SafePermitBadLength();
error HasMsgValue();
bytes4 internal constant HAS_MSG_VALUE = 0xf6a73902;
/*//////////////////////////////////////////////////////////////
CONSTRUCTOR
//////////////////////////////////////////////////////////////*/
constructor() { }
/**
* @notice The function attempts to call the permit function on a given ERC20 token and executes a transfer afterwards
* @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2.
* It accommodates both Compact and Full formats of these permit types.
* Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter
* for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by
* gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and
* zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one
* before invocation for optimized performance.
* Note that the implementation does not perform dirty bits cleaning, so it is the responsibility of
* the caller to make sure that the higher 96 bits of the `owner` and `spender` parameters are clean.
* @param token The address of the ERC20 token on which to call the permit function.
* @param amount Amount to pull from the caller - should be less than or equal the permit amount
* @param permit The off-chain permit data, containing different fields depending on the type of permit function.
*/
function _permitAndPull(address token, uint256 amount, bytes calldata permit) internal {
assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
// revert if native value provided
if gt(callvalue(), 0) {
mstore(0x0, HAS_MSG_VALUE)
revert(0x0, 0x4)
}
let ptr := mload(0x40)
// Switch case for different permit lengths, indicating different permit standards
switch permit.length
// Compact IERC20Permit
case 100 {
mstore(ptr, ERC20_PERMIT) // store selector
mstore(add(ptr, 0x04), caller()) // store owner
mstore(add(ptr, 0x24), address()) // store spender
// Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)
{ // stack too deep
let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23
let vs := calldataload(add(permit.offset, 0x44)) // loads permit.offset 0x44..0x63
calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // store value = copy permit.offset 0x00..0x19
mstore(add(ptr, 0x64), sub(deadline, 1)) // store deadline = deadline - 1
mstore(add(ptr, 0x84), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28)
calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r = copy permit.offset 0x24..0x43
mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) // store s = vs without most significant bit
}
// IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
let success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
if iszero(success) {
returndatacopy(ptr, 0x0, returndatasize())
revert(ptr, returndatasize())
}
////////////////////////////////////////////////////
// transferFrom on token
////////////////////////////////////////////////////
// selector for transferFrom(address,address,uint256)
mstore(ptr, ERC20_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller()) // store owner
// spender still in place
mstore(add(ptr, 0x44), amount) // store amount (we do not want to take the same as the permit one)
success := call(gas(), token, 0x0, ptr, 0x64, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0x0, rdsize)
revert(ptr, rdsize)
}
}
// Compact IDaiLikePermit
case 72 {
mstore(ptr, DAI_PERMIT) // store selector
mstore(add(ptr, 0x04), caller()) // store owner
mstore(add(ptr, 0x24), address()) // store spender
// Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)
{ // stack too deep
let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07
let vs := calldataload(add(permit.offset, 0x28)) // loads permit.offset 0x28..0x47
mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce = copy permit.offset 0x00..0x03
mstore(add(ptr, 0x64), sub(expiry, 1)) // store expiry = expiry - 1
mstore(add(ptr, 0x84), true) // store allowed = true
mstore(add(ptr, 0xa4), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28)
calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // store r = copy permit.offset 0x08..0x27
mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) // store s = vs without most significant bit
}
// IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
let success := call(gas(), token, 0, ptr, 0x104, 0, 0)
if iszero(success) {
returndatacopy(ptr, 0x0, returndatasize())
revert(ptr, returndatasize())
}
////////////////////////////////////////////////////
// transferFrom on token
////////////////////////////////////////////////////
// selector for transferFrom(address,address,uint256)
mstore(ptr, ERC20_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller()) // store owner
// spender still in place
mstore(add(ptr, 0x44), amount) // store amount
success := call(gas(), token, 0x0, ptr, 0x64, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0x0, rdsize)
revert(ptr, rdsize)
}
}
// IERC20Permit
case 224 {
mstore(ptr, ERC20_PERMIT)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
let success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
if iszero(success) {
returndatacopy(ptr, 0x0, returndatasize())
revert(ptr, returndatasize())
}
////////////////////////////////////////////////////
// transferFrom on token
////////////////////////////////////////////////////
// selector for transferFrom(address,address,uint256)
mstore(ptr, ERC20_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller()) // store owner
// spender still in place
mstore(add(ptr, 0x44), amount) // store amount (we do not want to take the same as the permit one)
success := call(gas(), token, 0x0, ptr, 0x64, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0x0, rdsize)
revert(ptr, rdsize)
}
}
// IDaiLikePermit
case 256 {
mstore(ptr, DAI_PERMIT)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
let success := call(gas(), token, 0, ptr, 0x104, 0, 0)
if iszero(success) {
returndatacopy(ptr, 0x0, returndatasize())
revert(ptr, returndatasize())
}
////////////////////////////////////////////////////
// transferFrom on token
////////////////////////////////////////////////////
// selector for transferFrom(address,address,uint256)
mstore(ptr, ERC20_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller()) // store owner
// spender still in place
mstore(add(ptr, 0x44), amount)
success := call(gas(), token, 0x0, ptr, 0x64, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0x0, rdsize)
revert(ptr, rdsize)
}
}
// Compact IPermit2
case 96 {
// Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)
mstore(ptr, PERMIT2_PERMIT) // store selector
mstore(add(ptr, 0x04), caller()) // store owner
mstore(add(ptr, 0x24), token) // store token
calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff)
mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b
mstore(add(ptr, 0xa4), address()) // store spender
// and(0xffffffffffff, ...) - conversion to uint48
mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff)
mstore(add(ptr, 0xe4), 0x100) // store offset = 256
mstore(add(ptr, 0x104), 0x40) // store length = 64
calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r = copy permit.offset 0x20..0x3f
calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs = copy permit.offset 0x40..0x5f
// IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
if iszero(call(gas(), PERMIT2, 0, ptr, 0x164, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
////////////////////////////////////////////////////
// transferFrom through permit2
////////////////////////////////////////////////////
mstore(ptr, PERMIT2_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller())
mstore(add(ptr, 0x24), address())
mstore(add(ptr, 0x44), amount)
mstore(add(ptr, 0x64), token)
if iszero(call(gas(), PERMIT2, 0, ptr, 0x84, 0x0, 0x0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
// IPermit2
case 352 {
mstore(ptr, PERMIT2_PERMIT)
calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata
// IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
if iszero(call(gas(), PERMIT2, 0, ptr, 0x164, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
////////////////////////////////////////////////////
// transferFrom through permit2
////////////////////////////////////////////////////
mstore(ptr, PERMIT2_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller())
mstore(add(ptr, 0x24), address())
mstore(add(ptr, 0x44), amount)
mstore(add(ptr, 0x64), token)
if iszero(call(gas(), PERMIT2, 0, ptr, 0x84, 0x0, 0x0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
// Just transfer
case 0 {
// selector for transferFrom(address,address,uint256)
mstore(ptr, ERC20_TRANSFER_FROM)
mstore(add(ptr, 0x04), caller())
mstore(add(ptr, 0x24), address())
mstore(add(ptr, 0x44), amount)
let success := call(gas(), token, 0x0, ptr, 0x64, ptr, 32)
let rdsize := returndatasize()
// Check for ERC20 success. ERC20 tokens should return a boolean,
// but some don't. We accept 0-length return data as success, or at
// least 32 bytes that starts with a 32-byte boolean true.
success := and(
success, // call itself succeeded
or(
iszero(rdsize), // no return data, or
and(
iszero(lt(rdsize, 32)), // at least 32 bytes
eq(mload(ptr), 1) // starts with uint256(1)
)
)
)
if iszero(success) {
returndatacopy(ptr, 0x0, rdsize)
revert(ptr, rdsize)
}
}
// Unknown
default {
mstore(ptr, _PERMIT_LENGTH_ERROR)
revert(ptr, 4)
}
}
}
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
abstract contract ERC20Selectors {
////////////////////////////////////////////////////
// ERC20 selectors
////////////////////////////////////////////////////
/// @dev selector for approve(address,uint256)
bytes32 internal constant ERC20_APPROVE = 0x095ea7b300000000000000000000000000000000000000000000000000000000;
/// @dev selector for transferFrom(address,address,uint256)
bytes32 internal constant ERC20_TRANSFER_FROM = 0x23b872dd00000000000000000000000000000000000000000000000000000000;
/// @dev selector for transfer(address,uint256)
bytes32 internal constant ERC20_TRANSFER = 0xa9059cbb00000000000000000000000000000000000000000000000000000000;
/// @dev selector for allowance(address,address)
bytes32 internal constant ERC20_ALLOWANCE = 0xdd62ed3e00000000000000000000000000000000000000000000000000000000;
/// @dev selector for balanceOf(address)
bytes32 internal constant ERC20_BALANCE_OF = 0x70a0823100000000000000000000000000000000000000000000000000000000;
}{
"evmVersion": "shanghai",
"libraries": {},
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 1000000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"HasMsgValue","type":"error"},{"inputs":[],"name":"HasNoMsgValue","type":"error"},{"inputs":[],"name":"InvalidSwapCall","type":"error"},{"inputs":[],"name":"NativeTransferFailed","type":"error"},{"inputs":[],"name":"SafePermitBadLength","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountPaid","type":"uint256"},{"internalType":"uint256","name":"amountReceived","type":"uint256"},{"internalType":"bytes","name":"errorData","type":"bytes"}],"name":"SimulationResults","type":"error"},{"inputs":[{"internalType":"bytes","name":"permitData","type":"bytes"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"bytes32","name":"assetInData","type":"bytes32"},{"internalType":"bytes32","name":"assetOutData","type":"bytes32"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"approvalTarget","type":"address"},{"internalType":"address","name":"swapTarget","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"simSwapMeta","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"permitData","type":"bytes"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"bytes32","name":"assetInData","type":"bytes32"},{"internalType":"bytes32","name":"assetOutData","type":"bytes32"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"approvalTarget","type":"address"},{"internalType":"address","name":"swapTarget","type":"address"},{"internalType":"address","name":"receiver","type":"address"}],"name":"swapMeta","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6080604052348015600e575f5ffd5b50610f448061001c5f395ff3fe60806040526004361061002b575f3560e01c806384475995146100365780639239fd171461004b575f5ffd5b3661003257005b5f5ffd5b610049610044366004610cbe565b61005e565b005b610049610059366004610cbe565b6102a5565b604080516080810182525f918101829052606081019190915273ffffffffffffffffffffffffffffffffffffffff87811682528616602082018190526100a49083610340565b604082015280516100b59033610340565b8160600181815250505f5f3073ffffffffffffffffffffffffffffffffffffffff16639239fd1760e01b8e8e8e8e8e8e8e8e8e8e6040516024016101029a99989796959493929190610dc0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161018b9190610e57565b5f60405180830381855af49150503d805f81146101c3576040519150601f19603f3d011682016040523d82523d5f602084013e6101c8565b606091505b509150915081610213575f5f826040517f8f7730bd00000000000000000000000000000000000000000000000000000000815260040161020a93929190610e72565b60405180910390fd5b50508060400151610228826020015184610340565b6102329190610ed0565b604082015280516102439033610340565b81606001516102529190610ed0565b606082810182905260408084015190517f8f7730bd0000000000000000000000000000000000000000000000000000000081526004810193909352602483015260448201525f606482015260840161020a565b73ffffffffffffffffffffffffffffffffffffffff86167f800000000000000000000000000000000000000000000000000000000000000087168115610300576102f182878e8e610398565b6102fb828661083e565b610308565b610308610937565b6103138a8a86610966565b61031e8a8a86610a1d565b6103288183610a3e565b6103328784610b27565b505050505050505050505050565b5f82156001811461038c577f70a08231000000000000000000000000000000000000000000000000000000005f528260045260205f60245f875afa610383575f5ffd5b5f519150610391565b823191505b5092915050565b34156103c6577ff6a73902000000000000000000000000000000000000000000000000000000005f5260045ffd5b604051816064811461042a576048811461052e5760e081146105da57610100811461061a576060811461065b5761016081146107855780156107d4577f68275857000000000000000000000000000000000000000000000000000000008252600482fd5b7fd505accf000000000000000000000000000000000000000000000000000000008252336004830152306024830152602084013560e01c604485013560208660448601376001820360648501528060ff1c601b01608485015260206024870160a48601377f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660c4840152505f8060e484828a5af1806104cc573d5f843e3d83fd5b7f23b872dd0000000000000000000000000000000000000000000000000000000083523360048401528560448401526020836064855f8b5af190503d6001845114602082101516811517821691508161052757805f853e8084fd5b5050610836565b7f8fcbaf0c000000000000000000000000000000000000000000000000000000008252336004830152306024830152600484013560e01c6028850135853560e01c6044850152600182036064850152600160848501528060ff1c601b0160a485015260206008870160c48601377f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e4840152505f8061010484828a5af1806104cc573d5f843e3d83fd5b7fd505accf000000000000000000000000000000000000000000000000000000008252828460048401375f5f60e4845f8a5af1806104cc573d5f843e3d83fd5b7f8fcbaf0c000000000000000000000000000000000000000000000000000000008252828460048401375f5f610104845f8a5af1806104cc573d5f843e3d83fd5b7f2b67b57000000000000000000000000000000000000000000000000000000000825233600483015285602483015260148460508401376001601485013560e01c0365ffffffffffff166064830152601884013560e01c60848301523060a48301526001601c85013560e01c0365ffffffffffff1660c483015261010060e4830152604061010483015260208085016101248401376020604085016101448401375f5f610164845f6e22d473030f116ddee9f6b43ac78ba35af1610721573d5f5f3e3d5ffd5b7f36c785160000000000000000000000000000000000000000000000000000000082523360048301523060248301528460448301528560648301525f5f6084845f6e22d473030f116ddee9f6b43ac78ba35af1610780573d5f5f3e3d5ffd5b610836565b7f2b67b570000000000000000000000000000000000000000000000000000000008252828460048401375f5f610164845f6e22d473030f116ddee9f6b43ac78ba35af1610721573d5f5f3e3d5ffd5b7f23b872dd0000000000000000000000000000000000000000000000000000000082523360048301523060248301528460448301526020826064845f8a5af13d6001845114602082101516811517821691508161083357805f853e8084fd5b50505b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8083165f908152602081815260408083209385168352929052205460ff16610933576040517f095ea7b30000000000000000000000000000000000000000000000000000000081528160048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526020816044835f875af16108d9575f5ffd5b5073ffffffffffffffffffffffffffffffffffffffff8083165f9081526020818152604080832093851683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b5050565b34610964577f07270ad5000000000000000000000000000000000000000000000000000000005f5260045ffd5b565b82357fffffffff00000000000000000000000000000000000000000000000000000000167f23b872dd0000000000000000000000000000000000000000000000000000000081036109d9577fee68db59000000000000000000000000000000000000000000000000000000005f5260045ffd5b506e22d473030f116ddee9f6b43ac78ba38103610a18577fee68db59000000000000000000000000000000000000000000000000000000005f5260045ffd5b505050565b604051828482375f5f848334865af1610a38573d5f5f3e3d5ffd5b50505050565b811561093357801560018114610aec577f70a08231000000000000000000000000000000000000000000000000000000005f523060045260205f60245f855afa505f518015610a38576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201528160248201526020816044835f885af13d60018351146020821015168115178216915081610ae357805f843e8083fd5b50505050505050565b478015610a38575f5f5f5f84335af1610a38577ff4b3b1bc000000000000000000000000000000000000000000000000000000005f5260045ffd5b817f80000000000000000000000000000000000000000000000000000000000000001615610933578173ffffffffffffffffffffffffffffffffffffffff16801560018114610c0f577f70a08231000000000000000000000000000000000000000000000000000000005f523060045260205f60245f855afa505f518015610c09576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081528460048201528160248201526020816044835f885af13d60018351146020821015168115178216915081610c0557805f843e8083fd5b5050505b50610a38565b478015610c4a575f5f5f5f84885af1610c4a577ff4b3b1bc000000000000000000000000000000000000000000000000000000005f5260045ffd5b5050505050565b5f5f83601f840112610c61575f5ffd5b50813567ffffffffffffffff811115610c78575f5ffd5b602083019150836020828501011115610c8f575f5ffd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610cb9575f5ffd5b919050565b5f5f5f5f5f5f5f5f5f5f6101008b8d031215610cd8575f5ffd5b8a3567ffffffffffffffff811115610cee575f5ffd5b610cfa8d828e01610c51565b909b5099505060208b013567ffffffffffffffff811115610d19575f5ffd5b610d258d828e01610c51565b90995097505060408b0135955060608b0135945060808b01359350610d4c60a08c01610c96565b9250610d5a60c08c01610c96565b9150610d6860e08c01610c96565b90509295989b9194979a5092959850565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b61010081525f610dd561010083018c8e610d79565b8281036020840152610de8818b8d610d79565b604084019990995250506060810195909552608085019390935273ffffffffffffffffffffffffffffffffffffffff91821660a0850152811660c08401521660e090910152949350505050565b5f5b83811015610e4f578181015183820152602001610e37565b50505f910152565b5f8251610e68818460208701610e35565b9190910192915050565b838152826020820152606060408201525f8251806060840152610e9c816080850160208701610e35565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01691909101608001949350505050565b81810381811115610f08577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea2646970667358221220a389e51fb7990b0abd9f93faae7cc346d4ec30a7315ae5f2a6fb836b8688e2f964736f6c634300081c0033
Deployed Bytecode
0x60806040526004361061002b575f3560e01c806384475995146100365780639239fd171461004b575f5ffd5b3661003257005b5f5ffd5b610049610044366004610cbe565b61005e565b005b610049610059366004610cbe565b6102a5565b604080516080810182525f918101829052606081019190915273ffffffffffffffffffffffffffffffffffffffff87811682528616602082018190526100a49083610340565b604082015280516100b59033610340565b8160600181815250505f5f3073ffffffffffffffffffffffffffffffffffffffff16639239fd1760e01b8e8e8e8e8e8e8e8e8e8e6040516024016101029a99989796959493929190610dc0565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161018b9190610e57565b5f60405180830381855af49150503d805f81146101c3576040519150601f19603f3d011682016040523d82523d5f602084013e6101c8565b606091505b509150915081610213575f5f826040517f8f7730bd00000000000000000000000000000000000000000000000000000000815260040161020a93929190610e72565b60405180910390fd5b50508060400151610228826020015184610340565b6102329190610ed0565b604082015280516102439033610340565b81606001516102529190610ed0565b606082810182905260408084015190517f8f7730bd0000000000000000000000000000000000000000000000000000000081526004810193909352602483015260448201525f606482015260840161020a565b73ffffffffffffffffffffffffffffffffffffffff86167f800000000000000000000000000000000000000000000000000000000000000087168115610300576102f182878e8e610398565b6102fb828661083e565b610308565b610308610937565b6103138a8a86610966565b61031e8a8a86610a1d565b6103288183610a3e565b6103328784610b27565b505050505050505050505050565b5f82156001811461038c577f70a08231000000000000000000000000000000000000000000000000000000005f528260045260205f60245f875afa610383575f5ffd5b5f519150610391565b823191505b5092915050565b34156103c6577ff6a73902000000000000000000000000000000000000000000000000000000005f5260045ffd5b604051816064811461042a576048811461052e5760e081146105da57610100811461061a576060811461065b5761016081146107855780156107d4577f68275857000000000000000000000000000000000000000000000000000000008252600482fd5b7fd505accf000000000000000000000000000000000000000000000000000000008252336004830152306024830152602084013560e01c604485013560208660448601376001820360648501528060ff1c601b01608485015260206024870160a48601377f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660c4840152505f8060e484828a5af1806104cc573d5f843e3d83fd5b7f23b872dd0000000000000000000000000000000000000000000000000000000083523360048401528560448401526020836064855f8b5af190503d6001845114602082101516811517821691508161052757805f853e8084fd5b5050610836565b7f8fcbaf0c000000000000000000000000000000000000000000000000000000008252336004830152306024830152600484013560e01c6028850135853560e01c6044850152600182036064850152600160848501528060ff1c601b0160a485015260206008870160c48601377f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660e4840152505f8061010484828a5af1806104cc573d5f843e3d83fd5b7fd505accf000000000000000000000000000000000000000000000000000000008252828460048401375f5f60e4845f8a5af1806104cc573d5f843e3d83fd5b7f8fcbaf0c000000000000000000000000000000000000000000000000000000008252828460048401375f5f610104845f8a5af1806104cc573d5f843e3d83fd5b7f2b67b57000000000000000000000000000000000000000000000000000000000825233600483015285602483015260148460508401376001601485013560e01c0365ffffffffffff166064830152601884013560e01c60848301523060a48301526001601c85013560e01c0365ffffffffffff1660c483015261010060e4830152604061010483015260208085016101248401376020604085016101448401375f5f610164845f6e22d473030f116ddee9f6b43ac78ba35af1610721573d5f5f3e3d5ffd5b7f36c785160000000000000000000000000000000000000000000000000000000082523360048301523060248301528460448301528560648301525f5f6084845f6e22d473030f116ddee9f6b43ac78ba35af1610780573d5f5f3e3d5ffd5b610836565b7f2b67b570000000000000000000000000000000000000000000000000000000008252828460048401375f5f610164845f6e22d473030f116ddee9f6b43ac78ba35af1610721573d5f5f3e3d5ffd5b7f23b872dd0000000000000000000000000000000000000000000000000000000082523360048301523060248301528460448301526020826064845f8a5af13d6001845114602082101516811517821691508161083357805f853e8084fd5b50505b505050505050565b73ffffffffffffffffffffffffffffffffffffffff8083165f908152602081815260408083209385168352929052205460ff16610933576040517f095ea7b30000000000000000000000000000000000000000000000000000000081528160048201527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60248201526020816044835f875af16108d9575f5ffd5b5073ffffffffffffffffffffffffffffffffffffffff8083165f9081526020818152604080832093851683529290522080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790555b5050565b34610964577f07270ad5000000000000000000000000000000000000000000000000000000005f5260045ffd5b565b82357fffffffff00000000000000000000000000000000000000000000000000000000167f23b872dd0000000000000000000000000000000000000000000000000000000081036109d9577fee68db59000000000000000000000000000000000000000000000000000000005f5260045ffd5b506e22d473030f116ddee9f6b43ac78ba38103610a18577fee68db59000000000000000000000000000000000000000000000000000000005f5260045ffd5b505050565b604051828482375f5f848334865af1610a38573d5f5f3e3d5ffd5b50505050565b811561093357801560018114610aec577f70a08231000000000000000000000000000000000000000000000000000000005f523060045260205f60245f855afa505f518015610a38576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523360048201528160248201526020816044835f885af13d60018351146020821015168115178216915081610ae357805f843e8083fd5b50505050505050565b478015610a38575f5f5f5f84335af1610a38577ff4b3b1bc000000000000000000000000000000000000000000000000000000005f5260045ffd5b817f80000000000000000000000000000000000000000000000000000000000000001615610933578173ffffffffffffffffffffffffffffffffffffffff16801560018114610c0f577f70a08231000000000000000000000000000000000000000000000000000000005f523060045260205f60245f855afa505f518015610c09576040517fa9059cbb0000000000000000000000000000000000000000000000000000000081528460048201528160248201526020816044835f885af13d60018351146020821015168115178216915081610c0557805f843e8083fd5b5050505b50610a38565b478015610c4a575f5f5f5f84885af1610c4a577ff4b3b1bc000000000000000000000000000000000000000000000000000000005f5260045ffd5b5050505050565b5f5f83601f840112610c61575f5ffd5b50813567ffffffffffffffff811115610c78575f5ffd5b602083019150836020828501011115610c8f575f5ffd5b9250929050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610cb9575f5ffd5b919050565b5f5f5f5f5f5f5f5f5f5f6101008b8d031215610cd8575f5ffd5b8a3567ffffffffffffffff811115610cee575f5ffd5b610cfa8d828e01610c51565b909b5099505060208b013567ffffffffffffffff811115610d19575f5ffd5b610d258d828e01610c51565b90995097505060408b0135955060608b0135945060808b01359350610d4c60a08c01610c96565b9250610d5a60c08c01610c96565b9150610d6860e08c01610c96565b90509295989b9194979a5092959850565b81835281816020850137505f602082840101525f60207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b61010081525f610dd561010083018c8e610d79565b8281036020840152610de8818b8d610d79565b604084019990995250506060810195909552608085019390935273ffffffffffffffffffffffffffffffffffffffff91821660a0850152811660c08401521660e090910152949350505050565b5f5b83811015610e4f578181015183820152602001610e37565b50505f910152565b5f8251610e68818460208701610e35565b9190910192915050565b838152826020820152606060408201525f8251806060840152610e9c816080850160208701610e35565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01691909101608001949350505050565b81810381811115610f08577f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b9291505056fea2646970667358221220a389e51fb7990b0abd9f93faae7cc346d4ec30a7315ae5f2a6fb836b8688e2f964736f6c634300081c0033
Net Worth in USD
Net Worth in MNT
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.