Devnet. The state can be reset at any time and SYN here has no value. Production will start from a new genesis.
synsemanetwork

Synsema Network · devnet · chain id 7960

The chain whereagents are registered.

Each agent gets a public record: the hash of its program, who controls it, what it is allowed to do and where it runs, plus the roots of its audit log. Checking an agent means reading its record, not trusting whoever runs it.

Checking the chain…

Get started Open the explorer Verify a payment

Latest agent on the chainloading
Program
SHA-256 of the agent's .syn file, or of the WASM module that embeds it.
Controller
The address that registered it. Only this address can anchor its audit log.
Capabilities
hash of its require lines
The ceiling of what the agent may do, as canonical JSON.
Environment
attestation measurement
The enclave it runs in. All zeros on this devnet: no enclave yet.
Agent card
Where the agent describes itself.
Audit anchors
Merkle roots of its audit log, numbered with no gaps: history can't be rewritten.

Use it

From nothing to a registered agent, in five steps.

Get a token in the first one and every command below fills in with it and with your address; nothing leaves your browser except the calls you make.

  1. Get an access token

    Every call to the RPC carries a token in its path. Get one here, instantly, or from a terminal with curl -X POST https://synsema.network/token. Already have one? Paste it.

  2. Create a key

    Any 32 random bytes are a key. Keep it in a .env file next to your programs: Synsema reads it from there and never prints it. address.syn shows the address that goes with it.

    openssl rand -hex 32
    .env
    L1_RPC={{RPC}}
    MY_KEY=the-64-hex-characters-from-openssl
    address.syn
    require secret("MY_KEY")
    print(eth_address(secret("MY_KEY")))
    synsema run address.syn
  3. Get SYN

    SYN pays for gas. The faucet sends 100 SYN to an address, once an hour per address.

    From a terminal instead:

    curl -X POST {{BASE}}/faucet -H 'content-type: application/json' \
      -d '{"address": "{{ADDR}}"}'
  4. Register an agent

    This registers agent.syn (any Synsema program; print("hello") is enough) and prints its id. Every value that moves money is written out: nothing is signed with a default you didn't see.

    register.syn
    -- synsema run register.syn
    require env("L1_RPC")
    require secret("MY_KEY")
    require sign("MY_KEY")
    require net("synsema.network")
    require file.read("agent.syn")
    
    let url be env("L1_RPC")
    let registry be "{{REGISTRY}}"
    let k be secret("MY_KEY")
    let me be eth_address(k)
    
    -- the record: program, capabilities, environment, agent card
    let program_hash be sha256(read_file("agent.syn"))
    let caps_hash be sha256('["net"]')
    let measurement be int_to_bytes(0, 32)
    let uri be "https://example.org/.well-known/agent-card.json"
    let data be abi_encode("register(bytes32,bytes32,bytes32,string)", [program_hash, caps_hash, measurement, uri])
    
    -- build, sign, send, wait
    let fees be eth_fee_history(url)
    let tx be tx_eip1559({"chain_id": 7960, "nonce": eth_nonce(url, me), "to": registry, "value": 0,
        "gas": eth_estimate_gas(url, {"from": me, "to": registry, "data": data}) * 2,
        "max_fee": fees["base_fee"] * 2 + fees["priority"], "max_priority": fees["priority"], "data": data})
    let hash be eth_send_raw(url, tx_eip1559_raw(tx, secp256k1_sign(tx["digest"], k)))
    let receipt be eth_wait_receipt(url, hash, 1, 60)
    assert(receipt != nothing and receipt["status"] == 1, "the registration did not go through")
    
    let n be abi_decode("uint256", eth_call(url, {"to": registry, "data": abi_encode("count()", [])}))[0]
    print(`registered as agent {n - 1}, tx {hash}`)
  5. Read the registry

    Reading needs no key and no SYN.

    require env("L1_RPC")
    require net("synsema.network")
    
    let url be env("L1_RPC")
    let registry be "{{REGISTRY}}"
    task call(sig, args)
        give eth_call(url, {"to": registry, "data": abi_encode(sig, args)})
    
    let n be abi_decode("uint256", call("count()", []))[0]
    print(`{n} agents on chain {eth_chain_id(url)}`)
    let a be abi_decode("(address,bytes32,bytes32,bytes32,string,uint64)", call("get(uint256)", [0]))
    print(`agent 0: controller {a[0]}, card {a[4]}`)

The whole guide, with the contract and the gotchas, is in the documentation: synsema.dev ↗

Wallet

Add it to a wallet.

MetaMask, Rabby or any EVM wallet. With the token checked above, one click adds the network; or enter the values by hand.

Network nameSynsema Network devnet
RPC URL{{RPC}}
Chain id7960
Currency symbolSYN (18 decimals)
Block explorerhttps://synsema.network/explorer

Reference

The agent registry and what to know about the chain.

Agent registry

{{REGISTRY}}

FunctionWho
register(bytes32 programHash, bytes32 capsHash, bytes32 measurement, string agentURI) → idanyone
anchor(uint256 id, uint64 seq, bytes32 root)the controller; seq = last + 1
count() → uint256read
get(uint256 id) → (owner, programHash, capsHash, measurement, agentURI, registeredAt)read
lastSeq(uint256 id), lastRoot(uint256 id)read

Events: Registered(id, owner, programHash, agentURI) and Anchored(id, seq, root).

Good to know

  • Blocks are made only when there are transactions. A height that doesn't move means the chain is idle, not stuck.
  • The node keeps recent state only. Reading an old block answers missing trie node.
  • Base fee is 25 gwei. Set max_fee to base_fee * 2 + priority; the suggested tip can be larger than twice the base.
  • Contracts are deployed with Foundry (forge create); Synsema can call them but not create them yet.
  • The EVM goes up to Cancun: compile with evm_version = "cancun".
  • /status is this page's data as JSON, open to anyone.