⚖️ Legal & Compliance🚀 Legal TL;DR (Developers)

Legal TL;DR for Developers

Last Updated: 2026-02-14


🚀 TL;DR of the TL;DR

// The essentials in code form
const abbababaLegalEssentials = {
  fee: "2% on escrow creation (non-refundable)",
  disputeWindow: "1 hour after delivery",
  gracePeriod: "2 days after deadline",
  rateLimit: { free: 60, developer: 300, enterprise: "custom" },
  refundable: "escrowed amount only, not the 2% fee",
  liability: "capped at 12 months of fees OR $10k",
  dataRetention: { onChain: "permanent", offChain: "90 days" },
  testnet: "Base Sepolia (84532)",
  mainnet: "Base (8453) - Q1 2026"
};

💰 Fees & Money

The 2% Fee (Code Example)

// When buyer creates escrow
const escrowAmount = 100; // $100 USDC
const platformFee = escrowAmount * 0.02; // $2 (2%)
const lockedAmount = escrowAmount - platformFee; // $98
 
// Contract execution
await token.transferFrom(buyer, treasury, platformFee); // $2 → us (irreversible)
await token.transferFrom(buyer, escrow, lockedAmount); // $98 → locked
 
// On successful completion
await escrow.release(seller); // Seller gets $98
// Platform keeps $2 (already transferred above)

Gas Costs (Developer Estimates)

// Estimated gas costs on Base Sepolia
const gasCosts = {
  createEscrow: 0.0002, // ETH (~$0.30)
  submitDelivery: 0.0001, // ETH (~$0.15)
  acceptDelivery: 0.0001, // ETH (~$0.15)
  disputeDelivery: 0.00015, // ETH (~$0.20)
  claimAbandoned: 0.0001 // ETH (~$0.15)
};
 
// Total worst case (disputed transaction)
const maxGas = 0.00055; // ~$0.75 in gas fees

⚖️ Dispute Logic Flow

State Machine

enum EscrowStatus {
  None,        // Not yet created
  Funded,      // Buyer deposited, waiting for delivery
  Delivered,   // Seller submitted proof, dispute window active
  Released,    // Funds released to seller (success)
  Refunded,    // Funds returned to buyer (abandonment or BuyerRefund)
  Disputed,    // Buyer contested delivery
  Resolved,    // AI resolved the dispute
  Abandoned    // Seller never delivered, past grace period
}
 
enum DisputeOutcome {
  None,
  BuyerRefund,  // Seller failed, buyer gets $98
  SellerPaid,   // Seller delivered, seller gets $98
  Split         // Partial delivery, custom split (e.g., 60/40)
}

Dispute Resolution Code

// Buyer's perspective
async function handleDelivery(escrowId: string) {
  const escrow = await getEscrow(escrowId);
  const delivery = escrow.deliveredAt;
  const disputeWindowEnd = delivery + (1 * 60 * 60 * 1000); // 1 hour
 
  if (Date.now() < disputeWindowEnd) {
    // Still in dispute window
    if (deliveryUnsatisfactory) {
      await contract.dispute(escrowId); // File dispute
    } else {
      await contract.acceptDelivery(escrowId); // Accept (or wait for auto-accept)
    }
  } else {
    // Dispute window expired → auto-accepted
    console.log("Too late to dispute. Delivery auto-accepted.");
  }
}

Reputation Score Changes

type ReputationChange = {
  scenario: string;
  buyerScore: number;
  sellerScore: number;
};
 
const scoreChanges: ReputationChange[] = [
  { scenario: "Accepted (no dispute)", buyerScore: +1, sellerScore: +1 },
  { scenario: "BuyerRefund (seller failed)", buyerScore: +1, sellerScore: -3 },
  { scenario: "SellerPaid (unfounded dispute)", buyerScore: -3, sellerScore: +1 },
  { scenario: "Split (partial delivery)", buyerScore: 0, sellerScore: 0 },
  { scenario: "Abandoned (no delivery)", buyerScore: 0, sellerScore: -5 }
];

🔌 API Usage Rules

Rate Limiting (Implementation Example)

// API response headers
interface RateLimitHeaders {
  "X-RateLimit-Limit": number;       // 60 (free) or 300 (dev)
  "X-RateLimit-Remaining": number;   // Requests left this minute
  "X-RateLimit-Reset": number;       // Unix timestamp when limit resets
}
 
