UNPKG

@tevm/actions

Version:

A typesafe library for writing forge scripts in typescript

1,326 lines (1,289 loc) 253 kB
import * as _tevm_utils from '@tevm/utils'; import { Abi as Abi$1, Address as Address$1, Hex as Hex$1, ContractFunctionName, EncodeFunctionDataParameters, DecodeFunctionResultReturnType, ContractConstructorArgs, EncodeDeployDataParameters, BlockTag as BlockTag$1 } from '@tevm/utils'; import { InvalidParamsError, InvalidSkipBalanceError, InvalidGasRefundError, InvalidBlockError, InvalidGasPriceError, InvalidOriginError, InvalidCallerError, InvalidDepthError, InvalidBlobVersionedHashesError, InvalidAddToMempoolError, InvalidAddToBlockchainError, UnknownBlockError, AuthCallUnsetError, BLS12381FpNotInFieldError, BLS12381InputEmptyError, BLS12381InvalidInputLengthError, BLS12381PointNotOnCurveError, CodeStoreOutOfGasError, CodeSizeExceedsMaximumError, CreateCollisionError, InvalidCommitmentError, EvmRevertError, InitcodeSizeViolationError, InsufficientBalanceError, InternalEvmError, InvalidBeginSubError, InvalidBytecodeResultError, InvalidEofFormatError, InvalidInputLengthError, InvalidJumpError, InvalidJumpSubError, InvalidKzgInputsError, InvalidOpcodeError, InvalidProofError, InvalidReturnSubError, OutOfGasError, OutOfRangeError, RefundExhaustedError, StackOverflowError, StackUnderflowError, StaticStateChangeError, StopError, ValueOverflowError, InvalidAddressError, InvalidGasLimitError, InvalidSaltError, InvalidDataError, InvalidBytecodeError, InternalError, ExecutionError, RevertError, ForkError, InvalidRequestError, InvalidAbiError, InvalidArgsError, InvalidFunctionNameError, AccountNotFoundError, InvalidBalanceError, InvalidDeployedBytecodeError, InvalidNonceError, InvalidStorageRootError } from '@tevm/errors'; import * as zod from 'zod'; import { z } from 'zod'; import { Address as Address$2 } from '@tevm/address'; import * as _tevm_evm from '@tevm/evm'; import { InterpreterStep, EvmResult, PrecompileInput, ExecResult } from '@tevm/evm'; import * as _tevm_node from '@tevm/node'; import { TevmNode, Filter } from '@tevm/node'; import * as _tevm_vm from '@tevm/vm'; import { JsonRpcRequest, JsonRpcResponse } from '@tevm/jsonrpc'; import * as _tevm_block from '@tevm/block'; import { Block as Block$1 } from '@tevm/block'; import * as viem from 'viem'; import * as abitype from 'abitype'; import { TevmState, ParameterizedTevmState, StateRoots } from '@tevm/state'; import { TxReceipt } from '@tevm/receipt-manager'; import { ChainOptions } from '@tevm/blockchain'; import { ConsensusAlgorithm, ConsensusType } from '@tevm/common'; import { TxPool } from '@tevm/txpool'; /** * The base parameters shared across all actions */ type BaseParams<TThrowOnFail extends boolean = boolean> = { /** * Whether to throw on errors or return errors as value on the 'errors' property * Defaults to `true` */ readonly throwOnFail?: TThrowOnFail; }; /** * A valid [Ethereum JSON ABI](https://docs.soliditylang.org/en/latest/abi-spec.html#json) */ type Abi = Abi$1; /** * An ethereum address represented as a hex string * @see https://abitype.dev/config#addresstype for configuration options to change type to being a string if preferred */ type Address = Address$1; /** * Header information of an ethereum block */ type Block = { /** * The block number (height) in the blockchain. */ readonly number: bigint; /** * The address of the miner or validator who mined or validated the block. */ readonly coinbase: Address; /** * The timestamp at which the block was mined or validated. */ readonly timestamp: bigint; /** * The difficulty level of the block (relevant in PoW chains). */ readonly difficulty: bigint; /** * The gas limit for the block, i.e., the maximum amount of gas that can be used by the transactions in the block. */ readonly gasLimit: bigint; /** * (Optional) The base fee per gas in the block, introduced in EIP-1559 for dynamic transaction fee calculation. */ readonly baseFeePerGas?: bigint; /** * The gas price for the block; may be undefined in blocks after EIP-1559. */ readonly blobGasPrice?: bigint; }; type BlockTag = 'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'; type BlockParam = BlockTag | Hex$1 | bigint; /** * Event emitted when a new contract is created */ interface NewContractEvent { /** Address of the newly created contract */ address: Address$2; /** Deployed contract bytecode */ code: Uint8Array; } /** * Message object representing a call to the EVM * This corresponds to the EVM's internal Message object */ interface Message { /** Target address (undefined for contract creation) */ to?: Address$2; /** Value sent with the call (in wei) */ value: bigint; /** Address of the account that initiated this call */ caller: Address$2; /** Gas limit for this call */ gasLimit: bigint; /** Input data to the call */ data: Uint8Array; /** Contract code for the call - can be bytecode or a precompile function */ code?: Uint8Array | any; /** Call depth */ depth: number; /** Whether the call is static (view) */ isStatic: boolean; /** Whether this is precompiled contract code */ isCompiled: boolean; /** Whether this is a DELEGATECALL */ delegatecall: boolean; /** Salt for CREATE2 calls */ salt?: Uint8Array; /** Origin address for AUTH calls */ authcallOrigin?: Address$2; /** Gas refund counter */ gasRefund?: bigint; } /** * Event handlers for EVM execution during a call * @example * ```typescript * import { createMemoryClient } from 'tevm' * import { tevmCall } from 'tevm/actions' * * const client = createMemoryClient() * * const result = await tevmCall(client, { * to: '0x1234...', * data: '0xabcdef...', * onStep: (step, next) => { * console.log(`Executing ${step.opcode.name} at PC=${step.pc}`) * next?.() * } * }) * ``` */ type CallEvents = { /** * Handler called on each EVM step (instruction execution) * @param data Step information including opcode, stack, and memory state * @param next Function to continue execution - must be called to proceed */ onStep?: (data: InterpreterStep, next?: () => void) => void; /** * Handler called when a new contract is created * @param data Contract creation information * @param next Function to continue execution - must be called to proceed */ onNewContract?: (data: NewContractEvent, next?: () => void) => void; /** * Handler called before a message (call) is processed * @param data Message information * @param next Function to continue execution - must be called to proceed */ onBeforeMessage?: (data: Message, next?: () => void) => void; /** * Handler called after a message (call) is processed * @param data Result information * @param next Function to continue execution - must be called to proceed */ onAfterMessage?: (data: EvmResult, next?: () => void) => void; }; /** * A hex string * @example * const hex: Hex = '0x1234ff' */ type Hex = `0x${string}`; type EmptyParams = readonly [] | {} | undefined | never; /** * Generic log information */ type Log = { readonly address: Address; readonly topics: Hex[]; readonly data: Hex; }; /** * A transaction request object */ type TransactionParams = { readonly from: Address; readonly to?: Address; readonly gas?: Hex; readonly gasPrice?: Hex; readonly value?: Hex; readonly input: Hex; readonly nonce?: Hex; }; /** * The type returned by block related * json rpc procedures */ type BlockResult<TIncludeTransactions extends boolean = false> = { /** * The block number (height) in the blockchain. */ readonly number: Hex; /** * The hex stringhash of the block. */ readonly hash: Hex; /** * The hex stringhash of the parent block. */ readonly parentHash: Hex; readonly nonce: Hex; /** * The hex stringhash of the uncles of the block. */ readonly sha3Uncles: Hex; readonly logsBloom: Hex; readonly transactionsRoot: Hex; readonly stateRoot: Hex; readonly miner: Hex; readonly difficulty: Hex; readonly totalDifficulty: Hex; readonly extraData: Hex; readonly size: Hex; readonly gasLimit: Hex; readonly gasUsed: Hex; readonly timestamp: Hex; readonly transactions: TIncludeTransactions extends true ? Array<TransactionParams> : Hex[]; readonly uncles: Hex[]; }; /** * FilterLog type for eth JSON-RPC procedures */ type FilterLog = { readonly address: Hex; readonly blockHash: Hex; readonly blockNumber: bigint; readonly data: Hex; readonly logIndex: bigint; readonly removed: boolean; readonly topics: readonly Hex[]; readonly transactionHash: Hex; readonly transactionIndex: bigint; }; /** * An event filter options object */ type FilterParams = { readonly fromBlock?: BlockParam; readonly toBlock?: BlockParam; readonly address?: Address; readonly topics?: ReadonlyArray<Hex> | ReadonlyArray<ReadonlyArray<Hex>>; }; /** * The type returned by transaction related * json rpc procedures */ type TransactionResult = { readonly blockHash: Hex; readonly blockNumber: Hex; readonly from: Hex; readonly gas: Hex; readonly gasPrice: Hex; readonly hash: Hex; readonly input: Hex; readonly nonce: Hex; readonly to: Hex; readonly transactionIndex: Hex; readonly value: Hex; readonly v: Hex; readonly r: Hex; readonly s: Hex; readonly chainId?: Hex; readonly maxFeePerGas?: Hex; readonly maxPriorityFeePerGas?: Hex; readonly type?: Hex; readonly accessList?: ReadonlyArray<{ readonly address: Hex; readonly storageKeys: ReadonlyArray<Hex>; }>; readonly maxFeePerBlobGas?: Hex; readonly blobVersionedHashes?: ReadonlyArray<Hex>; readonly isImpersonated?: boolean; }; /** * Transaction receipt result type for eth JSON-RPC procedures */ type TransactionReceiptResult = { readonly blockHash: Hex; readonly blockNumber: bigint; readonly contractAddress: Hex; readonly cumulativeGasUsed: bigint; readonly from: Hex; readonly gasUsed: bigint; readonly logs: readonly FilterLog[]; readonly logsBloom: Hex; readonly status: Hex; readonly to: Hex; readonly transactionHash: Hex; readonly transactionIndex: bigint; readonly blobGasUsed?: bigint; readonly blobGasPrice?: bigint; }; type TraceType = 'CALL' | 'DELEGATECALL' | 'STATICCALL' | 'CREATE' | 'CREATE2' | 'SELFDESTRUCT'; type TraceCall = { type: TraceType; from: Address; to: Address; value?: bigint; gas?: bigint; gasUsed?: bigint; input: Hex; output: Hex; error?: string; revertReason?: string; calls?: TraceCall[]; }; type StructLog = { readonly depth: number; readonly gas: bigint; readonly gasCost: bigint; readonly op: string; readonly pc: number; readonly stack: Array<Hex>; readonly error?: { error: string; errorType: string; }; }; /** Result from `debug_*` with no tracer */ type TraceResult = { failed: boolean; gas: bigint; returnValue: Hex; structLogs: Array<StructLog>; }; /** Result from `debug_*` with `callTracer` */ type CallTraceResult = { type: TraceType; from: Address; to: Address; value: bigint; gas: bigint; gasUsed: bigint; input: Hex; output: Hex; calls?: TraceCall[]; }; /** * The state of an account as captured by `debug_` traces */ type AccountState = { readonly balance: Hex; readonly nonce: number; readonly code: Hex; readonly storage: Record<Hex, Hex>; }; /** Result from `debug_*` with `prestateTracer` */ type PrestateTraceResult<TDiffMode extends boolean = boolean> = TDiffMode extends true ? { readonly pre: Record<Hex, AccountState>; readonly post: Record<Hex, Partial<AccountState>>; } : Record<Hex, AccountState>; /** * Represents a configuration for a forked or proxied network */ type NetworkConfig = { /** * The URL to the RPC endpoint */ url: string; /** * the block tag to fork from */ blockTag: BlockParam; }; /** * The fields of this optional object customize the block as part of which the call is simulated. The object contains the following fields: * This option cannot be used when `createTransaction` is set to `true` * Setting the block number to past block will not run in the context of that blocks state. To do that fork that block number first. */ type BlockOverrideSet = { /** * Fake block number */ number?: bigint; /** * Fake difficulty. Note post-merge difficulty should be 0. * not included as an option atm */ /** * Fake block timestamp */ time?: bigint; /** * Block gas capacity */ gasLimit?: bigint; /** * Block fee recipient */ coinbase?: Address$1; /** * Fake PrevRandao value * Not included as an option atm */ /** * Block base fee (see EIP-1559) */ baseFee?: bigint; /** * Block blob base fee (see EIP-4844) */ blobBaseFee?: bigint; }; /** * The state override set is an optional address-to-state mapping, where each entry specifies some state to be ephemerally overridden prior to executing the call. Each address maps to an object containing: * This option cannot be used when `createTransaction` is set to `true` * * The goal of the state override set is manyfold: * It can be used by DApps to reduce the amount of contract code needed to be deployed on chain. Code that simply returns internal state or does pre-defined validations can be kept off chain and fed to the node on-demand. * It can be used for smart contract analysis by extending the code deployed on chain with custom methods and invoking them. This avoids having to download and reconstruct the entire state in a sandbox to run custom code against. * It can be used to debug smart contracts in an already deployed large suite of contracts by selectively overriding some code or state and seeing how execution changes. Specialized tooling will probably be necessary. * @example * ```ts * { * "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3": { * "balance": "0xde0b6b3a7640000" * }, * "0xebe8efa441b9302a0d7eaecc277c09d20d684540": { * "code": "0x...", * "state": { * "0x...": "0x..." * } * } * } * ``` */ type StateOverrideSet = { [address: Address]: { /** * Fake balance to set for the account before executing the call. */ balance?: bigint; /** * Fake nonce to set for the account before executing the call. */ nonce?: bigint; /** * Fake code to set for the account before executing the call. */ code?: Hex$1; /** * Fake key-value mapping to override all slots in the account storage before executing the calls */ state?: Record<Hex$1, Hex$1>; /** * Fake key-value mapping to override individual slots in the account storage before executing the calls */ stateDiff?: Record<Hex$1, Hex$1>; }; }; /** * Properties shared across call-like params. * This type is used as the base for various call-like parameter types: * - [CallParams](https://tevm.sh/reference/tevm/actions/type-aliases/callparams-1/) * - [ContractParams](https://tevm.sh/reference/tevm/actions/type-aliases/contractparams-1/) * - [DeployParams](https://tevm.sh/reference/tevm/actions/type-aliases/deployparams-1/) * - [ScriptParams](https://tevm.sh/reference/tevm/actions/type-aliases/scriptparams-1/) * * @extends BaseParams * @example * ```typescript * import { BaseCallParams } from 'tevm' * * const params: BaseCallParams = { * createTrace: true, * createAccessList: true, * createTransaction: 'on-success', * blockTag: 'latest', * skipBalance: true, * gas: 1000000n, * gasPrice: 1n, * maxFeePerGas: 1n, * maxPriorityFeePerGas: 1n, * gasRefund: 0n, * from: '0x123...', * origin: '0x123...', * caller: '0x123...', * value: 0n, * depth: 0, * to: '0x123...', * } * ``` */ type BaseCallParams<TThrowOnFail extends boolean = boolean> = BaseParams<TThrowOnFail> & { /** * Whether to return a complete trace with the call. * Defaults to `false`. * @example * ```ts * import { createMemoryClient } from 'tevm' * * const client = createMemoryClient() * * const { trace } = await client.call({ address: '0x1234', data: '0x1234', createTrace: true }) * * trace.structLogs.forEach(console.log) * ``` */ readonly createTrace?: boolean; /** * Whether to return an access list mapping of addresses to storage keys. * Defaults to `false`. * @example * ```ts * import { createMemoryClient } from 'tevm' * * const client = createMemoryClient() * * const { accessList } = await client.tevmCall({ to: '0x1234...', data: '0x1234', createAccessList: true }) * console.log(accessList) // { "0x...": Set(["0x..."]) } * ``` */ readonly createAccessList?: boolean; /** * @deprecated Use `addToMempool` or `addToBlockchain` instead. * Whether or not to update the state or run the call in a dry-run. Defaults to `never`. * - `on-success`: Only update the state if the call is successful. * - `always`: Always include the transaction even if it reverts. * - `never`: Never include the transaction. * - `true`: Alias for `on-success`. * - `false`: Alias for `never`. * * @example * ```typescript * // Deprecated approach * const { txHash } = await client.call({ address: '0x1234', data: '0x1234', createTransaction: 'on-success' }) * await client.mine() * const receipt = await client.getTransactionReceipt({ hash: txHash }) * * // New approach * const { txHash } = await client.call({ address: '0x1234', data: '0x1234', addToMempool: true }) * await client.mine() * const receipt = await client.getTransactionReceipt({ hash: txHash }) * * // Or automatically mine the transaction * const { txHash } = await client.call({ address: '0x1234', data: '0x1234', addToBlockchain: true }) * const receipt = await client.getTransactionReceipt({ hash: txHash }) * ``` */ readonly createTransaction?: 'on-success' | 'always' | 'never' | boolean; /** * Whether to add the transaction to the mempool. Defaults to `false`. * - `on-success`: Only add the transaction to the mempool if the call is successful. * - `always`: Always add the transaction to the mempool even if it reverts. * - `never`: Never add the transaction to the mempool. * - `true`: Alias for `on-success`. * - `false`: Alias for `never`. * * This does NOT automatically mine the transaction. To include the transaction in a block, * you must call `client.mine()` afterward or use `addToBlockchain: true`. * * @example * ```typescript * const { txHash } = await client.call({ address: '0x1234', data: '0x1234', addToMempool: true }) * await client.mine() * const receipt = await client.getTransactionReceipt({ hash: txHash }) * ``` */ readonly addToMempool?: 'on-success' | 'always' | 'never' | boolean; /** * Whether to add the transaction to the blockchain (mine it immediately). Defaults to `false`. * - `on-success`: Only add the transaction to the blockchain if the call is successful. * - `always`: Always add the transaction to the blockchain even if it reverts. * - `never`: Never add the transaction to the blockchain. * - `true`: Alias for `on-success`. * - `false`: Alias for `never`. * * This automatically adds the transaction to the mempool AND mines it. * It only mines the current transaction, not any other transactions in the mempool. * * @example * ```typescript * const { txHash } = await client.call({ address: '0x1234', data: '0x1234', addToBlockchain: true }) * const receipt = await client.getTransactionReceipt({ hash: txHash }) * ``` */ readonly addToBlockchain?: 'on-success' | 'always' | 'never' | boolean; /** * The block number or block tag to execute the call at. Defaults to `latest`. * - `bigint`: The block number to execute the call at. * - `Hex`: The block hash to execute the call at. * - `BlockTag`: The named block tag to execute the call at. * * Notable block tags: * - 'latest': The canonical head. * - 'pending': A block that is optimistically built with transactions in the txpool that have not yet been mined. * - 'forked': If forking, the 'forked' block will be the block the chain was forked at. */ readonly blockTag?: BlockParam; /** * Whether to skip the balance check. Defaults to `false`, except for scripts where it is set to `true`. */ readonly skipBalance?: boolean; /** * The gas limit for the call. * Defaults to the block gas limit as specified by the common configuration or the fork URL. */ readonly gas?: bigint; /** * The gas price for the call. * Note: This option is currently ignored when creating transactions because only EIP-1559 transactions are supported. This will be fixed in a future release. */ readonly gasPrice?: bigint; /** * The maximum fee per gas for EIP-1559 transactions. */ readonly maxFeePerGas?: bigint; /** * The maximum priority fee per gas for EIP-1559 transactions. */ readonly maxPriorityFeePerGas?: bigint; /** * The refund counter. Defaults to `0`. */ readonly gasRefund?: bigint; /** * The from address for the call. Defaults to the zero address for reads and the first account for writes. * It is also possible to set the `origin` and `caller` addresses separately using those options. Otherwise, both are set to the `from` address. */ readonly from?: Address; /** * The address where the call originated from. Defaults to the zero address. * If the `from` address is set, it defaults to the `from` address; otherwise, it defaults to the zero address. */ readonly origin?: Address; /** * The address that ran this code (`msg.sender`). Defaults to the zero address. * If the `from` address is set, it defaults to the `from` address; otherwise, it defaults to the zero address. */ readonly caller?: Address; /** * The value in ether that is being sent to the `to` address. Defaults to `0`. */ readonly value?: bigint; /** * The depth of the EVM call. Useful for simulating an internal call. Defaults to `0`. */ readonly depth?: number; /** * Addresses to selfdestruct. Defaults to an empty set. */ readonly selfdestruct?: Set<Address>; /** * The address of the account executing this code (`address(this)`). Defaults to the zero address. * This is not set for create transactions but is required for most transactions. */ readonly to?: Address; /** * Versioned hashes for each blob in a blob transaction for EIP-4844 transactions. */ readonly blobVersionedHashes?: Hex[]; /** * The state override set is an optional address-to-state mapping where each entry specifies some state to be ephemerally overridden prior to executing the call. Each address maps to an object containing: * This option cannot be used when `createTransaction` is set to `true`. * * @example * ```ts * const stateOverride = { * "0xd9c9cd5f6779558b6e0ed4e6acf6b1947e7fa1f3": { * balance: "0xde0b6b3a7640000" * }, * "0xebe8efa441b9302a0d7eaecc277c09d20d684540": { * code: "0x...", * state: { * "0x...": "0x..." * } * } * } * const res = await client.call({ address: '0x1234', data: '0x1234', stateOverrideSet: stateOverride }) * ``` */ readonly stateOverrideSet?: StateOverrideSet; /** * The fields of this optional object customize the block as part of which the call is simulated. * The object contains fields such as block number, hash, parent hash, nonce, etc. * This option cannot be used when `createTransaction` is set to `true`. * Setting the block number to a past block will not run in the context of that block's state. To do that, fork that block number first. * * @example * ```ts * const blockOverride = { * number: "0x1b4", * hash: "0x...", * parentHash: "0x...", * nonce: "0x0000000000000042", * } * const res = await client.call({ address: '0x1234', data: '0x1234', blockOverrideSet: blockOverride }) * ``` */ readonly blockOverrideSet?: BlockOverrideSet; }; declare function validateBaseCallParams(action: BaseCallParams): ValidateBaseCallParamsError[]; type ValidateBaseCallParamsError = InvalidParamsError | InvalidSkipBalanceError | InvalidGasRefundError | InvalidBlockError | InvalidGasPriceError | InvalidOriginError | InvalidCallerError | InvalidDepthError | InvalidBlobVersionedHashesError | InvalidAddToMempoolError | InvalidAddToBlockchainError; declare const zBaseCallParams: z.ZodEffects<z.ZodObject<{ throwOnFail: z.ZodOptional<z.ZodBoolean>; } & { createTrace: z.ZodOptional<z.ZodBoolean>; createAccessList: z.ZodOptional<z.ZodBoolean>; createTransaction: z.ZodUnion<[z.ZodOptional<z.ZodBoolean>, z.ZodLiteral<"on-success">, z.ZodLiteral<"always">, z.ZodLiteral<"never">]>; addToMempool: z.ZodUnion<[z.ZodOptional<z.ZodBoolean>, z.ZodLiteral<"on-success">, z.ZodLiteral<"always">, z.ZodLiteral<"never">]>; addToBlockchain: z.ZodUnion<[z.ZodOptional<z.ZodBoolean>, z.ZodLiteral<"on-success">, z.ZodLiteral<"always">, z.ZodLiteral<"never">]>; skipBalance: z.ZodOptional<z.ZodBoolean>; gasRefund: z.ZodOptional<z.ZodBigInt>; blockTag: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"latest">, z.ZodLiteral<"earliest">, z.ZodLiteral<"pending">, z.ZodLiteral<"safe">, z.ZodLiteral<"finalized">, z.ZodBigInt, z.ZodEffects<z.ZodNumber, bigint, number>, z.ZodEffects<z.ZodString, `0x${string}`, string>]>>; gasPrice: z.ZodOptional<z.ZodBigInt>; origin: z.ZodOptional<z.ZodEffects<z.ZodString, `0x${string}`, string>>; caller: z.ZodOptional<z.ZodEffects<z.ZodString, `0x${string}`, string>>; gas: z.ZodOptional<z.ZodBigInt>; value: z.ZodOptional<z.ZodBigInt>; depth: z.ZodOptional<z.ZodNumber>; selfdestruct: z.ZodOptional<z.ZodSet<z.ZodEffects<z.ZodString, `0x${string}`, string>>>; to: z.ZodOptional<z.ZodEffects<z.ZodString, `0x${string}`, string>>; blobVersionedHashes: z.ZodOptional<z.ZodArray<z.ZodEffects<z.ZodString, `0x${string}`, string>, "many">>; stateOverrideSet: z.ZodOptional<z.ZodRecord<z.ZodEffects<z.ZodString, `0x${string}`, string>, z.ZodObject<{ balance: z.ZodOptional<z.ZodBigInt>; nonce: z.ZodOptional<z.ZodBigInt>; code: z.ZodOptional<z.ZodEffects<z.ZodString, `0x${string}`, string>>; state: z.ZodOptional<z.ZodRecord<z.ZodEffects<z.ZodString, `0x${string}`, string>, z.ZodEffects<z.ZodString, `0x${string}`, string>>>; stateDiff: z.ZodOptional<z.ZodRecord<z.ZodEffects<z.ZodString, `0x${string}`, string>, z.ZodEffects<z.ZodString, `0x${string}`, string>>>; }, "strict", z.ZodTypeAny, { code?: `0x${string}` | undefined; balance?: bigint | undefined; nonce?: bigint | undefined; state?: Partial<Record<`0x${string}`, `0x${string}`>> | undefined; stateDiff?: Partial<Record<`0x${string}`, `0x${string}`>> | undefined; }, { code?: string | undefined; balance?: bigint | undefined; nonce?: bigint | undefined; state?: Record<string, string> | undefined; stateDiff?: Record<string, string> | undefined; }>>>; blockOverrideSet: z.ZodOptional<z.ZodObject<{ number: z.ZodOptional<z.ZodBigInt>; time: z.ZodOptional<z.ZodBigInt>; gasLimit: z.ZodOptional<z.ZodBigInt>; coinbase: z.ZodOptional<z.ZodEffects<z.ZodString, `0x${string}`, string>>; baseFee: z.ZodOptional<z.ZodBigInt>; blobBaseFee: z.ZodOptional<z.ZodBigInt>; }, "strict", z.ZodTypeAny, { number?: bigint | undefined; time?: bigint | undefined; gasLimit?: bigint | undefined; coinbase?: `0x${string}` | undefined; baseFee?: bigint | undefined; blobBaseFee?: bigint | undefined; }, { number?: bigint | undefined; time?: bigint | undefined; gasLimit?: bigint | undefined; coinbase?: string | undefined; baseFee?: bigint | undefined; blobBaseFee?: bigint | undefined; }>>; maxFeePerGas: z.ZodOptional<z.ZodBigInt>; maxPriorityFeePerGas: z.ZodOptional<z.ZodBigInt>; onStep: z.ZodOptional<z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>>; onNewContract: z.ZodOptional<z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>>; onBeforeMessage: z.ZodOptional<z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>>; onAfterMessage: z.ZodOptional<z.ZodOptional<z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodUnknown>>>; }, "strip", z.ZodTypeAny, { value?: bigint | undefined; onStep?: ((...args: unknown[]) => unknown) | undefined; onNewContract?: ((...args: unknown[]) => unknown) | undefined; onBeforeMessage?: ((...args: unknown[]) => unknown) | undefined; onAfterMessage?: ((...args: unknown[]) => unknown) | undefined; throwOnFail?: boolean | undefined; createTrace?: boolean | undefined; createAccessList?: boolean | undefined; createTransaction?: boolean | "on-success" | "always" | "never" | undefined; addToMempool?: boolean | "on-success" | "always" | "never" | undefined; addToBlockchain?: boolean | "on-success" | "always" | "never" | undefined; skipBalance?: boolean | undefined; gasRefund?: bigint | undefined; blockTag?: bigint | `0x${string}` | "latest" | "earliest" | "pending" | "safe" | "finalized" | undefined; gasPrice?: bigint | undefined; origin?: `0x${string}` | undefined; caller?: `0x${string}` | undefined; gas?: bigint | undefined; depth?: number | undefined; selfdestruct?: Set<`0x${string}`> | undefined; to?: `0x${string}` | undefined; blobVersionedHashes?: `0x${string}`[] | undefined; stateOverrideSet?: Partial<Record<`0x${string}`, { code?: `0x${string}` | undefined; balance?: bigint | undefined; nonce?: bigint | undefined; state?: Partial<Record<`0x${string}`, `0x${string}`>> | undefined; stateDiff?: Partial<Record<`0x${string}`, `0x${string}`>> | undefined; }>> | undefined; blockOverrideSet?: { number?: bigint | undefined; time?: bigint | undefined; gasLimit?: bigint | undefined; coinbase?: `0x${string}` | undefined; baseFee?: bigint | undefined; blobBaseFee?: bigint | undefined; } | undefined; maxFeePerGas?: bigint | undefined; maxPriorityFeePerGas?: bigint | undefined; }, { value?: bigint | undefined; onStep?: ((...args: unknown[]) => unknown) | undefined; onNewContract?: ((...args: unknown[]) => unknown) | undefined; onBeforeMessage?: ((...args: unknown[]) => unknown) | undefined; onAfterMessage?: ((...args: unknown[]) => unknown) | undefined; throwOnFail?: boolean | undefined; createTrace?: boolean | undefined; createAccessList?: boolean | undefined; createTransaction?: boolean | "on-success" | "always" | "never" | undefined; addToMempool?: boolean | "on-success" | "always" | "never" | undefined; addToBlockchain?: boolean | "on-success" | "always" | "never" | undefined; skipBalance?: boolean | undefined; gasRefund?: bigint | undefined; blockTag?: string | number | bigint | undefined; gasPrice?: bigint | undefined; origin?: string | undefined; caller?: string | undefined; gas?: bigint | undefined; depth?: number | undefined; selfdestruct?: Set<string> | undefined; to?: string | undefined; blobVersionedHashes?: string[] | undefined; stateOverrideSet?: Record<string, { code?: string | undefined; balance?: bigint | undefined; nonce?: bigint | undefined; state?: Record<string, string> | undefined; stateDiff?: Record<string, string> | undefined; }> | undefined; blockOverrideSet?: { number?: bigint | undefined; time?: bigint | undefined; gasLimit?: bigint | undefined; coinbase?: string | undefined; baseFee?: bigint | undefined; blobBaseFee?: bigint | undefined; } | undefined; maxFeePerGas?: bigint | undefined; maxPriorityFeePerGas?: bigint | undefined; }>, { value?: bigint | undefined; onStep?: ((...args: unknown[]) => unknown) | undefined; onNewContract?: ((...args: unknown[]) => unknown) | undefined; onBeforeMessage?: ((...args: unknown[]) => unknown) | undefined; onAfterMessage?: ((...args: unknown[]) => unknown) | undefined; throwOnFail?: boolean | undefined; createTrace?: boolean | undefined; createAccessList?: boolean | undefined; createTransaction?: boolean | "on-success" | "always" | "never" | undefined; addToMempool?: boolean | "on-success" | "always" | "never" | undefined; addToBlockchain?: boolean | "on-success" | "always" | "never" | undefined; skipBalance?: boolean | undefined; gasRefund?: bigint | undefined; blockTag?: bigint | `0x${string}` | "latest" | "earliest" | "pending" | "safe" | "finalized" | undefined; gasPrice?: bigint | undefined; origin?: `0x${string}` | undefined; caller?: `0x${string}` | undefined; gas?: bigint | undefined; depth?: number | undefined; selfdestruct?: Set<`0x${string}`> | undefined; to?: `0x${string}` | undefined; blobVersionedHashes?: `0x${string}`[] | undefined; stateOverrideSet?: Partial<Record<`0x${string}`, { code?: `0x${string}` | undefined; balance?: bigint | undefined; nonce?: bigint | undefined; state?: Partial<Record<`0x${string}`, `0x${string}`>> | undefined; stateDiff?: Partial<Record<`0x${string}`, `0x${string}`>> | undefined; }>> | undefined; blockOverrideSet?: { number?: bigint | undefined; time?: bigint | undefined; gasLimit?: bigint | undefined; coinbase?: `0x${string}` | undefined; baseFee?: bigint | undefined; blobBaseFee?: bigint | undefined; } | undefined; maxFeePerGas?: bigint | undefined; maxPriorityFeePerGas?: bigint | undefined; }, { value?: bigint | undefined; onStep?: ((...args: unknown[]) => unknown) | undefined; onNewContract?: ((...args: unknown[]) => unknown) | undefined; onBeforeMessage?: ((...args: unknown[]) => unknown) | undefined; onAfterMessage?: ((...args: unknown[]) => unknown) | undefined; throwOnFail?: boolean | undefined; createTrace?: boolean | undefined; createAccessList?: boolean | undefined; createTransaction?: boolean | "on-success" | "always" | "never" | undefined; addToMempool?: boolean | "on-success" | "always" | "never" | undefined; addToBlockchain?: boolean | "on-success" | "always" | "never" | undefined; skipBalance?: boolean | undefined; gasRefund?: bigint | undefined; blockTag?: string | number | bigint | undefined; gasPrice?: bigint | undefined; origin?: string | undefined; caller?: string | undefined; gas?: bigint | undefined; depth?: number | undefined; selfdestruct?: Set<string> | undefined; to?: string | undefined; blobVersionedHashes?: string[] | undefined; stateOverrideSet?: Record<string, { code?: string | undefined; balance?: bigint | undefined; nonce?: bigint | undefined; state?: Record<string, string> | undefined; stateDiff?: Record<string, string> | undefined; }> | undefined; blockOverrideSet?: { number?: bigint | undefined; time?: bigint | undefined; gasLimit?: bigint | undefined; coinbase?: string | undefined; baseFee?: bigint | undefined; blobBaseFee?: bigint | undefined; } | undefined; maxFeePerGas?: bigint | undefined; maxPriorityFeePerGas?: bigint | undefined; }>; /** * TEVM parameters to execute a call on the VM. * `Call` is the lowest level method to interact with the VM, and other methods such as `contract` and `script` use `call` under the hood. * * @example * ```typescript * import { createClient } from 'viem' * import { createTevmTransport, tevmCall } from 'tevm' * import { optimism } from 'tevm/common' * * const client = createClient({ * transport: createTevmTransport({}), * chain: optimism, * }) * * const callParams = { * data: '0x...', * bytecode: '0x...', * gasLimit: 420n, * } * * await tevmCall(client, callParams) * ``` * * @see [BaseCallParams](https://tevm.sh/reference/tevm/actions/type-aliases/basecallparams-1/) * @see [tevmCall](https://tevm.sh/reference/tevm/memory-client/functions/tevmCall/) */ type CallParams<TThrowOnFail extends boolean = boolean> = BaseCallParams<TThrowOnFail> & { /** * An optional CREATE2 salt. * * @example * ```typescript * import { createClient } from 'viem' * import { createTevmTransport, tevmCall } from 'tevm' * import { optimism } from 'tevm/common' * * const client = createClient({ * transport: createTevmTransport({}), * chain: optimism, * }) * * const callParams = { * data: '0x...', * bytecode: '0x...', * gasLimit: 420n, * salt: '0x1234...', * } * * await tevmCall(client, callParams) * ``` * * @see [CREATE2](https://eips.ethereum.org/EIPS/eip-1014) */ readonly salt?: Hex; /** * The input data for the call. */ readonly data?: Hex; /** * The encoded code to deploy with for a deployless call. Code is encoded with constructor arguments, unlike `deployedBytecode`. * * @example * ```typescript * import { createClient } from 'viem' * import { createTevmTransport, tevmCall, encodeDeployData } from 'tevm' * import { optimism } from 'tevm/common' * * const client = createClient({ * transport: createTevmTransport({}), * chain: optimism, * }) * * const callParams = { * createTransaction: true, * data: encodeDeployData({ * bytecode: '0x...', * data: '0x...', * abi: [{...}], * args: [1, 2, 3], * }) * } * * await tevmCall(client, callParams) * ``` * Code is also automatically created if using TEVM contracts via the `script` method. * * @example * ```typescript * import { createClient } from 'viem' * import { createTevmTransport, tevmContract } from 'tevm' * import { optimism } from 'tevm/common' * import { SimpleContract } from 'tevm/contracts' * * const client = createClient({ * transport: createTevmTransport({}), * chain: optimism, * }) * * const script = SimpleContract.script({ constructorArgs: [420n] }) * * await tevmContract(client, script.read.get()) // 420n * ``` */ readonly code?: Hex; /** * The code to put into the state before executing the call. If you wish to call the constructor, use `code` instead. * * @example * ```typescript * import { createClient } from 'viem' * import { createTevmTransport, tevmCall } from 'tevm' * import { optimism } from 'tevm/common' * * const client = createClient({ * transport: createTevmTransport({}), * chain: optimism, * }) * * const callParams = { * data: '0x...', * deployedBytecode: '0x...', * } * * await tevmCall(client, callParams) * ``` */ readonly deployedBytecode?: Hex; }; declare function callHandlerOpts(client: _tevm_node.TevmNode, params: CallParams): Promise<{ data: Parameters<_tevm_evm.Evm["runCall"]>[0]; errors?: never; } | { data?: never; errors: Array<CallHandlerOptsError>; }>; type CallHandlerOptsError = UnknownBlockError | UnknownBlockError | InvalidParamsError; declare function handleRunTxError(e: unknown): HandleRunTxError; type EvmErrorConstructor = (typeof evmErrors)[number]; type TevmEvmError = AuthCallUnsetError | BLS12381FpNotInFieldError | BLS12381InputEmptyError | BLS12381InvalidInputLengthError | BLS12381PointNotOnCurveError | CodeStoreOutOfGasError | CodeSizeExceedsMaximumError | CreateCollisionError | InvalidCommitmentError | EvmRevertError | InitcodeSizeViolationError | InsufficientBalanceError | InternalEvmError | InvalidBeginSubError | InvalidBytecodeResultError | InvalidEofFormatError | InvalidInputLengthError | InvalidJumpError | InvalidJumpSubError | InvalidKzgInputsError | InvalidOpcodeError | InvalidProofError | InvalidReturnSubError | OutOfGasError | OutOfRangeError | RefundExhaustedError | StackOverflowError | StackUnderflowError | StaticStateChangeError | StopError | ValueOverflowError; type HandleRunTxError = TevmEvmError | InvalidGasPriceError | InvalidAddressError | InvalidGasLimitError; /** * @internal * Array of every error EVM can throw * @type {[typeof AuthCallUnsetError, typeof CodeSizeExceedsMaximumError, typeof CreateCollisionError, typeof InvalidCommitmentError, typeof EvmRevertError, typeof InitcodeSizeViolationError, typeof InsufficientBalanceError, typeof InternalEvmError, typeof InvalidBeginSubError, typeof InvalidBytecodeResultError, typeof InvalidEofFormatError, typeof InvalidInputLengthError, typeof InvalidJumpError, typeof InvalidJumpSubError, typeof InvalidKzgInputsError, typeof InvalidOpcodeError, typeof InvalidProofError, typeof InvalidReturnSubError, typeof OutOfGasError, typeof OutOfRangeError, typeof RefundExhaustedError, typeof StackOverflowError, typeof StackUnderflowError, typeof StaticStateChangeError, typeof StopError, typeof ValueOverflowError, typeof BLS12381InputEmptyError, typeof BLS12381FpNotInFieldError, typeof BLS12381InvalidInputLengthError, typeof BLS12381PointNotOnCurveError, typeof CodeStoreOutOfGasError]} */ declare const evmErrors: [typeof AuthCallUnsetError, typeof CodeSizeExceedsMaximumError, typeof CreateCollisionError, typeof InvalidCommitmentError, typeof EvmRevertError, typeof InitcodeSizeViolationError, typeof InsufficientBalanceError, typeof InternalEvmError, typeof InvalidBeginSubError, typeof InvalidBytecodeResultError, typeof InvalidEofFormatError, typeof InvalidInputLengthError, typeof InvalidJumpError, typeof InvalidJumpSubError, typeof InvalidKzgInputsError, typeof InvalidOpcodeError, typeof InvalidProofError, typeof InvalidReturnSubError, typeof OutOfGasError, typeof OutOfRangeError, typeof RefundExhaustedError, typeof StackOverflowError, typeof StackUnderflowError, typeof StaticStateChangeError, typeof StopError, typeof ValueOverflowError, typeof BLS12381InputEmptyError, typeof BLS12381FpNotInFieldError, typeof BLS12381InvalidInputLengthError, typeof BLS12381PointNotOnCurveError, typeof CodeStoreOutOfGasError]; declare function executeCall(client: _tevm_node.TevmNode, evmInput: _tevm_evm.EvmRunCallOpts, params: CallParams, events?: CallEvents): Promise<(ExecuteCallResult & { errors?: [ExecuteCallError]; }) | { errors: [ExecuteCallError]; }>; /** * The error returned by executeCall */ type ExecuteCallError = HandleRunTxError; /** * The return value of executeCall */ type ExecuteCallResult = { runTxResult: _tevm_vm.RunTxResult; trace: TraceResult | undefined; accessList: undefined | Map<string, Set<string>>; }; declare function validateCallParams(action: CallParams): ValidateCallParamsError[]; type ValidateCallParamsError = InvalidSaltError | InvalidDataError | InvalidBytecodeError | ValidateBaseCallParamsError; /** * All errors that can occur during a TEVM call. * This type is strongly typed if using `throwOnFail: false`. * * @example * ```typescript * import { TevmCallError } from 'tevm/errors' * import { createMemoryClient, tevmCall } from 'tevm' * * const client = createMemoryClient() * * const result = await tevmCall(client, { * throwOnFail: false, * to: '0x...', * data: '0x...', * }) * * const errors = result.errors satisfies Array<TevmCallError> | undefined * if (errors) { * errors.forEach((error) => console.error(error)) * } * ``` * * If `throwOnFail: true` is used (the default), the errors are thrown directly. This type can then be used to catch the errors. * * @example * ```typescript * import { TevmCallError } from 'tevm/errors' * import { createMemoryClient, tevmCall } from 'tevm' * * const client = createMemoryClient() * * try { * await tevmCall(client, { * to: '0x...', * data: '0x...', * }) * } catch (error) { * const typedError = error as TevmCallError * switch (typedError.name) { * case 'ValidateCallParamsError': * case 'CallHandlerOptsError': * case 'InternalError': * case 'ExecutionError': * case 'RevertError': * case 'HandleRunTxError': * case 'ExecuteCallError': * handleIt(typedError) * break * default: * throw error * } * } * ``` */ type TevmCallError = ValidateCallParamsError | CallHandlerOptsError | InternalError | ExecutionError | RevertError | HandleRunTxError | ExecuteCallError; /** * Result of a TEVM VM Call method. * * @example * ```typescript * import { createClient } from 'viem' * import { createTevmTransport, tevmCall } from 'tevm' * import { optimism } from 'tevm/common' * import { CallResult } from 'tevm/actions' * * const client = createClient({ * transport: createTevmTransport({}), * chain: optimism, * }) * * const callParams = { * data: '0x...', * bytecode: '0x...', * gasLimit: 420n, * } * * const result: CallResult = await tevmCall(client, callParams) * console.log(result) * ``` * * @see [tevmCall](https://tevm.sh/reference/tevm/memory-client/functions/tevmCall/) */ type CallResult<ErrorType = TevmCallError> = { /** * The call trace if tracing is enabled on call. * * @example * ```typescript * const trace = result.trace * trace.structLogs.forEach(console.log) * ``` */ trace?: TraceResult; /** * The access list if enabled on call. * Mapping of addresses to storage slots. * * @example * ```typescript * const accessList = result.accessList * console.log(accessList) // { "0x...": Set(["0x..."]) } * ``` */ accessList?: Record<Address, Set<Hex>>; /** * Preimages mapping of the touched accounts from the transaction (see `reportPreimages` option). */ preimages?: Record<Hex, Hex>; /** * The returned transaction hash if the call was included in the chain. * Will not be defined if the call was not included in the chain. * Whether a call is included in the chain depends on the `createTransaction` option and the result of the call. * * @example * ```typescript * const txHash = result.txHash * if (txHash) { * console.log(`Transaction included in the chain with hash: ${txHash}`) * } * ``` */ txHash?: Hex; /** * Amount of gas left after execution. */ gas?: bigint; /** * Amount of gas the code used to run within the EVM. * This only includes gas spent on the EVM execution itself and doesn't account for gas spent on other factors such as data storage. */ executionGasUsed: bigint; /** * Array of logs that the contract emitted. * * @example * ```typescript * const logs = result.logs * logs?.forEach(log => console.log(log)) * ``` */ logs?: Log[]; /** * The gas refund counter as a uint256. */ gasRefund?: bigint; /** * Amount of blob gas consumed by the transaction. */ blobGasUsed?: bigint; /** * Address of created account during the transaction, if any. */ createdAddress?: Address; /** * A set of accounts to selfdestruct. */ selfdestruct?: Set<Address>; /** * Map of addresses which were created (used in EIP 6780). * Note the addresses are not actually created until the transaction is mined. */ createdAddresses?: Set<Address>; /** * Encoded return value from the contract as a hex string. * * @example * ```typescript * const rawData = result.rawData * console.log(`Raw data returned: ${rawData}`) * ``` */ rawData: Hex; /** * Description of the exception, if any occurred. */ errors?: ErrorType[]; /** * Priority fee set by the transaction. */ priorityFee?: bigint; /** * The base fee of the transaction. */ baseFee?: bigint; /** * L1 fee that should be paid for the transaction. * Only included when an OP-Stack common is provided. * * @see [OP-Stack docs](https://docs.optimism.io/stack/transactions/fees) */ l1Fee?: bigint; /** * Amount of L1 gas used to publish the transaction. * Only included when an OP-Stack common is provided. * * @see [OP-Stac