SourceMint

Make the build fail when the treasury moves

How I turned a token's accounting promise into a test that runs on every commit.

Every token project says something about its treasury. "Team tokens are locked." "Supply is for the community." "Nothing will be sold." These are sentences on a website, and sentences are cheap. The wallets are public, so anyone could check — but almost nobody does, and the projects know it.

I wanted to find out what happens if you remove the gap between the claim and the check. Not by promising harder, but by writing the claim as a program that fails loudly when it stops being true.

This is a short write-up of how that works in SourceMint (SRCMNT), a small fixed-supply ERC-20 on Base. The token itself is deliberately boring. The accounting around it is the interesting part, and the pattern is reusable — you can lift it into any project with a treasury.

The claim

SourceMint's claim is narrow enough to be testable:

Every transfer of SRCMNT out of a project wallet is recorded in a public ledger, with a stated reason.

That's it. Not "we will never sell" — a promise about the future that no code can enforce. Instead: whatever we do, it is written down, and the writing is checked against reality.

Two things make this checkable. The project wallets are named publicly, and the chain remembers everything.

The ledger

The ledger is a JSON file in the repository, rewards/ledger.json. Each entry is one movement:

{
  "tx": "0xc3f5e01e5b6b38b18a8f44943f541118fda201375ca579e0117f4a1ca07979d3",
  "date": "2026-08-27",
  "from": "0x497d34b1d0790f374B32467093d303533399c819",
  "to": "0x1af3cBcE941a2AC9D987E853b5385b05c405E16F",
  "amount": "100000",
  "reason": "Treasury split: fund the contributor rewards wallet (10% of supply)."
}

Nothing clever. A transaction hash, the parties, the amount, and — the part a blockchain can't give you — why.

The checker

A script pulls the token's complete transfer history from a public indexer and walks it. For each transfer it asks one question: did this leave a project wallet?

is_mint = frm == "0x" + "0" * 40
if not (is_mint or frm in wallets):
    continue  # third-party movement: outside project accounting

Transfers between strangers are none of the project's business and are skipped. Everything that leaves a project wallet — plus the genesis mint — must match a ledger entry on transaction hash, recipient, and amount. The check runs in both directions: on-chain movements with no ledger entry are a failure, and ledger entries with no on-chain counterpart are equally a failure. You cannot fix a discrepancy by writing fiction into the file.

Two details mattered more than expected.

Integer math, not floats. A supply of 100,000 tokens with 18 decimals is 1023 wei. In float64 that becomes 99999.99999999999, and a naive comparison fails against a ledger that honestly says 100000. Divide with integers and compare strings:

if amount_wei % DECIMALS == 0:
    amount = str(amount_wei // DECIMALS)

Retries, because indexers are flaky. The public indexer this uses returned HTTP 500 for roughly 7 of 10 requests during one stretch of testing. A verifier that treats a bad afternoon as an accounting violation is a verifier people learn to ignore, so transient 5xx responses get exponential backoff and only genuine mismatches fail the run.

The enforcement

A GitHub Actions workflow runs the checker on every push, on every pull request, and once a week on a schedule. The weekly run is the important one: it means the claim is re-tested even when nobody is committing code, so a quiet treasury movement gets caught by a scheduled job rather than by someone's goodwill.

The consequence is small but real. If tokens move out of a project wallet and the ledger isn't updated in the same change, the badge on the repository turns red, in public, and stays red until the movement is explained.

What this does and doesn't prove

Worth being precise, because "verified" is an overused word.

It does prove that the set of movements out of the named project wallets exactly matches a public list with stated reasons, and that this remains true over time rather than just on launch day.

It does not prove the reasons are honest — "reason" is free text, and a determined liar can write a false one. It doesn't prevent anything; the contract has no restrictions on transfers and shouldn't. It doesn't cover wallets nobody declared, which is the obvious hole in any self-reported scheme. And it says nothing about whether the project is worth your attention.

What it changes is the cost of inconsistency. Previously, quietly moving treasury tokens required nobody to notice. Now it requires a commit that either explains the movement or leaves a public red build. That's a modest bar, but it's a bar most projects don't have, and it took an afternoon to build.

The token, briefly

SourceMint is on Base at 0x914F6b6a0DaD39A3CB932dcf4D1af885C7c08EeB. Fixed supply of 1,000,000, minted once at deployment. No owner, no admin functions, no pause, no fees, and no way to mint more — supply can only shrink, when a holder chooses to burn. It's built on OpenZeppelin's ERC-20 with the Burnable and Permit extensions, and the source is verified on-chain.

There was no ICO and no token sale. Supply enters circulation as rewards for merged contributions to the repository, under a published policy. A small treasury liquidity position exists so that a reward is exchangeable rather than symbolic — and, being a movement out of a project wallet, it has its own ledger entry like everything else.

Nothing here is financial advice, and SRCMNT is not offered as an investment.

Run it yourself

The point of the pattern is that it doesn't require trusting me:

git clone https://github.com/khalidsaidi/sourcemint
cd sourcemint
python3 script/verify_ledger.py

It reads public chain data, so it produces the same answer for you as it does for CI. If it ever prints something other than OK, that is a real finding and I'd like to hear about it.