Trust Score
What the score means, how it compounds, and how it decays.
Trust Score is a single u16 on the user's Anchor PDA. The number changes only at verification time, and only by the amount the protocol's scoring function permits.
The shape of the score
The score sums two contributions, recomputed at every verification:
- Weekly presence. The protocol splits the last 84 days into twelve seven-day bins and checks whether each bin holds at least one verification. Recent weeks carry more weight than older ones.
- Age bonus. The age of the Anchor adds a square-root term, capped at one year.
The initial mint of an Anchor sets the score to 0. The first re-verification lands it at 100. From there the score tracks how many separate weeks you have shown up in, so the rate of growth depends on cadence rather than on a fixed step per verification.
Decay shape
A verification counts toward the score for twelve weeks. Its weight falls as its bin ages, and it leaves the window once it passes 84 days. A wallet that stops verifying returns to 0 as its window empties.
Scoring the span of weeks rather than the count of verifications is deliberate. Filling a week you have already filled adds nothing, so verifying ten times in one afternoon scores the same as verifying once. Reaching the top of the range takes calendar time, and there is no way to compress it.
What the ranges mean
| Range | Profile |
|---|---|
| 0 | No Anchor minted, or an Anchor whose 84-day window has emptied |
| 100 | One re-verification on a fresh Anchor |
| 100–350 | Verifications in a few separate weeks |
| 350–550 | Presence across roughly half the window |
| 550–680 | Most weeks filled across the full 84 days |
| 680+ | Every week filled, on an Anchor open close to a year |
Under the current base_trust_increment of 100, the score tops out near 720. ProtocolConfig.max_trust_score sets the hard ceiling at 10000, which leaves room for the increment to be raised later without a program upgrade.
Integrators set thresholds based on stakes. The numbers above are descriptive, not normative, so your application's threshold should reflect your risk model rather than a global standard.
What to gate on
The score answers one question: how consistently has this wallet verified? It is a history, and it is the right signal for weighting, ranking and display.
For access, read a second field alongside it. last_verification_timestamp sits at offset 48 of the same account and says how long ago that history was last extended. EntrosGate takes both, as minTrustScore and maxVerificationAge.
And where an action is worth the friction, run a verification at the point of the action, then read the Anchor. The score is a history. The verification is the person.
| What you are gating | Pattern |
|---|---|
| Airdrop claim, governance vote, treasury action | Verify at the action, then read the Anchor |
| Account creation, high-value access | Verify at the action, or require a verification from the last hour |
| Routine access, rate limiting | Score floor plus a one-day recency window |
| Badges, leaderboards, profile display | Read the score |
<EntrosVerify /> runs the capture in a popup without leaving the page, so the top two rows cost one component. See the verification flow.
How to choose a threshold
Three lenses help.
Friction lens. A threshold of 100 admits any wallet that has re-verified at least once. A threshold above 100 requires the user to have come back in separate weeks, since verifications inside one week fill the same bin. If your action is one a real user might do soon after their first verification (commenting, joining a community), a 100 floor is the right baseline. If the action should reward sustained presence (airdrops, governance), the floor belongs higher.
Threshold selection. A 500-floor requires weeks of cadence per Anchor, and every capture in that history is scored by the detection stack and compared across wallets. Pick the floor from the value behind your gate: the higher the floor, the longer the verified history behind each identity that clears it.
Reversibility lens. Actions that are easily reversed (downvoting a comment, claiming a soulbound badge) tolerate lower thresholds. Actions that move money tolerate less.
How the score updates
The SDK bundles create_challenge, verify_proof and update_anchor into one transaction. verify_proof writes a VerificationResult PDA on the verifier program; update_anchor reads that PDA through an account constraint bound to the verifier's program ID, recalculates the score, and writes the new value to the user's IdentityState PDA. The protocol fee is charged in the same transaction. Neither program calls the other, so there is no cross-program invocation to account for in your compute budget.
Reading the Anchor from another program is a cross-program PDA read of the IdentityState account. No oracle, no cron, no external service. Both fields sit in the bytes you already borrowed.
Where to look next
- Quickstart: read a Trust Score—the byte layout and the offset
- Anchor PDA—full account layout
- Threat model—what the score is and isn't a defense against