diff --git a/benchmarks/ink-rpc.yml b/benchmarks/ink-rpc.yml
index 6f93117d..38f6a737 100644
--- a/benchmarks/ink-rpc.yml
+++ b/benchmarks/ink-rpc.yml
@@ -35,7 +35,7 @@ methodology:
- "Latency: client-side round-trip delta in milliseconds, exposed as both a gauge and a histogram (buckets 50 ms → 10 s), so percentiles are computed via Prometheus `quantile_over_time` over the last 24 hours."
- "Call-result classification: `ok` (HTTP 200 + non-empty result with a parsable hex block number), `http_err`, `jsonrpc_err` (HTTP 200 carrying an error body), `stale` (more than 25 blocks behind the cross-provider tip), `timeout`. Latency without reliability is a misleading ranking signal."
- "This page is part of the per-chain RPC cluster derived from the cross-chain [rpc-capabilities](https://openchainbench.com/benchmarks/rpc-capabilities) benchmark; the identical harness, cadence and exclusion rules apply on every chain."
- - "Chain scope: every query on this page is pinned to `chain=\"ink\"`. Provider coverage at launch: 4 no-key endpoints (Ink (Gelato), Ink (QuickNode), dRPC, Tenderly Gateway)."
+ - "Chain scope: every query on this page is pinned to `chain=\"ink\"`. Provider coverage at launch: 4 no-key endpoints (Gelato, QuickNode, dRPC, Tenderly Gateway)."
findings:
- "{{best_name}} currently leads free Ink RPC at {{best_p50}} (`eth_getBlockByNumber(\"latest\", false)` p50, 24h) across 4 measured providers."
@@ -44,7 +44,7 @@ faq:
- q: "What is the fastest free Ink RPC right now?"
a: "{{best_name}} currently leads at {{best_p50}} (`eth_getBlockByNumber(\"latest\", false)` p50 over the last 24h), measured against 4 no-key providers probed every 60 seconds from us-east, eu-west and Singapore. The leaderboard re-sorts continuously against fresh Prometheus samples, so the answer on this page is the answer right now, not a quarterly snapshot. Use the region tabs to see the leader from the origin closest to your deployment."
- q: "Which Ink RPCs work without an API key?"
- a: "5 endpoints sustain continuous keyless probing at launch: Ink (Gelato), Ink (QuickNode), dRPC, Tenderly Gateway. Every listed endpoint was live-verified with a `eth_getBlockByNumber(\"latest\", false)` POST returning a parsable response before inclusion. See the methodology section for the specific endpoints that were audited and excluded."
+ a: "5 endpoints sustain continuous keyless probing at launch: Gelato, QuickNode, dRPC, Tenderly Gateway. Every listed endpoint was live-verified with a `eth_getBlockByNumber(\"latest\", false)` POST returning a parsable response before inclusion. See the methodology section for the specific endpoints that were audited and excluded."
- q: "Does the fastest Ink RPC change by region?"
a: "Often. Public infra concentrates in specific regions; a gateway that wins from Amsterdam can lose from Singapore by multiples. The region tabs at the top of the page re-scope every number to a single origin; pick the one closest to where your requests originate."
- q: "How is Ink RPC latency measured here, technically?"
@@ -67,9 +67,9 @@ dimensions:
providers:
- slug: ink-official
- name: Ink (Gelato)
+ name: Gelato
tag: Kraken's Ink Chain official public RPC, Gelato-backed
- formula: "50th percentile over 24h of client-side round-trip latency (ms) for a single `eth_getBlockByNumber(\"latest\", false)` POST sent every 60s from 3 regions (us-east + eu-west + sgp) to Ink (Gelato)'s no-key ink RPC endpoint."
+ formula: "50th percentile over 24h of client-side round-trip latency (ms) for a single `eth_getBlockByNumber(\"latest\", false)` POST sent every 60s from 3 regions (us-east + eu-west + sgp) to Gelato's no-key ink RPC endpoint."
queries:
p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="ink-official", chain="ink"})
p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="ink-official", chain="ink"})
@@ -90,9 +90,9 @@ providers:
series: avg_over_time(rpc_latency_milliseconds{provider="ink-official", chain="ink", region="sgp"}[1h])
- slug: ink-quicknode
- name: Ink (QuickNode)
+ name: QuickNode
tag: Kraken's Ink Chain second official public RPC, QuickNode-backed
- formula: "50th percentile over 24h of client-side round-trip latency (ms) for a single `eth_getBlockByNumber(\"latest\", false)` POST sent every 60s from 3 regions (us-east + eu-west + sgp) to Ink (QuickNode)'s no-key ink RPC endpoint."
+ formula: "50th percentile over 24h of client-side round-trip latency (ms) for a single `eth_getBlockByNumber(\"latest\", false)` POST sent every 60s from 3 regions (us-east + eu-west + sgp) to QuickNode's no-key ink RPC endpoint."
queries:
p50: avg(ocb:rpc_latency_milliseconds:p50_24h{provider="ink-quicknode", chain="ink"})
p90: avg(ocb:rpc_latency_milliseconds:p90_24h{provider="ink-quicknode", chain="ink"})
diff --git a/benchmarks/rwa-yield-accuracy.yml b/benchmarks/rwa-yield-accuracy.yml
index 7266b720..5e94e365 100644
--- a/benchmarks/rwa-yield-accuracy.yml
+++ b/benchmarks/rwa-yield-accuracy.yml
@@ -147,3 +147,17 @@ providers:
success: rwa_yield_probe_ok{token="ousg"}
sample_size: rwa_yield_aum_usd{token="ousg"}
series: rwa_yield_delivered_bps_30d{token="ousg"}
+
+ - slug: syrup-usdc
+ name: SyrupUSDC
+ tag: "Maple, Ethereum, ERC-4626 NAV"
+ formula: "ERC-4626 convertToAssets(1 share) delta over 30d, annualized. SyrupUSDC is Maple's yield-bearing USDC vault backed by institutional loans, not T-bills. Compared to the pool's base APY on DefiLlama (excludes SYRUP token incentives)."
+ queries:
+ p50: rwa_yield_deviation_bps_30d{token="syrup-usdc"}
+ p90: rwa_yield_deviation_bps_7d{token="syrup-usdc"}
+ p99: rwa_yield_deviation_bps_lifetime{token="syrup-usdc"}
+ mean: rwa_yield_delivered_bps_30d{token="syrup-usdc"}
+ success: rwa_yield_probe_ok{token="syrup-usdc"}
+ sample_size: rwa_yield_aum_usd{token="syrup-usdc"}
+ series: rwa_yield_delivered_bps_30d{token="syrup-usdc"}
+
diff --git a/harnesses/rpc-capabilities/cmd/script/config.go b/harnesses/rpc-capabilities/cmd/script/config.go
index a09adca2..da545732 100644
--- a/harnesses/rpc-capabilities/cmd/script/config.go
+++ b/harnesses/rpc-capabilities/cmd/script/config.go
@@ -576,8 +576,8 @@ func chains() []Chain {
Slug: "ink",
Name: "Ink",
Providers: []Provider{
- {Slug: "ink-official", Name: "Ink (Gelato)", URL: envDefault("RPC_URL_INK_OFFICIAL", "https://rpc-gel.inkonchain.com")},
- {Slug: "ink-quicknode", Name: "Ink (QuickNode)", URL: envDefault("RPC_URL_INK_QUICKNODE", "https://rpc-qnd.inkonchain.com")},
+ {Slug: "ink-official", Name: "Gelato", URL: envDefault("RPC_URL_INK_OFFICIAL", "https://rpc-gel.inkonchain.com")},
+ {Slug: "ink-quicknode", Name: "QuickNode", URL: envDefault("RPC_URL_INK_QUICKNODE", "https://rpc-qnd.inkonchain.com")},
{Slug: "drpc", Name: "dRPC", URL: envDefault("RPC_URL_INK_DRPC", "https://ink.drpc.org")},
{Slug: "tenderly", Name: "Tenderly Gateway", URL: envDefault("RPC_URL_INK_TENDERLY", "https://ink.gateway.tenderly.co")},
},
diff --git a/harnesses/rwa-yield-accuracy/cmd/script/main.go b/harnesses/rwa-yield-accuracy/cmd/script/main.go
index dd7381b6..c2ef8450 100644
--- a/harnesses/rwa-yield-accuracy/cmd/script/main.go
+++ b/harnesses/rwa-yield-accuracy/cmd/script/main.go
@@ -18,26 +18,19 @@ import (
// this bench is: (1) implement IssuerProbe, (2) add its slug to
// promised-yields.yml, (3) append here.
//
-// Active cohort: USDY (rebase, totalSupply growth), USTB (NAV via
-// Chainlink feed), OUSG (NAV via OndoOracle). All three are fully
-// on-chain measurable — no off-chain HTTP dependency, no treasury
-// wallet assumption.
+// Active cohort:
+// - USDY (Ondo, rebase)
+// - USTB (Superstate, Chainlink NAV feed)
+// - OUSG (Ondo, OndoOracle IPriceOracle)
+// - SyrupUSDC (Maple, ERC-4626 convertToAssets)
//
-// BUIDL and BENJI stay dormant:
-// - BUIDL: distributor 0x5072Ed40EBa6bE38C2370cAD1Cb1df0202924e53
-// was identified but calls bulkIssuance (mints more BUIDL, not
-// USDC transfers). The current dividend.go model that scans USDC
-// Transfer events doesn't fit; needs a rebase-style measurement
-// PLUS a way to separate yield mints from new subscriptions.
-// - BENJI: Ethereum wrapper (0x3DDc...50dc9) has 3 holders, ~$48M,
-// no on-chain sharePrice function. NAV is $1.00 by design; yield
-// is only knowable via Franklin's off-chain fund page. Reached
-// out to digitalassets@franklintempleton.com; unblock once they
-// confirm an API endpoint or Chainlink feed.
+// BUIDL and BENJI dormant: distributor mints conflate yield with
+// subscriptions (BUIDL), Ethereum wrapper lacks on-chain NAV (BENJI).
var probes = []IssuerProbe{
NewUSDYProbe(),
NewUSTBProbe(),
NewOUSGProbe(),
+ NewSyrupUSDCProbe(),
// NewBUIDLProbe(), // TODO: split bulkIssuance mints from subscriptions
// NewBENJIProbe(), // TODO: waiting Franklin NAV endpoint confirmation
}
diff --git a/harnesses/rwa-yield-accuracy/cmd/script/syrupusdc.go b/harnesses/rwa-yield-accuracy/cmd/script/syrupusdc.go
new file mode 100644
index 00000000..8d272316
--- /dev/null
+++ b/harnesses/rwa-yield-accuracy/cmd/script/syrupusdc.go
@@ -0,0 +1,138 @@
+package main
+
+import (
+ "context"
+ "fmt"
+ "math/big"
+ "time"
+
+ "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/ethclient"
+)
+
+// SyrupUSDC is Maple Finance's yield-bearing USDC token — an ERC-4626
+// vault whose underlying position is a book of over-collateralized
+// (and, more recently, undercollateralized) institutional USDC loans.
+// Share price grows daily as pool interest accrues; no rebase, no
+// dividend transfers.
+//
+// Contract (Ethereum mainnet):
+// 0x80ac24aA929eaF5013f6436cdA2a7ba190f5Cc0b (6 decimals, asset=USDC)
+//
+// Yield model: NAV appreciation via ERC-4626 convertToAssets().
+// Passing 1e6 (one share in 6 decimals) returns the current USDC value
+// of one share directly. Called at a historical block, we get the NAV
+// that was current at that block — same clean methodology as OUSG and
+// USTB, no off-chain data needed.
+//
+// Scope note: SyrupUSDC is NOT a T-bill wrapper — it's collateralized
+// pool lending, so deviation from advertised APY reflects both loan-
+// book performance AND yield disclosure honesty. Included in bench 089
+// under the broader framing "on-chain yield-bearing stables promising
+// an APY," not the narrow "tokenized T-bill" reading.
+//
+// Advertised APY tracked here is the pool's BASE APY (yield generated
+// by the loan book), not the boosted APY including SYRUP token
+// incentives. This matches what we can measure on-chain: convertToAssets
+// only reflects underlying pool yield, not off-chain reward
+// distributions.
+
+const (
+ syrupUSDCContractEthereum = "0x80ac24aA929eaF5013f6436cdA2a7ba190f5Cc0b"
+ // One share in the token's 6-decimal base units. Passing this to
+ // convertToAssets returns USDC-per-share directly.
+ syrupUSDCOneShareRaw = uint64(1_000_000)
+)
+
+var erc4626ConvertToAssetsSelector []byte
+
+func init() {
+ erc4626ConvertToAssetsSelector = crypto.Keccak256([]byte("convertToAssets(uint256)"))[:4]
+}
+
+type syrupUSDCProbe struct {
+ contract common.Address
+}
+
+func NewSyrupUSDCProbe() IssuerProbe {
+ return &syrupUSDCProbe{
+ contract: common.HexToAddress(syrupUSDCContractEthereum),
+ }
+}
+
+func (p *syrupUSDCProbe) Slug() string { return "syrup-usdc" }
+func (p *syrupUSDCProbe) Issuer() string { return "maple" }
+func (p *syrupUSDCProbe) Chain() string { return "ethereum" }
+
+func (p *syrupUSDCProbe) Measure(ctx context.Context, rpc *ethclient.Client) (*Measurement, error) {
+ now := time.Now().UTC()
+
+ latest, err := rpc.BlockNumber(ctx)
+ if err != nil {
+ return nil, fmt.Errorf("latest block: %w", err)
+ }
+ block30dAgo := blockOffsetBySeconds(latest, int64(Window30d.Seconds()))
+ block7dAgo := blockOffsetBySeconds(latest, int64(Window7d.Seconds()))
+
+ // USDC-per-share at each snapshot. 6-decimal in, 6-decimal out; the
+ // returned float64 is already scaled to USD.
+ navNow, err := p.readSharePriceUSD(ctx, rpc, nil)
+ if err != nil {
+ return nil, fmt.Errorf("nav now: %w", err)
+ }
+ nav30d, err := p.readSharePriceUSD(ctx, rpc, block30dAgo)
+ if err != nil {
+ return nil, fmt.Errorf("nav 30d: %w", err)
+ }
+ nav7d, err := p.readSharePriceUSD(ctx, rpc, block7dAgo)
+ if err != nil {
+ return nil, fmt.Errorf("nav 7d: %w", err)
+ }
+
+ yield30dBps := annualizedYieldBpsFromNAV(navNow, nav30d, 30.0)
+ yield7dBps := annualizedYieldBpsFromNAV(navNow, nav7d, 7.0)
+
+ supply, err := readERC20TotalSupply(ctx, rpc, p.contract, nil)
+ if err != nil {
+ supply = 0
+ }
+ supplyUnits := supply / 1e6
+
+ return &Measurement{
+ Token: p.Slug(),
+ Issuer: p.Issuer(),
+ Chain: p.Chain(),
+ DeliveredBps30d: yield30dBps,
+ DeliveredBps7d: yield7dBps,
+ DeliveredBpsLifetime: 0,
+ TotalSupplyUnits: supplyUnits,
+ AUMUSD: supplyUnits * navNow,
+ NewDistributionsUSD: 0,
+ MeasuredAt: now,
+ }, nil
+}
+
+// readSharePriceUSD returns USDC-per-share as a float. Calls
+// convertToAssets(1 share) which for a 6-decimal vault yields a
+// 6-decimal USDC amount that we scale to USD (divide by 1e6).
+func (p *syrupUSDCProbe) readSharePriceUSD(ctx context.Context, rpc *ethclient.Client, blockNumber *big.Int) (float64, error) {
+ // ABI-encoded call: selector + uint256(1_000_000) left-padded.
+ amount := new(big.Int).SetUint64(syrupUSDCOneShareRaw)
+ data := make([]byte, 0, 4+32)
+ data = append(data, erc4626ConvertToAssetsSelector...)
+ data = append(data, common.LeftPadBytes(amount.Bytes(), 32)...)
+
+ msg := ethereum.CallMsg{To: &p.contract, Data: data}
+ result, err := rpc.CallContract(ctx, msg, blockNumber)
+ if err != nil {
+ return 0, err
+ }
+ if len(result) < 32 {
+ return 0, fmt.Errorf("convertToAssets: short response")
+ }
+ assets := new(big.Int).SetBytes(result[0:32])
+ f, _ := new(big.Float).SetInt(assets).Float64()
+ return f / 1e6, nil
+}
diff --git a/harnesses/rwa-yield-accuracy/promised-yields.yml b/harnesses/rwa-yield-accuracy/promised-yields.yml
index ed4267da..1502f927 100644
--- a/harnesses/rwa-yield-accuracy/promised-yields.yml
+++ b/harnesses/rwa-yield-accuracy/promised-yields.yml
@@ -54,3 +54,9 @@ issuers:
source: "https://ondo.finance/ousg"
source_date: 2026-07-22
notes: "Ondo OUSG NAV-appreciation yield estimate (probe inactive; NAV endpoint TBD)."
+
+ - token: syrup-usdc
+ promised_apy_bps: 482
+ source: "https://yields.llama.fi/pools"
+ source_date: 2026-07-24
+ notes: "Maple SyrupUSDC base APY (loan-book yield only, excludes SYRUP token incentives). Sourced from DefiLlama filter {project:maple, symbol:USDC, chain:Ethereum}. Delivered yield measured via ERC-4626 convertToAssets rate delta - matches the base disclosure, not the boosted APY."
diff --git a/public/logos/gelato.svg b/public/logos/gelato.svg
new file mode 100644
index 00000000..b974ede8
--- /dev/null
+++ b/public/logos/gelato.svg
@@ -0,0 +1,13 @@
+
diff --git a/src/data/provider-registry.ts b/src/data/provider-registry.ts
index 1c475fed..4d2b4231 100644
--- a/src/data/provider-registry.ts
+++ b/src/data/provider-registry.ts
@@ -711,6 +711,12 @@ export const PROVIDER_REGISTRY: Record = {
"ThirdWeb operates a keyless public RPC gateway at `.rpc.thirdweb.com` covering 2000+ EVM chains via chain-id routing. Free tier is rate-limited per IP with no signup; paid tiers unlock higher throughput and dedicated endpoints. Used keyless across 13 chains on the RPC latency cluster (arbitrum, ethereum, polygon, optimism, base, bnb, avalanche, linea, worldchain, kaia, ink, opbnb + more).",
twitter: "@thirdweb",
},
+ gelato: {
+ url: "https://gelato.network",
+ description:
+ "Gelato Network runs a rollup-as-a-service platform and operates RPC infrastructure for OP Stack + Arbitrum Orbit chains it hosts. On the RPC latency cluster it appears as the Kraken Ink chain's Gelato-backed official endpoint (`rpc-gel.inkonchain.com`), running active-active alongside the QuickNode-backed sibling.",
+ twitter: "@gelatonetwork",
+ },
infura: {
url: "https://www.infura.io",
description:
diff --git a/src/lib/logo-manifest.ts b/src/lib/logo-manifest.ts
index e7d3ac9f..6c87905f 100644
--- a/src/lib/logo-manifest.ts
+++ b/src/lib/logo-manifest.ts
@@ -107,6 +107,7 @@ const RAW: Record = {
chainstack: "/logos/chainstack.svg",
drpc: "/logos/drpc.webp",
thirdweb: "/logos/thirdweb.png",
+ gelato: "/logos/gelato.svg",
"1rpc": "/logos/1rpc.svg",
cloudflare: "/logos/cloudflare.svg",
parity: "/logos/parity.png",
@@ -408,8 +409,8 @@ const ALIASES: Record = {
"injective-official": "injective",
"worldchain-official": "world-chain",
"kaia-official": "kaia",
- "ink-official": "ink",
- "ink-quicknode": "ink",
+ "ink-official": "gelato",
+ "ink-quicknode": "quicknode",
"opbnb-official": "opbnb",
hood: "robinhood",
coin: "coinbase",