Target: ETHGlobal New York 2026. Sponsors: Base + ENS.
A CLI tool that takes a .dog spec for an onchain identity protocol and generates deployable Solidity contracts targeting Base Sepolia with ENS integration.
dotname
├── package.json — npm CLI: npx dotname
├── bin/dotname — entry point
├── src/
│ ├── cli.ts — commands: init, generate, deploy, register
│ ├── generate.ts — .dag → Solidity codegen
│ └── deploy.ts — Hardhat deploy to Base Sepolia + ENS registration
├── templates/
│ ├── Profile.sol — ERC-721 identity NFT
│ ├── Registry.sol — ENS-compatible name registry
│ ├── Resolver.sol — ENS resolver (name → profile)
│ └── Registrar.sol — Subdomain registrar (name.base.eth)
├── contracts/ — generated output
│ ├── Profile.sol
│ ├── Registry.sol
│ ├── Resolver.sol
│ └── Registrar.sol
└── specs/
└── onchain-id/ — our dogfood spec (already written)
├── SPEC.dog
├── data-model.dog
└── onchain-id.dag
dotname init [project] — scaffolds identity spec via dotdog
dotname generate — reads .dag, generates Solidity contracts
dotname deploy — deploys to Base Sepolia via Hardhat
dotname register <name> — registers name.base.eth
dotname demo — runs full demo: init → generate → deploy → register
For each entity in .dag where type = "contract":
→ Create .sol file with entity name
→ Properties → storage variables + getters
→ States → Solidity enum + modifiers
→ Lifecycle → event emissions on state transitions
→ Relationships → interface imports + cross-contract calls
For each entity where type = "event":
→ Solidity event definition
.dag entity Profile becomes:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
enum ProfileState { Created, Active, Suspended }
contract Profile is Ownable {
address public profileAddress;
string public name;
string public avatar;
string public bio;
string public links;
address public profileOwner;
ProfileState public state;
event StateChanged(ProfileState from, ProfileState to);
constructor(string memory _name, string memory _avatar) Ownable(msg.sender) {
name = _name;
avatar = _avatar;
state = ProfileState.Created;
emit StateChanged(ProfileState.Created, ProfileState.Created);
}
function activate() external onlyOwner {
require(state == ProfileState.Created);
state = ProfileState.Active;
emit StateChanged(ProfileState.Created, ProfileState.Active);
}
// ... more generated methods from lifecycle
}Uses Hardhat with Base Sepolia RPC. Deploys in order:
- Resolver (standalone)
- Registry (references Resolver)
- Registrar (references Registry)
- Profile (standalone)
dotname register alice:
- Checks
alice.base.ethavailability via ENS subgraph - Calls Registrar.register("alice", msg.sender)
- Profile contract stores ENS name mapping
- Resolver updated: alice.base.eth → profile address
| When | What |
|---|---|
| Submission | GitHub repo + demo video |
| Demo flow | Live: spec → generate → deploy → register → resolve |
| Pitch | "Spec your onchain identity. Deploy on Base. Resolve via ENS. 5 minutes." |
| Prize | Hook |
|---|---|
| Base | All contracts deploy on Base Sepolia |
| ENS | Subdomain registration + resolution |
| AI + Blockchain | dotdog MCP server — specs are agent-queryable |
| Best Dev Tool | Spec-first Solidity development |
| Open Source | MIT, built on dotdog |