> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tentaclepay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Architecture

> How dWallets, the verifier, and the on-chain protocol authorize cross-chain payments.

Cross-chain payment turns "pay USDC on Sui" into "a valid signature on another chain." This page explains the parts that make that safe.

## Components

<CardGroup cols={2}>
  <Card title="dWallet (Ika 2PC-MPC)" icon="key">
    A wallet whose private key is split across [Ika](https://ika.xyz)'s MPC network. It can sign for other chains, but no single party — including Tentacle Pay — ever holds the whole key.
  </Card>

  <Card title="Move contract" icon="file-contract">
    The `tentaclepay` package on Sui. It custodies the `DWalletCap`, collects the USDC payment, and routes the signing request to Ika's coordinator. See [Smart contracts](/contracts/overview).
  </Card>

  <Card title="Verifier" icon="shield-check">
    An off-chain service that prepares and attests each signing request. The contract refuses to sign without a fresh, valid attestation.
  </Card>

  <Card title="Coordinator" icon="network-wired">
    Ika's `DWalletCoordinator` — the on-chain entry point that runs the threshold signing protocol and returns the signature.
  </Card>
</CardGroup>

## The flow

<Steps>
  <Step title="The agent builds the destination payment">
    The x402 client produces the payment authorization for the destination chain (for example, an EVM `transferWithAuthorization`) and sends it to the verifier.
  </Step>

  <Step title="The verifier prepares and attests the request">
    The verifier builds the exact message the dWallet must sign and produces the dWallet's user-side signature — the centralized signature. It returns both, along with an Ed25519 attestation over a digest binding this exact call: the protocol, signer, coordinator, amount, message, and an expiry.
  </Step>

  <Step title="pay_and_sign runs on Sui">
    The agent calls `pay_and_sign`, paying USDC and passing the message, the centralized signature, and the verifier attestation. The contract checks the attestation, takes the payment, and requests the threshold signature from the coordinator.
  </Step>

  <Step title="Ika produces the signature">
    The coordinator consumes a pre-funded presign and runs the 2PC-MPC protocol, producing a signature valid on the destination chain.
  </Step>

  <Step title="The agent collects the signature">
    The SDK polls the verifier, which reads the completed sign session from Sui and returns the signature in the destination chain's format.
  </Step>

  <Step title="The payment settles on the destination">
    The signed authorization is submitted to the destination chain, paying the service.
  </Step>
</Steps>

The agent never talks to Ika directly — it exchanges messages with the verifier and pays on Sui; everything else happens between the contract and the coordinator.

## Why the verifier attestation

The contract will only ask the dWallet to sign a message that the verifier has approved. The verifier signs the digest:

```text theme={null}
keccak256(
  "pay_and_sign"
    || protocol.id || signer.id || coordinator.id
    || payment.value || message || keccak256(message_centralized_signature)
    || valid_before
)
```

Binding all of these into one digest gives three guarantees:

* **No tampering** — change the amount, message, or any object id, and the attestation no longer verifies.
* **No replay** — the digest commits to this specific call, so an attestation can't be reused for another.
* **Bounded lifetime** — `valid_before` is checked against Sui's on-chain `Clock`, so a stale attestation is rejected.

On-chain, the contract rebuilds this digest from the call's parameters and verifies it against the verifier's public key stored in the `Protocol` object. The key can be rotated by the protocol admin.

## Presigns and sponsored fees

Threshold signing is faster when part of the work is done ahead of time. The contract keeps a pool of single-use **presigns**; each signature consumes one, and the pool is refilled with `add_presigns`. It also holds sponsored IKA and SUI fee pools so callers don't have to supply the protocol fees themselves — anyone can top these up with `deposit_ika` and `deposit_sui`.

## Trust model

* The dWallet key is never reconstructed; signatures come from Ika's MPC protocol.
* The dWallet is a **shared** dWallet — its user-side share is public, so producing the centralized signature grants nothing by itself. Ika's network completes a signature only for a message the contract has approved.
* The Move contract is the only thing that can approve a message for the dWallet, and it does so only against a valid verifier attestation.
* The verifier decides which payments may be signed; it cannot move funds, and its attestation alone completes nothing without the USDC payment on Sui.
* USDC paid into the contract accumulates in an admin-gated vault — it funds the destination-side settlement.

## Next steps

<Card title="Smart contracts" icon="file-contract" href="/contracts/overview">
  The `tentaclepay` Move module in detail.
</Card>
