---
slug: 75-network
title: Synsema Network (L1)
description: La cadena de Synsema — una L1 de Avalanche (chain id 7960, SYN como gas) que es un registro público de agentes — desde Synsema. Token de acceso con un comando, el grifo, registrar un agente, leer el registro, verificar un pago sin confiar en nadie, el contrato AgentRegistry, la API del explorador y las trampas de la cadena.
example_ids: []
---

# Synsema Network (L1)

[Synsema Network](https://synsema.io) es una L1 de Avalanche cuyo primer trabajo es ser un
**registro público de agentes**: para cada agente, el hash de su programa, la dirección que lo
controla, el hash de las capacidades que declara, la medida de atestación de la máquina donde corre
y las raíces de Merkle de su auditoría. Comprobar un agente es leer su registro, no confiar en quien
lo opera. Encima, una EVM abierta: pagos, tokens, contratos. El gas se paga con el token nativo,
`SYN`.

La cadena no ejecuta agentes; los agentes corren en cualquier lado (tu máquina, un servidor, la
[plataforma](74-platform), un TEE) y usan la cadena con los builtins EVM de
[Blockchain](38-blockchain).

**Hoy es una devnet**, en [devnet.synsema.io](https://devnet.synsema.io): el estado se puede
reiniciar y el SYN ahí no tiene valor. Todo lo de esta página corre contra ella.

| | |
|---|---|
| Chain id | `7960` (`0x1f18`) |
| Token nativo | `SYN`, 18 decimales |
| RPC | `https://devnet.synsema.io/<token>/rpc` |
| Registro de agentes | `0x9124Ac7F5Ff9bA48aed29c78198b59a1Ba6732eF` |
| Explorador | [devnet.synsema.io/explorer](https://devnet.synsema.io/explorer) |
| EVM | hasta Cancun (compilá con `evm_version = "cancun"`) |

## Acceso: un token, una clave, algo de SYN

El RPC pide un token en la ruta. Sacá uno — sin registro, 10 por dirección IP por hora, 600 pedidos
por minuto cada uno:

```sh
curl -s -X POST https://devnet.synsema.io/token
```

La respuesta trae el token, la URL del RPC y la línea para tu `.env`. Después, una clave propia —
cualquier 32 bytes aleatorios — y su dirección:

```sh
openssl rand -hex 32
```

```text
# .env, next to your programs (Synsema reads it and never prints a secret)
L1_RPC=https://devnet.synsema.io/<token>/rpc
MY_KEY=<the 64 hex characters>
```

```synsema
-- address.syn
require secret("MY_KEY")
print(eth_address(secret("MY_KEY")))
```

El grifo manda 100 SYN a una dirección, una vez por hora por dirección:

```sh
curl -s -X POST https://devnet.synsema.io/<token>/faucet \
  -H 'content-type: application/json' -d '{"address": "0x…"}'
```

Una billetera (MetaMask, Rabby) toma los mismos valores: URL del RPC con tu token, chain id `7960`,
símbolo `SYN`. La [portada](https://devnet.synsema.io) tiene un botón que hace los tres pasos y
agrega la red a tu billetera.

## Registrar un agente

`agent.syn` es el programa que se registra (cualquier programa Synsema). Cada valor que mueve plata
está escrito: nada se firma con un valor por defecto que no viste.

```synsema
-- register.syn: synsema run register.syn
require env("L1_RPC")
require secret("MY_KEY")
require sign("MY_KEY")
require net("devnet.synsema.io")
require file.read("agent.syn")

let url be env("L1_RPC")
let registry be "0x9124Ac7F5Ff9bA48aed29c78198b59a1Ba6732eF"
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(canonical_json(["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}`)
```

Qué va en cada campo:

| Campo | Valor |
|---|---|
| `programHash` | `sha256` del programa: el `.syn`, o el módulo WASM que lo embebe, o cualquier artefacto de un agente escrito en otro lenguaje |
| `capsHash` | `sha256(canonical_json(<las líneas require>))` — el techo de lo que el agente puede hacer. `0x00…00` si el agente no declara nada |
| `measurement` | La medida de atestación del enclave donde corre ([Atestación](24-attestation)); cero sin TEE |
| `agentURI` | Donde el agente se describe (su Agent Card, [Identidad de agentes](46-agent-identity)). La cadena no lo comprueba |

El explorador marca cada agente con lo que declara y lo que prueba: *capacidades declaradas / no
declaradas*, *atestado / no atestado*.

## Leer el registro

Leer no necesita clave ni SYN:

```synsema
require env("L1_RPC")
require net("devnet.synsema.io")

let url be env("L1_RPC")
let registry be "0x9124Ac7F5Ff9bA48aed29c78198b59a1Ba6732eF"
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]}`)
```

Sin token, la API JSON del explorador responde lo mismo: `GET /api/agents`, `/api/agent/<id>`,
`/api/tx/<hash>`, `/api/address/<0x…>`, `/api/blocks`, `/api/tokens`, descriptas en
[`/openapi.json`](https://devnet.synsema.io/openapi.json).

## Verificar un pago sin confiar en nadie

Un `200` de una app no prueba un pago. Lo prueba el recibo en la cadena. Este programa responde
"¿este hash pagó exactamente este monto a esta dirección, y es final?":

```synsema
-- paid.syn: synsema run paid.syn -- <hash> <payee>
require env("L1_RPC")
require net("devnet.synsema.io")

task hex_int(s)
    let h be slice(s, 2)
    when length(h) % 2 == 1
        set h to "0" + h
    give bytes_to_int(bytes(h, "hex"))

task paid(hash, payee, amount_wei)
    let r be eth_receipt(env("L1_RPC"), hash)
    when r == nothing or r["status"] != 1
        give false
    let t be eth_rpc(env("L1_RPC"), "eth_getTransactionByHash", [hash])
    give lower(t["to"]) == lower(payee) and hex_int(t["value"]) == amount_wei

print(paid(args()[0], args()[1], 100 * 1000000000000000000))
```

En Avalanche un bloque aceptado es final — no hay reorganizaciones —, así que "incluida" significa
"no se puede deshacer". Para personas, la [página de verificación](https://devnet.synsema.io/verify)
del explorador hace lo mismo y tiene un botón que le pregunta directamente al nodo y compara.

## El contrato `AgentRegistry`

| Función | Quién |
|---|---|
| `register(bytes32 programHash, bytes32 capsHash, bytes32 measurement, string agentURI) → uint256 id` | cualquiera |
| `anchor(uint256 id, uint64 seq, bytes32 root)` | el controlador; `seq` tiene que ser el último + 1 (sin huecos, sin reescrituras) |
| `count() → uint256`, `get(uint256 id)`, `programHashOf(uint256 id)` | lectura |
| `lastSeq(uint256 id)`, `lastRoot(uint256 id)` | lectura |

Eventos: `Registered(uint256 indexed id, address indexed owner, bytes32 programHash, string agentURI)`
y `Anchored(uint256 indexed id, uint64 seq, bytes32 root)`.

## Tokens y contratos

Cualquiera con SYN puede desplegar contratos; el explorador encuentra los tokens ERC-20 por sus
eventos `Transfer`. Un programa Synsema todavía no puede crear un contrato (`tx_eip1559` exige
`to`): desplegá con Foundry y llamalo desde Synsema.

```sh
forge create --broadcast --rpc-url "$L1_RPC" --private-key "$MY_KEY" src/MyToken.sol:MyToken
```

## Trampas

- **Fees:** la base es de 25 gwei y la propina sugerida sigue a las transacciones recientes, así que
  puede superar dos veces la base. Usá `max_fee = base_fee * 2 + priority`; con `base_fee * 2` solo,
  `tx_eip1559` rechaza (`max_priority is greater than max_fee`).
- **Bloques sólo con transacciones.** Una altura que no se mueve significa que la cadena está quieta.
- **Sólo el estado reciente.** El nodo poda: `eth_call` contra un bloque viejo responde
  `missing trie node`. La historia está completa en el explorador.
- **Enteros grandes desde texto:** `number()` devuelve un float y pierde dígitos pasado 2⁵³ — armá
  los montos en wei con aritmética entera (`100 * 1000000000000000000`), no desde un texto parseado.
- **Hex:** `bytes(s, "hex")` no quiere el `0x`; `eth_rpc` devuelve todo con él — `slice(s, 2)`.
