Transactor Integration Guide
The Transactor
contract creates transactions on Signet from Ethereum.
Transactions made via the Transactor
always execute on Signet at the end of
the current block, bypassing any possibility of builder censorship.
Consult the Pecorino Quickstart
guide for contract addresses and RPC
endpoints.
Setup
- The Transactor ABI can be downloaded here: Transactor ABI.
$ curl -O https://signet.sh/docs/abis/Transactor.abi.json
- The
Transactor Contract
is also open source.$ forge install https://github.com/init4tech/zenith
- Rust alloy bindings are available via the
signet-bindings
crate.$ cargo add signet-bindings
Overview
Transactor.sol
exposes a basic EVM transaction as a single function:
1function transact(
2 address to,
3 bytes calldata data,
4 uint256 value,
5 uint256 gas,
6 uint256 maxFeePerGas
7) external payable
Calling the 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
field is the amount of ETH in wei to send on the rollup. The
msg.value
of the transact
call will be bridged to Signet, and could be more
or less than value
. I.e. the call transactor.transact{value: 5 ether}(.., 1 ether, ...)
will send 5 ETH to Signet, but only 1 ETH will be used to invoke
the to
address.
Transactions 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 it may revert or be dropped by the Signet Orders
system).
When to Use Transactor
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
Code Examples
Solidity
1contract YourContract {
2 Transactor public transactor;
3
4 constructor(Transactor _transactor) {
5 transactor = _transactor;
6 }
7
8 // Execute a function on Signet from Ethereum
9 function executeOnSignet(
10 address signetTarget,
11 bytes calldata functionData
12 ) external {
13 transactor.transact(
14 signetTarget,
15 functionData,
16 0, // value on Signet
17 1_000_000, // gas limit on Signet
18 100 gwei // max fee per gas on Signet
19 );
20 }
21
22 // Emergency action on Signet
23 function emergencyAction(address signetContract) external onlyOwner {
24 // Encode the emergency function call
25 bytes memory data = abi.encodeWithSignature("emergencyPause()");
26 executeOnSignet(signetContract, data);
27 }
28}
Monitoring Transactor Activity in JavaScript/TypeScript
Listen for Transactor events to track Host-driven transactions:
1import { ethers } from "ethers";
2
3const provider = new ethers.JsonRpcProvider("https://eth.llamarpc.com");
4const transactor = new ethers.Contract(
5 TRANSACTOR_ADDRESS,
6 TRANSACTOR_ABI, // Get ABI from contract source
7 provider
8);
9
10// Listen for Host-driven transactions
11// Event name and signature from Transactor.sol
12transactor.on("Transact", (...args) => {
13 console.log("Host-driven execution:", args);
14
15 // Decode the calldata if needed
16 const [from, to, data] = args; // Adjust based on actual event
17 console.log(`${from} Host-driven execution on ${to}`);
18});