Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions benchmarks/ink-rpc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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."
Expand All @@ -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?"
Expand All @@ -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"})
Expand All @@ -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"})
Expand Down
14 changes: 14 additions & 0 deletions benchmarks/rwa-yield-accuracy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"}

4 changes: 2 additions & 2 deletions harnesses/rpc-capabilities/cmd/script/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")},
},
Expand Down
23 changes: 8 additions & 15 deletions harnesses/rwa-yield-accuracy/cmd/script/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
138 changes: 138 additions & 0 deletions harnesses/rwa-yield-accuracy/cmd/script/syrupusdc.go
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 6 additions & 0 deletions harnesses/rwa-yield-accuracy/promised-yields.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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."
13 changes: 13 additions & 0 deletions public/logos/gelato.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions src/data/provider-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,12 @@ export const PROVIDER_REGISTRY: Record<string, ProviderRegistryEntry> = {
"ThirdWeb operates a keyless public RPC gateway at `<chainid>.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:
Expand Down
5 changes: 3 additions & 2 deletions src/lib/logo-manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ const RAW: Record<string, string> = {
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",
Expand Down Expand Up @@ -408,8 +409,8 @@ const ALIASES: Record<string, string> = {
"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",
Expand Down
Loading