Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 4217847 | 179 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
EIP7702EnsoShortcuts
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.28;
import { AbstractEnsoShortcuts } from "../AbstractEnsoShortcuts.sol";
import { AbstractMultiSend } from "../AbstractMultiSend.sol";
contract EIP7702EnsoShortcuts is AbstractMultiSend, AbstractEnsoShortcuts {
/// @notice Thrown caller is not this address.
error OnlySelfCall();
/// @notice Function to validate msg.sender.
function _checkMsgSender() internal view override(AbstractEnsoShortcuts, AbstractMultiSend) {
if (msg.sender != address(this)) revert OnlySelfCall();
}
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.16;
library CommandBuilder {
uint256 constant IDX_VARIABLE_LENGTH = 0x80;
uint256 constant IDX_VALUE_MASK = 0x7f;
uint256 constant IDX_END_OF_ARGS = 0xff;
uint256 constant IDX_USE_STATE = 0xfe;
uint256 constant IDX_ARRAY_START = 0xfd;
uint256 constant IDX_TUPLE_START = 0xfc;
uint256 constant IDX_DYNAMIC_END = 0xfb;
function buildInputs(
bytes[] memory state,
bytes4 selector,
bytes32 indices,
uint256 indicesLength
) internal view returns (bytes memory ret) {
uint256 idx; // The current command index
uint256 offsetIdx; // The index of the current free offset
uint256 count; // Number of bytes in whole ABI encoded message
uint256 free; // Pointer to first free byte in tail part of message
uint256[] memory dynamicLengths = new uint256[](10); // Optionally store the length of all dynamic types (a command cannot fit more than 10 dynamic types)
bytes memory stateData; // Optionally encode the current state if the call requires it
// Determine the length of the encoded data
for (uint256 i; i < indicesLength; ) {
idx = uint8(indices[i]);
if (idx == IDX_END_OF_ARGS) {
indicesLength = i;
break;
}
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
if (stateData.length == 0) {
stateData = abi.encode(state);
}
unchecked {
count += stateData.length;
}
} else {
(dynamicLengths, offsetIdx, count, i) = setupDynamicType(
state,
indices,
dynamicLengths,
idx,
offsetIdx,
count,
i
);
}
} else {
count = setupStaticVariable(state, count, idx);
}
unchecked {
free += 32;
++i;
}
}
// Encode it
ret = new bytes(count + 4);
assembly {
mstore(add(ret, 32), selector)
}
offsetIdx = 0;
// Use count to track current memory slot
assembly {
count := add(ret, 36)
}
for (uint256 i; i < indicesLength; ) {
idx = uint8(indices[i]);
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
assembly {
mstore(count, free)
}
memcpy(stateData, 32, ret, free + 4, stateData.length - 32);
unchecked {
free += stateData.length - 32;
}
} else if (idx == IDX_ARRAY_START) {
// Start of dynamic type, put pointer in current slot
assembly {
mstore(count, free)
}
(offsetIdx, free, i, ) = encodeDynamicArray(
ret,
state,
indices,
dynamicLengths,
offsetIdx,
free,
i
);
} else if (idx == IDX_TUPLE_START) {
// Start of dynamic type, put pointer in current slot
assembly {
mstore(count, free)
}
(offsetIdx, free, i, ) = encodeDynamicTuple(
ret,
state,
indices,
dynamicLengths,
offsetIdx,
free,
i
);
} else {
// Variable length data
uint256 argLen = state[idx & IDX_VALUE_MASK].length;
// Put a pointer in the current slot and write the data to first free slot
assembly {
mstore(count, free)
}
memcpy(
state[idx & IDX_VALUE_MASK],
0,
ret,
free + 4,
argLen
);
unchecked {
free += argLen;
}
}
} else {
// Fixed length data (length previously checked to be 32 bytes)
bytes memory stateVar = state[idx & IDX_VALUE_MASK];
// Write the data to current slot
assembly {
mstore(count, mload(add(stateVar, 32)))
}
}
unchecked {
count += 32;
++i;
}
}
}
function setupStaticVariable(
bytes[] memory state,
uint256 count,
uint256 idx
) internal pure returns (uint256 newCount) {
require(
state[idx & IDX_VALUE_MASK].length == 32,
"Static state variables must be 32 bytes"
);
unchecked {
newCount = count + 32;
}
}
function setupDynamicVariable(
bytes[] memory state,
uint256 count,
uint256 idx
) internal pure returns (uint256 newCount) {
bytes memory arg = state[idx & IDX_VALUE_MASK];
// Validate the length of the data in state is a multiple of 32
uint256 argLen = arg.length;
require(
argLen != 0 && argLen % 32 == 0,
"Dynamic state variables must be a multiple of 32 bytes"
);
// Add the length of the value, rounded up to the next word boundary, plus space for pointer
unchecked {
newCount = count + argLen + 32;
}
}
function setupDynamicType(
bytes[] memory state,
bytes32 indices,
uint256[] memory dynamicLengths,
uint256 idx,
uint256 offsetIdx,
uint256 count,
uint256 index
) internal view returns (
uint256[] memory newDynamicLengths,
uint256 newOffsetIdx,
uint256 newCount,
uint256 newIndex
) {
if (idx == IDX_ARRAY_START) {
(newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicArray(
state,
indices,
dynamicLengths,
offsetIdx,
count,
index
);
} else if (idx == IDX_TUPLE_START) {
(newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicTuple(
state,
indices,
dynamicLengths,
offsetIdx,
count,
index
);
} else {
newDynamicLengths = dynamicLengths;
newOffsetIdx = offsetIdx;
newIndex = index;
newCount = setupDynamicVariable(state, count, idx);
}
}
function setupDynamicArray(
bytes[] memory state,
bytes32 indices,
uint256[] memory dynamicLengths,
uint256 offsetIdx,
uint256 count,
uint256 index
) internal view returns (
uint256[] memory newDynamicLengths,
uint256 newOffsetIdx,
uint256 newCount,
uint256 newIndex
) {
// Current idx is IDX_ARRAY_START, next idx will contain the array length
unchecked {
newIndex = index + 1;
newCount = count + 32;
}
uint256 idx = uint8(indices[newIndex]);
require(
state[idx & IDX_VALUE_MASK].length == 32,
"Array length must be 32 bytes"
);
(newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicTuple(
state,
indices,
dynamicLengths,
offsetIdx,
newCount,
newIndex
);
}
function setupDynamicTuple(
bytes[] memory state,
bytes32 indices,
uint256[] memory dynamicLengths,
uint256 offsetIdx,
uint256 count,
uint256 index
) internal view returns (
uint256[] memory newDynamicLengths,
uint256 newOffsetIdx,
uint256 newCount,
uint256 newIndex
) {
uint256 idx;
uint256 offset;
newDynamicLengths = dynamicLengths;
// Progress to first index of the data and progress the next offset idx
unchecked {
newIndex = index + 1;
newOffsetIdx = offsetIdx + 1;
newCount = count + 32;
}
while (newIndex < 32) {
idx = uint8(indices[newIndex]);
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_DYNAMIC_END) {
newDynamicLengths[offsetIdx] = offset;
// explicit return saves gas ¯\_(?)_/¯
return (newDynamicLengths, newOffsetIdx, newCount, newIndex);
} else {
require(idx != IDX_USE_STATE, "Cannot use state from inside dynamic type");
(newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicType(
state,
indices,
newDynamicLengths,
idx,
newOffsetIdx,
newCount,
newIndex
);
}
} else {
newCount = setupStaticVariable(state, newCount, idx);
}
unchecked {
offset += 32;
++newIndex;
}
}
revert("Dynamic type was not properly closed");
}
function encodeDynamicArray(
bytes memory ret,
bytes[] memory state,
bytes32 indices,
uint256[] memory dynamicLengths,
uint256 offsetIdx,
uint256 currentSlot,
uint256 index
) internal view returns (
uint256 newOffsetIdx,
uint256 newSlot,
uint256 newIndex,
uint256 length
) {
// Progress to array length metadata
unchecked {
newIndex = index + 1;
newSlot = currentSlot + 32;
}
// Encode array length
uint256 idx = uint8(indices[newIndex]);
// Array length value previously checked to be 32 bytes
bytes memory stateVar = state[idx & IDX_VALUE_MASK];
assembly {
mstore(add(add(ret, 36), currentSlot), mload(add(stateVar, 32)))
}
(newOffsetIdx, newSlot, newIndex, length) = encodeDynamicTuple(
ret,
state,
indices,
dynamicLengths,
offsetIdx,
newSlot,
newIndex
);
unchecked {
length += 32; // Increase length to account for array length metadata
}
}
function encodeDynamicTuple(
bytes memory ret,
bytes[] memory state,
bytes32 indices,
uint256[] memory dynamicLengths,
uint256 offsetIdx,
uint256 currentSlot,
uint256 index
) internal view returns (
uint256 newOffsetIdx,
uint256 newSlot,
uint256 newIndex,
uint256 length
) {
uint256 idx;
uint256 argLen;
uint256 freePointer = dynamicLengths[offsetIdx]; // The pointer to the next free slot
unchecked {
newSlot = currentSlot + freePointer; // Update the next slot
newOffsetIdx = offsetIdx + 1; // Progress to next offsetIdx
newIndex = index + 1; // Progress to first index of the data
}
// Shift currentSlot to correct location in memory
assembly {
currentSlot := add(add(ret, 36), currentSlot)
}
while (newIndex < 32) {
idx = uint8(indices[newIndex]);
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_DYNAMIC_END) {
break;
} else if (idx == IDX_ARRAY_START) {
// Start of dynamic type, put pointer in current slot
assembly {
mstore(currentSlot, freePointer)
}
(newOffsetIdx, newSlot, newIndex, argLen) = encodeDynamicArray(
ret,
state,
indices,
dynamicLengths,
newOffsetIdx,
newSlot,
newIndex
);
unchecked {
freePointer += argLen;
length += (argLen + 32); // data + pointer
}
} else if (idx == IDX_TUPLE_START) {
// Start of dynamic type, put pointer in current slot
assembly {
mstore(currentSlot, freePointer)
}
(newOffsetIdx, newSlot, newIndex, argLen) = encodeDynamicTuple(
ret,
state,
indices,
dynamicLengths,
newOffsetIdx,
newSlot,
newIndex
);
unchecked {
freePointer += argLen;
length += (argLen + 32); // data + pointer
}
} else {
// Variable length data
argLen = state[idx & IDX_VALUE_MASK].length;
// Start of dynamic type, put pointer in current slot
assembly {
mstore(currentSlot, freePointer)
}
memcpy(
state[idx & IDX_VALUE_MASK],
0,
ret,
newSlot + 4,
argLen
);
unchecked {
newSlot += argLen;
freePointer += argLen;
length += (argLen + 32); // data + pointer
}
}
} else {
// Fixed length data (length previously checked to be 32 bytes)
bytes memory stateVar = state[idx & IDX_VALUE_MASK];
// Write to first free slot
assembly {
mstore(currentSlot, mload(add(stateVar, 32)))
}
unchecked {
length += 32;
}
}
unchecked {
currentSlot += 32;
++newIndex;
}
}
}
function writeOutputs(
bytes[] memory state,
bytes1 index,
bytes memory output
) internal pure returns (bytes[] memory) {
uint256 idx = uint8(index);
if (idx == IDX_END_OF_ARGS) return state;
if (idx & IDX_VARIABLE_LENGTH != 0) {
if (idx == IDX_USE_STATE) {
state = abi.decode(output, (bytes[]));
} else {
require(idx & IDX_VALUE_MASK < state.length, "Index out-of-bounds");
// Check the first field is 0x20 (because we have only a single return value)
uint256 argPtr;
assembly {
argPtr := mload(add(output, 32))
}
require(
argPtr == 32,
"Only one return value permitted (variable)"
);
assembly {
// Overwrite the first word of the return data with the length - 32
mstore(add(output, 32), sub(mload(output), 32))
// Insert a pointer to the return data, starting at the second word, into state
mstore(
add(add(state, 32), mul(and(idx, IDX_VALUE_MASK), 32)),
add(output, 32)
)
}
}
} else {
require(idx & IDX_VALUE_MASK < state.length, "Index out-of-bounds");
// Single word
require(
output.length == 32,
"Only one return value permitted (static)"
);
state[idx & IDX_VALUE_MASK] = output;
}
return state;
}
function writeTuple(
bytes[] memory state,
bytes1 index,
bytes memory output
) internal view {
uint256 idx = uint8(index);
if (idx == IDX_END_OF_ARGS) return;
bytes memory entry = state[idx & IDX_VALUE_MASK] = new bytes(output.length + 32);
memcpy(output, 0, entry, 32, output.length);
assembly {
let l := mload(output)
mstore(add(entry, 32), l)
}
}
function memcpy(
bytes memory src,
uint256 srcIdx,
bytes memory dest,
uint256 destIdx,
uint256 len
) internal view {
assembly {
pop(
staticcall(
gas(),
4,
add(add(src, 32), srcIdx),
len,
add(add(dest, 32), destIdx),
len
)
)
}
}
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.16;
import "./CommandBuilder.sol";
abstract contract VM {
using CommandBuilder for bytes[];
uint256 constant FLAG_CT_DELEGATECALL = 0x00; // Delegate call not currently supported
uint256 constant FLAG_CT_CALL = 0x01;
uint256 constant FLAG_CT_STATICCALL = 0x02;
uint256 constant FLAG_CT_VALUECALL = 0x03;
uint256 constant FLAG_CT_MASK = 0x03;
uint256 constant FLAG_DATA = 0x20;
uint256 constant FLAG_EXTENDED_COMMAND = 0x40;
uint256 constant FLAG_TUPLE_RETURN = 0x80;
uint256 constant SHORT_COMMAND_FILL =
0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
error ExecutionFailed(
uint256 command_index,
address target,
string message
);
function _execute(bytes32[] calldata commands, bytes[] memory state)
internal
returns (bytes[] memory)
{
bytes32 command;
uint256 flags;
bytes32 indices;
bool success;
bytes memory outData;
uint256 commandsLength = commands.length;
uint256 indicesLength;
for (uint256 i; i < commandsLength; i = _uncheckedIncrement(i)) {
command = commands[i];
flags = uint256(uint8(bytes1(command << 32)));
if (flags & FLAG_EXTENDED_COMMAND != 0) {
i = _uncheckedIncrement(i);
indices = commands[i];
indicesLength = 32;
} else {
indices = bytes32(uint256(command << 40) | SHORT_COMMAND_FILL);
indicesLength = 6;
}
if (flags & FLAG_CT_MASK == FLAG_CT_CALL) {
(success, outData) = address(uint160(uint256(command))).call( // target
// inputs
flags & FLAG_DATA == 0
? state.buildInputs(
bytes4(command), // selector
indices,
indicesLength
)
: state[
uint8(bytes1(indices)) &
CommandBuilder.IDX_VALUE_MASK
]
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_STATICCALL) {
(success, outData) = address(uint160(uint256(command))) // target
.staticcall(
// inputs
flags & FLAG_DATA == 0
? state.buildInputs(
bytes4(command), // selector
indices,
indicesLength
)
: state[
uint8(bytes1(indices)) &
CommandBuilder.IDX_VALUE_MASK
]
);
} else if (flags & FLAG_CT_MASK == FLAG_CT_VALUECALL) {
bytes memory v = state[
uint8(bytes1(indices)) &
CommandBuilder.IDX_VALUE_MASK
];
require(v.length == 32, "Value must be 32 bytes");
uint256 callEth = uint256(bytes32(v));
(success, outData) = address(uint160(uint256(command))).call{ // target
value: callEth
}(
// inputs
flags & FLAG_DATA == 0
? state.buildInputs(
bytes4(command), // selector
indices << 8, // skip value input
indicesLength - 1 // max indices length reduced by value input
)
: state[
uint8(bytes1(indices << 8)) & // first byte after value input
CommandBuilder.IDX_VALUE_MASK
]
);
} else {
revert("Invalid calltype");
}
if (!success) {
string memory message = "Unknown";
if (outData.length > 68) {
// This might be an error message, parse the outData
// Estimate the bytes length of the possible error message
uint256 estimatedLength = _estimateBytesLength(outData, 68);
// Remove selector. First 32 bytes should be a pointer that indicates the start of data in memory
assembly {
outData := add(outData, 4)
}
uint256 pointer = uint256(bytes32(outData));
if (pointer == 32) {
// Remove pointer. If it is a string, the next 32 bytes will hold the size
assembly {
outData := add(outData, 32)
}
uint256 size = uint256(bytes32(outData));
// If the size variable is the same as the estimated bytes length, we can be fairly certain
// this is a dynamic string, so convert the bytes to a string and emit the message. While an
// error function with 3 static parameters is capable of producing a similar output, there is
// low risk of a contract unintentionally emitting a message.
if (size == estimatedLength) {
// Remove size. The remaining data should be the string content
assembly {
outData := add(outData, 32)
}
message = string(outData);
}
}
}
revert ExecutionFailed({
command_index: flags & FLAG_EXTENDED_COMMAND == 0
? i
: i - 1,
target: address(uint160(uint256(command))),
message: message
});
}
if (flags & FLAG_TUPLE_RETURN != 0) {
state.writeTuple(bytes1(command << 88), outData);
} else {
state = state.writeOutputs(bytes1(command << 88), outData);
}
}
return state;
}
function _estimateBytesLength(bytes memory data, uint256 pos) internal pure returns (uint256 estimate) {
uint256 length = data.length;
estimate = length - pos; // Assume length equals alloted space
for (uint256 i = pos; i < length; ) {
if (data[i] == 0) {
// Zero bytes found, adjust estimated length
estimate = i - pos;
break;
}
unchecked {
++i;
}
}
}
function _uncheckedIncrement(uint256 i) private pure returns (uint256) {
unchecked {
++i;
}
return i;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Interface that must be implemented by smart contracts in order to receive
* ERC-1155 token transfers.
*/
interface IERC1155Receiver is IERC165 {
/**
* @dev Handles the receipt of a single ERC-1155 token type. This function is
* called at the end of a `safeTransferFrom` after the balance has been updated.
*
* NOTE: To accept the transfer, this must return
* `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
* (i.e. 0xf23a6e61, or its own function selector).
*
* @param operator The address which initiated the transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param id The ID of the token being transferred
* @param value The amount of tokens being transferred
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
*/
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
/**
* @dev Handles the receipt of a multiple ERC-1155 token types. This function
* is called at the end of a `safeBatchTransferFrom` after the balances have
* been updated.
*
* NOTE: To accept the transfer(s), this must return
* `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
* (i.e. 0xbc197c81, or its own function selector).
*
* @param operator The address which initiated the batch transfer (i.e. msg.sender)
* @param from The address which previously owned the token
* @param ids An array containing ids of each token being transferred (order and length must match values array)
* @param values An array containing amounts of each token being transferred (order and length must match ids array)
* @param data Additional data with no specified format
* @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
*/
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)
pragma solidity ^0.8.20;
import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
import {IERC1155Receiver} from "../IERC1155Receiver.sol";
/**
* @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
*
* IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
* stuck.
*/
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual override returns (bytes4) {
return this.onERC1155BatchReceived.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.20;
import {IERC721Receiver} from "../IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
* {IERC721-setApprovalForAll}.
*/
abstract contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)
pragma solidity ^0.8.20;
import {IERC165} from "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.28;
import { VM } from "enso-weiroll/VM.sol";
import { ERC1155Holder } from "openzeppelin-contracts/token/ERC1155/utils/ERC1155Holder.sol";
import { ERC721Holder } from "openzeppelin-contracts/token/ERC721/utils/ERC721Holder.sol";
abstract contract AbstractEnsoShortcuts is VM, ERC721Holder, ERC1155Holder {
event ShortcutExecuted(bytes32 accountId, bytes32 requestId);
// @notice Execute a shortcut
// @param accountId The bytes32 value representing an API user
// @param requestId The bytes32 value representing an API request
// @param commands An array of bytes32 values that encode calls
// @param state An array of bytes that are used to generate call data for each command
function executeShortcut(
bytes32 accountId,
bytes32 requestId,
bytes32[] calldata commands,
bytes[] calldata state
)
public
payable
virtual
returns (bytes[] memory response)
{
_checkMsgSender();
response = _execute(commands, state);
emit ShortcutExecuted(accountId, requestId);
}
//@notice Abstract function to validate msg.sender
function _checkMsgSender() internal view virtual;
receive() external payable virtual { }
}// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.28;
abstract contract AbstractMultiSend {
/// @notice Emitted when a multiSend is executed.
/// @param accountId The bytes32 value representing an API user
/// @param requestId The bytes32 value representing an API request
event MultiSendExecuted(bytes32 accountId, bytes32 requestId);
/// @dev Sends multiple transactions and reverts all if one fails.
/// @param _transactions Encoded transactions. Each transaction is encoded as a packed bytes of
/// operation has to be uint8(0) in this version (=> 1 byte),
/// to as a address (=> 20 bytes),
/// value as a uint256 (=> 32 bytes),
/// data length as a uint256 (=> 32 bytes),
/// data as bytes.
/// see abi.encodePacked for more information on packed encoding
/// @notice The code is for most part the same as the normal MultiSend (to keep compatibility),
/// but reverts if a transaction tries to use a delegatecall.
function executeMultiSend(
bytes32 _accountId,
bytes32 _requestId,
bytes memory _transactions
)
public
payable
virtual
{
_checkMsgSender();
emit MultiSendExecuted(_accountId, _requestId);
// solhint-disable-next-line no-inline-assembly
assembly {
let length := mload(_transactions)
let i := 0x20
for {
// Pre block is not used in "while mode"
} lt(i, length) {
// Post block is not used in "while mode"
} {
// First byte of the data is the operation.
// We shift by 248 bits (256 - 8 [operation byte]) it right since mload will always load 32 bytes (a
// word).
// This will also zero out unused data.
let operation := shr(0xf8, mload(add(_transactions, i)))
// We offset the load address by 1 byte (operation byte)
// We shift it right by 96 bits (256 - 160 [20 address bytes]) to right-align the data and zero out
// unused data.
let to := shr(0x60, mload(add(_transactions, add(i, 0x01))))
// We offset the load address by 21 byte (operation byte + 20 address bytes)
let value := mload(add(_transactions, add(i, 0x15)))
// We offset the load address by 53 byte (operation byte + 20 address bytes + 32 value bytes)
let dataLength := mload(add(_transactions, add(i, 0x35)))
// We offset the load address by 85 byte (operation byte + 20 address bytes + 32 value bytes + 32 data
// length bytes)
let data := add(_transactions, add(i, 0x55))
let success := 0
switch operation
case 0 { success := call(gas(), to, value, data, dataLength, 0, 0) }
// This version does not allow delegatecalls
case 1 { revert(0, 0) }
if eq(success, 0) { revert(0, 0) }
// Next entry starts at 85 byte + data length
i := add(i, add(0x55, dataLength))
}
}
}
/// @notice Abstract function to validate msg.sender.
function _checkMsgSender() internal view virtual;
}{
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"appendCBOR": false,
"bytecodeHash": "none",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/",
"@layerzerolabs/lz-evm-protocol-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/protocol/",
"@layerzerolabs/lz-evm-oapp-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/oapp/",
"@uniswap/v4-core/=lib/v4-core/",
"@uniswap/v4-periphery/=lib/v4-periphery/",
"devtools/=lib/devtools/packages/toolbox-foundry/src/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"enso-weiroll/=lib/enso-weiroll/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"layerzero-v2/=lib/layerzero-v2/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"safe-contracts/=lib/safe-tools/lib/safe-contracts/contracts/",
"safe-tools/=lib/safe-tools/src/",
"solady/=lib/solady/src/",
"solmate/=lib/solady/lib/solmate/src/",
"@ensdomains/=lib/v4-core/node_modules/@ensdomains/",
"@openzeppelin/=lib/v4-core/lib/openzeppelin-contracts/",
"forge-gas-snapshot/=lib/v4-periphery/lib/permit2/lib/forge-gas-snapshot/src/",
"hardhat/=lib/v4-core/node_modules/hardhat/",
"permit2/=lib/v4-periphery/lib/permit2/",
"v4-core/=lib/v4-core/src/",
"v4-periphery/=lib/v4-periphery/"
],
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"uint256","name":"command_index","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"message","type":"string"}],"name":"ExecutionFailed","type":"error"},{"inputs":[],"name":"OnlySelfCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"accountId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"MultiSendExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"accountId","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"ShortcutExecuted","type":"event"},{"inputs":[{"internalType":"bytes32","name":"_accountId","type":"bytes32"},{"internalType":"bytes32","name":"_requestId","type":"bytes32"},{"internalType":"bytes","name":"_transactions","type":"bytes"}],"name":"executeMultiSend","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"accountId","type":"bytes32"},{"internalType":"bytes32","name":"requestId","type":"bytes32"},{"internalType":"bytes32[]","name":"commands","type":"bytes32[]"},{"internalType":"bytes[]","name":"state","type":"bytes[]"}],"name":"executeShortcut","outputs":[{"internalType":"bytes[]","name":"response","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608080604052346015576114ec908161001a8239f35b5f80fdfe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c806301ffc9a714610079578063150b7a021461007457806395352c9f1461006f578063bc197c811461006a578063de388bef146100655763f23a6e610361000e5761052a565b61045d565b6103c8565b6102a0565b610198565b346100cd5760203660031901126100cd5760043563ffffffff60e01b81168091036100cd57630271189760e51b81149081156100bc575b50151560805260206080f35b6301ffc9a760e01b149050816100b0565b5f80fd5b600435906001600160a01b03821682036100cd57565b602435906001600160a01b03821682036100cd57565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761013257604052565b6100fd565b6001600160401b03811161013257601f01601f191660200190565b81601f820112156100cd5780359061016982610137565b926101776040519485610111565b828452602083830101116100cd57815f926020809301838601378301015290565b346100cd5760803660031901126100cd576101b16100d1565b506101ba6100e7565b506064356001600160401b0381116100cd576101da903690600401610152565b50604051630a85bd0160e11b8152602090f35b9181601f840112156100cd578235916001600160401b0383116100cd576020808501948460051b0101116100cd57565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b602081016020825282518091526040820191602060408360051b8301019401925f915b83831061027357505050505090565b9091929394602080610291600193603f19868203018752895161021d565b97019301930191939290610264565b60803660031901126100cd576024356004356044356001600160401b0381116100cd576102d19036906004016101ed565b90926064356001600160401b0381116100cd57610350947f049d8dd84b6a6cc45d5f68a74b23450bd3e54d84fd405d91b8b286c78d51d2499361032d61031e6103339436906004016101ed565b6103266105ea565b369161057f565b9161075b565b60408051948552602085019290925292a160405191829182610241565b0390f35b6001600160401b0381116101325760051b60200190565b9080601f830112156100cd57813561038281610354565b926103906040519485610111565b81845260208085019260051b8201019283116100cd57602001905b8282106103b85750505090565b81358152602091820191016103ab565b346100cd5760a03660031901126100cd576103e16100d1565b506103ea6100e7565b506044356001600160401b0381116100cd5761040a90369060040161036b565b506064356001600160401b0381116100cd5761042a90369060040161036b565b506084356001600160401b0381116100cd5761044a903690600401610152565b5060405163bc197c8160e01b8152602090f35b60603660031901126100cd576004356044356024356001600160401b0382116100cd576104af7f2419e5ca5826c0a65719cc3c1861d1a5ecd28b94c916adfa63a6a37b5181214a923690600401610152565b926104b86105ea565b604080519182526020820192909252a180519060205b8281106104d757005b808201805160f81c600182015160601c91601581015160358201519384915f9493845f1461051957505050506001146100cd575b156100cd57016055016104ce565b5f9550859450605501915af161050b565b346100cd5760a03660031901126100cd576105436100d1565b5061054c6100e7565b506084356001600160401b0381116100cd5761056c903690600401610152565b5060405163f23a6e6160e01b8152602090f35b92919061058b81610354565b936105996040519586610111565b602085838152019160051b8101918383116100cd5781905b8382106105bf575050505050565b81356001600160401b0381116100cd576020916105df8784938701610152565b8152019101906105b1565b3033036105f357565b63ff54bf4b60e01b5f5260045ffd5b634e487b7160e01b5f52603260045260245ffd5b91908110156106265760051b0190565b610602565b80518210156106265760209160051b010190565b1561064657565b60405162461bcd60e51b815260206004820152601660248201527556616c7565206d75737420626520333220627974657360501b6044820152606490fd5b602081519101519060208110610698575090565b5f199060200360031b1b1690565b634e487b7160e01b5f52601160045260245ffd5b5f198101919082116106c857565b6106a6565b601f198101919082116106c857565b3d15610706573d906106ed82610137565b916106fb6040519384610111565b82523d5f602084013e565b606090565b6040519061071a604083610111565b60078252662ab735b737bbb760c91b6020830152565b9081526001600160a01b0390911660208201526060604082018190526107589291019061021d565b90565b905f5b81811061076b5750505090565b610776818385610616565b35906107a461079e61079861078b8560201b90565b6001600160f81b03191690565b60f81c90565b60ff1690565b9160408316159182610a6257600101926107bf848688610616565b356020905b600383166001810361091d57505f9182919060208516610906576107f3916001600160e01b031987168c610adb565b805190602001826001600160a01b0387165af19261080f6106dc565b935b84901561086a5750506080161561084857610843929161083761078b61083d9360581b90565b87610fdf565b60010190565b61075e565b90610843929561085e61078b6108649460581b90565b90610f34565b9361083d565b85925061087561070b565b9460448151116108c5575b5050906108b2915f146108b657925b60405163ef3dcb2f60e01b81529384936001600160a01b03169060048501610730565b0390fd5b6108bf906106ba565b9261088f565b60206108dc60046108d584610d08565b9301610684565b03610880576108ed60248301610684565b146108f9575b80610880565b60440193506108b26108f3565b50607f6109179160f81c168a61062b565b516107f3565b6002810361098057505f918291906020851661096957610948916001600160e01b031987168c610adb565b8051906020016001600160a01b0386165afa926109636106dc565b93610811565b50607f61097a9160f81c168a61062b565b51610948565b600303610a2a575f91816109b161099e607f869560f81c168d61062b565b516109ac602082511461063f565b610684565b9160208616158414610a03576109d36109cd6109e59360081b90565b916106ba565b906001600160e01b031988168d610adb565b905b815191602001906001600160a01b0387165af1926109636106dc565b50607f610a1c61079e61079861078b610a239560081b90565b168b61062b565b51906109e7565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b6044820152606490fd5b926006602883901b6001600160d01b03176107c4565b6040516101609190610a8a8382610111565b600a815291601f1901366020840137565b90600482018092116106c857565b90610ab382610137565b610ac06040519182610111565b8281528092610ad1601f1991610137565b0190602036910137565b91939290935f5f915f92610aed610a78565b906060935f905b878210610c49575b5050610b0a610b0f91610a9b565b610aa9565b9760208901525f9060248901925f955b878710610b3157505050505050505050565b602087101561062657888b83891a6080811615610c275760fe8103610b8c575050506020816001928752610b798d610b6883610a9b565b610b728b516106cd565b918b61118d565b875101601f1901955b0196019593610b1f565b60fd819794959697145f14610bc1575092610bb592868660019b948a9998978560209c526112e3565b50979195909594610b82565b60fc8103610be3575092610bb592868660019b948a9998978560209c5261119f565b93610c20888293610c0f602096607f6001999c9b9a1690610c04828261062b565b51519788955261062b565b5190610c1a85610a9b565b9161117b565b0195610b82565b60209250600193979150610c3f607f8492168d61062b565b5101518152610b82565b9093959160208510156106265786851a60ff8114610cf4576080811615610cdf5760fe8103610cbf5750855115610c8f575b6020600191875101935b0196940190610af4565b945060016020604051610cb681610ca88d858301610241565b03601f198101835282610111565b96915050610c7b565b90610cd39260019692602095968a8d6110ac565b95919390939294610c85565b610cee6020916001938c611039565b93610c85565b509396509094929050610b0a610b0f610afc565b90815160431981018181116106c8579260445b828110610d2757505050565b815181101561062657818101602001516001600160f81b03191615610d4e57600101610d1b565b929350505060431981019081116106c85790565b15610d6957565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f75742d6f662d626f756e647360681b6044820152606490fd5b15610dab57565b60405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b6064820152608490fd5b15610e0857565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b6064820152608490fd5b6020818303126100cd578051906001600160401b0382116100cd57019080601f830112156100cd57815191610e9483610354565b92610ea26040519485610111565b80845260208085019160051b830101918383116100cd5760208101915b838310610ece57505050505090565b82516001600160401b0381116100cd57820185603f820112156100cd57602081015191610efa83610137565b610f076040519182610111565b83815260408385010188106100cd575f602085819660408397018386015e83010152815201920191610ebf565b91908060f81c60ff8114610fd9576080811615610fa15760fe8103610f69575050610758915060208082518301019101610e60565b602091610f7f610fe092607f8751911610610d62565b82840193610f8f84865114610e01565b51601f1901845260f31c168301015290565b610fd5929150607f1690610fb784518310610d62565b610fc46020825114610da4565b610fce828561062b565b528261062b565b5090565b50505090565b9060f81c60ff811461103457825190602082018092116106c857602092607f61100a61101d94610aa9565b921691611017838361062b565b5261062b565b51918051604084018184840160045afa5051910152565b505050565b61104a90607f60209394169061062b565b5151036110575760200190565b60405162461bcd60e51b815260206004820152602760248201527f537461746963207374617465207661726961626c6573206d75737420626520336044820152663220627974657360c81b6064820152608490fd5b90969594939260fd81036110cc5750956110c69596611470565b90919293565b60fc81036110e05750956110c69596611389565b91965091949392916110f591607f169061062b565b515180151580611170575b1561110c570160200191565b60405162461bcd60e51b815260206004820152603660248201527f44796e616d6963207374617465207661726961626c6573206d7573742062652060448201527561206d756c7469706c65206f6620333220627974657360501b6064820152608490fd5b50601f811615611100565b916020809185930101920160045afa50565b910160200190829060400160045afa50565b9193959692905f946111b1888461062b565b51936024600180878b019b019b0198820101915b602089106111d6575b505050505050565b80891a60808116156112ba5760fb81036111f057506111ce565b60fd819c92959a9499969b93979c145f1461124157509061121892918b89528a858b896112e3565b9260209a93926001928c969480919d939d97929d9e01970101985b0193019792919394906111c5565b60fc810361127b57509061125c92918b89528a858b8961119f565b9260209a93926001928c969480919d939d97929d9e0197010198611233565b6020898b8e6001959f9e9798966112ae607f869716948d610c0f61129f888861062b565b5151978897889788955261062b565b019d0197010198611233565b60206001929397969499816112d788607f999e998396169061062b565b5101518b520198611233565b93929190949560010194602086101561062657602061131d978161130c607f868b1a168561062b565b51015160248289010152019461119f565b929391929091602090910190565b1561133257565b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207573652073746174652066726f6d20696e736964652064796e604482015268616d6963207479706560b81b6064820152608490fd5b6001808501976020909601960194935f929091905b602087106113f75760405162461bcd60e51b8152602060048201526024808201527f44796e616d6963207479706520776173206e6f742070726f7065726c7920636c6044820152631bdcd95960e21b6064820152608490fd5b80871a60808116156114585760fb810361141f57505050611418908361062b565b5293929190565b61143f949561143860fe839c949a969b959c141561132b565b888b6110ac565b9197909692939192916001906020905b0193019561139e565b61146a60209160019399969a85611039565b9861144f565b9291909394600101936020851015610626576020611493607f83881a168661062b565b5151036114a75760206110c6960193611389565b60405162461bcd60e51b815260206004820152601d60248201527f4172726179206c656e677468206d7573742062652033322062797465730000006044820152606490fd
Deployed Bytecode
0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c806301ffc9a714610079578063150b7a021461007457806395352c9f1461006f578063bc197c811461006a578063de388bef146100655763f23a6e610361000e5761052a565b61045d565b6103c8565b6102a0565b610198565b346100cd5760203660031901126100cd5760043563ffffffff60e01b81168091036100cd57630271189760e51b81149081156100bc575b50151560805260206080f35b6301ffc9a760e01b149050816100b0565b5f80fd5b600435906001600160a01b03821682036100cd57565b602435906001600160a01b03821682036100cd57565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761013257604052565b6100fd565b6001600160401b03811161013257601f01601f191660200190565b81601f820112156100cd5780359061016982610137565b926101776040519485610111565b828452602083830101116100cd57815f926020809301838601378301015290565b346100cd5760803660031901126100cd576101b16100d1565b506101ba6100e7565b506064356001600160401b0381116100cd576101da903690600401610152565b50604051630a85bd0160e11b8152602090f35b9181601f840112156100cd578235916001600160401b0383116100cd576020808501948460051b0101116100cd57565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b602081016020825282518091526040820191602060408360051b8301019401925f915b83831061027357505050505090565b9091929394602080610291600193603f19868203018752895161021d565b97019301930191939290610264565b60803660031901126100cd576024356004356044356001600160401b0381116100cd576102d19036906004016101ed565b90926064356001600160401b0381116100cd57610350947f049d8dd84b6a6cc45d5f68a74b23450bd3e54d84fd405d91b8b286c78d51d2499361032d61031e6103339436906004016101ed565b6103266105ea565b369161057f565b9161075b565b60408051948552602085019290925292a160405191829182610241565b0390f35b6001600160401b0381116101325760051b60200190565b9080601f830112156100cd57813561038281610354565b926103906040519485610111565b81845260208085019260051b8201019283116100cd57602001905b8282106103b85750505090565b81358152602091820191016103ab565b346100cd5760a03660031901126100cd576103e16100d1565b506103ea6100e7565b506044356001600160401b0381116100cd5761040a90369060040161036b565b506064356001600160401b0381116100cd5761042a90369060040161036b565b506084356001600160401b0381116100cd5761044a903690600401610152565b5060405163bc197c8160e01b8152602090f35b60603660031901126100cd576004356044356024356001600160401b0382116100cd576104af7f2419e5ca5826c0a65719cc3c1861d1a5ecd28b94c916adfa63a6a37b5181214a923690600401610152565b926104b86105ea565b604080519182526020820192909252a180519060205b8281106104d757005b808201805160f81c600182015160601c91601581015160358201519384915f9493845f1461051957505050506001146100cd575b156100cd57016055016104ce565b5f9550859450605501915af161050b565b346100cd5760a03660031901126100cd576105436100d1565b5061054c6100e7565b506084356001600160401b0381116100cd5761056c903690600401610152565b5060405163f23a6e6160e01b8152602090f35b92919061058b81610354565b936105996040519586610111565b602085838152019160051b8101918383116100cd5781905b8382106105bf575050505050565b81356001600160401b0381116100cd576020916105df8784938701610152565b8152019101906105b1565b3033036105f357565b63ff54bf4b60e01b5f5260045ffd5b634e487b7160e01b5f52603260045260245ffd5b91908110156106265760051b0190565b610602565b80518210156106265760209160051b010190565b1561064657565b60405162461bcd60e51b815260206004820152601660248201527556616c7565206d75737420626520333220627974657360501b6044820152606490fd5b602081519101519060208110610698575090565b5f199060200360031b1b1690565b634e487b7160e01b5f52601160045260245ffd5b5f198101919082116106c857565b6106a6565b601f198101919082116106c857565b3d15610706573d906106ed82610137565b916106fb6040519384610111565b82523d5f602084013e565b606090565b6040519061071a604083610111565b60078252662ab735b737bbb760c91b6020830152565b9081526001600160a01b0390911660208201526060604082018190526107589291019061021d565b90565b905f5b81811061076b5750505090565b610776818385610616565b35906107a461079e61079861078b8560201b90565b6001600160f81b03191690565b60f81c90565b60ff1690565b9160408316159182610a6257600101926107bf848688610616565b356020905b600383166001810361091d57505f9182919060208516610906576107f3916001600160e01b031987168c610adb565b805190602001826001600160a01b0387165af19261080f6106dc565b935b84901561086a5750506080161561084857610843929161083761078b61083d9360581b90565b87610fdf565b60010190565b61075e565b90610843929561085e61078b6108649460581b90565b90610f34565b9361083d565b85925061087561070b565b9460448151116108c5575b5050906108b2915f146108b657925b60405163ef3dcb2f60e01b81529384936001600160a01b03169060048501610730565b0390fd5b6108bf906106ba565b9261088f565b60206108dc60046108d584610d08565b9301610684565b03610880576108ed60248301610684565b146108f9575b80610880565b60440193506108b26108f3565b50607f6109179160f81c168a61062b565b516107f3565b6002810361098057505f918291906020851661096957610948916001600160e01b031987168c610adb565b8051906020016001600160a01b0386165afa926109636106dc565b93610811565b50607f61097a9160f81c168a61062b565b51610948565b600303610a2a575f91816109b161099e607f869560f81c168d61062b565b516109ac602082511461063f565b610684565b9160208616158414610a03576109d36109cd6109e59360081b90565b916106ba565b906001600160e01b031988168d610adb565b905b815191602001906001600160a01b0387165af1926109636106dc565b50607f610a1c61079e61079861078b610a239560081b90565b168b61062b565b51906109e7565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b6044820152606490fd5b926006602883901b6001600160d01b03176107c4565b6040516101609190610a8a8382610111565b600a815291601f1901366020840137565b90600482018092116106c857565b90610ab382610137565b610ac06040519182610111565b8281528092610ad1601f1991610137565b0190602036910137565b91939290935f5f915f92610aed610a78565b906060935f905b878210610c49575b5050610b0a610b0f91610a9b565b610aa9565b9760208901525f9060248901925f955b878710610b3157505050505050505050565b602087101561062657888b83891a6080811615610c275760fe8103610b8c575050506020816001928752610b798d610b6883610a9b565b610b728b516106cd565b918b61118d565b875101601f1901955b0196019593610b1f565b60fd819794959697145f14610bc1575092610bb592868660019b948a9998978560209c526112e3565b50979195909594610b82565b60fc8103610be3575092610bb592868660019b948a9998978560209c5261119f565b93610c20888293610c0f602096607f6001999c9b9a1690610c04828261062b565b51519788955261062b565b5190610c1a85610a9b565b9161117b565b0195610b82565b60209250600193979150610c3f607f8492168d61062b565b5101518152610b82565b9093959160208510156106265786851a60ff8114610cf4576080811615610cdf5760fe8103610cbf5750855115610c8f575b6020600191875101935b0196940190610af4565b945060016020604051610cb681610ca88d858301610241565b03601f198101835282610111565b96915050610c7b565b90610cd39260019692602095968a8d6110ac565b95919390939294610c85565b610cee6020916001938c611039565b93610c85565b509396509094929050610b0a610b0f610afc565b90815160431981018181116106c8579260445b828110610d2757505050565b815181101561062657818101602001516001600160f81b03191615610d4e57600101610d1b565b929350505060431981019081116106c85790565b15610d6957565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f75742d6f662d626f756e647360681b6044820152606490fd5b15610dab57565b60405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b6064820152608490fd5b15610e0857565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b6064820152608490fd5b6020818303126100cd578051906001600160401b0382116100cd57019080601f830112156100cd57815191610e9483610354565b92610ea26040519485610111565b80845260208085019160051b830101918383116100cd5760208101915b838310610ece57505050505090565b82516001600160401b0381116100cd57820185603f820112156100cd57602081015191610efa83610137565b610f076040519182610111565b83815260408385010188106100cd575f602085819660408397018386015e83010152815201920191610ebf565b91908060f81c60ff8114610fd9576080811615610fa15760fe8103610f69575050610758915060208082518301019101610e60565b602091610f7f610fe092607f8751911610610d62565b82840193610f8f84865114610e01565b51601f1901845260f31c168301015290565b610fd5929150607f1690610fb784518310610d62565b610fc46020825114610da4565b610fce828561062b565b528261062b565b5090565b50505090565b9060f81c60ff811461103457825190602082018092116106c857602092607f61100a61101d94610aa9565b921691611017838361062b565b5261062b565b51918051604084018184840160045afa5051910152565b505050565b61104a90607f60209394169061062b565b5151036110575760200190565b60405162461bcd60e51b815260206004820152602760248201527f537461746963207374617465207661726961626c6573206d75737420626520336044820152663220627974657360c81b6064820152608490fd5b90969594939260fd81036110cc5750956110c69596611470565b90919293565b60fc81036110e05750956110c69596611389565b91965091949392916110f591607f169061062b565b515180151580611170575b1561110c570160200191565b60405162461bcd60e51b815260206004820152603660248201527f44796e616d6963207374617465207661726961626c6573206d7573742062652060448201527561206d756c7469706c65206f6620333220627974657360501b6064820152608490fd5b50601f811615611100565b916020809185930101920160045afa50565b910160200190829060400160045afa50565b9193959692905f946111b1888461062b565b51936024600180878b019b019b0198820101915b602089106111d6575b505050505050565b80891a60808116156112ba5760fb81036111f057506111ce565b60fd819c92959a9499969b93979c145f1461124157509061121892918b89528a858b896112e3565b9260209a93926001928c969480919d939d97929d9e01970101985b0193019792919394906111c5565b60fc810361127b57509061125c92918b89528a858b8961119f565b9260209a93926001928c969480919d939d97929d9e0197010198611233565b6020898b8e6001959f9e9798966112ae607f869716948d610c0f61129f888861062b565b5151978897889788955261062b565b019d0197010198611233565b60206001929397969499816112d788607f999e998396169061062b565b5101518b520198611233565b93929190949560010194602086101561062657602061131d978161130c607f868b1a168561062b565b51015160248289010152019461119f565b929391929091602090910190565b1561133257565b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207573652073746174652066726f6d20696e736964652064796e604482015268616d6963207479706560b81b6064820152608490fd5b6001808501976020909601960194935f929091905b602087106113f75760405162461bcd60e51b8152602060048201526024808201527f44796e616d6963207479706520776173206e6f742070726f7065726c7920636c6044820152631bdcd95960e21b6064820152608490fd5b80871a60808116156114585760fb810361141f57505050611418908361062b565b5293929190565b61143f949561143860fe839c949a969b959c141561132b565b888b6110ac565b9197909692939192916001906020905b0193019561139e565b61146a60209160019399969a85611039565b9861144f565b9291909394600101936020851015610626576020611493607f83881a168661062b565b5151036114a75760206110c6960193611389565b60405162461bcd60e51b815260206004820152601d60248201527f4172726179206c656e677468206d7573742062652033322062797465730000006044820152606490fd
Loading...
Loading
Loading...
Loading
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.