You might have heard about the COMP token launch. With a current market cap of over 350 million USD, the token has accumulated massive value. But what is the actual utility of COMP?
It's a governance token. Compound being a fully decentralized system (or at least on the way towards it), has a decentralized governance mechanism in place. The same system that was copied and used also in the SushiSwap governance.
But how does it work in detail?
On a high-level, the governance is a simple set of smart contracts. They allow calling any other smart contract with any data from within the governance core contract in a decentralized way. In Compound the core contract is set as the admin of the other Compound protocol contracts. This means the core contract will be able to call all kinds of management functions like adding new markets, changing parameters and even upgrading the contracts itself.
COMP token holders are allowed to vote. Further COMP is distributed to active participants in the system, ensuring the people who use Compound are the people who get to decide on its future.
The upgrade functionality is the most powerful. Compound is using a typical proxy upgrade pattern, so by allowing governance to do upgrades, literally everything can be changed including the governance mechanism itself.
The mechanism of governance follows a strict timeline of creating proposals, voting for proposals and a two day timelock before execution:
Since the governance system is live and ongoing for Compound, you can see the system live in action in various different places:
Now let's examine the governance contracts in detail. They consist of
The core contract is called GovernorAlpha. It contains all the logic for creating and executing proposals.
At the heart of the governance is the
propose function. It takes in a list of actions, each action consists of:
target: A target address for a call to be made.
msg.valueto be passed to the call.
signature: The function signature for the call, e.g., '
calldata: The data (parameters) to be passed to the function call.
function propose( address memory targets, uint memory values, string memory signatures, bytes memory calldatas, string memory description ) returns (uint)
Each COMP token holder with at least 100,000 tokens, i.e., ≥ 1% of supply, is allowed to add a new proposal, but they can only have one active proposal at any given time. Lastly a
description string must be passed that contains a human-readable explanation the proposal.
Referendum: After a proposal has been added, a referendum begins. Addresses that held voting weight, at the start of the proposal, invoked through the
compToken.getPriorVotes function, can submit their votes, either 'Yes' or 'No', during a 3 day voting period.
Cast a vote on a proposal. The account's voting weight is determined by the number of votes the account had delegated to it at the time the proposal state became active.
The same method exists also using EIP-712 signatures. The idea is the same to the ERC-20 Permit that we previously discussed. If you haven't seen it yet, you can read it here.
function castVote( uint proposalId, bool support )
function castVoteBySig( uint proposalId, bool support, uint8 v, bytes32 r, bytes32 s )
A referendum is successful if
After a proposal has succeeded, any address can call the
queue method to move the proposal into the Timelock queue.
function queue( uint proposalId )
Once the Timelock delay has passed, anyone may call the execute method. This will now run each action part of the accepted proposal sequentially. For any action (target, value, signature, calldata), we execute the transaction as:
bytes memory callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); (bool success,) = target.call.value(value)(callData);
Remember that the calldata begins with the function selector which is calculated as the first four bytes of the hash of the signature string. So here we simply prepend the result to our existing calldata and then call the target address with our given data.
function execute( uint proposalId )
In rare cases an accepted proposal can still be cancelled. Currently there still exists a guardian address which has the power to cancel any proposal. It is currently held by the Compound Labs, Inc. itself. In the future this guardian address may be removed.
A proposal can also be cancelled if the original proposer looses the required amount of COMP tokens to create proposals after it was added. This is useful to prevent someone from doing a malicious proposal and immediately selling off all his COMP before the value of COMP might drop due to the malicious proposal being accepted.
function cancel( uint proposalId )
The Timelock contract is a wrapper around the execution of proposals. It consists of
Besides being a regular ERC-20 token, the COMP contract includes relevant governance methods.
Users can delegate their COMP to one other address. That address will be able to cast votes with the added voting power of their own COMP balances + all COMP balances from addresses that set that address as delegatee.
Just as before there also exists a
delegateBySig to be used with EIP-712 signatures.
function delegate( address delegatee )
To receive the voting power at a given block number, we can call getPriorVotes to retrieve the value. Obviously this works only for past block numbers.
function getPriorVotes( address account, uint blockNumber ) returns (uint96)
Since the requirement of 100,000 COMP tokens to create a proposal is a very high barrier, after all that's over 10 million USD at the current COMP prices, a new mechanism called Compound Autonomous Proposals (CAPs) was introduced. This will allow anyone with 100 COMP or more to propose a proposal. Any CAP that gets 100,000 votes can be added as regular proposal.
You can see and vote for CAPs under https://app.compound.finance/vote.
You can also find useful tools around governance from Compound directly via JS SDK and API:
0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B 0x35A18000230DA775CAc24873d00Ff85BccdeD550 0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B
_setPriceOracle(address) _supportMarket(address) _addCompMarkets(address) _setCollateralFactor(address,uint256) _setReserveFactor(uint256) _setMarketBorrowCaps(address,uint256)
0x000000000000000000000000922018674c12a7f0d394ebeef9b58f186cde13c1 0x00000000000000000000000035a18000230da775cac24873d00ff85bccded550 0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000100000000000000000000000035a18000230da775cac24873d00ff85bccded550 0x00000000000000000000000035a18000230da775cac24873d00ff85bccded5500000000000000000000000000000000000000000000000000853a0d2313c0000 0x00000000000000000000000000000000000000000000000002c68af0bb140000 0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000100000000000000000000000035a18000230da775cac24873d00ff85bccded550000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000001a784379d99db42000000
Add UNI Support This proposal adds [Uniswap](https://etherscan.io/token/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984) as a supported asset and implements an updated [Open Price Feed](https://compound.finance/docs/prices) view contract that supports cUNI. [...]
Further, the values (msg.value) were all set to 0. Once the proposal was accepted and later executed, all six actions were executed. You can use a tool like Ethtx.info to see the transaction in detail here.
That was the Compound Governance in a nutshell. It is a simple design, but still pretty powerful. Many projects have adopted the same mechanism or were at least inspired by it. We will see where this develops in the future, but it's an important step towards more decentralization.
We all love Etherscan . It's a great tool to interact with contracts, read the source codes or just see the status of your transactions. But unfortunately as great as it is, we should not forget that it's a centralized service. The website could be taken down any day. This kind of defeats the...
How can you add 0x to your contracts to automatically convert between tokens? We have done this in a similar fashion before with Uniswap and Balancer . The 0x API has a bit of a twist. Let's take a look why... Why you want 0x in your contracts? It's simple: Okay, but seriously. Let's see why the...
The new upgraded standard for ERC-20 tokens is becoming more and more popular. It's fully backwards compatible, you can easily create one using the Openzeppelin contracts and there are many interesting new features not available in ERC-20. Should you upgrade from ERC-20? Well let's look into what...