Skip to content
This repository has been archived by the owner on Nov 27, 2024. It is now read-only.

docs: Token Voting Module documentation #91

Closed
wants to merge 25 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Overview

## What is Llama?

Llama is an onchain governance and access control framework for smart contracts.

Using Llama, teams can deploy fully independent instances that define granular roles and permissions for executing transactions, known as "actions".

Llama instances can adapt to a changing environment by incrementally adding new participants and expanding the set of available actions. Actions can be any operation that is represented by invoking a smart contract function. This includes transferring funds, updating a registry, changing protocol parameters, or activating an emergency pause.

Learn more about Llama by reading [the protocol documentation](https://github.com/llamaxyz/llama/tree/main/docs) in the llama repository.

## What is Llama Periphery?

This repository contains supporting modules for operating Llama instances. Modules are extensions to Llama instances that can be adopted by using a Llama action to configure and deploy.

## Modules

- [Token Voting](https://github.com/llamaxyz/llama-periphery/tree/main/docs/token-voting/README.md): smart contract policies that allow voting token holders to create actions enforced by delegated token thresholds or collectively approve or disapprove an action through token voting.
9 changes: 9 additions & 0 deletions docs/token-voting/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Llama Token Voting
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use consistent language. I've seen:

  • Llama Token Voting
  • Llama Token Voting Module
  • Llama token voting governor contract
  • llama token voting module factory
  • LlamaTokenVotingFactory
  • Llama Token Voting Factory
  • token governor
  • Llama Token Governor


Llama Token Voting is extensions to Llama instances. They allow token holders to create actions and collectively cast approvals or disapprovals. The `LlamaTokenGovernor` contract follows established token voting framework best practices and is designed to integrate directly with instances.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there is a grammatical error at the start of the sentence here "Llama Token Voting is"


Llama Token Voting consists of two components:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason why we're capitalizing Llama Token Voting here?


- [Token Governor](/docs/token-voting/TokenGovernor.md)

- [Token Voting Factory](/docs/token-voting/Factory.md)
100 changes: 100 additions & 0 deletions docs/token-voting/token-governor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Llama Token Governor

`LlamaTokenGovernor` is the contract that enables token holders to create actions and cast votes/vetoes.

Llama Token Voting works by issuing a Llama policy to the `LlamaTokenGovernor` contract, which can hold roles and permissions that enable the contract to cast approvals/disapprovals and create actions. The Governor contract exposes this policyholder functionality via public functions to token holders.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be more grammatically correct to say the token voting module.

I think it makes sense to capitalize Llama since it's a proper noun and contract names like LlamaTokenGovernor, but I don't see why Governor should be capitalized here


## Voting Periods

There are three distinct periods during a voting cycle:

- The delay period
- The casting period
- The submission period

Llama Token Voting process begins with a delay period. This period is calculated by multiplying the `delayPeriodPct` by the action's approval or disapproval period. The purpose of the delay period is to provide token holders a window to delegate their tokens before voting balances are crystallized for the duration of the vote.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Llama Token Voting process" is a grammatical error as well.


The casting period is when token holders vote/veto a pending action. It is calculated as the product of the `votingPeriodPct` and the action's approval or disapproval period. It automatically begins at the end of the delay period.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's worth adding a sentence that explains that voting occurs doing the approval period and vetoing occurs during the disapproval period.


Finally, the submission period is when the result is submitted to the instance's `LlamaCore` contract if consensus is reached. It is calculated by subtract the `delayPeriodPct` and `votingPeriodPct` from `ONE_HUNDRED_IN_BPS`. It automatically begins at the end of the casting period.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean subtracting instead of subtract here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's easier to just say the submission period is equal to 100% minus the delay and voting period. I wouldn't expect a reader to know what ONE_HUNDRED_IN_BPS is without looking at the code.


## Casting Votes/Vetoes

The `LlamaTokenGovernor` contract allows token holders to participate in the governance process by casting votes/vetoes on actions. This functionality is crucial for the decentralized decision-making process, ensuring that the actions reflect the collective will of the token holders.

### Delay Period

The Llama Token Voting process begins with a delay period. This period is calculated by multiplying the `delayPeriodPct` by the action's approval or disapproval period. The purpose of the delay period is to provide token holders a window to delegate their tokens before voting balances are crystallized for the duration of the token vote.

This checkpoint occurs at the conclusion of the delay period, so any token transfers or delegation updates after the checkpoint will have no affect on this action's token voting process.

### Casting Votes

Token holders can cast their votes during the casting period on actions created within the Llama governance system if the Governor holds the approval or force approval role for the action's strategy. The process of casting a vote involves indicating support or opposition to a particular action. The contract provides the `castVote` function, which requires the following parameters:

```solidity
uint8 role,
ActionInfo actionInfo,
uint8 support,
string reason
```

- Role: This parameter specifies the role of the token holder in the governance process. It is used to determine the permission ID of the `LlamaTokenGovernor`.
- ActionInfo: This struct contains all the necessary information about the action on which the vote is being cast, including the action ID, creator, strategy, target, value, and data.
- Support: Indicates the token holder's stance on the action. The values can be:
- 0 for Against
- 1 for For
- 2 for Abstain
- Reason: A human-readable string providing the rationale behind the token holder's vote.
Comment on lines +42 to +48
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should bold these terms like we do in the llama docs


The function returns the weight of the cast, representing the influence of the token holder's vote based on their token balance.

### Casting Vetoes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the key point to communicate here is that castVote and castVeto are the same but votes occur during the approval period and vetoes occur during the disapproval period


In addition to casting votes, token holders also have the ability to cast vetoes.

The `castVeto` function is similar to castVote and requires the same parameters. The parameters have the same meaning as in the castVote function. The support parameter, in this context, indicates the token holder's stance on vetoing the action.

### Reaching Quorum and Approval

Quorum is calculated using the amount of `For` votes. `Abstain` votes do not count towards the quorum.

Approval is reached when the quorum is met, and the `For` votes surpass the `Against` votes.

### Submitting Results

Once the casting period is over, the result can be submitted.

If the action has not passed, no action needs to be taken.

If the action has passed, anyone now can call the `submitApproval` or `submitDisapproval` function depending on if the action is being voted or vetoed. The submit functions must be called before the end of the submission period, otherwise it expires.

## Creating Actions

Token holders can create actions on the Llama instance if they have a sufficient token balance.

The `creationThreshold` is the number of tokens required to create an action; it can be updated by the token governor's instance.

To create an action, a user must call the `createAction` function which has the following fields:

```solidity
uint8 role,
ILlamaStrategy strategy,
address target,
uint256 value,
bytes data,
string description
```

- Role: The role that will be used to determine the permission ID of the `LlamaTokenGovernor`.
- Strategy: The strategy contract that will determine how the action is executed.
- Target: The contract called when the action is executed.
- Value: The value in wei to be sent when the action is executed.
- Data: Data to be called on the target when the action is executed.
- Description: A human readable description of the action and the changes it will enact.

Note that if the Governor itself does not have the permission to create the action on the instance's `LlamaCore`, `createAction` will fail.

The action creation process is the same as the core Llama system, but instead of creating actions based on the user's policy and permissions the Governor's validation check is based on if they hold enough tokens.
Copy link
Contributor

@AustinGreen AustinGreen Jan 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say something like if they hold more tokens than the creation threshold instead of hold enough tokens


If unfamiliar with the canonical Llama action creation process, our the main [Llama docs](https://github.com/llamaxyz/llama/tree/main/docs) will help.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a typo/grammar mistake here with "our"

27 changes: 27 additions & 0 deletions docs/token-voting/token-voting-factory.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Llama Token Voting Factory

The `LlamaTokenVotingFactory` contract enables the deployment of Llama Token Voting. This factory contract deploys a new `LlamaTokenGovernor` and `LlamaTokenAdapter`. These two contracts comprise Llama Token Voting which is how holders of a specified token can participate in Llama governance.
AustinGreen marked this conversation as resolved.
Show resolved Hide resolved

## Deployment

To Deploy a `LlamaTokenGovernor` and a `LlamaTokenAdapter` through the `LlamaTokenVotingFactory`, a `LlamaTokenVotingConfig` struct is passed to the deploy method on the factory contract.

At deploy time, a `LlamaTokenAdapter` logic contract and config are passed to the factory's deploy function.

### Token Adapters

`LlamaTokenAdapter` allow the `LlamaTokenGovernor` to connect to many different implementations of tokens.
AustinGreen marked this conversation as resolved.
Show resolved Hide resolved

We've implemented a `LlamaTokenAdapter` that works with ERC20 and ERC721 tokens that implement the [IVotes interface](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/governance/utils/IVotes.sol) and checkpoint supply using `block.timestamp`.
AustinGreen marked this conversation as resolved.
Show resolved Hide resolved

Many tokens checkpoint using `block.number`, or have different method names than the `IVotes` interface. The purpose of the adapter is to provide a constant interface for the governor, while being flexible to handle many different token implementations.

Currently only timestamp based tokens are supported, but we can extend functionality to tokens that checkpoint in block number by writing a new adapter.
dd0sxx marked this conversation as resolved.
Show resolved Hide resolved

## Integrating with a Llama instance

A dedicated role and policy with the corresponding role to the `LlamaTokenVotingGovernor` contract.

In order for token holders to approve or disapprove actions, Strategies have to utilize the `LlamaTokenVotingGovernor` as the approval or disapproval role so token holders can vote on certain actions.

Additionally, Permissions can be issued to the governor contract so that policyholders can create certain actions on your Llama instance.
Loading