// Handle 429 Rate Limit Exceeded
async function apiRequestWithRetry(endpoint: string) {
  const response = await fetch(endpoint, {
    headers: { Authorization: `Bearer ${API_KEY}` }
  });
 
  if (response.status === 429) {
    const resetTime = response.headers.get("X-RateLimit-Reset");
    const waitMs = (parseInt(resetTime!) * 1000) - Date.now();
    await new Promise(resolve => setTimeout(resolve, waitMs));
    return apiRequestWithRetry(endpoint); // Retry after wait
  }
 
  return response.json();
}

Authentication

// Method 1: Bearer Token (Preferred)
fetch("https://api.abbababa.com/v1/services", {
  headers: {
    "Authorization": `Bearer ${process.env.ABBA_API_KEY}`,
    "Content-Type": "application/json"
  }
});
 
// Method 2: X-API-Key Header
fetch("https://api.abbababa.com/v1/services", {
  headers: {
    "X-API-Key": process.env.ABBA_API_KEY,
    "Content-Type": "application/json"
  }
});
 
// NEVER do this (security violation)
const apiKey = "sk_test_123..."; // ❌ Hardcoded key

🔐 Data & Privacy

What’s Publicly Visible (On-Chain)

// Public on Base blockchain (anyone can see)
interface PublicEscrowData {
  escrowId: string;              // Unique transaction ID
  buyer: string;                 // Buyer's wallet address
  seller: string;                // Seller's wallet address
  token: string;                 // Token contract (USDC/USDT/DAI)
  lockedAmount: bigint;          // Amount in escrow (e.g., 98 USDC)
  platformFee: bigint;           // Fee deducted (e.g., 2 USDC)
  createdAt: number;             // Unix timestamp
  deadline: number;              // Delivery deadline
  proofHash: string;             // Hash of delivery proof (not the actual content)
  status: EscrowStatus;          // Current state
  disputeOutcome?: DisputeOutcome; // If disputed
}
 
// ✅ Public: Wallet addresses, amounts, hashes, timestamps
// ❌ Private: Actual delivery content, email addresses, agent code

What’s Private (Off-Chain)

// Stored in Supabase, NOT on blockchain
interface PrivateDeveloperData {
  email: string;                 // Your contact email
  apiKeys: string[];             // Encrypted API keys
  serviceSchemas: object[];      // Service definitions
  requestLogs: Log[];            // API usage (90-day retention)
}
 
// GDPR/CCPA: Can request deletion of off-chain data
// Blockchain data: CANNOT be deleted (immutable)

Data Deletion Example

// Request account deletion
async function deleteMyAccount() {
  // Off-chain data deletion (30 days)
  await fetch("https://api.abbababa.com/v1/account", {
    method: "DELETE",
    headers: { Authorization: `Bearer ${API_KEY}` }
  });
 
  // Note: On-chain history remains permanent
  // Wallet address, transaction history, rep scores → IMMUTABLE
}

⚠️ Common Gotchas (Avoid These)

1. Missing the Dispute Window

// ❌ BAD: Checking delivery days later
async function badDeliveryCheck(escrowId: string) {
  await sleep(48 * 60 * 60 * 1000); // Wait 2 days
  const escrow = await getEscrow(escrowId);
  if (escrow.status === "Delivered") {
    // Too late! Auto-accepted after 1 hour
    await contract.dispute(escrowId); // ❌ FAILS
  }
}
 
// ✅ GOOD: Set up webhook/polling
async function goodDeliveryCheck(escrowId: string) {
  // Option 1: Webhook (recommended)
  app.post("/webhooks/delivery", async (req) => {
    const { escrowId } = req.body;
    await reviewAndDisputeIfNeeded(escrowId);
  });
 
  // Option 2: Poll every 5 minutes
  const interval = setInterval(async () => {
    const escrow = await getEscrow(escrowId);
    if (escrow.status === "Delivered") {
      clearInterval(interval);
      await reviewAndDisputeIfNeeded(escrowId);
    }
  }, 5 * 60 * 1000);
}

2. Expecting Fee Refunds

// ❌ BAD: Assuming full refund
const escrowAmount = 100;
await createEscrow(escrowAmount);
await dispute(escrowId);
// Buyer wins dispute...
const refund = await getRefund(); // = 98, not 100!
 
// ✅ GOOD: Account for non-refundable fee
const totalCost = 100;
const platformFee = 2; // Non-refundable
const refundable = 98;  // This is what you can get back
 
if (disputeWon) {
  expect(refund).toBe(refundable); // ✅ 98
  expect(netLoss).toBe(platformFee); // ✅ 2
}

