BearerSwap: Private Crypto Transfers Without Mixers or ZK Proofs
Private transfers on Ethereum have historically relied on either mixers (like Tornado Cash) or zero-knowledge proofs (like Railgun). Both approaches introduce complexity, regulatory scrutiny, or computational overhead. BearerSwap, part of the FLAT Protocol, offers a simpler alternative: private transfers via bearer instruments, similar to physical cash.
Unlike traditional transfers where the chain records a direct movement between addresses, BearerSwap breaks the on-chain link by treating transfers as mint-and-burn operations. The sender creates a one-time token (a "bearer instrument"), and the recipient claims it—without ever revealing the connection between them.
Here’s how it works, why it’s different, and how you can use it today.
How BearerSwap Works
BearerSwap enables private transfers in three steps:
Mint a Bearer Token
The sender creates a new ERC-20 token (a "bearer instrument") with a unique identifier. This token is minted to a null address (effectively burned on creation), but its metadata is stored off-chain in a registry. The sender retains a private claim to this token.Transfer the Claim
The sender shares the token’s claim (e.g., a signed message or secret) with the recipient off-chain. This could be via encrypted chat, email, or even physical transfer—just like handing over cash.Claim the Token
The recipient uses the claim to redeem the token on-chain. The contract burns the old token (if it existed) and mints a new one to the recipient’s address. The chain only sees a mint and burn, not a transfer between two known addresses.
This process ensures no direct link between sender and recipient is ever recorded on-chain.
Comparison: BearerSwap vs. Tornado Cash vs. Railgun
| Feature | BearerSwap | Tornado Cash | Railgun (ZK) |
|---|---|---|---|
| Privacy Mechanism | Bearer tokens (mint+burn) | Mixer (pool-based) | Zero-knowledge proofs |
| Regulatory Status | Not sanctioned | Sanctioned by OFAC | Not sanctioned |
| Complexity | Low (simple mint/burn) | Medium (pool management) | High (ZK circuit setup) |
| Gas Cost | ~50–80k gas per operation | ~100–150k gas (deposit/withdraw) | ~500k+ gas (ZK proof verification) |
| Trust Assumptions | Trust in protocol registry | Trust in mixer operators | Trust in ZK circuit |
| Censorship Risk | Low (no mixer contracts) | High (sanctioned) | Low |
Key Advantages of BearerSwap:
- No mixers: Avoids the regulatory and operational risks of pool-based privacy.
- No ZK proofs: Eliminates the complexity and gas costs of zero-knowledge systems.
- Works on mainnet: Fully compatible with Ethereum, no L2 or sidechain required.
Limitations:
- Off-chain trust: The protocol relies on a registry to track bearer tokens. If the registry is compromised or malicious, privacy could be broken.
- No formal audit: As of writing, BearerSwap is experimental and not yet audited.
Code Example: Using BearerSwap via MCP
The FLAT Protocol provides a Multi-Chain Protocol (MCP) interface for interacting with BearerSwap. Below is a Python example showing how an agent (e.g., a bot or service) would mint and claim a bearer token.
Prerequisites
- Python 3.8+
-
web3.py(pip install web3) - Ethereum node (e.g., Infura, Alchemy)
- BearerSwap contract address (see flat.cash/docs)
Example: Mint and Claim a Bearer Token
from web3 import Web3
from eth_account import Account
from eth_account.messages import encode_defunct
# Configuration
RPC_URL = "https://mainnet.infura.io/v3/YOUR_INFURA_KEY"
CONTRACT_ADDRESS = "0x..." # BearerSwap contract
PRIVATE_KEY = "0x..." # Sender's private key
RECIPIENT_ADDRESS = "0x..." # Recipient's address
# Initialize Web3
w3 = Web3(Web3.HTTPProvider(RPC_URL))
if not w3.is_connected():
raise Exception("Failed to connect to Ethereum")
# Load contract ABI (simplified; use full ABI in production)
abi = [
{
"inputs": [
{"internalType": "address", "name": "recipient", "type": "address"},
{"internalType": "bytes32", "name": "tokenId", "type": "bytes32"}
],
"name": "claim",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{"internalType": "bytes32", "name": "tokenId", "type": "bytes32"}
],
"name": "mint",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
contract = w3.eth.contract(address=CONTRACT_ADDRESS, abi=abi)
# Step 1: Mint a bearer token (sender)
token_id = w3.keccak(text="unique_token_id_123") # Generate a unique ID
sender_account = Account.from_key(PRIVATE_KEY)
mint_tx = contract.functions.mint(token_id).build_transaction({
"from": sender_account.address,
"nonce": w3.eth.get_transaction_count(sender_account.address),
"gas": 100000,
"gasPrice": w3.eth.gas_price
})
signed_tx = sender_account.sign_transaction(mint_tx)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
print(f"Minted token {token_id.hex()}: https://etherscan.io/tx/{tx_hash.hex()}")
# Step 2: Off-chain transfer (sender shares `token_id` with recipient)
# In practice, this could be encrypted or sent via a secure channel.
print(f"Share this token ID with recipient: {token_id.hex()}")
# Step 3: Claim the token (recipient)
recipient_account = Account.create() # In practice, use recipient's private key
claim_tx = contract.functions.claim(RECIPIENT_ADDRESS, token_id).build_transaction({
"from": recipient_account.address, # Simplified; recipient signs
"nonce": w3.eth.get_transaction_count(recipient_account.address),
"gas": 100000,
"gasPrice": w3.eth.gas_price
})
# Recipient signs and sends the claim transaction
signed_claim_tx = recipient_account.sign_transaction(claim_tx)
claim_hash = w3.eth.send_raw_transaction(signed_claim_tx.rawTransaction)
print(f"Claimed token for {RECIPIENT_ADDRESS}: https://etherscan.io/tx/{claim_hash.hex()}")
Notes:
-
Token ID: The
token_idshould be unique and unpredictable to prevent front-running or replay attacks. -
Off-Chain Transfer: The actual transfer of the
token_id(step 2) happens off-chain. Use encryption (e.g., PGP, Signal) for security. - Gas Costs: Minting and claiming cost ~50–80k gas each, making it cheaper than ZK-based solutions.
Limitations and Future Work
While BearerSwap offers a novel approach to private transfers, it has key limitations:
- Trust in Registry: The protocol relies on a registry to track bearer tokens. If the registry is compromised or malicious, privacy could be broken. A decentralized registry (e.g., IPFS + ENS) could mitigate this.
- No Formal Audit: BearerSwap is experimental. A security audit would be required for production use.
- Off-Chain Complexity: The off-chain transfer of claims introduces operational overhead (e.g., secure channels, key management).
Future Improvements:
- Decentralized Registry: Use IPFS or Arweave to store token metadata, reducing reliance on a single registry.
- Batch Operations: Support batch minting/claiming to reduce gas costs.
- EIP-712 Signatures: Improve the security of off-chain claims with typed signatures.
Conclusion
BearerSwap demonstrates that private transfers don’t require mixers or ZK proofs. By leveraging bearer instruments—conceptually similar to physical cash—it achieves privacy with minimal on-chain complexity. While not a silver bullet, it offers a pragmatic alternative for users seeking simplicity and regulatory neutrality.
For developers, the MCP interface makes integration
For the full protocol reference, see docs.flat.cash.
Top comments (0)