ETH Price: $2,191.16 (-0.15%)

Contract

0x9c9e42a7a55Be98e9C04bdd9d364D46f5f594507
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
Age
From
To

There are no matching entries

6 Internal Transactions found.

Latest 6 internal transactions

Advanced mode:
Parent Transaction Hash Method Block
Age
From
To
Transfer204133302024-07-29 16:10:59220 days ago1722269459
0x9c9e42a7...f5f594507
0.0000024 ETH
Transfer204133302024-07-29 16:10:59220 days ago1722269459
0x9c9e42a7...f5f594507
0.0000024 ETH
Deposit ETH204133302024-07-29 16:10:59220 days ago1722269459
0x9c9e42a7...f5f594507
0.00067421 ETH
Transfer204133302024-07-29 16:10:59220 days ago1722269459
0x9c9e42a7...f5f594507
0.00132578 ETH
Transfer203511752024-07-20 23:57:59228 days ago1721519879
0x9c9e42a7...f5f594507
0.002 ETH
0x3d60ad80203511752024-07-20 23:57:59228 days ago1721519879
 Contract Creation
0 ETH
Loading...
Loading

Minimal Proxy Contract for 0x787a700be36966c316fc737dc21abe2bb904ed71

Contract Name:
ScrollerAccount

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 1000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 47 : ScrollerAccount.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./AccountV3.sol"; // tokenbound base account contract
import "./interfaces/IL1GatewayRouter.sol";
import "./interfaces/IL2GasOracle.sol";
/**
* @title Tokenbound ERC-6551 Account Implementation
* @dev Implementation of an account contract with ERC-6551 compliance, capable of bridging Ether
* balances and handling gas reimbursements.
*/
contract ScrollerAccount is AccountV3 {
/**
* @dev Address of the Scroll NFT Admin Router.
*/
address constant ADMIN = 0x2b8fF41DAf40028d71c06bD71Fb1Cbb04fFceF02;
/**
* @dev Scroll bridge core contracts used by Scroller.
*/
address constant L1ROUTER = 0xF8B1378579659D8F7EE5f3C929c2f3E332E41Fd6;
address constant L2ORACLE = 0x0d7E906BD9cAFa154b048cFa766Cc1E54E39AF9B;
event PaidFees(address to, uint256 gasFee, uint256 serviceFee);
event RefundedEther(address to, uint256 amount);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 2 of 47 : BaseAccount.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-empty-blocks */
import "../interfaces/IAccount.sol";
import "../interfaces/IEntryPoint.sol";
import "./Helpers.sol";
/**
* Basic account implementation.
* this contract provides the basic logic for implementing the IAccount interface - validateUserOp
* specific account implementation should inherit it and provide the account-specific logic
*/
abstract contract BaseAccount is IAccount {
using UserOperationLib for UserOperation;
//return value in case of signature failure, with no time-range.
// equivalent to _packValidationData(true,0,0);
uint256 constant internal SIG_VALIDATION_FAILED = 1;
/**
* Return the account nonce.
* This method returns the next sequential nonce.
* For a nonce of a specific key, use `entrypoint.getNonce(account, key)`
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 3 of 47 : Helpers.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable no-inline-assembly */
/**
* returned data from validateUserOp.
* validateUserOp returns a uint256, with is created by `_packedValidationData` and parsed by `_parseValidationData`
* @param aggregator - address(0) - the account validated the signature by itself.
* address(1) - the account failed to validate the signature.
* otherwise - this is an address of a signature aggregator that must be used to validate the signature.
* @param validAfter - this UserOp is valid only after this timestamp.
* @param validaUntil - this UserOp is valid only up to this timestamp.
*/
struct ValidationData {
address aggregator;
uint48 validAfter;
uint48 validUntil;
}
//extract sigFailed, validAfter, validUntil.
// also convert zero validUntil to type(uint48).max
function _parseValidationData(uint validationData) pure returns (ValidationData memory data) {
address aggregator = address(uint160(validationData));
uint48 validUntil = uint48(validationData >> 160);
if (validUntil == 0) {
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 4 of 47 : IAccount.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
import "./UserOperation.sol";
interface IAccount {
/**
* Validate user's signature and nonce
* the entryPoint will make the call to the recipient only if this validation call returns successfully.
* signature failure should be reported by returning SIG_VALIDATION_FAILED (1).
* This allows making a "simulation call" without a valid signature
* Other failures (e.g. nonce mismatch, or invalid signature format) should still revert to signal failure.
*
* @dev Must validate caller is the entryPoint.
* Must validate the signature and nonce
* @param userOp the operation that is about to be executed.
* @param userOpHash hash of the user's request data. can be used as the basis for signature.
* @param missingAccountFunds missing funds on the account's deposit in the entrypoint.
* This is the minimum amount to transfer to the sender(entryPoint) to be able to make the call.
* The excess is left as a deposit in the entrypoint, for future calls.
* can be withdrawn anytime using "entryPoint.withdrawTo()"
* In case there is a paymaster in the request (or the current deposit is high enough), this value will be zero.
* @return validationData packaged ValidationData structure. use `_packValidationData` and `_unpackValidationData` to encode and decode
* <20-byte> sigAuthorizer - 0 for valid signature, 1 to mark signature failure,
* otherwise, an address of an "authorizer" contract.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 5 of 47 : IAggregator.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
import "./UserOperation.sol";
/**
* Aggregated Signatures validator.
*/
interface IAggregator {
/**
* validate aggregated signature.
* revert if the aggregated signature does not match the given list of operations.
*/
function validateSignatures(UserOperation[] calldata userOps, bytes calldata signature) external view;
/**
* validate signature of a single userOp
* This method is should be called by bundler after EntryPoint.simulateValidation() returns (reverts) with ValidationResultWithAggregation
* First it validates the signature over the userOp. Then it returns data to be used when creating the handleOps.
* @param userOp the userOperation received from the user.
* @return sigForUserOp the value to put into the signature field of the userOp when calling handleOps.
* (usually empty, unless account and aggregator support some kind of "multisig"
*/
function validateUserOpSignature(UserOperation calldata userOp)
external view returns (bytes memory sigForUserOp);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 6 of 47 : IEntryPoint.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
** Account-Abstraction (EIP-4337) singleton EntryPoint implementation.
** Only one instance required on each chain.
**/
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable avoid-low-level-calls */
/* solhint-disable no-inline-assembly */
/* solhint-disable reason-string */
import "./UserOperation.sol";
import "./IStakeManager.sol";
import "./IAggregator.sol";
import "./INonceManager.sol";
interface IEntryPoint is IStakeManager, INonceManager {
/***
* An event emitted after each successful request
* @param userOpHash - unique identifier for the request (hash its entire content, except signature).
* @param sender - the account that generates this request.
* @param paymaster - if non-null, the paymaster that pays for this request.
* @param nonce - the nonce value from the request.
* @param success - true if the sender transaction succeeded, false if reverted.
* @param actualGasCost - actual amount paid (by account or paymaster) for this UserOperation.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 7 of 47 : INonceManager.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
interface INonceManager {
/**
* Return the next nonce for this sender.
* Within a given key, the nonce values are sequenced (starting with zero, and incremented by one on each userop)
* But UserOp with different keys can come with arbitrary order.
*
* @param sender the account address
* @param key the high 192 bit of the nonce
* @return nonce a full nonce to pass for next UserOp with this sender.
*/
function getNonce(address sender, uint192 key)
external view returns (uint256 nonce);
/**
* Manually increment the nonce of the sender.
* This method is exposed just for completeness..
* Account does NOT need to call it, neither during validation, nor elsewhere,
* as the EntryPoint will update the nonce regardless.
* Possible use-case is call it with various keys to "initialize" their nonces to one, so that future
* UserOperations will not pay extra for the first transaction with a given key.
*/
function incrementNonce(uint192 key) external;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 8 of 47 : IStakeManager.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.12;
/**
* manage deposits and stakes.
* deposit is just a balance used to pay for UserOperations (either by a paymaster or an account)
* stake is value locked for at least "unstakeDelay" by the staked entity.
*/
interface IStakeManager {
event Deposited(
address indexed account,
uint256 totalDeposit
);
event Withdrawn(
address indexed account,
address withdrawAddress,
uint256 amount
);
/// Emitted when stake or unstake delay are modified
event StakeLocked(
address indexed account,
uint256 totalStaked,
uint256 unstakeDelaySec
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 9 of 47 : UserOperation.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.12;
/* solhint-disable no-inline-assembly */
import {calldataKeccak} from "../core/Helpers.sol";
/**
* User Operation struct
* @param sender the sender account of this request.
* @param nonce unique value the sender uses to verify it is not a replay.
* @param initCode if set, the account contract will be created by this constructor/
* @param callData the method call to execute on this account.
* @param callGasLimit the gas limit passed to the callData method call.
* @param verificationGasLimit gas used for validateUserOp and validatePaymasterUserOp.
* @param preVerificationGas gas not calculated by the handleOps method, but added to the gas paid. Covers batch overhead.
* @param maxFeePerGas same as EIP-1559 gas parameter.
* @param maxPriorityFeePerGas same as EIP-1559 gas parameter.
* @param paymasterAndData if set, this field holds the paymaster address and paymaster-specific data. the paymaster will pay for the transaction
         instead of the sender.
* @param signature sender-verified signature over the entire request, the EntryPoint address and the chain ID.
*/
struct UserOperation {
address sender;
uint256 nonce;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 10 of 47 : IERC1271.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*/
interface IERC1271 {
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 11 of 47 : ERC2771Context.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (metatx/ERC2771Context.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Context variant with ERC2771 support.
*
* WARNING: Avoid using this pattern in contracts that rely in a specific calldata length as they'll
* be affected by any forwarder whose `msg.data` is suffixed with the `from` address according to the ERC2771
* specification adding the address size in bytes (20) to the calldata size. An example of an unexpected
* behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive`
* function only accessible if `msg.data.length == 0`.
*
* WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption.
* Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender}
* recovery.
*/
abstract contract ERC2771Context is Context {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable _trustedForwarder;
/**
* @dev Initializes the contract with a trusted forwarder, which will be able to
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 12 of 47 : IERC1155Receiver.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 ERC1155 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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 13 of 47 : ERC1155Holder.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 ERC1155 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,
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 14 of 47 : IERC721.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/
interface IERC721 is IERC165 {
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 15 of 47 : IERC721Receiver.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.20;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 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
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 16 of 47 : ERC721Holder.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 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;
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 17 of 47 : Context.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 18 of 47 : Create2.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Create2.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer.
* `CREATE2` can be used to compute in advance the address where a smart
* contract will be deployed, which allows for interesting new mechanisms known
* as 'counterfactual interactions'.
*
* See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more
* information.
*/
library Create2 {
/**
* @dev Not enough balance for performing a CREATE2 deploy.
*/
error Create2InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev There's no code to deploy.
*/
error Create2EmptyBytecode();
/**
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 19 of 47 : ECDSA.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)
pragma solidity ^0.8.20;
/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/
error ECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 20 of 47 : SignatureChecker.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/SignatureChecker.sol)
pragma solidity ^0.8.20;
import {ECDSA} from "./ECDSA.sol";
import {IERC1271} from "../../interfaces/IERC1271.sol";
/**
* @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
* signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
* Argent and Safe Wallet (previously Gnosis Safe).
*/
library SignatureChecker {
/**
* @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
* signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
*
* NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
* change through time. It could return true at block N and false at block N+1 (or the opposite).
*/
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error, ) = ECDSA.tryRecover(hash, signature);
return
(error == ECDSA.RecoverError.NoError && recovered == signer) ||
isValidERC1271SignatureNow(signer, hash, signature);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 21 of 47 : ERC165.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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 ERC165 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;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 22 of 47 : IERC165.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* 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[EIP 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);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 23 of 47 : ERC4337Account.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {IEntryPoint} from "@account-abstraction/contracts/interfaces/IEntryPoint.sol";
import {UserOperation} from "@account-abstraction/contracts/interfaces/UserOperation.sol";
import {BaseAccount as BaseERC4337Account} from "@account-abstraction/contracts/core/BaseAccount.sol";
import "../utils/Errors.sol";
/**
* @title ERC-4337 Support
* @dev Implements ERC-4337 account support
*/
abstract contract ERC4337Account is BaseERC4337Account {
using ECDSA for bytes32;
IEntryPoint immutable _entryPoint;
constructor(address entryPoint_) {
if (entryPoint_ == address(0)) revert InvalidEntryPoint();
_entryPoint = IEntryPoint(entryPoint_);
}
/**
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 24 of 47 : ERC6551Account.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "erc6551/lib/ERC6551AccountLib.sol";
import "erc6551/interfaces/IERC6551Account.sol";
import "./Signatory.sol";
/**
* @title ERC-6551 Account Support
* @dev Implements the ERC-6551 Account interface
*/
abstract contract ERC6551Account is IERC6551Account, ERC165, Signatory {
uint256 _state;
receive() external payable virtual {}
/**
* @dev See: {IERC6551Account-isValidSigner}
*/
function isValidSigner(address signer, bytes calldata data)
external
view
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 25 of 47 : BaseExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/utils/Context.sol";
import "./SandboxExecutor.sol";
/**
* @title Base Executor
* @dev Base configuration for all executors
*/
abstract contract BaseExecutor is Context, SandboxExecutor {
function _beforeExecute() internal virtual {}
function _isValidExecutor(address executor) internal view virtual returns (bool);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 26 of 47 : BatchExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "../../utils/Errors.sol";
import "./BaseExecutor.sol";
/**
* @title Batch Executor
* @dev Allows multiple operations to be executed from this account in a single transaction
*/
abstract contract BatchExecutor is BaseExecutor {
struct Operation {
address to;
uint256 value;
bytes data;
uint8 operation;
}
/**
* @notice Executes a batch of operations if the caller is authorized
* @param operations Operations to execute
*/
function executeBatch(Operation[] calldata operations)
external
payable
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 27 of 47 : ERC6551Executor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "erc6551/interfaces/IERC6551Executable.sol";
import "erc6551/interfaces/IERC6551Account.sol";
import "erc6551/lib/ERC6551AccountLib.sol";
import "../../utils/Errors.sol";
import "../../lib/LibExecutor.sol";
import "../../lib/LibSandbox.sol";
import "./SandboxExecutor.sol";
import "./BaseExecutor.sol";
/**
* @title ERC-6551 Executor
* @dev Basic executor which implements the IERC6551Executable execution interface
*/
abstract contract ERC6551Executor is IERC6551Executable, ERC165, BaseExecutor {
/**
* Executes a low-level operation from this account if the caller is a valid executor
*
* @param to Account to operate on
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 28 of 47 : NestedAccountExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
import "erc6551/interfaces/IERC6551Executable.sol";
import "erc6551/interfaces/IERC6551Account.sol";
import "erc6551/lib/ERC6551AccountLib.sol";
import "../../utils/Errors.sol";
import "../../lib/LibExecutor.sol";
import "../../lib/LibSandbox.sol";
import "./SandboxExecutor.sol";
import "./BaseExecutor.sol";
import "../Lockable.sol";
/**
* @title Nested Account Executor
* @dev Allows the root owner of a nested token bound account to execute transactions directly
* against the nested account, even if intermediate accounts have not been created.
*/
abstract contract NestedAccountExecutor is BaseExecutor {
address immutable __self = address(this);
address public immutable erc6551Registry;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 29 of 47 : SandboxExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/utils/Create2.sol";
import "../../interfaces/ISandboxExecutor.sol";
import "../../utils/Errors.sol";
import "../../lib/LibSandbox.sol";
import "../../lib/LibExecutor.sol";
/**
* @title Sandbox Executor
* @dev Allows the sandbox contract for an account to execute low-level operations
*/
abstract contract SandboxExecutor is ISandboxExecutor {
/**
* @dev Ensures that a given caller is the sandbox for this account
*/
function _requireFromSandbox() internal view {
if (msg.sender != LibSandbox.sandbox(address(this))) revert NotAuthorized();
}
/**
* @dev Allows the sandbox contract to execute low-level calls from this account
*/
function extcall(address to, uint256 value, bytes calldata data)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 30 of 47 : TokenboundExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
import "erc6551/interfaces/IERC6551Executable.sol";
import "erc6551/interfaces/IERC6551Account.sol";
import "erc6551/lib/ERC6551AccountLib.sol";
import "../../utils/Errors.sol";
import "../../lib/LibExecutor.sol";
import "../../lib/LibSandbox.sol";
import "./ERC6551Executor.sol";
import "./BatchExecutor.sol";
import "./NestedAccountExecutor.sol";
/**
* @title Tokenbound Executor
* @dev Enables basic ERC-6551 execution as well as batch, nested, and mult-account execution
*/
abstract contract TokenboundExecutor is
ERC6551Executor,
BatchExecutor,
NestedAccountExecutor,
ERC2771Context
{
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 31 of 47 : Lockable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "erc6551/lib/ERC6551AccountLib.sol";
import "../utils/Errors.sol";
/**
* @title Account Lock
* @dev Allows the root owner of a token bound account to lock access to an account until a
* certain timestamp
*/
abstract contract Lockable {
/**
* @notice The timestamp at which this account will be unlocked
*/
uint256 public lockedUntil;
event LockUpdated(uint256 lockedUntil);
/**
* @dev Locks the account until a certain timestamp
*
* @param _lockedUntil The time at which this account will no longer be locke
*/
function lock(uint256 _lockedUntil) external virtual {
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 32 of 47 : Overridable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "erc6551/lib/ERC6551AccountLib.sol";
import "../utils/Errors.sol";
import "../lib/LibSandbox.sol";
/**
* @title Account Overrides
* @dev Allows the root owner of a token bound account to override the implementation of a given
* function selector on the account. Overrides are keyed by the root owner address, so will be
* disabled upon transfer of the token which owns this account tree.
*/
abstract contract Overridable {
/**
* @dev mapping from owner => selector => implementation
*/
mapping(address => mapping(bytes4 => address)) public overrides;
event OverrideUpdated(address owner, bytes4 selector, address implementation);
/**
* @dev Sets the implementation address for a given array of function selectors. Can only be
* called by the root owner of the account
*
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 33 of 47 : Permissioned.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "erc6551/lib/ERC6551AccountLib.sol";
import "../utils/Errors.sol";
/**
* @title Account Permissions
* @dev Allows the root owner of a token bound account to allow another account to execute
* operations from this account. Permissions are keyed by the root owner address, so will be
* disabled upon transfer of the token which owns this account tree.
*/
abstract contract Permissioned {
/**
* @dev mapping from owner => caller => has permissions
*/
mapping(address => mapping(address => bool)) public permissions;
event PermissionUpdated(address owner, address caller, bool hasPermission);
/**
* @dev Grants or revokes execution permissions for a given array of callers on this account.
* Can only be called by the root owner of the account
*
* @param callers Array of callers to grant permissions to
* @param _permissions Array of booleans, true if execution permissions should be granted,
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 34 of 47 : Signatory.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/interfaces/IERC1271.sol";
/**
* @title Signatory
* @dev Implements ERC-1271 signature verification
*/
abstract contract Signatory is IERC1271 {
/**
* @dev See {IERC1721-isValidSignature}
*/
function isValidSignature(bytes32 hash, bytes calldata signature)
external
view
returns (bytes4 magicValue)
{
if (_isValidSignature(hash, signature)) {
return IERC1271.isValidSignature.selector;
}
return bytes4(0);
}
function _isValidSignature(bytes32 hash, bytes calldata signature)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 35 of 47 : AccountV3.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol";
import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";
import "erc6551/lib/ERC6551AccountLib.sol";
import "./abstract/Lockable.sol";
import "./abstract/Overridable.sol";
import "./abstract/Permissioned.sol";
import "./abstract/ERC6551Account.sol";
import "./abstract/ERC4337Account.sol";
import "./abstract/execution/TokenboundExecutor.sol";
import "./lib/OPAddressAliasHelper.sol";
import "./interfaces/IAccountGuardian.sol";
/**
* @title Tokenbound ERC-6551 Account Implementation
*/
contract AccountV3 is
ERC721Holder,
ERC1155Holder,
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 36 of 47 : IAccountGuardian.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IAccountGuardian {
function setTrustedImplementation(address implementation, bool trusted) external;
function setTrustedExecutor(address executor, bool trusted) external;
function defaultImplementation() external view returns (address);
function isTrustedImplementation(address implementation) external view returns (bool);
function isTrustedExecutor(address implementation) external view returns (bool);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 37 of 47 : IL1GatewayRouter.sol
1
2
3
4
5
6
7
8
9
10
11
12
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.16;
interface IL1GatewayRouter {
function depositETH(
address _to,
uint256 _amount,
uint256 _gasLimit
) external payable;
function ethGateway() external view returns (address);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 38 of 47 : IL2GasOracle.sol
1
2
3
4
5
6
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IL2GasOracle {
function l2BaseFee() external view returns (uint256);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 39 of 47 : ISandboxExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface ISandboxExecutor {
function extcall(address to, uint256 value, bytes calldata data)
external
returns (bytes memory result);
function extcreate(uint256 value, bytes calldata data) external returns (address);
function extcreate2(uint256 value, bytes32 salt, bytes calldata bytecode)
external
returns (address);
function extsload(bytes32 slot) external view returns (bytes32 value);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 40 of 47 : LibExecutor.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "../utils/Errors.sol";
import "./LibSandbox.sol";
library LibExecutor {
uint8 constant OP_CALL = 0;
uint8 constant OP_DELEGATECALL = 1;
uint8 constant OP_CREATE = 2;
uint8 constant OP_CREATE2 = 3;
function _execute(address to, uint256 value, bytes calldata data, uint8 operation)
internal
returns (bytes memory)
{
if (operation == OP_CALL) return _call(to, value, data);
if (operation == OP_DELEGATECALL) {
address sandbox = LibSandbox.sandbox(address(this));
if (sandbox.code.length == 0) LibSandbox.deploy(address(this));
return _call(sandbox, value, abi.encodePacked(to, data));
}
if (operation == OP_CREATE) return abi.encodePacked(_create(value, data));
if (operation == OP_CREATE2) {
bytes32 salt = bytes32(data[:32]);
bytes calldata bytecode = data[32:];
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 41 of 47 : LibSandbox.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/utils/Create2.sol";
library LibSandbox {
bytes public constant header = hex"604380600d600039806000f3fe73";
bytes public constant footer =
hex"3314601d573d3dfd5b363d3d373d3d6014360360143d5160601c5af43d6000803e80603e573d6000fd5b3d6000f3";
function bytecode(address owner) internal pure returns (bytes memory) {
return abi.encodePacked(header, owner, footer);
}
function sandbox(address owner) internal view returns (address) {
return
Create2.computeAddress(keccak256("org.tokenbound.sandbox"), keccak256(bytecode(owner)));
}
function deploy(address owner) internal {
Create2.deploy(0, keccak256("org.tokenbound.sandbox"), bytecode(owner));
}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 42 of 47 : OPAddressAliasHelper.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
// Source: https://github.com/ethereum-optimism/optimism/blob/96562692558e5c3851899488bcebe51fbe3b7f09/packages/contracts-bedrock/src/vendor
    /AddressAliasHelper.sol
library OPAddressAliasHelper {
uint160 constant offset = uint160(0x1111000000000000000000000000000000001111);
/// @notice Utility function that converts the address in the L1 that submitted a tx to
/// the inbox to the msg.sender viewed in the L2
/// @param l1Address the address in the L1 that triggered the tx to L2
/// @return l2Address L2 address as viewed in msg.sender
function applyL1ToL2Alias(address l1Address) internal pure returns (address l2Address) {
unchecked {
l2Address = address(uint160(l1Address) + offset);
}
}
/// @notice Utility function that converts the msg.sender viewed in the L2 to the
/// address in the L1 that submitted a tx to the inbox
/// @param l2Address L2 address as viewed in msg.sender
/// @return l1Address the address in the L1 that triggered the tx to L2
function undoL1ToL2Alias(address l2Address) internal pure returns (address l1Address) {
unchecked {
l1Address = address(uint160(l2Address) - offset);
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 43 of 47 : Errors.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
error InvalidOperation();
error ContractCreationFailed();
error NotAuthorized();
error InvalidInput();
error ExceedsMaxLockTime();
error AccountLocked();
error InvalidAccountProof();
error InvalidGuardian();
error InvalidImplementation();
error AlreadyInitialized();
error InvalidEntryPoint();
error InvalidMulticallForwarder();
error InvalidERC6551Registry();
error OwnershipCycle();
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 44 of 47 : IERC6551Account.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @dev the ERC-165 identifier for this interface is `0x6faff5f1`
interface IERC6551Account {
/**
* @dev Allows the account to receive Ether.
*
* Accounts MUST implement a `receive` function.
*
* Accounts MAY perform arbitrary logic to restrict conditions
* under which Ether can be received.
*/
receive() external payable;
/**
* @dev Returns the identifier of the non-fungible token which owns the account.
*
* The return value of this function MUST be constant - it MUST NOT change over time.
*
* @return chainId The EIP-155 ID of the chain the token exists on
* @return tokenContract The contract address of the token
* @return tokenId The ID of the token
*/
function token()
external
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 45 of 47 : IERC6551Executable.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/// @dev the ERC-165 identifier for this interface is `0x51945447`
interface IERC6551Executable {
/**
* @dev Executes a low-level operation if the caller is a valid signer on the account.
*
* Reverts and bubbles up error if operation fails.
*
* Accounts implementing this interface MUST accept the following operation parameter values:
* - 0 = CALL
* - 1 = DELEGATECALL
* - 2 = CREATE
* - 3 = CREATE2
*
* Accounts implementing this interface MAY support additional operations or restrict a signer's
* ability to execute certain operations.
*
* @param to The target address of the operation
* @param value The Ether value to be sent to the target
* @param data The encoded operation calldata
* @param operation A value indicating the type of operation to perform
* @return The result of the operation
*/
function execute(address to, uint256 value, bytes calldata data, uint8 operation)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 46 of 47 : ERC6551AccountLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Create2.sol";
import "./ERC6551BytecodeLib.sol";
library ERC6551AccountLib {
function computeAddress(
address registry,
address _implementation,
bytes32 _salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) internal pure returns (address) {
bytes32 bytecodeHash = keccak256(
ERC6551BytecodeLib.getCreationCode(
_implementation, _salt, chainId, tokenContract, tokenId
)
);
return Create2.computeAddress(_salt, bytecodeHash, registry);
}
function isERC6551Account(address account, address expectedImplementation, address registry)
internal
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

File 47 of 47 : ERC6551BytecodeLib.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
library ERC6551BytecodeLib {
/**
* @dev Returns the creation code of the token bound account for a non-fungible token.
*
* @return result The creation code of the token bound account
*/
function getCreationCode(
address implementation,
bytes32 salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) internal pure returns (bytes memory result) {
assembly {
result := mload(0x40) // Grab the free memory pointer
// Layout the variables and bytecode backwards
mstore(add(result, 0xb7), tokenId)
mstore(add(result, 0x97), shr(96, shl(96, tokenContract)))
mstore(add(result, 0x77), chainId)
mstore(add(result, 0x57), salt)
mstore(add(result, 0x37), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(result, 0x28), implementation)
mstore(add(result, 0x14), 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Settings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"evmVersion": "paris",
"optimizer": {
"enabled": true,
"runs": 1000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"entryPoint_","type":"address"},{"internalType":"address","name":"multicallForwarder","type":"address"},{"internalType":"address","name":"erc6551Registry","type":"address"},{"internalType":"address","name":"_guardian","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccountLocked","type":"error"},{"inputs":[],"name":"ContractCreationFailed","type":"error"},{"inputs":[],"name":"Create2EmptyBytecode","type":"error"},{"inputs":[],"name":"Create2FailedDeployment","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"Create2InsufficientBalance","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"ExceedsMaxLockTime","type":"error"},{"inputs":[],"name":"InvalidAccountProof","type":"error"},{"inputs":[],"name":"InvalidERC6551Registry","type":"error"},{"inputs":[],"name":"InvalidEntryPoint","type":"error"},{"inputs":[],"name":"InvalidInput","type":"error"},{"inputs":[],"name":"InvalidMulticallForwarder","type":"error"},{"inputs":[],"name":"InvalidOperation","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"OwnershipCycle","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"lockedUntil","type":"uint256"}],"name":"LockUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"address","name":"implementation","type":"address"}],"name":"OverrideUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"gasFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"serviceFee","type":"uint256"}],"name":"PaidFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"hasPermission","type":"bool"}],"name":"PermissionUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RefundedEther","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"uint256","name":"_l1AdminGasLimit","type":"uint256"},{"internalType":"uint256","name":"_l1BridgeGasLimit","type":"uint256"},{"internalType":"uint256","name":"_l2GasLimit","type":"uint256"},{"internalType":"address payable","name":"_feeWallet","type":"address"}],"name":"bridgeEthBalance","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"entryPoint","outputs":[{"internalType":"contract IEntryPoint","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc6551Registry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint8","name":"operation","type":"uint8"}],"name":"execute","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint8","name":"operation","type":"uint8"}],"internalType":"struct BatchExecutor.Operation[]","name":"operations","type":"tuple[]"}],"name":"executeBatch","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint8","name":"operation","type":"uint8"},{"components":[{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"internalType":"struct NestedAccountExecutor.ERC6551AccountInfo[]","name":"proof","type":"tuple[]"}],"name":"executeNested","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"extcall","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"bytecode","type":"bytes"}],"name":"extcreate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes","name":"bytecode","type":"bytes"}],"name":"extcreate2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"extsload","outputs":[{"internalType":"bytes32","name":"value","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isLocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"hash","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"isValidSigner","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lockedUntil","type":"uint256"}],"name":"lock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lockedUntil","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"tokenId","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"overrides","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"permissions","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"},{"internalType":"address[]","name":"implementations","type":"address[]"}],"name":"setOverrides","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"callers","type":"address[]"},{"internalType":"bool[]","name":"_permissions","type":"bool[]"}],"name":"setPermissions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"state","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"tokenContract","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"initCode","type":"bytes"},{"internalType":"bytes","name":"callData","type":"bytes"},{"internalType":"uint256","name":"callGasLimit","type":"uint256"},{"internalType":"uint256","name":"verificationGasLimit","type":"uint256"},{"internalType":"uint256","name":"preVerificationGas","type":"uint256"},{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"bytes","name":"paymasterAndData","type":"bytes"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UserOperation","name":"userOp","type":"tuple"},{"internalType":"bytes32","name":"userOpHash","type":"bytes32"},{"internalType":"uint256","name":"missingAccountFunds","type":"uint256"}],"name":"validateUserOp","outputs":[{"internalType":"uint256","name":"validationData","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

Block Age Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Age Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Age Amount
View All Withdrawals

Transaction Hash Block Age Value Eth2 PubKey Valid
View All Deposits
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.