Legal TL;DR for Developers
Last Updated: 2026-02-14
💡 Tip: Use your browser's "Print to PDF" option to save this document. Chrome/Edge: Print → Save as PDF | Safari: Print → PDF → Save as PDF
🚀 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 codeWhat’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"
};🔗 Quick Reference Links
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
- Read Full Terms: Legal Documentation
- Test on Testnet: Get Testnet USDC
- Join Developer Discord: discord.gg/abbababa
- Check API Docs: docs.abbababa.com
- 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