Skip to main content

Stealth Actions

The SDK provides easy high-level but modular functionality for atomic stealth actions initiated from and circling back into the shielded pool.

For now these functions have only been designed for use with single-owner accounts - we are actively working on a seamless dev UX for stealth actions performed with multisigs like Safes.

We opted for a design that allows dev users to compose contract interactions without having to worry whether the target contract function makes use of msg.sender and/or msg.value. That's why we chose a EIP-7702 based design, in which the generated stealth account is upgraded to a multicall-capable smart account and funded with gas through a withdrawal from the shielded pool. Since EIP-7702 upgrades only become effective after transaction execution this must happen in a separate setup transaction.

Example

Setup includes an EIP-7702 authorization and gas unshield.

The user's Bermuda key pair is used in conjunction with the id parameter to derive the stealth (meta) address.

gasTank is the amount of WETH to withdraw from the shielded pool as ETH onto the stealth address in the setup step.

let id = 0n
let gasTank = parseEther('.003')
let stealthFunds = parseEther('.5')

let setupPayload = await sdk.stealthSetup({ shieldedKeyPair, id, gasTank })

let { payload, signer: stealthSigner } = await sdk.stealth(
{
spender: alice,
id,
unshield: { token: sdk.config.WETH, amount: stealthFunds },
// The payloads returned from the stealth action handler will be
// sandwiched right here inbetween the optional un- and reshield.
reshield: { token: sdk.config.WETH, amount: stealthFunds, to }
},
// Within this handler devs can compose actions with the stealth signer.
stealthSigner => {
// Here just a dummy interaction with WETH as example interacting with
// contract functions that rely on msg.sender and/or msg.value.
let actions = [
{
to: sdk.config.WETH,
data: sdk.WETH_ABI.encodeFunctionData('withdraw', [stealthFunds])
},
{
to: sdk.config.WETH,
data: sdk.WETH_ABI.encodeFunctionData('deposit'),
value: stealthFunds
}
]
return actions
}
)

The setup payload including the EIP-7702 authorization should be sent through a relayer. Depending on the calls encoded as stealth actions the action payload might be sent through a relayer too, else it should be sent with the stealth signer itself.