---
title: "Execute from Ethereum"
url: "/docs/build-on-signet/advanced/execute-from-ethereum/index.md"
description: "Execute transactions from Ethereum to Signet with guaranteed inclusion"
--- The Transactor contract provides guaranteed, censorship-resistant execution on Signet from Ethereum. Any Ethereum account can call Transactor to trigger a transaction on Signet that builders cannot censor or reorder. ## Overview `Transactor.sol` exposes two function signatures for sending transactions to Signet: ### Default Chain ```solidity function transact( address to, bytes calldata data, uint256 value, uint256 gas, uint256 maxFeePerGas ) external payable ``` This version uses the contract's `defaultRollupChainId` configured at deployment. ### Explicit Chain ```solidity function transact( uint256 rollupChainId, address to, bytes calldata data, uint256 value, uint256 gas, uint256 maxFeePerGas ) external payable ``` Use this version when targeting a specific Signet chain in multi-chain deployments. --- Calling either `transact` function results in a system transaction being issued on Signet **from the address of the caller**. This allows Ethereum contracts to own assets on Signet, and to trigger contract execution on Signet from Ethereum with native authentication. The `value` argument is the amount of USD in wei to send **on the rollup**. USD is the native asset of Signet. This amount will be attached to the Signet transaction. The balance of the originating address on Signet must be sufficient to cover this value. > **Note:** See the [Address Aliasing](/docs/learn-about-signet/evm-behavior/index.md#address-aliasing) section in the EVM Behavior docs for important information on how contract addresses are modified when using the Transactor. Transact events are executed at the **end** of the Signet block. Contract creation via `Transactor` is not currently supported. The Transactor emits a `Transact` event that can be monitored. The Signet node listens for these events directly, so if the event fired, the transaction **was** included in Signet, although the inner call may revert. > **Use Transactor when...:** - You need guaranteed transaction inclusion - You want to trigger Signet actions from Ethereum - You're building cross-chain workflows - You need censorship resistance > **Don't use Transactor when...:** - You're just moving assets (use [Passage] instead) - Gas cost is a primary concern (direct Signet txs are cheaper) - You don't need L1-triggered execution [Passage]: https://github.com/init4tech/zenith/blob/main/src/passage/Passage.sol 

## TypeScript

