- Demonstrates how to create a governance token, a mintable token, and a DAO governor to manage proposals on Aurora.
- Uses OpenZeppelin Wizard to generate ERC-20 contracts (one with Votes, one mintable) and a Governor contract, deployed via Remix.
- Walks through the governance cycle: delegating votes, creating a proposal, voting, and executing successful proposals to mint new tokens.
- Showcases seamless interaction with Aurora’s testnet using MetaMask, Explorer, and your own node endpoint.
Main article
The battle-tested set of OpenZeppelin contracts and the user-friendly contract wizard make it very easy to run through a simple on-chain governance example. In this tutorial, you will:- Create an ERC-20 governance token contract that you will use to cast votes on the governance proposals.
- Create a standard governor contract for your on-chain governance.
- Create a mintable ERC-20 contract that will mint new tokens on your successfully passed on-chain governance proposals.
- Run a full on-chain governance cycle.
Prerequisites
- Aurora Testnet node.
- Remix IDE to compile the contracts and deploy through MetaMask.
- MetaMask to deploy the contracts through your Chainstack node and interact with the contracts.
Overview
To get from zero to the deployed contracts on the Aurora testnet, do the following:Step-by-step
Set up MetaMask
See Aurora tooling: MetaMask.Fund your account
You can use the Aurora faucet to fund your account, although the amount of Aurora ether dispensed will not be enough to cover the costs of this tutorial. If you have some Goerli ether, you may bridge it from the Ethereum Goerli testnet to the Aurora testnet using the Rainbow bridge. The transfer may take up to 20 mins.Create and deploy your ERC-20 governance token
This will be your governance token—the token that you will use to vote on proposals in the governance contract.OpenZeppelin Wizard
Open OpenZeppelin Wizard.
Remix
This will engage your MetaMask to deploy the contract to the Aurora testnet through your currently selected MetaMask account. Click Confirm in the MetaMask modal.
Verify the contract
To use the Aurora explorer as a web app to interact with your contracts, verify them in the explorer.In the Aurora explorer, navigate to the contract that you deployed.
Create and deploy your ERC-20 mintable token contract
This will be the contract that will be used by the governance contract to mint tokens on passing the on-chain proposal.OpenZeppelin Wizard
Open OpenZeppelin Wizard.
Remix
This will engage your MetaMask to deploy the contract to the Aurora testnet through your currently selected MetaMask account. Click Confirm in the MetaMask modal.
Verify the contract similarly to the previous one.
Create and deploy your governance contract
This will be your on-chain governance contract.OpenZeppelin Wizard
Open OpenZeppelin Wizard.
In Voting Delay, keep
1 block. In Voting Period, put 600 blocks. In 1 block=, put 1 second. This will be about 10 minutes for a voting period.Remix
In Deploy, provide the address of the ERC-20 governance token that you deployed as the first contract of this tutorial. This will make the deployed contract recognize the ERC-20 token as the contract’s voting token.
Delegate the votes
You have preminted the ERC-20 governance token to the account you deployed the contract with. As the governance token owner, you now need to delegate the voting power to an account. For simplicity, you can delegate it to your account:In the Aurora explorer, open your verified ERC-20 governance contract.
Click Connect to Web3 > MetaMask. Make sure you connect with the same account that you used to deploy the contract as this is the account that holds the preminted tokens.
Transfer the ERC-20 mintable contract ownership to the governance contract
The ERC-20 mintable contract is ownable. To be able to mint the tokens through the governance contract, you need to transfer the ownership of the ERC-20 contract to the governance contract.In the Aurora explorer, open your verified ERC-20 mintable contract.
Click Connect to Web3 > MetaMask. Make sure you connect with the same account that you used to deploy the contract.
Create a proposal
At this point, you have three contracts deployed:- An ERC-20 governance token contract with preminted tokens assigned to your account
- An ERC-20 mintable token contract owned by the governance contract
- The governance contract to run proposals
mint(address to, uint256 amount).
To get the call data:
Go to the online ABI encoding service.
In Enter your parameters manually, select:
- Function > your function >
mint. - Argument > Address > the address to mint the tokens to.
- Argument > Uint256 > the amount of tokens to mint in 18 decimal unit. See Ethereum unit converter.
In the Aurora explorer, open your verified governance contract.
In
propose, provide your proposal details:- In
targets, provide the address of your ERC-20 mintable token. - In
values, provide the amount of Aurora ether that should be deposited with the proposal. Typically, it is0. - In
calldatas, provide the call data that you acquired with MetaMask. - In
description, provide any description.
In the Aurora explorer, open your transaction that created the proposal.
Cast your vote
At this point, you have:- A running proposal
- The proposal ID
- The voting power delegated to your account
In the Aurora explorer, open your verified governance contract.
In
castVote, provide your vote:- In
proposalId, paste the proposal ID. - In
support, provide your voting decision:0is against,1is for,2is abstain. For the proposal to pass, vote1.
Execute the passed proposal
Once the proposal is voted on and the voting period reaches the deadline, the proposal is passed. You can now execute the passed proposal. To execute:In the Aurora explorer, open your verified governance contract.
In
execute, provide details:- In
execute, provide0as payable amount as you are minting ERC-20 tokens and not depositing Aurora ether. - In
targets, provide the address of your ERC-20 mintable token. - In
values, provide0for the amount of Aurora ether. - In
calldatas, provide the same call data that you generated earlier for the functionmint(address to, uint256 amount). - In
descriptionHash, provide the hash of the description that you used to generate the proposal. To do this the easy way, go to an online Keccak-256 generator and paste your description text, copy the result and precede it with0x.
