Skip to content

Repository files navigation

BuyAnAnswer

Your link in bio, but every tip buys a real answer.

A creator shares one link. A fan pays USDC to ask a question, and the money sits in a non-custodial escrow contract on Base — not in a company account. The creator answers (and gets paid, minus a capped platform fee), declines (fan refunded in full), or the fan cancels before a deadline. If the creator goes silent, anyone can reclaim the funds back to the fan after the deadline, so money is never stuck.

Live at buyananswer.com · app at app.buyananswer.com


Deployment

Everything below is public and on-chain. It is here so you can verify the deployed contract against this source yourself.

Base mainnet (chain id 8453) — live

BuyAnAnswerEscrow 0x04a814daa6421D5B0C7f3758476f0150D48198b6 — source-verified on Basescan
Deploy block 49867011
Deploy tx 0x543c7b80…5d6daca
Owner Safe 0xEc1276A188df9603fE280a42eBbeB90f32aa6034 (v1.4.1, 1-of-1)
Fee recipient 0xE0f0275d3Db47d9DcD056766b02fc7606F36cc43
Token Circle native USDC 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 (6 decimals) — not the bridged USDbC
Compiler solc 0.8.28, optimizer on (200 runs), EVM version cancun

Base Sepolia (chain id 84532) — testnet

BuyAnAnswerEscrow 0x40A4bfEc9441752BcABBd4b3939503671c8724dB
Deploy block 45351822
Token Circle testnet USDC 0x036CbD53842c5426634e7929541eC2318f3dCF7e

Both records are the single source of truth in packages/shared/src/contracts/deployments.ts — the app, the SDK, and the indexer all read addresses from there rather than hardcoding them.

Fees and the answer window

Action Who pays Fee Recipient gets
Answer 4.2% (hard cap 10%) creator receives 95.8%
Decline 0% asker refunded 100%
Cancel (before deadline) asker 1% (hard cap 5%) asker refunded 99%
Reclaim (at/after deadline, permissionless) 0% asker refunded 100%

The answer window is 7 days (hard cap 30 days). Fees and the window are owner-adjustable within the caps written into the contract — the owner can never exceed a cap, seize escrowed principal, or block a withdrawal. See ARCHITECTURE.md.

Verifying the contract yourself

git clone --recurse-submodules https://github.com/buyananswer-base-eth/buyananswer.git
cd buyananswer/contracts && forge build

Then compare the compiled bytecode and the source of src/BuyAnAnswerEscrow.sol against the verified source on Basescan. The compiler settings above are pinned in contracts/foundry.toml, and the dependency commits are pinned as git submodules, so the build is reproducible.


Repository map

contracts/          Solidity escrow (Foundry, BUSL-1.1) — the only place money lives
apps/web/           React Router SSR app: link-in-bio board, ask+pay, creator inbox
workers/api/        Cloudflare Worker — SIWE auth, profiles, question/answer content
workers/indexer/    Cloudflare Worker — chain events → D1. Sole writer of payment state
packages/shared/    DB schema, migrations, deployment records, on/off-chain ref codec
packages/sdk/       Typed contract helpers (viem) — approve, ask, settle, withdraw
packages/worker-kit/ Shared Worker plumbing: errors, logging, rate limits, idempotency

The important boundary: the indexer is the only component that writes payment state off-chain, and it does so by reflecting events the chain has already finalized. Nothing else writes money state. The chain is authoritative; the database is a mirror.


Quickstart

Prerequisites: Node 20.19.5 (see .nvmrc), pnpm 10+, and Foundry for the contracts.

git clone --recurse-submodules https://github.com/buyananswer-base-eth/buyananswer.git
cd buyananswer
pnpm install
pnpm --filter "./packages/*" build   # required before typecheck on a fresh checkout

If you cloned without --recurse-submodules:

git submodule update --init --recursive

Verify everything

pnpm lint && pnpm typecheck && pnpm test && pnpm build
cd contracts && forge build && forge test && forge snapshot --check

Expected: 274 TypeScript tests, 79 Solidity tests, and 100% line/statement/branch/function coverage on src/BuyAnAnswerEscrow.sol.

Run it locally

Copy the example env files and fill in the placeholders — none of them contain or require a secret for local development:

cp apps/web/.env.example apps/web/.env
cp workers/api/.dev.vars.example workers/api/.dev.vars
cp workers/indexer/.dev.vars.example workers/indexer/.dev.vars

Then start the pieces you need:

pnpm --filter @buyananswer/api exec wrangler dev
pnpm --filter @buyananswer/web dev

Always invoke wrangler via pnpm --filter <pkg> exec wrangler, never pnpm exec wrangler from the repo root. A globally installed wrangler 4.x will shadow the pinned 3.114.x and fail on Node 20 — every wrangler 4 release hard-asserts Node >= 22, and this repo pins Node 20.19.5.

A note on the committed Cloudflare ids

The env.production blocks in workers/*/wrangler.jsonc and apps/web/wrangler.jsonc contain real D1 database and KV namespace ids. These are resource identifiers, not credentials — they are inert without an authenticated Cloudflare account, which is the same reason Cloudflare's own docs and templates put them in version control. They are committed so wrangler deploy --env production is reproducible from this source. Actual secrets (API tokens, RPC provider keys, the Farcaster hub key, the reconcile bearer) live in wrangler secret / .dev.vars and are never in this repository.


Security

The escrow holds real money. Please read SECURITY.md before anything else — it covers how to report a vulnerability privately, what's in scope, and, importantly, the fact that this contract has not had an external security audit.

Never open a public issue or pull request for a security vulnerability.


License

This repository is dual-licensed by directory:

Path License
contracts/src/, contracts/script/ BUSL-1.1 — see LICENSE-BSL and contracts/LICENSE
apps/, packages/, workers/, contracts/test/ MIT — see LICENSE-MIT

Copyright (c) 2026 Jayanth Komarraju. The BUSL Change Date is 2030-08-12, on which the escrow contracts convert to GPL-2.0-or-later. Until then you may use them in production provided the use does not compete with BuyAnAnswer; non-production use is unrestricted.

The contract tests and mocks are MIT on purposeMockUSDC and ReentrantToken are useful outside this project and shouldn't carry a competing-use restriction.

Every source file carries its own SPDX-License-Identifier header, and that header governs the file it appears in.

About

Your link in bio, but every tip buys a real answer. Non-custodial paid Q&A in USDC on Base.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages