Skip to content

Trust model

Integrators must separate trusted metadata from ABI guesses. Shipping the latter as “clear signing” is false confidence.

source What it is officialOnlyPolicy officialOrLocalPolicy confidence if accepted
Official registry (commit SHA pin) or attestation Curated ERC-7730 accepted: true accepted: true "high"
Local extend() override App-supplied false true "medium"
Trusted-token template Bundled ERC-20 / ERC-721 false policy-dependent never "high" under official-only
Sourcify / generateDescriptor ABI-generated fallback false false never "high"
Inferred / basic selector decode Guess from 4-byte + types false false "low"

Clear signing is not ABI pretty-printing. Inject officialOnlyPolicy(), attestedPolicy(), officialOrLocalPolicy(), or composePolicies() so the wallet decides who to believe. When trust is omitted, decode uses a stub (policy: "unspecified") with the same accept/reject rows as officialOrLocalPolicy. Production should pass officialOnlyPolicy() or attestedPolicy().

import { officialOnlyPolicy, attestedPolicy, composePolicies } from '@erc7730/sdk';
const pinOnly = officialOnlyPolicy();
const attested = attestedPolicy({
attesters: ['0x3846c3A30E62075Fa916216b35EF04B8F53931f6'],
eas: {
call: async (chainId, { to, data }) => rpcEthCall(chainId, to, data),
},
});
const pinOrAttested = composePolicies([pinOnly, attested], 'any');

attestedPolicy verifies ERC-8176 attestations; the SDK never issues them. Without eas.call it fails closed (ATTESTATION_OPTIONS_INCOMPLETE / NO_TRUSTED_ATTESTATION).

Recipe Code
Pin only trust: officialOnlyPolicy()
Pin + local extend() trust: officialOrLocalPolicy()
ERC-8176 attesters trust: attestedPolicy({ attesters, eas })
Pin or attested composePolicies([officialOnlyPolicy(), attestedPolicy(...)], 'any')
Pin and attested composePolicies([officialOnlyPolicy(), attestedPolicy(...)], 'all')

trust.reasons are stable codes (source:official-registry:accepted, ATTESTED, …) — safe for telemetry. Prefer them over free-form sentences.

The interactive demo injects officialOrLocalPolicy() so local overrides and generate drafts are easy to explore. That is a playground default. Production wallets should pass officialOnlyPolicy() or attestedPolicy().