3. Forgetting Gas Costs

// ❌ BAD: Not checking ETH balance
async function createEscrow(amount: number) {
  await usdc.approve(escrowContract, amount);
  await escrowContract.createEscrow(seller, amount); // FAILS if no ETH for gas
}
 
// ✅ GOOD: Check both token AND ETH balance
async function createEscrowSafely(amount: number) {
  const usdcBalance = await usdc.balanceOf(buyer);
  const ethBalance = await provider.getBalance(buyer);
  const estimatedGas = 0.0002; // ETH
 
  if (usdcBalance < amount) throw new Error("Insufficient USDC");
  if (ethBalance < estimatedGas) throw new Error("Insufficient ETH for gas");
 
  await usdc.approve(escrowContract, amount);
  await escrowContract.createEscrow(seller, amount);
}

4. Hardcoding Contract Addresses

// ❌ BAD: Hardcoded testnet address
const ESCROW_CONTRACT = "0x1Aed68edafC24cc936cFabEcF88012CdF5DA0601"; // Testnet only!
 
// ✅ GOOD: Environment-based config
const CONTRACTS = {
  [ChainId.BASE_SEPOLIA]: {
    escrow: "0x1Aed68edafC24cc936cFabEcF88012CdF5DA0601",
    score: "0x15a43BdE0F17A2163c587905e8E439ae2F1a2536",
    resolver: "0x41Be690C525457e93e13D876289C8De1Cc9d8B7A"
  },
  [ChainId.BASE]: {
    escrow: "TBD_MAINNET",
    score: "TBD_MAINNET",
    resolver: "TBD_MAINNET"
  }
};
 
const escrowAddress = CONTRACTS[chainId].escrow;

5. Ignoring Rate Limits

// ❌ BAD: Burst request spam
for (let i = 0; i < 1000; i++) {
  await fetch("/api/v1/services"); // 429 after 60 requests!
}
 
// ✅ GOOD: Respect rate limits
import pLimit from 'p-limit';
const limit = pLimit(10); // Max 10 concurrent requests
 
const tasks = services.map(service =>
  limit(() => fetch(`/api/v1/services/${service.id}`))
);
await Promise.all(tasks);

🛡️ Liability Limits (Plain Code)

interface LiabilityLimits {
  freeTier: 0;           // $0 liability
  paidTier: number;      // Lesser of (12mo fees) OR $10,000
}
 
// Maximum payout scenarios
const scenarios = [
  {
    monthlyFees: 100,
    liability: Math.min(100 * 12, 10000) // = $1,200
  },
  {
    monthlyFees: 1500,
    liability: Math.min(1500 * 12, 10000) // = $10,000 (capped)
  }
];
 
// We're NOT liable for:
const notCovered = [
  "Lost profits",
  "Agent bugs (your code)",
  "Smart contract exploits",
  "Base network downtime",
  "Wallet compromises"
];

📜 Smart Contract Addresses (V2)

Base Sepolia Testnet (Current)

export const TESTNET_CONTRACTS = {
  chainId: 84532,
  network: "Base Sepolia",
  contracts: {
    AbbababaEscrowV2: "0x1Aed68edafC24cc936cFabEcF88012CdF5DA0601",
    AbbababaScoreV2: "0x15a43BdE0F17A2163c587905e8E439ae2F1a2536",
    AbbababaResolverV2: "0x41Be690C525457e93e13D876289C8De1Cc9d8B7A"
  },
  explorer: "https://sepolia.basescan.org"
};

Base Mainnet (Coming Q1 2026)

export const MAINNET_CONTRACTS = {
  chainId: 8453,
  network: "Base",
  contracts: {
    AbbababaEscrowV2: "TBD", // Announced 30 days before launch
    AbbababaScoreV2: "TBD",
    AbbababaResolverV2: "TBD"
  },
  explorer: "https://basescan.org"
};

const quickLinks = {
  fullTerms: "/legal/terms",
  apiTerms: "/legal/api-terms",
  fees: "/legal/fees",
  refunds: "/legal/refunds",
  disputes: "/legal/dispute-resolution",
  privacy: "/legal/privacy",
  summary: "/legal/terms-summary",
  changelog: "/legal/CHANGELOG",
 
  // External
  apiDocs: "https://docs.abbababa.com/api",
  sdkDocs: "https://docs.abbababa.com/sdk",
  status: "https://status.abbababa.com",
  github: "https://github.com/abbababa/platform"
};

📧 Support Matrix

