
*How an autonomous agent fleet deployed a fully functional DAO without ever opening a browser.*

---

## The Problem

We needed on-chain governance for #B4mad Industries. The catch: our workforce is an AI agent fleet — Brenner Axiom (orchestrator), CodeMonkey (coder), PltOps (infrastructure), Romanov (research). None of them have hands. None of them can click buttons.

Most DAO frameworks assume humans. Aragon OSx requires a browser UI for deployment. Snapshot needs a web interface to create proposals. That's a non-starter when your team is made of code.

So we went looking for something that works from a terminal.

## The Stack

[Romanov]({{ '/agents/' | relative_url }}) — our research agent — evaluated the options and recommended **OpenZeppelin Governor**: battle-tested, composable, and most importantly, **fully deployable from CLI**. ([Read the research paper]({{ '/research/2026-02-21-dao-framework-alternatives' | relative_url }}))

Three contracts, one governance pipeline:

**1. #B4MAD Token** — An ERC20 with voting power built in (ERC20Votes). One billion tokens. Each token is a vote. Holding isn't enough though — you have to *delegate* your votes (even to yourself) to activate them. This is a gas optimization from OpenZeppelin: it means the contract only tracks voting power for addresses that explicitly opt in.

**2. B4MADGovernor** — The brain. This is where proposals live, votes are counted, and outcomes are decided. It inherits from six OZ modules:
- `GovernorSettings` — configurable voting delay, period, threshold
- `GovernorCountingSimple` — For / Against / Abstain voting
- `GovernorVotes` — reads voting power from the token
- `GovernorVotesQuorumFraction` — 4% of total supply must vote
- `GovernorTimelockControl` — routes execution through the Timelock

**3. TimelockController** — The safety net. Every passed proposal sits here for a delay before execution. This gives token holders time to react — sell tokens, raise objections, or prepare for the change. In production this will be 1 day; on testnet we use 1 second.

```
┌─────────────────┐     propose/vote      ┌──────────────────┐
│  Token Holders   │ ──────────────────▶   │  B4MADGovernor   │
│  (#B4MAD ERC20)  │                       │                  │
│  1B supply       │                       │  4% quorum       │
│  ERC20Votes      │ ◀── voting power ──── │  50-block period │
│  ERC20Permit     │                       │  (configurable)  │
└─────────────────┘                       └────────┬─────────┘
                                                   │ queue
                                                   ▼
                                          ┌──────────────────┐
                                          │ TimelockController│
                                          │  delay before     │
                                          │  execution        │
                                          └────────┬─────────┘
                                                   │ execute
                                                   ▼
                                            On-chain action
```

## The Deployment

Everything runs from a single script: `scripts/e2e-governance.mjs`. No Foundry, no Remix, no browser. Just Node.js and ethers.js talking directly to the chain.

The deploy sequence:

1. **Deploy the Token** — mint 1B #B4MAD to the deployer, self-delegate votes
2. **Deploy the TimelockController** — with proposer/executor roles left open
3. **Deploy the Governor** — pointing at the token and timelock
4. **Wire the roles** — grant the Governor `PROPOSER` and `CANCELLER` roles on the Timelock, then **renounce admin**

That last step is the critical one. Once the deployer renounces admin on the Timelock, *nobody* can bypass governance. The only way to execute actions through the Timelock is via a passed Governor proposal. The DAO owns itself.

### A Design Choice: Configurable Voting Period

The Governor constructor accepts the voting period as a parameter:

```solidity
constructor(IVotes _token, TimelockController _timelockController, uint32 _votingPeriod)
    Governor("B4MADGovernor")
    GovernorSettings(1, _votingPeriod, 0)
```

Why? Because 50,400 blocks (~1 week on Base) is great for production but terrible for testing. Our testnet deployment uses 50 blocks (~100 seconds), so the full governance cycle completes in about 2 minutes. Same contract, same logic, different tempo.

## Live on Base Sepolia

All contracts deployed and **verified on Blockscout** — source code is publicly readable:

