@telaro/evm-bridge
v0.1.1
Published
EVM-side reader of Telaro's Solana bond state. Solidity contracts plus the TypeScript SDK an EVM DApp uses to gate capital on a Telaro-bonded agent.
Downloads
254
Maintainers
Readme
@telaro/evm-bridge
Read Telaro bond state on EVM, gate capital on a Solana agent from a Solidity DApp.
Telaro bonds happen on Solana (cheap, atomic CPI gate, USDC). For an EVM DApp (Base, Arbitrum, Optimism, mainnet) that wants to delegate capital to a Solana-bonded agent, this package ships:
- The
TelaroBridgeSolidity contract that mirrors per-agent profile attestations from Solana. - The TypeScript SDK an EVM DApp uses to call
gate(...)/tryGate(...)before delegating capital. - The relayer pieces a Telaro operator runs to push profile updates from Solana into the EVM contract.
Install
npm install @telaro/evm-bridge ethersDrop-in DApp gate
import {
TelaroBridgeClient,
TelaroBridgeGateError,
} from "@telaro/evm-bridge";
import { JsonRpcProvider } from "ethers";
const client = new TelaroBridgeClient({
provider: new JsonRpcProvider("https://base.publicnode.com"),
bridgeAddress: "0xBRIDGE...",
});
try {
const profile = await client.gate("AgentPubkey...", {
minBondAtomic: 1_000_000_000n, // 1000 USDC
minScore: 700,
maxStaleSeconds: 600, // optional, fail if older than 10 min
});
// profile.bondAtomic, profile.score, profile.frozen, profile.slot
} catch (err) {
if (err instanceof TelaroBridgeGateError) {
// err.code: NOT_BONDED | FROZEN | BOND_BELOW_MIN | SCORE_BELOW_MIN | STALE_PROFILE
}
}Or non-throwing:
const r = await client.tryGate(agent, policy);
if (!r.ok) return res.status(402).json({ code: r.code });What ships
| Layer | Where |
| --- | --- |
| Solidity contract | contracts/TelaroBridge.sol |
| Interface | contracts/IRiskGate.sol |
| TS SDK | src/client.ts (re-exported from index) |
| Relayer core | src/relayer.ts (RelayerCore, BridgePoster, bridgeAttestationDigest) |
| Pinned ABI | src/abi.ts |
How it works
Solana EVM
──────────────── ───────────────
Telaro program → relayer signs → TelaroBridge.sol
emits BondTopUp, (agent, bond, storage:
ClaimResolved, etc. score, frozen, profile[agent]
slot) lastSlot[agent]
↓ read
EVM DApp.gate()
reverts on
policy fail- The relayer subscribes to Telaro Solana events, holds the latest per-agent profile, signs canonical EIP-191 digests with the Telaro key.
- The contract stores only the latest profile (history lives on Solana). Slot monotonicity blocks replay.
- v1 trust model: single signer. The on-chain
signerslot is rotatable by theadmin. v2 moves to multisig; v3 to light-client proofs.
Agent identity on EVM
EVM stores agents as bytes32. We use sha256(utf-8(base58_pubkey)):
import { agentBytes32 } from "@telaro/evm-bridge";
const agentHash = agentBytes32("8K5g1Duo6V7LjkNCmpX8J6BD7crDTabq5rhGtkyaLG2");
// 0x...32 bytesThe choice is intentional. SHA-256 keeps the hash family aligned with Anchor's discriminator scheme so a Rust caller (CPI on Solana, or an EVM helper crate later) can produce the same hash. Base58 is the canonical Solana string form, never ambiguous.
Tests
The Solidity contract is covered by a Foundry test suite that walks
every code path in TelaroBridge:
# install foundry once
curl -L https://foundry.paradigm.xyz | bash && foundryup
# from packages/evm-bridge
pnpm test:contracts # forge test
pnpm test # node test runner (relayer + hash)27 forge tests cover constructor, the relayer write path (happy /
bad-sig / tampered / stale / same-slot / event), every IRiskGate
read code path (NOT_BONDED, FROZEN, BOND_BELOW_MIN,
SCORE_BELOW_MIN) under both gate and tryGate, admin + signer
rotation with authorisation, and domain separation across two
deployed bridges.
Deploy plan
Out of scope for v0.1 of this package. The contract is audit-ready
shape; deploy ships in Wave 3 (after Solana mainnet ships and a
first EVM partner asks for the bridge). Design doc:
docs/internal/cross-chain-ars-spike.md.
License
MIT.
