Skip to content

Filter revoked EAS attestations in propdates service (enable edit-via-revoke flow) #73

Description

@r4topunk

Context

Propdates on Gnars are EAS attestations on Base (schema 0x8bd0d42901ce3cd9898dbea6ae2fbf1e796ef0923e7cbb0a1cecac2e42d47cb3, recipient = DAO token). The schema is append-only — there is no native update path. Attestations are created with revocable: true (src/services/propdates.ts:272), so the intended "edit" flow is revoke the old attestation, then create a new one.

Problem: the site currently renders revoked attestations as if they were live.

Root cause

  1. The Builder SDK query propdates does not filter by revoked:

    query propdates($schemaId: String!, $recipient: String!) {
      attestations(where: { schemaId: { equals: $schemaId }, recipient: { equals: $recipient } }) {
        ...Attestation
      }
    }

    (from @buildeross/sdknode_modules/@buildeross/sdk/dist/chunk-*.js)

  2. Our service layer does not drop revoked entries either:

    • fetchDaoPropdatesFromEas maps every attestation returned by the SDK.
    • listPropdates returns getPropDates(...) directly with no filter.
    • There are zero references to revoked anywhere under src/.

Result: even after a user revokes their attestation onchain, it keeps showing up in the proposal detail view.

Proposed fix

Filter revoked === true (or equivalently revocationTime > 0) in the propdates service before returning to consumers.

  • fetchDaoPropdatesFromEas → drop revoked attestations from attestations before the map in propdates.ts:69.
  • listPropdates → filter the array returned by getPropDates before returning.
  • The Propdate type (re-exported PropDate from @buildeross/sdk/eas) already exposes revoked / revocationTime fields.
  • No schema or UI changes required. Thread/reply logic in Propdates.tsx keeps working because children of a revoked root would simply become orphaned — acceptable for v1, or we can drop replies whose parent is revoked as a follow-up.

Edit flow (to document alongside the fix)

Once the filter is in place, the canonical "edit a propdate" flow is:

  1. Only the original attester can revoke — EAS enforces msg.sender == attestation.attester. A different wallet cannot edit someone else's propdate.
  2. Attester calls revoke() on the Base EAS contract 0x4200000000000000000000000000000000000021 with:
    { schema: <PROPDATE_SCHEMA_UID>, data: { uid: <attestationId>, value: 0 } }
    
  3. Attester (or anyone) submits a new propdate via the existing UI (PropdateForm) with the corrected content.

Gas cost on Base is negligible (cents).

Optional UX follow-ups (out of scope for this issue, but worth tracking):

  • Expose a "Delete" / "Edit" button on the attester's own propdates that chains revoke + re-submit in one flow.
  • Show a subtle "edited" indicator when a new propdate's originalMessageId matches a revoked one (requires a convention — current schema has no edit pointer; originalMessageId currently means "reply parent").

Why this matters

Without the filter, the documented revoke path is a no-op from the user's perspective: they pay gas to revoke and the bad content is still there. This blocks any real edit/cleanup workflow for authors who post a propdate they want to take back.

Acceptance criteria

  • Revoked attestations are excluded from listDaoPropdates, listPropdates, and getPropdateByTxid.
  • Manual verification: revoke an attestation on Base, reload the proposal page, confirm it disappears.
  • docs/ entry (or inline comment) describing the edit-via-revoke flow so future contributors don't re-ask this question.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    Status
    Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions