feat: MutualAttestationHook — Airbnb-style bilateral reviews for ERC-8183#14
feat: MutualAttestationHook — Airbnb-style bilateral reviews for ERC-8183#14JhiNResH wants to merge 7 commits into
Conversation
…8183 Inspired by Airbnb's mutual review system: both client and provider attest each other after job completion, building two-sided reputation. How it works: Job completes → 7-day review window opens Client reviews provider: 'Was the work good?' (1-5 stars + comment) Provider reviews client: 'Was the client fair?' (1-5 stars + comment) Each review creates a permanent EAS attestation on Base Why bilateral matters: Current hooks only track provider quality. But bad clients exist too — vague specs, unfair rejections, slow payments. MutualAttestationHook makes both sides accountable, just like Airbnb made both hosts and guests build reputation. Security (audited with Cyfrin + Trail of Bits + Slither methodology): - msg.sender verified against ACP getJob() participants (no spoofing) - ReentrancyGuard on both review functions - reviewWindow is immutable (gas optimization) - Rejected jobs can also be reviewed (both parties deserve a voice) - Error names follow ContractName__ prefix convention - 31 tests passing (including 3 fuzz tests) Hooks into BaseACPHook via: _postComplete() — records participants + opens review window _postReject() — same, so rejected jobs get reviewed too Integrates with: - EAS (Base: 0x4200...0021) for permanent attestations - IAgenticCommerceReader for type-safe job participant lookup - MaiatRouterHook (can be chained as plugin at any priority)
4dd7cd2 to
2f94e8a
Compare
… 5 PRs - Added MutualAttestationHook to contract listing - Updated test count: 175 → 206 - Updated PR count: 3 → 5 (added erc-8183#13, erc-8183#14) - Added Quick Demo section with forge test + simulation + deploy commands - Added MutualAttestationHook to architecture diagram - Added Security section with audit summary table - Added Off-Chain Companion section linking to app.maiat.io - Added ERC-8004 Reputation Registry to deployed contracts
|
Love this - bilateral reputation is essential for agent commerce. Some questions
Nit: 7-day window is in constructor but not documented as configurable. Consider adding to natspec. |
|
Updated — removed vendor-specific references. Also working on addressing the review comments from the earlier feedback (participant auth check, storage growth, review disputes, natspec for 7-day window). |
|
Thanks for the thorough review! Addressing each point: 1. Verify reviewer is job participant ✅ Already enforced:
Both functions check 2. One review per party ✅ Confirmed — 3. Storage growth — Intentional tradeoff for this version. On-chain reviews need to be queryable by other contracts (e.g., trust hooks that read historical reviews). EAS attestations are complementary — they provide cross-protocol portability, but the on-chain mapping enables composability within the ERC-8183 ecosystem. For v2, we could add an archival mechanism that migrates old reviews to EAS-only after N days. Open to suggestions — redirecting to ERC-8004 reviews is worth exploring. 4. No review disputes — Yes, intentional. Same model as Airbnb: reviews are immutable once posted. Both parties have the full review window to submit (or not). Adding a dispute/response mechanism would increase complexity and create griefing vectors. Could add a "response to review" feature in a future PR if there's demand. Nit (7-day window): Good catch — will add natspec. The |
…6 refactor) - Added missing 'address caller' parameter to _postComplete and _postReject - Fixed function signatures to match updated BaseACPHook virtual methods - Resolves compilation errors after 2026-03-26 BaseACPHook refactor
Inline IEAS interface removed. IAttestationService extracted to contracts/interfaces/ — same attest() signature, works with: - EAS (Base) - BAS (BSC) - SimpleAttestation (X Layer) Inject the correct address at deploy time, no code changes needed per chain. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Hi @JhiNResH,
|
|
Updated PR #14 in commit f200181.\n\nAddressed the requested changes:\n1. Pulled current upstream main into this branch.\n2. Added MultiHookRouter support by implementing IERC8183HookMetadata; requiredSelectors() now declares complete + reject.\n3. Moved IAttestationService into MutualAttestationHook.sol as an inline minimal interface.\n\nThe PR diff is now a single file: contracts/hooks/MutualAttestationHook.sol. |
|
Closing this PR. The trigger-time logic is two cache writes (jobCompletedAt, client/provider). No gating, no transformation, no fund movement. A standalone reader achieves the same result: pull participants and status from ERC8183.getJob() at review time, and stamp the completion timestamp on the first review submission. Lastly, the NatSpec carries vendor names that violate PR Rules in CONTRIBUTING.md. |
MutualAttestationHook
Inspired by Airbnb's mutual review system — both client and provider attest each other after job completion, building two-sided reputation.
Problem
Current hooks only track one side — did the provider deliver? But bad clients exist too: vague specs, unfair disputes, slow communication. One-sided reviews create power imbalances in agent marketplaces.
Solution
After job completion (or rejection), both parties submit a review (1-5 stars + comment). Each review creates an immutable EAS attestation. Both sides build reputation. Both sides are accountable.
Security (Audited)
Cyfrin + Trail of Bits + Slither methodology. All findings fixed:
msg.senderverified via ACPgetJob()— no spoofingReentrancyGuardon both review functionsreviewWindownot immutableimmutable_postReject()override^0.8.20uint256Features
MutualReviewCompleteevent when both reviews submittedReentrancyGuardprotectionContractName__prefix convention (Cyfrin standard)Tests
31 tests (up from 21) including:
Why This Matters
The Airbnb insight: mutual trust is what makes strangers transact safely. In agent commerce:
Files
contracts/hooks/MutualAttestationHook.sol(249 lines)Extends BaseACPHook via
_postComplete+_postReject. Compatible with MaiatRouterHook plugin chain.