# The US government as a smart contract

By [Alex Kroeger](https://paragraph.com/@alex-kroeger) · 2021-11-30

---

A technical guide to on-chain governance
========================================

_Disclaimer: this post and accompanying code is meant for educational purposes only. None of this is audited, and you should seek out audits before using contracts in production._

There has been much ado about DAOs lately--they are being used to [govern financial protocols](https://vote.makerdao.com/), [form modern day guilds](https://twitter.com/developer_dao), and [crowdfund the sale of historical documents](https://twitter.com/ConstitutionDAO).

But how do they work on-chain? This post will walk through an example of setting up governance using a variant of the popular governance contracts created by Compound Finance. The task? Deploying the U.S. federal government as smart contracts on Ethereum.

All the code discussed in this post can be found in a GitHub repo [here](https://github.com/alexkroeger/the-federal-govt-as-solidity/tree/main). Hat tip to [OpenZeppelin](https://openzeppelin.com/) for an excellent and extensive [library of contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) that I use heavily in this tutorial.

The contracts
-------------

### CongressToken

[link to file](https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/CongressToken.sol)

The first step in on-chain governance is for determining who will be doing the governing! For the federal government, that will be Congress.

DAO voting power is typically determined by one’s balance of an [ERC20 token](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/). To create our governance token, which I’ll be calling `CongressToken`, we’ll use OpenZeppelin’s standard ERC20 implementation as well as an extension they’ve made called [ERC20Votes](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Votes.sol).

`ERC20Votes` will give us the ability to keep track of voting power and exposes an interface to delegate the voting power of your tokens to yourself or someone else.

![CongressToken](https://storage.googleapis.com/papyrus_images/9803739cb087f09a547b4a1b3eecbabec4bef3e11aaf78fb5859358dea5132a1.png)

CongressToken

Two items to note here. First, in the constructor, I mint 3 tokens (technically there should be 535, one for each member of Congress, but I’m too lazy to simulate more than 3 members) and transfer them to the deployer address.

`_mint(msg.sender, 3);`

Since there is no publicly available `mint()` function, this will be the total supply of CONGRESS forever. I leave it up to the deployer to distribute these tokens, which is not what you want to do in prod. It would be more appropriate to grant the tokens to a separate contract that will distribute tokens according to some rule.

Second item to note is that I set `decimals()` to 0. Token balances are always stored as an integer on-chain, and the ERC20 standard dictates that you specify the number of decimal places used to convert these integers into the desired fractional units. 18 decimals is most common, as that is used by ether itself. Here, I don’t desire any ability to fractionalize votes (it’ll be one senator, one vote), so I set decimals to 0.

### FederalGovernment

[link to file](https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/FederalGovernment.sol)

Next we need to create the logic for governance--how do proposals get created and voted on?

For this we use the OpenZeppelin [Governor](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/Governor.sol) contract. It’s based on the popular Compound governance contracts, which are also used by Uniswap. Additionally, OpenZeppelin has made an extension called [GovernorCompatabilityBravo](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/compatibility/GovernorCompatibilityBravo.sol), which can make the interface of the governance contract compatible with Compound’s [GovernorBravo](https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorBravoDelegate.sol).

![](https://storage.googleapis.com/papyrus_images/cdbc5103939cec75a76f3a999ae249ec13caeaca121f9b3799633297498db9a1.png)

There are two constructor arguments--the first (`_token`) is an `ERCVotes`\-compatible ERC20 that will serve as the governance token. For my setup this will be the address of `CongressToken`. The second (`_timelock`) is address of a timelock contract, which we’ll get to shortly.

I set a few constants in the contract. `GovernorVotesQuorumFraction` controls what percent of the total supply of the governance token needs to vote in order for a proposal to pass. I (somewhat arbitrarily) have 4%.

`GovernorVotesQuorumFraction(4)`

The `votingDelay` is the amount of time between when a proposal is created and when voting begins, specified in terms of number of blocks. This gives governance token holders time to review the proposal and delegate their voting power if they choose to do so. I set this at a low value (2 blocks), but this should probably be a day or two in production systems.

![](https://storage.googleapis.com/papyrus_images/831a1b9d0d882ba371bac6224c914ba6e08782c77ac59857338d64ca6f2e213f.png)

The `votingPeriod` is the amount of time allocated for voting in terms of number of blocks. Addresses with delegated voting power would need to submit an on-chain vote transaction during that amount of time. I again set this to a low value (100 blocks), but this should be probably 3-5 days in a production system for sensitive items.

![](https://storage.googleapis.com/papyrus_images/15926f6d9e98a7a43afad1435b0a997aadde5f7cc00651bb97b53963850765e5.png)

Finally, I set the `proposalThreshold`. This ensures that not just anyone can submit a proposal--you need to have a certain amount of delegated voting power. Here, I choose 1, meaning any member of congress (delegated CONGRESS voting power of 1) can submit a proposal.

![](https://storage.googleapis.com/papyrus_images/70e15cecec47b6c83ff2046b19ce9ec6e31a218995ac80993a9f3ced25ebc078.png)

### FederalGovernmentTimelock

[link to file](https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/FederalGovernmentTimelock.sol)

Many DeFi protocol governance systems include a timelock contract. This contract is the one that has the ability to update critical systems, and ensures that no changes can be made without some delay that allows affected users to withdraw funds, change parameters, etc. before a change is made.

![](https://storage.googleapis.com/papyrus_images/fba5f61c085bc91375b2efcae329e1aad3633c2ded03b7f636ed410378857d0b.png)

For this contract I simply use OpenZeppelin’s [TimelockController](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/TimelockController.sol), which has 3 constructor arguments. The first, `_minDelay`, specifies the amount of time (in seconds this time) that must pass before a change is put into effect. The second and third are arrays of addresses having to do with who can affect changes. `_proposers` can queue a change and `_executors` can enact the change.

We’ll get into how to set those values when we get into the deployment.

### USDollar

[link to file](https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/contracts/USDollar.sol)

Every governance system needs something to govern!

In this setup, the federal government manages an ERC20 contract representing the US Dollar.

![](https://storage.googleapis.com/papyrus_images/f11087d3c77e0e7a0e66470a126efea3021940e8afeda5a8ef46475b98deeb9c.png)

I again use OpenZeppelin’s standard ERC20 implementation, but I don’t use the `ERC20Votes` extension, because USD won’t be a governance token. I make use of OpenZeppelin’s [Ownable](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol) contract.

`Ownable` allows you to restrict certain functions to be used by an admin only. The default owner is the contract deployer. In the constructor, I add an argument to specify the owner to override the default behavior. I’ll make the timelock contract the owner during deployment.

I add two public functions here, `mint` and `burn`, that have the modifier `onlyOwner`. This will give the federal government the ability to mint and burn USD by proposal.

Generally, governance should have the ability to call certain admin functions (like `mint` and `burn` in this case).

Deployment
----------

In the accompanying repo, I include a script called [deploy\_util](https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/scripts/deploy_util.ts) that sets up the governance system.

The first step is to deploy the governance token:

![deploying CongressToken.](https://storage.googleapis.com/papyrus_images/98489b9ea4fc92299365713a7360332285f0d89a1859fb881c1279f4bdd84563.png)

deploying CongressToken.

This is straightforward--I print out the deployed address along with decimals and total supply.

Next step is to deploy the timelock contract, as it will be an input argument for the governance contract.

![deploying the timelock contract](https://storage.googleapis.com/papyrus_images/d57910f50e9dbc3994990960afc3e29093ef2497dcf2110ce504234f559cd96f.png)

deploying the timelock contract

Note that I leave `_proposers` empty here. The governance contract will be the only proposer, but we do not yet know its address. For `_executors`, I include only the zero address (0x000…) which means any address can execute. This isn’t insecure, since only transactions that are proposed can be executed, and only governance can propose.

Next I deploy the governor contract, passing in the addresses for the governance token and the timelock.

![deploying the governor contract](https://storage.googleapis.com/papyrus_images/84d1c826d383e8b6a59b75b364dd8b37176aaa450e6fd2953f18d0df81bc2105.png)

deploying the governor contract

At this point the deployer address is an admin on the timelock. I grant the `FederalGovernment` contract the role of proposer, and then renounce the deployer’s admin privilege on the timelock so that governance is in control.

Finally, I deploy the `USDollar` contract, passing in the timelock contract as the owner. With that, we’re ready for governance!

![](https://storage.googleapis.com/papyrus_images/317bc8f2c7b5e1af894522297c6df7e6bde6509cbc8891a125264f7d7818a626.png)

Creating and executing a proposal
---------------------------------

Now we can see what the governance system can do.

The repo contains another script called [proposal\_scenario](https://github.com/alexkroeger/the-federal-govt-as-solidity/blob/main/scripts/proposal_scenario.ts) that walks through the creation of a proposal in a local hardhat environment.

First, some housekeeping. I need to distribute the CONGRESS tokens to some senators. I grab three spare addresses to have 3 senators (`redSenator`, `blueSenator`, and `swingSenator`\--think Joe Manchin). In order to vote later, the token balances must be delegated to a voter. In this case, all the senators delegate to themselves.

![](https://storage.googleapis.com/papyrus_images/bc92408107b224daf96c508be2fc20c8c61974164a732bb8fc7f97174acc4e88.png)

Now we’re ready to create a proposal.

### Creating a proposal

`redSenator` wants to propose that $2M is minted, and $1M goes to them and $1M goes to `swingSenator`.

The `FederalGovernment` contract interface has a `propose` function, whereby you can pass calldata to be executed by the timelock.

![](https://storage.googleapis.com/papyrus_images/cce28ef515ce751f82200ecf759dc3e6e7f5584dead7a9f12ee1f9cd88f4cd54.png)

I create the calldata for the 2 calls to mint on the USDollar contract, and add them to the proposal. The proposal also needs the address to call for each calldata (the USDollar contract for both in this case), the amount of ETH to be sent with the call (0 in this case), and a description.

Once we create the proposal, the governance contract recognizes it as “pending.”

### Voting

We can’t quite vote on the proposal yet. You might remember that I set `reviewPeriod` value on the governance contract that requires `n` blocks pass before voting begins, giving folks a chance to delegate if they choose to do so.

Since this is a local environment, we can speed through it.

Now the senators can vote. Given that they’ll receive $1M each, `redSenator` and `swingSenator` are strongly in favor. `blueSenator`, who will receive nothing, opposes.

![](https://storage.googleapis.com/papyrus_images/919d780181731ca9e04cf82b153ecc0644537ef1f948744da507b32dd01ba75e.png)

If we call the governance contract, we can see the votes recorded.

### Queuing the proposal

Before we can queue up the proposal with the timelock, the voting period must finish. You may recall that I set this to 100 blocks in the governance contract.

Once again, we speed through. Since the yeas have it, the proposal is in the “succeeded” state.

The next step is to queue the proposal with the timelock. The governance contract allows anyone to do this once the voting process is done, so I have `swingSenator` do the honors.

![](https://storage.googleapis.com/papyrus_images/cd232aa70d1cbc0e487edc79093e47dfce504ac7f3eb224c60abf64615ae1018.png)

### Executing the proposal

The final step is to go live with the changes. We have another delay, this time enforced by the timelock contract.

After the time has passed, anyone can execute the proposal. I have the original contract deployer do so.

![](https://storage.googleapis.com/papyrus_images/5a87047e85d2d33aa17cb0025471619b31daa18e3c94386a72a38f2095036cc8.png)

The USD is successfully minted, governance in action!

Concluding thoughts
-------------------

I hope you found this tutorial helpful!

To recap, we:

*   re-created a simplified version of the federal government via on-chain governance, with a governance token (CONGRESS), a governor contract based on Compound’s popular contract, a timelock contract, and a managed ERC20 (USD)
    
*   walked through creating, voting on, and executing an on-chain proposal in this setup.
    

Here are links for your reference:

*   [the repository](https://github.com/alexkroeger/the-federal-govt-as-solidity)
    
*   [OpenZeppelin documentation](https://docs.openzeppelin.com/contracts/4.x/)
    
*   Ropsten deployments of the contracts:
    
    *   [CongressToken](https://ropsten.etherscan.io/address/0x2eeff881aa0c77c289502daa024f152186966a6e)
        
    *   [FederalGovernmentTimelock](https://ropsten.etherscan.io/address/0xe14a123e562b59fd8d7d910f772222ba575bb302)
        
    *   [FederalGovernment](https://ropsten.etherscan.io/address/0x89bbec3be60b9673aef71861093f463f3db6ab1e)
        
    *   [USDollar](https://ropsten.etherscan.io/address/0x859fe758307e9af3c2ed2190c0a0ff2ef4618156)

---

*Originally published on [Alex Kroeger](https://paragraph.com/@alex-kroeger/the-us-government-as-a-smart-contract)*
