For the complete documentation index, see llms.txt. This page is also available as Markdown.

Token Interaction

Reading and writing SRC20 token balances and allowances

Read shielded balances and write shielded state changes on SRC20 tokens using seismic-alloy.

Overview

SRC20 token interaction in Rust follows the same builder pattern as all seismic-alloy contract calls:

  • Transparent reads (metadata) — Use contract.name().call() without .seismic()

  • Signed reads (balances, allowances) — Use contract.balanceOf(addr).seismic().call() with .seismic() (no shielded params in arguments)

  • Shielded writes (transfers, approvals) — Use contract.transfer(to, amount).send() directly (auto-encrypts because suint256 is a shielded param)

Defining the Interface

use seismic_prelude::client::*;

sol! {
    #[sol(rpc)]
    interface ISRC20 {
        function name() public view returns (string);
        function symbol() public view returns (string);
        function decimals() public view returns (uint8);
        function totalSupply() public view returns (uint256);

        function balanceOf(address account) public view returns (suint256);
        function transfer(address to, suint256 amount) public returns (bool);
        function approve(address spender, suint256 amount) public returns (bool);
        function allowance(address owner, address spender) public view returns (suint256);
        function transferFrom(address from, address to, suint256 amount) public returns (bool);

        event Transfer(address indexed from, address indexed to, suint256 value);
        event Approval(address indexed owner, address indexed spender, suint256 value);
    }
}

Reading Token Metadata

Token metadata (name, symbol, decimals, totalSupply) is not shielded. Use a plain transparent read:

Metadata reads do not require a wallet or signed provider. An unsigned provider works fine since these values are not shielded.

Reading Shielded Balances

balanceOf() is a shielded read. The contract uses msg.sender to authenticate the caller, so you must use .seismic().call() (a signed read) on a provider created with a wallet.

Reading Allowances

Allowance reads may also be shielded depending on the contract implementation. Use a signed read to be safe:

Shielded Writes

Transfer Tokens

Send tokens using a shielded write. The transfer amount is encrypted in calldata:

Approve a Spender

Operation Summary

Operation
Method
Builder
Provider Required

Read name/symbol/decimals

contract.name().call()

No encryption

Any provider

Read balanceOf

contract.balanceOf(addr).seismic().call()

.seismic()

Signed provider

Read allowance

contract.allowance(o, s).seismic().call()

.seismic()

Signed provider

Transfer tokens

contract.transfer(to, amt).send()

Auto-encrypts

Signed provider

Approve spender

contract.approve(s, amt).send()

Auto-encrypts

Signed provider

Notes

  • All shielded operations require a provider built with a wallet via SeismicProviderBuilder

  • Functions with shielded parameters (suint256) like transfer and approve auto-encrypt via ShieldedCallBuilder

  • For functions without shielded params (like balanceOf and allowance), use .seismic() to opt into encryption

  • The filler pipeline automatically handles encryption nonce, TEE pubkey, and AES-GCM encryption

  • Shielded types (suint256) appear as their standard counterparts (uint256) in the ABI encoding

See Also

Last updated