This page assumes you've [set up your clients](/docs/build-on-signet/getting-started/index.md) .
Sometimes an Ethereum contract needs to trigger execution on Signet: a DAO proposal passes, a governance timelock expires, a multisig approves a parameter change. The Transactor contract handles this. It guarantees transaction inclusion on Signet in the same block, bypassing builder discretion.
## How Transactor works The [Transactor](https://github.com/init4tech/zenith/blob/main/src/Transactor.sol) contract lives on Ethereum. You call transact with the Signet call you want to execute. The system creates a transaction on Signet from the caller's address, executing at the end of the Signet block. No builder can exclude it.
Normally, builders choose which transactions to include in Signet blocks. If a builder has a reason to censor yours (MEV extraction, competitive pressure), you have no recourse through the normal path. Transactor bypasses builder discretion entirely.
## When you need it Direct Signet transactions are cheaper and simpler. Transactor exists for three situations:
Your logic lives on Ethereum. The Ethereum contract calls Transactor directly, with no off-chain relayer and no trust assumptions.
You need censorship resistance. The transaction executes unconditionally. This matters for liquidations, time-sensitive governance, or any operation where inclusion is non-negotiable.
You want L1 security for the trigger. The Ethereum transaction is the source of authority. Signet execution follows deterministically.
## Contracts Contract Address Transactor (host) `0x0B4fc18e78c585687E01c172a1087Ea687943db9` All contract addresses on this page are for [Parmigiana testnet](/docs/build-on-signet/parmigiana/index.md) .
## Execute a transaction Encode the Signet call and submit through Transactor on Ethereum:
```typescript import { transactorAbi } from '@signet-sh/sdk/abi'; import { PARMIGIANA } from '@signet-sh/sdk/constants'; import { encodeFunctionData, parseGwei } from 'viem'; const innerData = encodeFunctionData({ abi: targetContractAbi, functionName: 'someFunction', args: [arg1, arg2], }); const hash = await hostWalletClient.writeContract({ address: PARMIGIANA.hostTransactor, abi: transactorAbi, functionName: 'transact', args: [ signetTargetAddress, innerData, 0n, // USD value on Signet 1_000_000n, // gas limit parseGwei('100'), // max fee per gas ], }); ``` **Without the SDK** ```typescript import { encodeFunctionData, parseGwei } from 'viem'; const transactorAbi = [ { name: 'transact', type: 'function', stateMutability: 'payable', inputs: [ { name: 'to', type: 'address' }, { name: 'data', type: 'bytes' }, { name: 'value', type: 'uint256' }, { name: 'gas', type: 'uint256' }, { name: 'maxFeePerGas', type: 'uint256' }, ], outputs: [], }, ] as const; const innerData = encodeFunctionData({ abi: targetContractAbi, functionName: 'someFunction', args: [arg1, arg2], }); const hash = await hostWalletClient.writeContract({ address: '`0x0B4fc18e78c585687E01c172a1087Ea687943db9` ', abi: transactorAbi, functionName: 'transact', args: [ signetTargetAddress, innerData, 0n, 1_000_000n, parseGwei('100'), ], }); ``` > **Address aliasing:** When a *contract* calls Transactor, the Signet sender address is aliased. EOAs are not aliased. See [Address Aliasing](/docs/learn-about-signet/evm-behavior/index.md#address-aliasing). ## Verifying execution The Transact event on Ethereum confirms your transaction was included on Signet, but the inner call can still revert. Check the Signet transaction receipt for the corresponding block to confirm success.
```typescript const receipt = await hostPublicClient.waitForTransactionReceipt({ hash }); // Transact event confirms inclusion on Signet // Check the Signet transaction receipt for the actual result ``` ## When to use something else > **Don't use Transactor when...:** - You're just moving assets. Use [Passage](/docs/build-on-signet/transfers/enter-signet/index.md#typescript). - Gas cost matters. Direct Signet transactions are cheaper. - You don't need censorship resistance. ## Next steps [Passage](/docs/build-on-signet/transfers/enter-signet/index.md) moves assets to Signet without guaranteed inclusion [EVM behavior](/docs/learn-about-signet/evm-behavior/index.md) covers address aliasing details for contract callers 

## Rust

This page assumes you've [set up your providers](/docs/build-on-signet/getting-started/index.md) .
The [Transactor](https://github.com/init4tech/zenith/blob/main/src/Transactor.sol) contract lives on Ethereum. You call transact with the Signet call you want to execute, and the system creates a transaction on Signet from the caller's address. No builder can exclude it.
See [Parmigiana Testnet](/docs/build-on-signet/parmigiana/index.md) for the Transactor contract address.
## Execute a transaction Encode the calldata for your target Signet contract, then call transact on the Transactor contract via the host chain provider:
```rust use alloy::primitives::{utils::parse_units, Address, Bytes, U256}; use alloy::providers::{Provider, ProviderBuilder}; use signet_constants::parmigiana; use signet_zenith::Transactor; // Encode the function call for the target Signet contract let calldata: Bytes = /* your encoded calldata */; let transactor = Transactor::new(parmigiana::HOST_TRANSACTOR, &host_provider); let tx = transactor .transact_0( signet_target_address, // target contract on Signet calldata, // encoded function call U256::ZERO, // USD value on Signet U256::from(1_000_000), // gas limit parse_units("100", "gwei")?.into(), // max fee per gas ) .send() .await?; let receipt = tx.get_receipt().await?; ``` Use transact_1 instead of transact_0 to specify an explicit rollup chain ID for multi-chain deployments.
> **Address aliasing:** When a *contract* calls Transactor, the Signet sender address is aliased. EOAs are not aliased. See [Address Aliasing](/docs/learn-about-signet/evm-behavior/index.md#address-aliasing). ## Verifying execution The Transact event on Ethereum confirms your transaction was included on Signet, but the inner call can still revert. Check the Signet transaction receipt for the corresponding block to confirm success.
## Next steps [Passage (Rust)](/docs/build-on-signet/transfers/enter-signet/index.md#rust) – move assets without guaranteed inclusion [EVM behavior](/docs/learn-about-signet/evm-behavior/index.md) – address aliasing details 

## Solidity

This page assumes you've completed the [getting started](/docs/build-on-signet/getting-started/index.md) setup.
```solidity import {Transactor} from "zenith/src/Transactor.sol"; contract YourContract { Transactor public transactor; constructor(Transactor _transactor) { transactor = _transactor; } // Execute a function on Signet from Ethereum function executeOnSignet( address signetTarget, bytes calldata functionData ) external { transactor.transact( signetTarget, functionData, 0, // USD value on Signet 1_000_000, // gas limit on Signet 100 gwei // max fee per gas (in USD) on Signet ); } // Emergency action on Signet function emergencyAction(address signetContract) external onlyOwner { // Encode the emergency function call bytes memory data = abi.encodeWithSignature("emergencyPause()"); executeOnSignet(signetContract, data); } } ``` ## Source [Transactor.sol](https://github.com/init4tech/zenith/blob/main/src/Transactor.sol) source code ABIs available on the [Parmigiana quickstart](/docs/build-on-signet/parmigiana/index.md#abis) 

## Terminal

## Call transact (default chain) The simpler form uses the contract's defaultRollupChainId:
```bash cast send `0x0B4fc18e78c585687E01c172a1087Ea687943db9` \ "transact(address,bytes,uint256,uint256,uint256)" \ $SIGNET_TARGET \ $CALLDATA \ 0 \ 1000000 \ 100000000000 \ --rpc-url $HOST_RPC \ --private-key $PRIVATE_KEY ``` The arguments:
to: target contract address on Signet data: ABI-encoded calldata for the Signet function value: USD (in wei) to attach on Signet. The caller's Signet balance must cover this. gas: gas limit for the Signet transaction maxFeePerGas: max fee per gas in USD (here, 100 gwei) ## Call transact (explicit chain ID) For multi-chain deployments, specify the rollup chain ID directly:
```bash cast send `0x0B4fc18e78c585687E01c172a1087Ea687943db9` \ "transact(uint256,address,bytes,uint256,uint256,uint256)" \ 88888 \ $SIGNET_TARGET \ $CALLDATA \ 0 \ 1000000 \ 100000000000 \ --rpc-url $HOST_RPC \ --private-key $PRIVATE_KEY ``` 88888 is the Parmigiana rollup chain ID.
## Encoding calldata Use cast calldata to produce the $CALLDATA argument:
```bash CALLDATA=$(cast calldata "someFunction(uint256,address)" 42 0xYourAddress) ``` Then pass it to the transact call above.
## Verifying execution The Transact event on Ethereum confirms inclusion on Signet. Check for it in the transaction receipt:
```bash cast receipt $TX_HASH --rpc-url $HOST_RPC ``` The inner call on Signet can still revert. Check the corresponding Signet block for the actual result.
All contract addresses on this page are for [Parmigiana testnet](/docs/build-on-signet/parmigiana/index.md) .

