PaladinFi Trust — pre-trade OFAC + GoPlus + lookalike risk gate for evm agents (designing plugin, feedback welcome) #7242
Replies: 10 comments 5 replies
-
|
Quick update — v0.0.1 skeleton just shipped to anchor this Discussion with a real artifact instead of a design doc:
v0.0.1 scope is intentionally narrow — see the file-level comment in
Reproducible smoke test (verifies the live API + the package's client end-to-end): v0.1.0 target — by 2026-05-16. Tracking issue with full checklist + subscribable progress: paladinfi/eliza-plugin-trust#1 One specific design question: if you've wired a swap action in Eliza, would you compose this trust check inline with the swap action, or call it as a separate guardrail step? The action signature in v0.1.0 turns on that answer — happy to iterate based on what fits real character flows. |
Beta Was this translation helpful? Give feedback.
-
|
Shipped: v0.1.0 live on npm (release notes). Follow-up to the original post: the skeleton v0.0.1 promised functional v0.1.0 within ~2 weeks. v0.1.0 is here, on the early end of that window. What’s in:
Quick start (preview, free): import { paladinTrustPlugin } from "@paladinfi/eliza-plugin-trust";
export const character = { plugins: [paladinTrustPlugin], ... };Paid ($0.001 USDC/call): import { privateKeyToAccount } from "viem/accounts";
import { createPaladinTrustPlugin } from "@paladinfi/eliza-plugin-trust";
const account = privateKeyToAccount(process.env.PALADIN_TRUST_KEY);
const plugin = createPaladinTrustPlugin({ walletClientAccount: account });Verified end-to-end against live API. Settled USDC tx on Base mainnet for the first paid integration call: Feedback (alpha API drift, paid-mode UX, missing factors) very welcome here or at the issue tracker. |
Beta Was this translation helpful? Give feedback.
-
|
On inline vs separate: the evaluator path is cleaner. Composing this as a pre-action evaluator step rather than inlining the gate inside the swap action keeps the swap action testable without mocking the trust endpoint, and means trust-check failures are handled at the graph level rather than forcing the swap action to implement its own abort semantics. The v0.1.0 LLM extraction pattern ( One boundary worth naming explicitly in the threat model: the |
Beta Was this translation helpful? Give feedback.
-
|
The Provider direction maps to what you described — context-prep phase, result in State, swap action reads it in On wrapper-approval friction: a one-time approve at first paid call is acceptable for agent UX — agents don't carry the click-cost that human wallets do, and a scoped escrow approve is the same trust ask as any ERC-20 spend the agent already issues. The pattern worth comparing against is EIP-2612 permit-per-call: no pre-approve needed, each request carries a single-use signed authorization scoped to the exact call amount and a short expiry. That removes the approve transaction entirely rather than minimizing it. On the Base side we've used per-call EIP-712 authorizations for agent spend limits for this reason — the worst-case exposure is bounded to a single call even if the signing scope leaks, whereas a standing allowance to the escrow stays live until explicitly revoked. For the operator ≠ plugin-author case you named, per-call permit is meaningfully stronger than scoped approve even if the approve target is narrow. |
Beta Was this translation helpful? Give feedback.
-
|
The EIP-3009 correction is right — The THREAT_MODEL.md §6-7 framing does more work than it looks like. Explicitly separating blast-radius discipline ( |
Beta Was this translation helpful? Give feedback.
-
|
For a pre-trade risk gate, I would keep the plugin as a decision-support/evaluator layer rather than letting it silently decide execution. The output shape should be explicit enough that downstream agents can explain why a trade was allowed, warned, or blocked. Useful fields would be:
The hard part is stale or missing data. A newly deployed contract with no GoPlus classification should not look the same as a clean contract. I would encode unknowns as first-class states and let policy decide whether unknown means warn or block. For testing, I would include negative cases for symbol lookalikes, proxy contracts, stale OFAC cache, unverified source, and conflicting signals across providers. That will make the plugin much easier to trust in autonomous trading graphs. |
Beta Was this translation helpful? Give feedback.
-
|
Three useful threads here — going to answer each against what's currently shipping vs. what's open. On "first-class states for stale/missing data": shipped last week (server v0.11.73). When any underlying source (OFAC / paladin.anomaly / scam_intel) raises, the factor is now included in the response with On the suggested output fields: split into what we emit today vs. what's open.
On negative test cases: The "treat unknowns as first-class states" framing maps cleanly to what we shipped and what's still open. Useful inputs as we scope v0.3.0; no schema commitments here. |
Beta Was this translation helpful? Give feedback.
-
|
Quick update against the design threads from this conversation — v0.3.0 has shipped ( v0.3.0 is the first public release; the prior internal v0.2.0 candidate was held back for a security-hardening sprint, which is now incorporated. What was open in this thread → what's now in v0.3.0: On signer-key custody + recovery (musaabhasan + MrTalecky threads). Each On rotation and the 7-day window. All key rotations + token-registry-hash changes + indexer-key changes go through a 7-day timelock at the contract level. The owner (a Gnosis Safe 2-of-3 at On decision-support vs silent execution (musaabhasan's framing — "keep the plugin as a decision-support/evaluator layer"). Load-bearing in the design. The plugin's verifier returns a structured
On state-diff visibility (Engineering thread). Every signed On the EIP-3009 framing (MrTalecky's point about per-call authorizations). Held. v0.3.0's paid New in v0.3.0 (server release v0.12.0 + plugin v0.3.0 — note
Honest scope notes (what v0.3.0 is NOT):
Where to look:
Open to questions on any of the above. Real-money signing on every paid call is the load-bearing security claim — pushback on threat-model framing is exactly the conversation we wanted from this thread. — mgopal20 |
Beta Was this translation helpful? Give feedback.
-
|
The on-chain The explicit One observation on the RPC quorum side worth surfacing in |
Beta Was this translation helpful? Give feedback.
-
|
The §13 disclosure shape is right — a bounded, documented 2-hour HMAC-verified fallback is categorically different from an undisclosed one. "The plugin doesn't blindly trust any single RPC" being false during the grace window is exactly the kind of precision that makes a threat model useful: integrators can design around a disclosed exposure; they can't design around a guarantee they believed was stronger than it was. The KNOWN_BASE_RPC_OPERATORS M&A-drift callout has the same character — the failure mode is named, the customer-side defense is explicit, and the gap between "distinct at classification time" and "distinct under M&A" is visible rather than assumed away. Nothing in §13 conflicts with the framing I was pointing at. The through-line from registry reads load-bearing on the trust path → baseRpcUrls security-critical → operator guidance for provider diversity is the right layering. The honest exposure notes on the grace window and classification drift make the threat model stronger, not weaker — you can audit a documented exposure. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Hi all — designing an Eliza plugin and posting here for feedback before npm-publish.
What it does
@paladinfi/eliza-plugin-trustwill give evm-plugin-using agents a pre-trade composed risk gate on the buy token, in a single HTTP call:Returns
recommendation: allow | warn | blockplus a per-factor breakdown.Today: Base only (chainId 8453); other EVMs on roadmap.
Why an evm-agent operator might want this
Three concrete failure modes that today's evm-plugin swap path doesn't gate on:
In each case the swap completes silently, the operator notices on sell-attempt.
Request shape (free preview, available now)
Response (truncated):
{ "address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "chainId": 8453, "trust": { "recommendation": "sample-allow", "factors": [ {"source": "ofac", "signal": "not_listed", "real": false}, {"source": "etherscan_source", "signal": "verified", "real": false}, {"source": "goplus", "signal": "ok", "real": false}, {"source": "anomaly", "signal": "ok", "real": false} ], "_preview": true, "_message": "Preview response — SAMPLE FIXTURE. POST /v1/trust-check (x402-paid, $0.001/call) for live evaluation." } }The preview is intentionally sample-only (
real: falseon every factor,recommendation: "sample-allow"so it can't be screenshot-misused). The paid endpoint atPOST /v1/trust-checkruns live signals.Plugin shape
Standalone plugin:
@paladinfi/eliza-plugin-trust. Characters compose it in their action graph; before any swap, plugin emits the trust-check call (against the agent's existing wallet for x402 payment). Onblock, the agent abstains and posts to the operator log.Looking for feedback on
@elizaos/plugin-evmswap path that this should integrate with, not bypass?@paladinfi/eliza-plugin-trustis our scope (we own@paladinfi), but if there's a community-preferred third-party plugin pattern I'm missing, happy to adjust.Build status
Cost
$0.001 USDC settled via x402 on Base per paid call. Free preview unlimited at the rate-limited preview path.
Links
io.github.paladinfi/paladin-swap— Mallesh (@mgopal20), Malcontent Games LLC / PaladinFi
Beta Was this translation helpful? Give feedback.
All reactions