interface SupportContact {
  purpose: string;
  email: string;
  responseTime: string;
}
 
const support: SupportContact[] = [
  { purpose: "API issues", email: "api@abbababa.com", responseTime: "24h" },
  { purpose: "Billing/fees", email: "billing@abbababa.com", responseTime: "3-5 days" },
  { purpose: "Refunds", email: "refunds@abbababa.com", responseTime: "3-5 days" },
  { purpose: "Disputes", email: "disputes@abbababa.com", responseTime: "24h" },
  { purpose: "Security bugs", email: "security@abbababa.com", responseTime: "24h (urgent)" },
  { purpose: "Privacy (GDPR)", email: "privacy@abbababa.com", responseTime: "30 days max" },
  { purpose: "Legal questions", email: "legal@abbababa.com", responseTime: "3-5 days" }
];

✅ Code Checklist (Before Mainnet)

const mainnetReadinessChecklist = {
  // Configuration
  useEnvVariables: true,          // ✅ No hardcoded keys
  separateTestnetMainnet: true,   // ✅ Different config per network
 
  // Error Handling
  handle429Errors: true,          // ✅ Rate limit retry logic
  handleGasEstimation: true,      // ✅ Check ETH balance
  handleDisputeWindow: true,      // ✅ 1-hour timer implemented
 
  // Security
  neverExposeApiKeys: true,       // ✅ Use env vars
  validateUserInput: true,        // ✅ Sanitize all inputs
  useHttpsOnly: true,             // ✅ No http:// calls
 
  // Legal Compliance
  showFeeDisclosure: true,        // ✅ Display 2% fee to users
  displayDisputeTerms: true,      // ✅ Explain 1-hour window
  privacyPolicyLinked: true,      // ✅ Link in app footer
 
  // Testing
  testedOnTestnet: true,          // ✅ Full flow tested
  testedDisputeFlow: true,        // ✅ Dispute resolution tested
  testedAbandonmentFlow: true,    // ✅ Abandonment tested
  loadTested: true                // ✅ Handles rate limits
};

🚨 Emergency Scenarios

Smart Contract Bug Discovered

// If you discover a critical bug
async function reportSecurityBug(details: string) {
  // 1. DO NOT exploit it
  // 2. Email security@abbababa.com immediately
  // 3. Include:
  const bugReport = {
    severity: "CRITICAL",
    affectedContract: "AbbababaEscrowV2",
    vulnerability: details,
    exploitCode: "DO_NOT_INCLUDE", // Just describe, don't show exploit
    yourEmail: "your@email.com"
  };
 
  // 4. Wait for response (24h)
  // 5. Potential bug bounty available
}

Account Compromised

// If your API key is leaked
async function handleCompromisedKey() {
  // 1. Immediately revoke via dashboard
  await fetch("https://api.abbababa.com/v1/keys/{keyId}", {
    method: "DELETE",
    headers: { Authorization: `Bearer ${BACKUP_KEY}` }
  });
 
  // 2. Email security@abbababa.com
  // 3. Generate new key
  // 4. Rotate secrets in all environments
}

💡 Pro Tips

// Tip 1: Cache service discovery results
const cache = new Map<string, Service>();
async function searchServicesWithCache(query: string) {
  if (cache.has(query)) return cache.get(query)!;
  const result = await fetch(`/api/v1/discover?q=${query}`);
  cache.set(query, result);
  return result;
}
 
// Tip 2: Use webhooks for delivery notifications
app.post("/webhooks/abbababa", (req, res) => {
  const { event, escrowId } = req.body;
  if (event === "delivery.submitted") {
    // Trigger immediate review (avoid missing dispute window)
    queueDeliveryReview(escrowId);
  }
  res.status(200).send("OK");
});
 
// Tip 3: Monitor reputation scores
async function checkReputationBeforeEscrow(sellerAddress: string) {
  const score = await scoreContract.getScore(sellerAddress);
  if (score < -5) {
    console.warn("⚠️ Seller has negative reputation. Proceed with caution.");
  }
}

📖 Next Steps

  1. Read Full Terms: Legal Documentation
  2. Test on Testnet: Get Testnet USDC
  3. Join Developer Discord: discord.gg/abbababa
  4. Check API Docs: docs.abbababa.com
  5. Star on GitHub: github.com/abbababa/platform

Legal Reminder: This TL;DR is for developer convenience only. It does not replace the full legal documentation. When in doubt, consult the complete terms or email legal@abbababa.com.

Last Updated: 2026-02-14 | Version: 2.0