intermediatecookbook
AI-Judged Dispute Resolution
Smart contract escrow where an LLM rules on disputes, in a TEE.
Two parties stake collateral. If they disagree, an on-chain LLM call reads both submissions and rules. The TEE attestation makes the ruling verifiable.
Architecture
┌──────────┐ stake ┌─────────┐
│ Buyer │ ───────────▶ │ Escrow │ ◀── stake ──┐
└──────────┘ └────┬────┘ │
│ dispute ┌────┴────┐
▼ │ Seller │
┌─────────────┐ └─────────┘
│ LLM 0x0802 │
│ rules in TEE│
└──────┬──────┘
│ release
▼ to winnerCode
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";
contract DisputeEscrow is PrecompileConsumer {
address constant LLM = address(0x802);
struct Case { address a; address b; string evidence; uint256 stake; bool resolved; }
mapping(uint256 => Case) public cases;
uint256 public nextCase;
function judge(uint256 id, address executor) external {
Case storage c = cases[id];
require(!c.resolved, "done");
string memory messages = string.concat(
'[{"role":"system","content":"You are a fair judge. Reply with EXACTLY \"A\" or \"B\"."},',
'{"role":"user","content":"', c.evidence, '"}]'
);
// 30-field LLM ABI — minimal valid encoding.
bytes memory enc = _encodeLLM(executor, messages);
bytes memory out = _executePrecompile(LLM, enc);
(bool hasError, bytes memory completion, , , ) =
abi.decode(out, (bool, bytes, bytes, string, (string, string, string)));
require(!hasError, "llm error");
// Naive parse: reply starts with "A" or "B".
bytes1 verdict = bytes(string(completion))[0];
address winner = verdict == "A" ? c.a : c.b;
payable(winner).transfer(c.stake * 2);
c.resolved = true;
}
function _encodeLLM(address executor, string memory messages)
internal pure returns (bytes memory) {
// truncated for brevity — see /playground/llm for full ABI
}
}