# Understanding the Swap, Swear, and Swindle Protocols in the Swarm Ecosystem

> Explore Swarm's Swap Swear Swindle protocols for trust-minimized accounting. Learn how on-chain escrow off-chain payment channels and atomic settlement enable scalable peer-to-peer microtransactions.

- Repository: [Ethersphere/awesome-swarm](https://github.com/ethersphere/awesome-swarm)
- Tags: deep-dive
- Published: 2026-03-01

---

**TLDR:** The Swap-Swear-Swindle suite forms Swarm's trust-minimized accounting layer, using on-chain escrow (Swap), off-chain payment channels (Swear), and atomic settlement (Swindle) to enable scalable peer-to-peer microtransactions without central authority.

The Swap-Swear-Swindle protocols power the economic layer of the Swarm decentralized storage network. Implemented in the [ethersphere/swap-swear-and-swindle](https://github.com/ethersphere/swap-swear-and-swindle) repository, these three interconnected components provide a complete payment channel system that lets Bee nodes exchange services for BZZ tokens efficiently.

## Core Components of the Accounting Stack

The protocols operate as a unified stack where each layer handles a specific aspect of peer-to-peer accounting. Together, they minimize on-chain transactions while maintaining cryptographic guarantees.

### Swap: The On-Chain Escrow Foundation

**Swap** acts as the token-based escrow that maintains the ground truth for peer balances. According to the source code in [`swap/client.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swap/client.go) and the Solidity contract in `contracts/Swap.sol`, this layer stores the current credit or debit amount for each peer relationship alongside the last settlement nonce.

When a Bee node first interacts with a peer, it checks the Swap balance via the `swap.NewClient` interface before accepting requests that require payment. This on-chain ledger serves as the anchor for all off-chain activity, ensuring that every peer has sufficient collateral to cover potential debts.

### Swear: Off-Chain Payment Channels

**Swear** implements the state channel logic that makes Swarm economically viable at scale. Located in [`swear/channel.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/channel.go) and [`swear/cheque.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/cheque.go), this protocol allows peers to exchange signed "cheques" that incrementally update balances without writing to the blockchain.

Peers open a Swear channel using `swear.NewChannel`, then exchange cryptographically signed updates for each service rendered—such as storing a chunk or retrieving data. The recipient verifies signatures using the methods in [`swear/cheque.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/cheque.go) and updates its local view. Because these operations stay off-chain, they remain fast and inexpensive regardless of transaction volume.

### Swindle: Trustless Settlement Arbitration

**Swindle** serves as the final arbiter that guarantees atomicity when channels close. The implementation in [`swindle/settle.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/settle.go) and the `contracts/Swindle.sol` contract handle the verification of final states, resolution of out-of-order updates, and the atomic transfer of tokens.

When a channel closes, the closing party calls `swindleClient.Settle` with the latest signed state. Swindle validates both signatures, resolves any disputes where one party attempts to submit an outdated state, and writes the definitive balance back to Swap. This ensures both parties receive exactly what they are owed with a single on-chain transaction.

## Architectural Workflow: Four-Phase Lifecycle

The protocols follow a strict lifecycle that maximizes efficiency while preventing double-spending.

### 1. Channel Creation

When two Bee nodes establish a relationship, they negotiate a Swear payment channel. Both parties invoke `swapClient.Deposit` (as defined in [`swap/client.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swap/client.go)) to create a Swap account entry and fund it with BZZ tokens. This on-chain deposit serves as the collateral backing the off-channel activity.

### 2. Off-Chain Updates

During normal operation, peers exchange services for signed cheques. The service provider calls `ch.Increment` to update the local channel state, then `ch.Sign()` to generate a cryptographic proof. The recipient verifies this cheque using the logic in [`swear/cheque.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/cheque.go) and updates its local ledger. No blockchain interaction occurs during this phase, enabling high-throughput microtransactions.

### 3. Channel Closure

Either party may initiate closure by transmitting the latest signed state to the counter-party. The receiving node can accept the state or provide a newer signed update if the submitted state is stale. This exchange happens off-chain via Swarm's P2P protocol, giving both parties a chance to present the most recent valid state.

### 4. Settlement

The closing party retrieves the final state using `ch.LatestState()` and submits it to the Swindle contract. The [`swindle/settle.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/settle.go) implementation validates the signatures, resolves any discrepancies, and atomically updates the Swap balances. The on-chain token contract transfers only the net difference, minimizing gas costs.

## Implementing the Protocols in Go

The `ethersphere/swap-swear-and-swindle` repository exposes a Go SDK that Bee nodes use to interact with these protocols. Below are minimal examples illustrating the public API surface.

### Initialize a Swap Account and Deposit Funds

This example demonstrates creating a Swap client and funding a peer's escrow balance. The `swap.NewClient` constructor binds to the token contract, while `Deposit` handles the on-chain transaction.

```go
import (
    "context"
    "log"

    swap "github.com/ethersphere/swap-swear-and-swindle/swap"
    eth  "github.com/ethereum/go-ethereum/ethclient"
)

func fundSwap(peerAddr string, amount uint64) {
    // Connect to an Ethereum node (used only for token transfers)
    ethClient, _ := eth.Dial("https://mainnet.infura.io/v3/YOUR-PROJECT-ID")

    // Create a Swap client bound to the token contract
    swapClient := swap.NewClient(ethClient, swapContractAddress)

    // Deposit BZZ tokens into the peer’s Swap balance
    tx, err := swapClient.Deposit(context.Background(), peerAddr, amount)
    if err != nil {
        log.Fatalf("deposit failed: %v", err)
    }
    log.Printf("deposit tx sent: %s", tx.Hash().Hex())
}

```

*Source:* [`swap/client.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swap/client.go)

### Open a Swear Payment Channel

Channels are instantiated using `swear.NewChannel`, which initializes the off-chain state with a starting balance and peer identifier.

```go
import (
    "log"
    "github.com/ethersphere/swap-swear-and-swindle/swear"
)

func openChannel(peerID string, initAmount uint64) *swear.Channel {
    // Initialise a new off‑chain channel with a starting balance
    ch, err := swear.NewChannel(peerID, initAmount)
    if err != nil {
        log.Fatalf("cannot create channel: %v", err)
    }
    // Persist the channel locally (e.g., to a DB) – omitted for brevity
    return ch
}

```

*Source:* [`swear/channel.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/channel.go)

### Send a Signed Cheque After Providing a Service

The service provider increments the channel balance and signs the update. The `ch.Sign()` method uses the node's private key to generate the cryptographic proof.

```go
func sendCheque(ch *swear.Channel, value uint64) (*swear.Cheque, error) {
    // Increment the channel’s local balance
    if err := ch.Increment(value); err != nil {
        return nil, err
    }
    // Sign the updated state – the library uses the node’s private key
    cheque, err := ch.Sign()
    if err != nil {
        return nil, err
    }
    // Transmit the cheque to the counter‑party (e.g., via Bee’s P2P protocol)
    return cheque, nil
}

```

*Source:* [`swear/cheque.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/cheque.go)

### Close the Channel and Settle with Swindle

Final settlement requires retrieving the latest state and submitting it to the Swindle contract. The `Settle` method in [`swindle/settle.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/settle.go) handles the atomic transfer.

```go
import (
    "context"
    "log"
    swindle "github.com/ethersphere/swap-swear-and-swindle/swindle"
)

func closeChannel(ch *swear.Channel) {
    // Retrieve the latest signed state (both signatures)
    state := ch.LatestState()

    // Call the Swindle contract to finalize the settlement
    swindleClient := swindle.NewClient(ethClient, swindleContractAddress)
    receipt, err := swindleClient.Settle(context.Background(), state)
    if err != nil {
        log.Fatalf("settlement failed: %v", err)
    }
    log.Printf("channel settled, tx: %s", receipt.TxHash.Hex())
}

```

*Source:* [`swindle/settle.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/settle.go)

## Key Source Files and Contracts

The following files define the protocol implementations and their data structures:

- [`swap/client.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swap/client.go) – Core API for creating, depositing to, and querying Swap accounts.
- [`swap/types.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swap/types.go) – Data structures (balances, nonces) used by the Swap contract interface.
- [`swear/channel.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/channel.go) – Implementation of off-chain payment channels, state tracking, and nonce management.
- [`swear/cheque.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swear/cheque.go) – Logic for creating, signing, and verifying cheques (the off-chain payment objects).
- [`swindle/settle.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/settle.go) – Settlement contract wrapper; validates signatures and writes final balances to Swap.
- [`swindle/types.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/types.go) – Types that represent the on-chain settlement payload.
- `contracts/Swap.sol` – Solidity contract that holds the on-chain escrow.
- `contracts/Swindle.sol` – Solidity contract that performs the final atomic settlement.

## Summary

- **Swap** maintains the on-chain escrow balance per peer, serving as the economic anchor for all transactions.
- **Swear** enables scalable off-chain payments through cryptographically signed cheques, minimizing blockchain interactions to channel open and close operations only.
- **Swindle** guarantees atomic settlement and dispute resolution, preventing either party from cheating by submitting outdated channel states.
- The architecture achieves **scalability** by keeping intermediate accounting off-chain, **atomicity** through the Swindle arbitration layer, and **transparency** via the publicly queryable Swap balances.

## Frequently Asked Questions

### What is the difference between Swap and Swear?

**Swap** is the on-chain escrow layer that stores the definitive balance sheet and collateral for each peer relationship. **Swear** is the off-chain payment channel protocol that sits on top of Swap, allowing peers to exchange signed cheques for services without blockchain transactions. While Swap maintains the ground truth, Swear enables the high-throughput microtransactions necessary for a functional storage network.

### How does Swindle prevent cheating during settlement?

Swindle prevents cheating by requiring both parties' signatures on the final channel state and implementing a dispute window. If one party attempts to submit an outdated state with a lower balance, the counter-party can present a newer signed state to prove the attempted fraud. The [`swindle/settle.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swindle/settle.go) implementation validates these signatures and resolves conflicts before atomically transferring the correct amounts via the Swap contract.

### Why are these protocols necessary for Swarm?

Without Swap-Swear-Swindle, every chunk storage or retrieval would require an on-chain transaction, making the network economically and technically infeasible due to gas costs and latency. These protocols enable the **incentivization layer** of Swarm, ensuring that storage providers receive BZZ tokens for their services while keeping operational costs low enough to support decentralized, peer-to-peer bandwidth and storage markets.

### Which blockchain does Swap-Swear-Swindle use for settlement?

The protocols settle on **Ethereum** (or Ethereum-compatible chains) using the BZZ token. The [`swap/client.go`](https://github.com/ethersphere/awesome-swarm/blob/main/swap/client.go) implementation connects via standard Ethereum JSON-RPC endpoints (such as Infura or local nodes) to interact with the Swap and Swindle Solidity contracts. All on-chain operations—deposits, withdrawals, and final settlements—execute as transactions against these smart contracts.