Governor
Showcase port of OpenZeppelin-style governance (Governor,
TimelockController, ERC20Votes) under examples/governor/ in
cambrian-lang. Targets EVM with deterministic CREATE2; Lean project
file is project.lean.yaml.
Do not expect a line-for-line OZ clone — see the repo README.md /
PLAN.md for intentional simplifications (snapshot-free voting,
single-target proposals, fixed quorum, …).
Layout
examples/governor/
project.yaml # target: evm
project.lean.yaml
ERC20Votes.cam (+ .test / .fuzz / .invariant)
TimelockController.cam (+ .test / .invariant)
Governor.cam (+ .test / .fuzz / .invariant)
ref/ # vendored OZ reference
build/ # generated (gitignored)
Entities
| Entity | Shape | Role |
|---|---|---|
ERC20Votes | Token + votes | getVotes / transfers; feed for castVote |
TimelockController | Singleton | Schedule / execute / cancel with role from |
Governor | Singleton | Propose → vote → queue → execute |
Cross-contract handles use typed addresses:
constructor(token: Address<ERC20Votes>,
timelock: Address<TimelockController>,
admin: address,
voting_period: u64,
quorum_votes: U256) => []
Idioms exercised
Phased var capture — read voting power, then tally only if weight
is positive (Phased Routes):
castVote(proposal_id: U256, support: u8) => [
read: [
var weight = getVotes(msg::sender) ~> m_token;
]
tally where weight > 0 : throw 100 : [
]
]
Role from on members — Timelock gates schedule / execute / cancel:
schedule(...) from m_proposer : throw 1
where delay >= m_min_delay : throw 2
=> []
execute(...) from m_executor : throw 3 => [
~> target with { value: value, data: data }
]
Unphased execute relies on EVM SSTORE-before-CALL so reentry cannot
re-run a finished op.
Enums — ProposalState / OpState drive member transforms.
hashOf(...) — proposal / operation ids → keccak256(abi.encode(...))
on EVM.
Build and test
# From the cambrian-lang repo root:
cargo run -p cambrian-transpiler --release -- \
--project examples/governor/project.yaml
cd examples/governor/build
bash setup.sh
forge build
forge test -vv
# Lean (separate project file):
cambrian-transpiler --project examples/governor/project.lean.yaml
Full commands and status live in examples/governor/README.md.