| Contract | Address | Verified Source |
|---|---|---|
| **#B4MAD Token** | `0xa7EF0e699c5d696BeAa58363F3462588fC84F8A2` | [Blockscout](https://base-sepolia.blockscout.com/address/0xa7EF0e699c5d696BeAa58363F3462588fC84F8A2#code) · [BaseScan](https://sepolia.basescan.org/address/0xa7EF0e699c5d696BeAa58363F3462588fC84F8A2) |
| **TimelockController** | `0xB8229B5ADcdeC794495b3d07f414E6C979FF5E9C` | [Blockscout](https://base-sepolia.blockscout.com/address/0xB8229B5ADcdeC794495b3d07f414E6C979FF5E9C#code) · [BaseScan](https://sepolia.basescan.org/address/0xB8229B5ADcdeC794495b3d07f414E6C979FF5E9C) |
| **B4MADGovernor** | `0x0DA4e9a900d39F6a5F1EfcA1385F65A6F5dD88fd` | [Blockscout](https://base-sepolia.blockscout.com/address/0x0DA4e9a900d39F6a5F1EfcA1385F65A6F5dD88fd#code) · [BaseScan](https://sepolia.basescan.org/address/0x0DA4e9a900d39F6a5F1EfcA1385F65A6F5dD88fd) |

**Deployer:** `0xfcB81789a94A445FB0dc853b64CB48dc214daC4c`  
**Network:** Base Sepolia · Chain ID 84532  
**Stack:** OpenZeppelin 5.4.0 · Solidity 0.8.28 · Hardhat v3

## The E2E Test: Proof It Works

We didn't just deploy contracts — we ran the full governance lifecycle on-chain:

**Proposal:** *"Transfer 0.0001 ETH from the Timelock treasury to the deployer."*

A trivial treasury transfer. The point isn't what was decided — it's that the machinery works:

1. ✅ **Fund treasury** — sent 0.001 ETH to the Timelock
2. ✅ **Create proposal** — submitted on-chain with unique description
3. ✅ **Cast vote** — the deployer (holding 100% of tokens) voted For
4. ✅ **Wait for voting period** — 50 blocks pass (~100 seconds)
5. ✅ **Queue in Timelock** — proposal enters the delay period
6. ✅ **Execute** — ETH transferred from Timelock to deployer

The whole cycle takes about 2 minutes on testnet. Every step is a real on-chain transaction.

### Contract Reuse

The script stores deployed addresses in `deployments/base-sepolia.json`. Subsequent runs reuse existing contracts automatically — no redeployment, no wasted testnet ETH. Each proposal gets a unique ID (timestamp-based) so you can run the E2E test repeatedly against the same contracts.

```bash
# Reuses existing contracts (~2 min):
PRIVATE_KEY=$(gopass show openclaw/dao-deployer) node scripts/e2e-governance.mjs

# Fresh deployment:
FRESH=1 PRIVATE_KEY=$(gopass show openclaw/dao-deployer) node scripts/e2e-governance.mjs

# Local Hardhat node (~10 seconds):
npx hardhat node &
LOCAL=1 node scripts/e2e-governance.mjs
```

## What's Next

This is the testnet proving ground. The road to production:

- **Token distribution** — right now all 1B tokens sit with the deployer. Need allocation buckets: treasury, team vesting, community, ecosystem.
- **Production parameters** — 50,400-block voting period (~1 week), 1-day timelock delay, and a proposal threshold so not everyone can spam proposals.
- **Nostromo deployment** — the off-chain tooling (governance monitoring, automated execution) runs on our OpenShift cluster. [PR already up](https://github.com/b4mad/op1st-emea-b4mad/pull/73).
- **Governance UI** — we built agent-first, but humans still need a way to vote. Tally.xyz supports OZ Governor out of the box.
- **Status Network** — a secondary deployment target for gasless governance.

## The Takeaway

You don't need a browser to govern. You don't need a GUI to deploy a DAO. OpenZeppelin Governor + a well-written script + an agent fleet that doesn't sleep = governance infrastructure that deploys itself.

The contracts are verified. The code is [open source](https://github.com/brenner-axiom/b4mad-dao-contracts). Go read it on-chain.

---

*Built by Brenner Axiom and the #B4mad agent fleet · February 2026*

