Voting & Governance
Aave Governance V2 is an exciting new evolution of on-chain governance, allowing unique features such as delegated voting and proposition powers, rapid protocol upgrades via short time lock executors, and governance upgrades via long time lock executors.
This ensures the protocol can rapidly adjust to changing market conditions, as well as upgrade core parts of the protocol as time goes on.
This section is for developers and technical users. For a non-technical overview, see the Protocol Governance section of Aavenomics or the Governance Docs.
Overview
AAVE and/or stkAAVE token holders receive governance powers proportionally to the sum of their balance.
There are initially two powers associated with each governance token:
The proposal power that gives access to creating and sustaining a proposal.
The voting power which is used to vote for or against existing proposals.
Any user can chose to delegate one or both of the governance powers associated with a token, either through our governance portal or programatically.
A user that has received delegated power can not forward this delegated power to another delegatee. I.e. delegated power cannot be passed on further.
The code for Aave Governance V2 can be found on Github.
Deployed Contracts
Audits
Proposal Types
There are two types of proposals with different parameters which affect the length and execution of a proposal, i.e. critical proposals that affect governance consensus require more voting time and a higher vote differential, whereas proposals affecting only protocol parameters require less voting time and can be quickly implemented.
As an initial safeguard to the protocol, a guardian account, controlled by a community multisig, is able to cancel a proposal before the proposal is executed.
Each type of proposal can only be validated and executed by a certain executor.
Short time lock executor
The short time lock executor can execute proposals that change parts of the Aave protocol or the Ecosystem reserve that require quick intervention.
Long time lock executor
The long time lock executor can execute proposals that change parts of the Aave protocol that affect governance consensus.
Proposition/Voting Power
An account's proposition/voting power at a given block is equal to the snapshot of that account's AAVE/stkAAVE balances plus the balances of all delegators.
An account's balance contributes to both proposition and voting power while delegators can choose to delegate proposition power, voting power or both to another account.
A creator must have proposition power higher than PROPOSITION_THRESHOLD
at the block before the proposal is created and until the proposal is executed.
A user can vote only once. The weight of this vote is equal to the user's voting power at the block when submitVote()
is called.
Both AAVE and stkAAVE maintain _propositionSnapshots
/_votingSnapshots
mappings. New snapshots are taken on every call to:
transfer()
Proposition/Voting power available at a specified block can be fetched from AaveGovernanceStrategy
System: Total supply of AAVE at that block
getVotingPropositionSupplyAt()/getTotalPropositionSupplyAt()
User: AAVE + stkAAVE snapshot of the user at the block
getVotingPowerAt(), getPropositionPowerAt()
Proposal Life Cycle
0) Off-chain process
The ARC and AIP process should be followed, with a resulting AIP and payload ready to be used for the proposal. Learn more about the ARC and AIP process here.
The AIP should be merged into the AIP repository, with an associated IPFS hash of the parsed AIP file, before the next steps are taken.
1) Proposal Creation
A proposal can be created by calling create()
, with the following caveats:
The proposer must have a proposal power higher than
PROPOSITION_THRESHOLD
.The proposer needs to maintain the proposal power threshold or higher until the proposal is actually executed (i.e. during the vote and until the actual execution of the proposal)
The proposal is now in a PENDING
state until the vote begins.
2) Proposal Voting
If votingDelay = 0
, then the voting period begins at the next block. Otherwise the voting begins after the votingDelay
. The votingDelay
value can be fetched from getVotingDelay()
. A snapshot of voting powers is taken and can no longer be delegated/transferred for the proposal being voted on.
The proposal state is ACTIVE
and users can submit a vote for or against the proposal, weighted by the users total voting power (tokens + delegated voting power), within the allotted VOTING_DURATION
.
3) End of Voting Period
For a proposal to pass:
The voting power (in % of total voting power) of for-votes needs to reach the quorum set by the
MINIMUM_QUORUM
parameter, andThe difference between for-votes and against-votes (in % of total voting power) needs to exceed the vote differential threshold set by the
VOTE_DIFFERENTIAL
parameter.
If the proposal has passed, then the proposal state becomes SUCCEEDED
, otherwise it is FAILED
4) Proposal Queuing and Execution
A SUCCEEDED
proposal can be queued and will be executed after the execution delay and before grace period expiration. The delay
can be fetched from getDelay()
and the GRACE_PERIOD
can be fetched from GRACE_PERIOD()
.
The validation and execution of the proposal is performed by the time lock executor.
A queued proposal state is QUEUED.
A successfully executed proposal state is EXECUTED
.
If a queued proposal has not been executed before expiration, then the proposal state is EXPIRED
.
(Optional) Proposal Canceling
If the proposal creator's proposal power decrease and no longer meet the PROPOSITION_THRESHOLD
, any user can cancel the proposal.
In addition as an initial safeguard to the protocol, a guardian account, controlled by a communtity multisig, is able to cancel a proposal before a proposal is executed.
A cancelled proposal state is CANCELED
.
Integrating Governance
Delegation
To perform delegation in your integration, call the function delegate()
or delegateByType()
on the AAVE and/or the stkAAVE token contracts to delegate one or both of the voting and proposition powers.
Voting
To enable your users to vote:
Retrieve a list of proposals and associated details. This can be done via the subgraph or directly from the on-chain governance contracts.
Vote on the proposals by using
submitVote()
.Fetch the state of the proposal via the subgraph or directly on-chain.
Proposals
To fetch a proposal and its associated details, call getProposal()
or getProposals()
.
To get the token power of an address, call getTokenPower()
.
Subgraphs
The governance subgraph gives access to three main objects:
Proposals with their states and votes
Available executors and their parameters
Votes
Subgraphs on the graph explorer:
Example query for fetching active proposals
Relevant Methods
create()
Contract: AaveGovernanceV2
function create(address executor, address[] memory targets, uint256[] memory values, string[] memory signatures, bytes[] memory calldatas, bool[] memory withDelegatecalls, bytes32 ipfsHash) external returns (uint256 proposalId)
Creates a proposal for a specific executor. A proposal includes a list of underlying transactions.
The caller must have the necessary proposition power to create a proposal.
return values
PROPOSITION_THRESHOLD()
Contract: ProposalValidator
(Executor)
function PROPOSITION_THRESHOLD()
Returns the minimum percentage of the voting token supply needed to submit a proposal (in BPS, e.g. 1 bps = 0.01%, 10,000 bps = 100%) in the Proposal Creation step.
Currently the Short time lock executor is 0.5% and the Long time lock executor is 2%.
getVotingDelay()
Contract: AaveGovernanceV2
function getVotingDelay()
Returns the current delay before a created proposal can be voted on by the community in the Proposal Creation phase.
VOTING_DURATION()
Contract: ProposalValidator
(Executor)
function VOTING_DURATION()
Returns the duration of the voting period (in blocks) in the Proposal Creation phase.
Currently the Short time lock executor is 3 days and the Long time lock executor is 10 days.
MINIMUM_QUORUM()
Contract: ProposalValidator
(Executor)
function MINIMUM_QUORUM()
Returns the minimum percentage of the voting token supply of 'for' (i.e. positive) votes of a proposal to successfully pass (in BPS, e.g. 1 bps = 0.01%, 10,000 bps = 100%), in End of Voting phase.
Currently the Short time lock executor is 2% and the Long time lock executor is 20%.
VOTE_DIFFERENTIAL()
Contract: ProposalValidator
(Executor)
function VOTE_DIFFERENTIAL()
Returns the percentage of the voting token supply of 'for' (i.e. positive) votes needed over 'against' (i.e.negative) votes for a proposal to successfully pass (in BPS, e.g. 1 bps = 0.01%, 10,000 bps = 100%), in End of Voting phase.
Currently the Short time lock executor is 0.5% and the Long time lock executor is 15%.
getDelay()
Contract: ExecutorWithTimeLock
(Executor)
function getDelay()
Returns the delay between queuing and execution of a proposal (in seconds) in Proposal Queueing and Execution Period.
Currently the Short time lock executor is 1 day and the Long time lock executor is 7 days.
GRACE_PERIOD()
Contract: ExecutorWithTimeLock
(Executor)
function GRACE_PERIOD()
Returns the time after delay
(getDelay()
) in seconds when a proposal can be executed in Proposal Queueing and Execution Period.
Currently the Short time lock executor is 5 days and the Long time lock executor is 5 days.
delegate()
function delegate(address delegatee)
Delegate both powers of a token (vote and proposition) to a delegatee
delegateByType()
function delegateByType(address delegatee, uint8 delegationType)
Delegate one specific power of a token (vote or proposition) to a delegatee
To reset delegation, set the delegatee address to the delegator address.
submitVote()
Contract: AaveGovernanceV2
``
submitVote(uint256 proposalId, bool support)
Submits a vote by the caller.
getDelegateeByType()
function getDelegateeByType(address delegator, uint8 delegationType) returns(address delegatee)
Returns the address of the delegatee for a delegator
If the return value is the delegator address, then there is no delegation.
getVotingPowerAt(), getPropositionPowerAt()
Contract: AaveGovernanceStrategy
function get{Voting,Proposition}PowerAt(address user, uint256 blockNumber) returns(power uint256)
Returns the Voting/Proposition power of the user at a specified block
When submitting a vote, the voting power is calculated at the time of the beginning of the vote.
getTotalVotingSupplyAt(), getTotalPropositionSupplyAt()
Contract: AaveGovernanceStrategy
function getTotal{Voting,Proposition}SupplyAt(uint256 blockNumber) returns(totalSupply uint256)
Returns the total Voting/Proposition power available at a specified block
The total available power is equal to the total supply of not staked AAVE + the total supply of staked AAVE = total supply of AAVE
getProposal()
Contract: GovV2Helper
function getProposal(uint256 id, IAaveGovernanceV2 governance)
Returns the details of a proposal.
getProposals()
Contract: GovV2Helper
function getProposals(uint256 skip, uint256 limit, IAaveGovernanceV2 governance)
Returns an array of proposals with associated details.
getTokensPower()
Contract: GovV2Helper
function getTokensPower(address user, address[] memory tokens)
Return the power (voting and proposition) of the user
.
Returns the votingPower
, delegatedAddressVotingPower
, propositionPower
, delegatedAddressPropositionPower
.
Last updated