Merge branch 'master' of github.com:Liqwid-Labs/agora into jhodgdev/github-actions
This commit is contained in:
commit
51da0cf080
21 changed files with 745 additions and 220 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -19,3 +19,4 @@ tags
|
|||
|
||||
# direnv files
|
||||
.envrc
|
||||
.direnv/
|
||||
|
|
|
|||
100
README.md
100
README.md
|
|
@ -1,23 +1,105 @@
|
|||
# `agora`
|
||||
# Agora
|
||||
|
||||
Agora is a set of Plutus scripts that compose together to form a Governance system.
|
||||
Agora is a set of Plutus scripts that compose together to form a governance system.
|
||||
|
||||
### What is Agora
|
||||
|
||||
Goals:
|
||||
- Agora aims to reduce duplication in Liqwid and LiqwidX and to serve as a one-size-fits-all governance library for projects on the Cardano Network.
|
||||
- Agora aims to be modular and allow customizing specific needs, but presents an opinionated architecture.
|
||||
|
||||
- Agora aims to reduce duplication in Liqwid and LiqwidX and to serve as a one-size-fits-all governance library for projects on the Cardano blockchain.
|
||||
- Agora aims to be modular and flexible for specific needs but presents an opinionated architecture.
|
||||
|
||||
Non-goals:
|
||||
- Agora is not a DAO. It doesn't have tokenomics or even a token. It is simply a library for governance.
|
||||
- Agora doesn't aim to provide any primitive tools for plutus that are not governance-specific. For this, see [plutus-extra](https://github.com/Liqwid-Labs/plutus-extra/).
|
||||
|
||||
- Agora is not a DAO. It doesn't have tokenomics or even a token. It is simply a library for governance.
|
||||
- Agora doesn't aim to provide any primitive tools for Plutus that are not governance-specific. For this, see [plutus-extra](https://github.com/Liqwid-Labs/plutus-extra/).
|
||||
|
||||
## Project setup
|
||||
|
||||
An up to date `nix` (>=2.3) is required to build this project. For information on how to install, see the [nixos website](https://nixos.org/download.html). Important: See also [this section](https://github.com/input-output-hk/plutus#nix-advice) on binary caches.
|
||||
An up to date version of the [Nix package manager](nixos.org) (>=2.3) is required to build this project. For information on how to install, see the [NixOS website](https://nixos.org/download.html). Important: see also [this section](https://github.com/input-output-hk/plutus#nix-advice) on binary caches.
|
||||
|
||||
Open a dev-shell with `nix develop`, and build with `cabal build`.
|
||||
Open a development shell with `nix develop` and build the project with `cabal build`. Those pained by the need to remember to enter a Nix shell may consider using [nix-direnv](https://github.com/nix-community/nix-direnv).
|
||||
|
||||
## Documentation
|
||||
|
||||
See documentation of the agora architecture in [docs](./docs).
|
||||
Documentation for Agora may be found in [docs](./docs).
|
||||
|
||||
## Road-map
|
||||
|
||||
### v1
|
||||
|
||||
- [ ] Governor
|
||||
- [ ] Treasury
|
||||
- [ ] Staking pool
|
||||
- [ ] Proposals
|
||||
- [ ] Effects
|
||||
|
||||
### v2
|
||||
|
||||
- [ ] Rewards distribution
|
||||
- [ ] Escrow staking pool solution
|
||||
|
||||
### Beyond
|
||||
|
||||
- [ ] ...
|
||||
|
||||
|
||||
# Governance concepts
|
||||
|
||||
This section seeks to introduce to the reader the concept of governance systems on Cardano and acquaint them with the core components of a generic governance system.
|
||||
|
||||
## Simple questions, simple answers
|
||||
|
||||
### Q: What's a 'governance'?
|
||||
|
||||
A: A _governance system_ is a component of a Cardano system, that allows for its community to issue and vote on proposals.
|
||||
|
||||
### Q: What can be proposed?
|
||||
|
||||
A: That depends on the Cardano protocol in-question. An example for a proposal could suggest that funds be released from a community treasury. Another might propose an alteration to some parameter in the wider-system.
|
||||
|
||||
### Q: Who can vote?
|
||||
|
||||
A: The right to vote is conferred by the _staking_ of some designated _governance token_ (GT). If one owns the relevant token, they may 'stake' some of it to vote in favour of, or opposition to, some proposal.
|
||||
|
||||
## Overview of components
|
||||
|
||||
<p align="center">
|
||||
<img src="/docs/diagrams/gov-overview.svg"/>
|
||||
</p>
|
||||
|
||||
More-detailed information on individual components will be included in their own, specific documentation. This section provides brief descriptions on the purpose of each component.
|
||||
|
||||
### Users
|
||||
|
||||
A user is a member of the DAO (decentralised autonomous organisation), who
|
||||
may choose to redeem governance tokens (GT) from the treasury and stake those GT
|
||||
to vote in favour of, or opposition to, proposals.
|
||||
|
||||
### Governance tokens
|
||||
|
||||
Governance tokens (GTs) are a currency, which confer the right to vote on proposals.
|
||||
|
||||
### Treasury
|
||||
|
||||
The treasury of a governance system is responsible for determining which users are entitled to what GT rewards and when. If a user is eligible for a reward, it they must claim it from the treasury. A treasury can also serve as a form of 'DAO wallet', storing and saving funds that can be later spent by the community.
|
||||
|
||||
### Stakes
|
||||
|
||||
Users are required to 'lock' their GT in stakes, so that the system has some idea of their eligibility to vote on proposal.
|
||||
|
||||
### Staking pool
|
||||
|
||||
A staking pool can be introduced, for the purpose of tracking the aggregate status of all stakes in the system. Some systems may not require a staking pool.
|
||||
|
||||
### Proposal
|
||||
|
||||
A proposal suggests for some specified changes to be made to a Cardano system. It is voted upon by the community and, if passed, its effects are applied to the system.
|
||||
|
||||
### Effects
|
||||
|
||||
Proposals may have one or many 'effects', which represent the concrete, individual changes the proposal would make to the system. If their corresponding proposals have been passed, each effect is granted a _governance authority token_ (GAT) by the governor. This token permits the effect to alter the system.
|
||||
|
||||
### Governor
|
||||
|
||||
The governor is responsible for validating whether proposals have passed. If they have, it issues GATs to the proposals' effects.
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ common deps
|
|||
, serialise
|
||||
, template-haskell
|
||||
, text
|
||||
, plutus-extra
|
||||
|
||||
common test-deps
|
||||
build-depends:
|
||||
|
|
|
|||
|
|
@ -1,19 +1,21 @@
|
|||
# Agora specification & documentation
|
||||
# Agora specification and documentation
|
||||
|
||||
This folder contains all of the specification and architecture documentation of agora.
|
||||
This folder contains documents explaining the conceptual background and technical implementation of Agora components.
|
||||
|
||||
## Technical design
|
||||
|
||||
The `tech-design/` subdirectory contains high level description of architecture involved in building agora's governance system.
|
||||
The `tech-design/` subdirectory contains high level descriptions of the architecture of Agora's governance solution.
|
||||
|
||||
## Implementation
|
||||
## Plutarch
|
||||
|
||||
Agora makes extensive use of plutarch. So it's prerequisite for understanding the implementation. Plutarch features an [_extensive_ guide](https://github.com/Plutonomicon/plutarch/blob/master/docs/GUIDE.md), which explains many intricacies of plutarch and its use.
|
||||
Agora makes extensive use of [Plutarch](https://github.com/plutonomicon/plutarch). One unfamiliar with the library will be unable to suitably understand the technical parts of this documentation. The maintainers provide an extensive [guide](https://github.com/Plutonomicon/plutarch/blob/master/docs/GUIDE.md) that will familiarise the developer with the language and thereby this set of documentation.
|
||||
|
||||
## Glossary
|
||||
|
||||
The following is a list of words/shorthands that are frequently used:
|
||||
The following is a list of terms that are used frequently throughout the documentation:
|
||||
|
||||
- **Governance Token (GT)**: The token that holds value within the protocol and is used for voting, rewards, etc. _Examples: Liqwid's LQ_.
|
||||
- **Authority Token (GAT)**: A token that delegates authority of a particular script / token. See [tech-design/authority-token.md](./tech-design/authority-tokens.md)
|
||||
- **Effect**: The result of a proposal, enforced by an effect script.
|
||||
- **DAO**: decentralised autonomous organisation.
|
||||
- **Proposal**: a set of changes to a Cardano protocol, suggested by a community member. Will be enacted, if passed by the community.
|
||||
- **Governance token (GT)**: the token that confers the right to vote on proposals within the protocol. May affect the user's eligibility for rewards. Examples include Liqwid's LQ.
|
||||
- **Governance authority token (GAT)**: A token that grant's the effects of a proposal the authority to alter the system. More information can be read [here](./tech-design/authority-tokens.md).
|
||||
- **Effect**: A script for implementing changes suggested by a proposal. An effect can make numerous changes and a proposal may have multiple effects.
|
||||
|
|
|
|||
3
docs/diagrams/README.md
Normal file
3
docs/diagrams/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Diagrams
|
||||
|
||||
This directory is for diagram source files (.dot) and output files (.svg, .png), which will be referenced throughout the documentation.
|
||||
8
docs/diagrams/gov-overview.dot
Normal file
8
docs/diagrams/gov-overview.dot
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
digraph {
|
||||
"Staking pool" -> Stakes [label="tracks"]
|
||||
Stakes -> Proposals [label="are put on"]
|
||||
Proposals -> Effects [label="have"]
|
||||
Governor -> Effects [label="issues GATs to"]
|
||||
Users -> Stakes [label="lock GT in"]
|
||||
Users -> Treasury [label="claim GT from"]
|
||||
}
|
||||
96
docs/diagrams/gov-overview.svg
Normal file
96
docs/diagrams/gov-overview.svg
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.48.0 (0)
|
||||
-->
|
||||
<!-- Pages: 1 -->
|
||||
<svg width="334pt" height="305pt"
|
||||
viewBox="0.00 0.00 333.89 305.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 301)">
|
||||
<polygon fill="white" stroke="transparent" points="-4,4 -4,-301 329.89,-301 329.89,4 -4,4"/>
|
||||
<!-- Staking pool -->
|
||||
<g id="node1" class="node">
|
||||
<title>Staking pool</title>
|
||||
<ellipse fill="none" stroke="black" cx="68.89" cy="-279" rx="68.79" ry="18"/>
|
||||
<text text-anchor="middle" x="68.89" y="-275.3" font-family="Times,serif" font-size="14.00">Staking pool</text>
|
||||
</g>
|
||||
<!-- Stakes -->
|
||||
<g id="node2" class="node">
|
||||
<title>Stakes</title>
|
||||
<ellipse fill="none" stroke="black" cx="94.89" cy="-192" rx="42.49" ry="18"/>
|
||||
<text text-anchor="middle" x="94.89" y="-188.3" font-family="Times,serif" font-size="14.00">Stakes</text>
|
||||
</g>
|
||||
<!-- Staking pool->Stakes -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>Staking pool->Stakes</title>
|
||||
<path fill="none" stroke="black" d="M66.77,-260.91C66.15,-251.05 66.4,-238.55 69.89,-228 71.09,-224.39 72.81,-220.82 74.78,-217.43"/>
|
||||
<polygon fill="black" stroke="black" points="77.8,-219.21 80.45,-208.95 71.98,-215.32 77.8,-219.21"/>
|
||||
<text text-anchor="middle" x="92.39" y="-231.8" font-family="Times,serif" font-size="14.00">tracks</text>
|
||||
</g>
|
||||
<!-- Proposals -->
|
||||
<g id="node3" class="node">
|
||||
<title>Proposals</title>
|
||||
<ellipse fill="none" stroke="black" cx="94.89" cy="-105" rx="55.79" ry="18"/>
|
||||
<text text-anchor="middle" x="94.89" y="-101.3" font-family="Times,serif" font-size="14.00">Proposals</text>
|
||||
</g>
|
||||
<!-- Stakes->Proposals -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>Stakes->Proposals</title>
|
||||
<path fill="none" stroke="black" d="M94.89,-173.8C94.89,-162.16 94.89,-146.55 94.89,-133.24"/>
|
||||
<polygon fill="black" stroke="black" points="98.39,-133.18 94.89,-123.18 91.39,-133.18 98.39,-133.18"/>
|
||||
<text text-anchor="middle" x="131.89" y="-144.8" font-family="Times,serif" font-size="14.00">are put on</text>
|
||||
</g>
|
||||
<!-- Effects -->
|
||||
<g id="node4" class="node">
|
||||
<title>Effects</title>
|
||||
<ellipse fill="none" stroke="black" cx="158.89" cy="-18" rx="42.79" ry="18"/>
|
||||
<text text-anchor="middle" x="158.89" y="-14.3" font-family="Times,serif" font-size="14.00">Effects</text>
|
||||
</g>
|
||||
<!-- Proposals->Effects -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>Proposals->Effects</title>
|
||||
<path fill="none" stroke="black" d="M107.54,-87.21C116.89,-74.79 129.78,-57.67 140.3,-43.7"/>
|
||||
<polygon fill="black" stroke="black" points="143.27,-45.56 146.49,-35.47 137.68,-41.35 143.27,-45.56"/>
|
||||
<text text-anchor="middle" x="147.89" y="-57.8" font-family="Times,serif" font-size="14.00">have</text>
|
||||
</g>
|
||||
<!-- Governor -->
|
||||
<g id="node5" class="node">
|
||||
<title>Governor</title>
|
||||
<ellipse fill="none" stroke="black" cx="222.89" cy="-105" rx="53.89" ry="18"/>
|
||||
<text text-anchor="middle" x="222.89" y="-101.3" font-family="Times,serif" font-size="14.00">Governor</text>
|
||||
</g>
|
||||
<!-- Governor->Effects -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>Governor->Effects</title>
|
||||
<path fill="none" stroke="black" d="M210.25,-87.21C200.9,-74.79 188.01,-57.67 177.49,-43.7"/>
|
||||
<polygon fill="black" stroke="black" points="180.11,-41.35 171.29,-35.47 174.51,-45.56 180.11,-41.35"/>
|
||||
<text text-anchor="middle" x="246.89" y="-57.8" font-family="Times,serif" font-size="14.00">issues GATs to</text>
|
||||
</g>
|
||||
<!-- Users -->
|
||||
<g id="node6" class="node">
|
||||
<title>Users</title>
|
||||
<ellipse fill="none" stroke="black" cx="212.89" cy="-279" rx="38.19" ry="18"/>
|
||||
<text text-anchor="middle" x="212.89" y="-275.3" font-family="Times,serif" font-size="14.00">Users</text>
|
||||
</g>
|
||||
<!-- Users->Stakes -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>Users->Stakes</title>
|
||||
<path fill="none" stroke="black" d="M185.75,-266.08C173.12,-259.97 158.21,-251.95 145.89,-243 135.34,-235.33 124.85,-225.52 116.15,-216.63"/>
|
||||
<polygon fill="black" stroke="black" points="118.44,-213.96 109.01,-209.12 113.37,-218.78 118.44,-213.96"/>
|
||||
<text text-anchor="middle" x="181.89" y="-231.8" font-family="Times,serif" font-size="14.00">lock GT in</text>
|
||||
</g>
|
||||
<!-- Treasury -->
|
||||
<g id="node7" class="node">
|
||||
<title>Treasury</title>
|
||||
<ellipse fill="none" stroke="black" cx="231.89" cy="-192" rx="51.99" ry="18"/>
|
||||
<text text-anchor="middle" x="231.89" y="-188.3" font-family="Times,serif" font-size="14.00">Treasury</text>
|
||||
</g>
|
||||
<!-- Users->Treasury -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>Users->Treasury</title>
|
||||
<path fill="none" stroke="black" d="M216.74,-260.8C219.34,-249.16 222.83,-233.55 225.81,-220.24"/>
|
||||
<polygon fill="black" stroke="black" points="229.29,-220.7 228.05,-210.18 222.46,-219.17 229.29,-220.7"/>
|
||||
<text text-anchor="middle" x="274.89" y="-231.8" font-family="Times,serif" font-size="14.00">claim GT from</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
3
docs/meta/README.md
Normal file
3
docs/meta/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Docs meta
|
||||
|
||||
This folder includes notes to assist in the writing of documentation. Those not involved with spec writing have no need for these files.
|
||||
119
docs/meta/status-format.md
Normal file
119
docs/meta/status-format.md
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
# Spec status format
|
||||
|
||||
This document specifies a format used to denote the 'status' of a spec document.
|
||||
|
||||
## Overview
|
||||
|
||||
Each specification document should be headed by a simple table outlining aspects of its status in relation to:
|
||||
|
||||
- Authorship: who has contributed to it?
|
||||
- Ownership: who is responsible for it?
|
||||
- Implementation(s): where is it used?
|
||||
- Completeness: is it done yet?
|
||||
|
||||
This format should be used at the start of any documentation that may be considered a _technical specification_, with a related implementation.
|
||||
|
||||
## Format
|
||||
|
||||
The format is as follows, with {substitutions} in curly braces.
|
||||
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-------------:|:--------------:|:-------------:|
|
||||
| {status} | {status} | {version} {date} |
|
||||
|
||||
--------------------
|
||||
|
||||
**Specification ownership:** {[Spec owner]}
|
||||
|
||||
**Authors**:
|
||||
- {[Spec owner]}
|
||||
- {[Author]}
|
||||
|
||||
**Implementation ownership:** {[Impl owner]}
|
||||
|
||||
**Current status**:
|
||||
|
||||
{Short description of status regarding __both__ specification and implementation}.
|
||||
|
||||
[Spec owner]: https://genrandom.com/cats/
|
||||
[Author]: https://genrandom.com/cats/
|
||||
[Impl owner]: https://genrandom.com/cats/
|
||||
|
||||
```markdown
|
||||
| Specification | Implementation | Last Revision |
|
||||
|:-------------:|:--------------:|:-------------:|
|
||||
| {status} | {status} | {version}, {date} |
|
||||
|
||||
--------------------
|
||||
|
||||
**Specification ownership:** [{owner name}]
|
||||
|
||||
**Authors**:
|
||||
- [{owner name}]
|
||||
- [{author name}]
|
||||
|
||||
|
||||
**Implementation ownership:** [{impl owner name}]
|
||||
|
||||
**Current status**:
|
||||
|
||||
{Short description of status}
|
||||
|
||||
[{owner name}]: {github url}
|
||||
[{author name}]: {github url}
|
||||
[{impl owner name}]: {github url}
|
||||
|
||||
--------------------
|
||||
```
|
||||
|
||||
### Specification/Implementation status
|
||||
|
||||
The 'Specification' and 'Implementation' status should be one of the following:
|
||||
|
||||
- `WIP`: Work In Progress, currently incomplete, pending current or future work by the current owner or a future owner.
|
||||
- `Draft`: Complete but pending further evaluation or changes to be accounted for in the future.
|
||||
- `Final`: Complete and finalised to some degree of certainty.
|
||||
|
||||
### Last revision
|
||||
|
||||
- version - An optional version/revision number for the spec document.
|
||||
- date - date the document was last updated in [ISO 8601 format](https://www.wikiwand.com/en/ISO_8601#/Calendar_dates) (YYYY-MM-DD).
|
||||
|
||||
### Authors
|
||||
|
||||
The authors and contributors of the spec document.
|
||||
|
||||
### Specification ownership
|
||||
|
||||
The person currently, or most recently tasked with writing and maintaining the spec document.
|
||||
|
||||
### Implementation ownership
|
||||
|
||||
The person currently or most recently tasked with the implementation of the features described in the document.
|
||||
|
||||
- For individual features, this will be the person most recently assigned to related GitHub issues.
|
||||
- For broader sections, this will be a person leading the implementation efforts for the particular system.
|
||||
|
||||
## Example
|
||||
|
||||
| Specification | Implementation | Last Revision |
|
||||
|:-------------:|:--------------:|:-------------:|
|
||||
| WIP | Draft | 0.1 2022-01-31 |
|
||||
|
||||
--------------------
|
||||
|
||||
**Specification ownership:** [Jack Hodgkinson]
|
||||
|
||||
**Authors**:
|
||||
- [Jack Hodgkinson]
|
||||
- [Emily Martins]
|
||||
|
||||
**Implementation ownership:** [Emily Martins]
|
||||
|
||||
**Current status**:
|
||||
|
||||
Draft completed in project repo. Spec needs revisiting to address issues outlined in #42. Section on staking pool behaviour is out-dated.
|
||||
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
[Emily Martins]: https://github.com/emiflake
|
||||
***
|
||||
52
docs/meta/style-guide.md
Normal file
52
docs/meta/style-guide.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Agora docs style guide
|
||||
|
||||
This document includes a couple of notes on how Agora documentation should be written and formatted.
|
||||
|
||||
## British/American spelling and grammatical differences
|
||||
|
||||
The difference between British and American English is wider than a lot of people presume. Authors are permitted to use whichever of the two they learned and therefore feel more comfortable with. The only exception to this is when writing changes that would result in a 'mixing' of styles e.g. having 'color' in a sentence and 'colour' in the next. In this instance please alter your use of the language to maintain consistency.
|
||||
|
||||
## Capitalised words
|
||||
|
||||
The following words should always in the forms below:
|
||||
|
||||
- Agora
|
||||
- Liqwid
|
||||
- LiqwidX
|
||||
- Nix
|
||||
- NixOS
|
||||
- Plutus
|
||||
- Plutarch
|
||||
|
||||
Sensible exceptions naturally exist, including referencing shell commands (`nix-shell`) or code:
|
||||
|
||||
```haskell
|
||||
plutarchTerm :: Term s a
|
||||
plutarchTerm = ...
|
||||
```
|
||||
|
||||
## Upper-case terms
|
||||
|
||||
The following terms should always be rendered in all capital letters:
|
||||
|
||||
- UTXO
|
||||
- EUTXO
|
||||
|
||||
## Lower-case words
|
||||
|
||||
The following words should always be rendered lower-case (unless used at the beginning of a sentence):
|
||||
|
||||
- governance
|
||||
|
||||
## ADA, Ada, ada
|
||||
|
||||
Cardano's native token suffers from a frustrating variety of acceptable forms. Reputable sources can be found using all three variants listed in the header. As such, no usage shall be mandated with two caveats:
|
||||
|
||||
1. Whilst the name of the currency is subject to variance, its 'symbol' is unambiguously 'ADA'. Therefore when talking about amounts e.g. 'Trillian deposits 100ADA', use 'ADA'.
|
||||
2. Exercise _reasonable consistency_. The use of an 'Ada' at the beginning of the document and an 'ada' 3000 words later is not something worth losing sleep over. Inconsistency within paragraphs or (gasp!) _sentences_ should always be avoided.
|
||||
|
||||
## Avoid
|
||||
|
||||
The following practices should be avoided:
|
||||
|
||||
- The use of '&' apart from in proper nouns such as AT\&T.
|
||||
|
|
@ -1,52 +1,80 @@
|
|||
# Authority token technical design
|
||||
|
||||
| Spec Status | Impl Status | Last Revision |
|
||||
|-------------|-------------|---------------|
|
||||
| WIP | WIP | 2022-01-18 |
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-----------:|:-----------:|:-------------:|
|
||||
| WIP | WIP | 2022-02-02 |
|
||||
|
||||
--------------------
|
||||
***
|
||||
|
||||
**Spec Ownership:** [@Emily Martins]
|
||||
**Specification owner:** [Emily Martins]
|
||||
|
||||
**Authors**: [@Emily Martins]
|
||||
**Authors**:
|
||||
|
||||
**Impl Owner:** [@Emily Martins]
|
||||
- [Emily Martins]
|
||||
- [Jack Hodgkinson]
|
||||
|
||||
[@Emily Martins]: https://github.com/emiflake
|
||||
**Implementation owner:** [Emily Martins]
|
||||
|
||||
--------------------
|
||||
[Emily Martins]: https://github.com/emiflake
|
||||
|
||||
## Authority Tokens
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
|
||||
In order to allow proposals to have a large number of potential effects, and to be extensible for different applications of governance, it is useful to have the effects be decided at a later time. In Ethereum systems, often times this is done by encoding some untyped data and calls to specific contract hashes. Compound encodes it with `address[] Proposal.targets` (the contracts to be called) and `bytes[] Proposal.calldatas` (the data to be passed). Of course, this doesn't quite translate to Cardano's EUTXO model, so we need to achieve this some different way.
|
||||
[Peter Dragos]: https://github.com/peter-mlabs
|
||||
|
||||
In order to allow this flexibility, there are two facts that we rely on:
|
||||
- We trust the community to validate the proposal entirely, including whether or not the effects encoded in it are written correctly. (This may mean we have a set of known and trusted effects we agree are correct and safe, collectively)
|
||||
- The effects are given authority only after the proposal that promises them succeeds.
|
||||
**Current status:**
|
||||
|
||||
To achieve the former is rather simple, the effect validator's source code is available for anyone to look at, and it hashes correctly to the hash stored in the proposal itself. So, the LQ holders can decide on whether it is a positive for the system.
|
||||
Initially written up by [Emily Martins] for Liqwid. Transferred across to Agora. Rewritten by [Jack Hodgkinson]. Outstanding suggestions from [Peter Dragos] that require addressing.
|
||||
|
||||
In order to achieve the latter, we must introduce some way to give effects authority to perform their actions.
|
||||
***
|
||||
|
||||
We do this by handing out "Governance Authority Tokens" (GATs) to each of the the effects belonging to a proposal after the proposal passes. When these authority tokens are *burned*, they act as a way of saying "the DAO validated this, so trust that I will ensure this transaction is correct".
|
||||
## Authority tokens
|
||||
|
||||
The components that need to be adjustable at a later point, will need to allow this as means for proving authority and validation of a transaction. So, for example, a Liqwid Market might need to have its parameters updated, the following diagram shows how this would happen after a proposal has successfully been voted on and passed:
|
||||
In the spirit of extensibility, a governance system should be able to readily expand the effects proposals can have on their protocol. With Ethereum systems, this is often done with untyped data and references to specific contract hashes. [Compound](https://medium.com/compound-finance/compound-governance-5531f524cf68) encodes an array of the contracts' addresses (`address[] Proposal.targets`) and the data to be passed to them (`bytes[] Proposal.calldatas`). This does not translate to Cardano's EUTXO model, so we require an alternative approach.
|
||||
|
||||

|
||||
Our approach relies on two core assumptions:
|
||||
|
||||
As a result of this approach, there's a number of benefits, but also details we need to watch out for:
|
||||
- We trust the community to thoroughly assess the effects of a proposal. This ensures that the effects are safe and will work as intended.
|
||||
|
||||
#### Handling multiple effects in a single Proposal
|
||||
- The effects of a proposal may only alter the system, after their associated proposal has been passed by the community.
|
||||
|
||||
Handling multile effects this way is very doable. For one, a single effect can do multiple things at once, if the script sizes allow it. But another point is that a proposal can have a *list* of hashes that it distributes GATs to. And this is all without growing size almost at all, because the actual effects are encoded in their scripts.
|
||||
The first assumption is justified by the fact that any proposal stores the hash of its effects' codes, and these effects are available for any user to inspect. The community of GT-holders will be able to verify a proposal's purported benefits.
|
||||
|
||||
There is the concern of expiration date of effects and incomplete execution now, however. But the customizability allows for failsafes (like retrying) and encoding expiration correctly. Due to the nature of these effects being handled by the DAO, it's assumed no conflicting effects will be executed in short succession. This is essentially impossible to encode in the system itself, so this tradeoff must be taken.
|
||||
To ensure the latter assumption holds true, we introduce 'governance authority tokens' (GATs). Any effect that wishes to alter the system will be required to _burn_ a GAT, when it is enacted. These GATs will be issued to a proposal's effects via the governor component, which has the responsibility of ensuring that a proposal passed in a correct and valid manner. Conceptually, the ownership of a GAT by an effect is a way of demonstrating to a component: 'the DAO (decentralised autonomous organisation) has granted me permission to alter your parameters'.
|
||||
|
||||
#### Writing effect code needs a *lot* of care
|
||||
> The components that need to be adjustable at a later point will need to allow this as means for proving authority and validation of a transaction. So, for example, a Liqwid market might need to have its parameters updated, the following diagram shows how this would happen after a proposal has successfully been voted on and passed:
|
||||
|
||||
Having delegated the authority of *the entire system* in a single token is a lot of power for one tiny script. And with great power comes great responsibility. It is important that this token doesn't fall into the wrong hands or is executed in a way that was unexpected (by the community). There's a few things we can do to help mitigate this:
|
||||
This model naturally requires that any component of the system, desired to be adjustable via governance is aware of the existence and significance of GATs. For example, a [Liqwid](https://github.com/mlabs-haskell/liqwid-contracts/) market may be subject to the effects of a successful proposal to alter its parameters. The following diagram shows how such an update would occur:
|
||||
|
||||
- We write the validator with the transaction in mind specified out in fullest. No extra inputs, no extra outputs, no extra mints, etc. Essentially this is the opposite of what we do in other places, where we try to be only as specific as we need.
|
||||
- We have the transaction be executed by one of a number of community trusted members. This of course is something that is encoded in the effect, rather than anywhere else.
|
||||

|
||||
|
||||
Hopefully, this is sufficient to ensure the transactions are created correctly, and nothing unexpected slips in. This problem is no more complicated or dangerous than elsewhere where we delegate certain trust or authority to just the validation or movement of a token.
|
||||
> Peter, 2022-01-24: You should add a link to what conventions you're following for you UTXO flows to the README
|
||||
|
||||
> Peter 2022-01-24: I think I see what's going on here, but it could use some annotations/additional description.
|
||||
> Tx1, a.) A proposal is closed via Tx1, and the transaction emits a continuing `Proposal` and `Governance` UtXO,
|
||||
> along with an "Effect" UTxO (presumably identified in the content of the proposal). The Effect UTxO encodes effect `f` in it's validation logic.
|
||||
> Question: where is this effect encoded?
|
||||
> Tx1, b.) In the same transaction, a GAT is minted and paid to the UTxO.
|
||||
> Tx1, c.) The `min utxo` ADA is paid to the Effect UTxO from "user inputs". I'm not certain where this is, but I'm assuming it's accumulated during voting or something? What is it used for?\
|
||||
> Tx2, a.) The Effect UTxO and the component to be governed are consumed in transaction 2.\
|
||||
> Tx2, b.) The Market's usual validation logic is short-circuited since the GAT was burned, and the continuing Market UTxO updates its datum.
|
||||
> Tx2, c.) There is a continuing "Effect" UTxO; presumably, this serves as a proof that an effect has taken place? Meaning that a sequence of effects that require a particular order of execution can consume the output UTxO as a witness?
|
||||
> Tx2, d.) The min ADA is paid to "user outputs"; is this just "collateral" to make sure that the effect is executed in a timely fashion?
|
||||
|
||||
This approach has a number of benefits but some important details must be kept in mind:
|
||||
|
||||
#### Handling multiple effects in a single proposal
|
||||
|
||||
Cardano script sizes are restricted to 16KB and previous proposal/effect models have had difficulties generating scripts which keep under this limit. By decoupling proposals and their effects, a proposal can have a far greater number of effects, as all it contains is a list of hashes for said effects. Effects themselves can make any number of changes to the system, as long as the resulting script is kept to an allowable size.
|
||||
|
||||
It is essentially impossible for the system to prevent conflicting effects taking place in short order and harming the system but the likelihood of this occurring is sufficiently reduced by all effects first having be passed by the DAO. There is scope for adding a notion of 'expiration', after which effects will no longer be able to enact their changes.
|
||||
|
||||
#### Writing effect code requires a _lot_ of care
|
||||
|
||||
The ability to alter large swathes of the system being conferred by the ownership of a single token poses the risk of (purposeful or inadvertent) harm. There are steps one can take to lessen this risk:
|
||||
|
||||
- All validators for an effect transaction are specified **in full**. In comparison to the normal writing of validators, where one only specifies what they must, one must do all they can to avoid undesired behaviour being permitted by the validator.
|
||||
- All transactions are only executed by one of a few 'trusted' DAO members. This would necessarily have to be encoded in the effect.
|
||||
|
||||
This should be sufficient to prevent loopholes. Delegating authority through validation or movement of tokens is often a necessary risk in blockchain systems and this problem is no more complex than others of its kind.
|
||||
|
||||
There is scope for expanding GATs to make them more restrictive and therefore less dangerous. One proposal is to store the hash of the effect script within the GAT, thus allowing for the minting of 'bespoke GATs', which are only authorised to make changes allowed for in the effect hash.
|
||||
|
|
|
|||
53
docs/tech-design/effects.md
Normal file
53
docs/tech-design/effects.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Effects technical design
|
||||
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-----------:|:--------------:|:-------------:|
|
||||
| WIP | WIP | v0.1 2022-02-03 |
|
||||
|
||||
---
|
||||
|
||||
**Specification ownership:** [Jack Hodgkinson]
|
||||
|
||||
**Authors**:
|
||||
|
||||
- [Jack Hodgkinson]
|
||||
|
||||
**Implementation ownership:** _unassigned_
|
||||
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
|
||||
**Current Status**:
|
||||
|
||||
First draft of effect article. Subject to review from @emiflake.
|
||||
|
||||
---
|
||||
|
||||
[Proposals](proposals.md) in a governance system are necessarily going to perform some actions or alter some parameters (otherwise, what's the point?). Due to script size limitations on Cardano, it is difficult to encapsulate all of a proposal's effects alongside other necessary information, such as vote counts. Rather than be constrained by such limitations, Agora _decouples_ proposals from their effects.
|
||||
|
||||
Effects will exist as their own scripts on the blockchain and proposals will simply include a list of an effect's hashes. This way, users are still able to identify the changes a given proposal would make to the system and thereby assess the proposal's desirability.
|
||||
|
||||
A proposal's effects will be initiated by the community, whom we assume will have sufficient incentive to pay the required transaction fee. However, if these effects are independent scripts, sitting there waiting to be initiated, how can we trust community members to only activate the effects of _passed_ proposals?
|
||||
|
||||
We don't. Effects will be _unable_ to alter the system without burning [_governance authority tokens_ (GATs)](authority-tokens.md). These are bestowed upon an effect, via the [governor](governor.md), if their associated proposal has been passed by the community.
|
||||
|
||||
All 'governable' components of a system must be able to interface with effects and allow them to make necessary changes, so long as they are in possession of a GAT.
|
||||
|
||||
## What can an effect _be_?
|
||||
|
||||
The range of powers an effect may have is at the discretion of the protocol maker. For usability purposes, Agora might offer a _buffet approach_ as an option for proposals and effects.
|
||||
|
||||
<p align="center">
|
||||
<img height=300 src="https://images.unsplash.com/photo-1583338917496-7ea264c374ce?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1740&q=80" alt="Get the effects, whilst they're hot!"/>
|
||||
</p>
|
||||
|
||||
In this model, a proposal is defined by the _combination_ of _effect templates_, in much the same way a diner's meal at a buffet is defined by which dishes they choose.
|
||||
|
||||
Conceiving of proposals this way makes them only marginally less powerful, as users will be able to combine effects in such a way as to render the desired effect. It does however prevent a user wishing to issue a proposal from having to construct their effects from whole cloth.
|
||||
|
||||
Whilst Agora may offer this functionality, there is nothing stopping DAO members from writing their own effect code.
|
||||
|
||||
## The issue of partial execution
|
||||
|
||||
An anticipated problem with this model is the danger of 'partial execution'. The model relies on the assumption that desired effects will be processed by community members, as they are seen as desirable.There could however be an issue, if users deem some effects as more desirable than others. If the effects of a proposal are not executed **in their entirety**, this may lead to unanticipated and undesirable outcomes.
|
||||
|
||||
This should not be a major limitation in the system, as community members _should_ recognise the necessity to implement the proposal in its entirety. However, one might consider _incentivising effect execution_ to prevent such an occurrence.
|
||||
25
docs/tech-design/governor.md
Normal file
25
docs/tech-design/governor.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Governor technical design
|
||||
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-----------:|:--------------:|:-------------:|
|
||||
| WIP | WIP | v0.1 2022-02-03 |
|
||||
|
||||
---
|
||||
|
||||
**Specification ownership:** [Jack Hodgkinson]
|
||||
|
||||
**Authors**:
|
||||
|
||||
- [Jack Hodgkinson]
|
||||
|
||||
**Implementation ownership:** _unassigned_
|
||||
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
|
||||
**Current Status**:
|
||||
|
||||
First draft. Subject to review by @emiflake.
|
||||
|
||||
---
|
||||
|
||||
The governor is a simpler component than others in the system but still provides an invaluable role. Firstly, it acts as a repository for all the governance parameters e.g. the duration of proposal phases or GT thresholds. Secondly, and perhaps most importantly, it verifies whether proposals have passed legally and, if they have, grants their [effects](effects.md) powerful [governance authority tokens](authority-tokens.md).
|
||||
|
|
@ -1,81 +1,86 @@
|
|||
# Proposals Technical Design
|
||||
# Proposals technical design
|
||||
|
||||
This document gives an overview of technical design aspects of the Proposals system for introducing, voting on and executing Governance Proposals.
|
||||
This document gives an overview of the technical design of the proposals system for introducing, voting on and executing governance proposals.
|
||||
|
||||
| Spec Status | Impl Status | Last Revision |
|
||||
|-------------|-------------|---------------|
|
||||
| WIP | WIP | 2022-01-19 |
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-----------:|:-----------:|:-------------:|
|
||||
| WIP | WIP | v0.1 2022-02-02 |
|
||||
|
||||
--------------------
|
||||
---
|
||||
|
||||
**Spec Ownership:** [@Emily Martins]
|
||||
**Specification ownership:** [Emily Martins]
|
||||
|
||||
**Authors**: [@Emily Martins]
|
||||
**Authors**:
|
||||
|
||||
**Impl Owner:** [@Emily Martins]
|
||||
- [Emily Martins]
|
||||
- [Jack Hodgkinson]
|
||||
|
||||
[@Emily Martins]: https://github.com/emiflake
|
||||
**Implementation ownership:** [Emily Martins]
|
||||
|
||||
--------------------
|
||||
[Emily Martins]: https://github.com/emiflake
|
||||
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
|
||||
**Current status**:
|
||||
|
||||
Imported from Liqwid by [Emily Martins]. Underwent rewrite by [Jack Hodgkinson].Further amendments to the 'period table' should be considered.
|
||||
|
||||
---
|
||||
|
||||
## Proposals
|
||||
|
||||
Initiating a proposal requires you to have more than a certain amount of LQ in the StakingPool (e.g. around 6-10 LQ). This is checked by consuming the proposer's stake utxo. Creating a proposal forges a proposal script state thread which is where all voting interactions happen with. Proposals are tracked in coordination with the governance, so it must be included in the transaction as well.
|
||||
Initiating a proposal requires the proposer to have more than a certain amount of GT staked in the system e.g. 5GT. This is checked by consuming the UTXO representing the user's stake. Initiating a proposal creates a script, which will handle all voting interactions.
|
||||
|
||||
### Proposal voting
|
||||
## Voting
|
||||
|
||||
##### Overview of stages
|
||||
### Voting stages
|
||||
|
||||
A proposal fits into a state machine neatly. Draft being the starting state, and Executed or Failed being the final states. It should be noted that, for optimization reasons, not all states are exactly physical, instead, the current state is a product of the current time as well. For instance, after the voting has ended, no state transition on-chain occurs.
|
||||
The life-cycle of a proposal is neatly represented by a state machine, with the 'draft' phase being the initial state, and 'executed' and 'failed' being the terminating states. Please note that this state-machine representation is purely conceptual and should not be expected to reflect technical implementation.
|
||||
|
||||

|
||||
|
||||
##### When is each interaction valid?
|
||||
#### When may interactions occur?
|
||||
|
||||
- `S`: When the proposal was created
|
||||
- `D`: The length of the draft period
|
||||
- `V`: The length of the voting period
|
||||
- `L`: The length of the locking period
|
||||
- `E`: The length of the execution period
|
||||
Consider the following 'stages' of a proposal:
|
||||
|
||||
| Action | Valid POSIXTimeRange | Valid *stored* state(s) |
|
||||
- `S`: when the proposal was created.
|
||||
- `D`: the length of the draft period.
|
||||
- `V`: the length of the voting period.
|
||||
- `L`: the length of the locking period.
|
||||
- `E`: the length of the execution period.
|
||||
|
||||
| Action | Valid POSIXTimeRange | Valid _stored_ state(s) |
|
||||
|-------------------------------------|------------------------------------|-------------------------|
|
||||
| Witness | [S, ∞) | * |
|
||||
| Cosign | [S, S + D) | Draft |
|
||||
| AdvanceProposal | [S, S + D) | Draft |
|
||||
| Vote | [S + D, S + D + V) | Voting |
|
||||
| Unlock | [S + D, ∞) | * |
|
||||
| CountVotes (? see spec comment) | [S + D + V, S + D + V + L) | Voting |
|
||||
| ExecuteProposal (if quorum reached) | [S + D + V + L, S + D + V + L + E) | Voting |
|
||||
| Witness | \[S, ∞) | \* |
|
||||
| Cosign | \[S, S + D) | Draft |
|
||||
| AdvanceProposal | \[S, S + D) | Draft |
|
||||
| Vote | \[S + D, S + D + V) | Voting |
|
||||
| Unlock | \[S + D, ∞) | \* |
|
||||
| CountVotes (? see spec comment) | \[S + D + V, S + D + V + L) | Voting |
|
||||
| ExecuteProposal (if quorum reached) | \[S + D + V + L, S + D + V + L + E) | Voting |
|
||||
|
||||
```diff
|
||||
- CountVotes takes a snapshot after voting has ended, it allows users to unlock their stake without affecting votes, after the lock period has ended. This is an optional feature of locking, do we want this?
|
||||
```
|
||||
|
||||
> Jack 2022-02-02: I will consider revising this table further at a later time.
|
||||
|
||||
#### Draft phase
|
||||
|
||||
During the Draft phase, the proposal script has been minted. At this stage, only positive votes will count and for the proposal to get into the voting phase, a certain amount of LQ will have to be backing the proposal. The UTXO can be queried for any metadata it contains, should it contain any useful information. LQ holders can "cosign" the proposal and add their LQ in order to allow the motion to get into the voting phase.
|
||||
During the draft phase, a new UTXO at the proposal script has been created. At this stage, only votes in favor of co-signing the draft are counted. For the proposal to transition to the voting phase, a threshold of GT will have to be staked backing the proposal. This threshold will be determined on a per-system basis and could itself be a 'governable' parameter.
|
||||
|
||||
#### Voting phase
|
||||
|
||||
During the voting phase a voter can submit a vote either in favour or against the proposal. This simply adds their PubKey to the list of votes as a state-machine action. By virtue of being a state-machine action, this causes contention, and may be rate-limited through some means.
|
||||
|
||||
##### What determines a successful proposal?
|
||||
|
||||
When initializing a proposal, the governance's thresholds are passed along, one of the thresholds is the `quorum`.
|
||||
In the voting phase, users may utilise their stakes to vote in-favour or in-opposition to a proposal. This will add their vote to the relevant count. There is potential for contention within the system and therefore voting on proposals may have to be rate-limited. The method by which a user's stakes are weighted and the thresholds required for proposals to pass are determined on a per-protocol basis.
|
||||
|
||||
#### Lock phase
|
||||
|
||||
After the voting phase has completed, the proposal has either passed, or failed.
|
||||
|
||||
We wait a set time before allowing execution of the proposal's effects. This is to allow LQ holders time to prepare for the change in whichever way they seem fit. This is also a security mechanism, should the system be at risk of hostile takeover.
|
||||
Upon completion of the voting phase, a proposal will either have been passed or failed. A delay between the passing of a proposal and execution of its effects will be enforced, to allow users to prepare for incoming changes to the system. It'll further give the system maintainers opportunity to intervene, in the case of a hostile action.
|
||||
|
||||
#### Execution phase
|
||||
|
||||
In the case of a failed proposal, the proposal will simply be frozen in time and never interacted with anymore. There is no value locked behind a proposal, besides the state thread itself, so nothing is lost.
|
||||
Failed proposals will not be interacted with further. The only value they will contain is their state thread tokens and the minimum ADA requirement, so little of worth is lost.
|
||||
|
||||
In the case of a successful proposal, anyone can execute the effects, as it can only be done in a lawful way.
|
||||
Successful proposals will be verified by the governor component, which will issue ['governance authority tokens'](/docs/tech-design/authority-tokens.md) (GATs) to a proposal's separate 'effects'. The burning of these tokens will be a pre-requisite for system changes to be made, therefore the possession of one will serve as a form of 'licence' for making the changes.
|
||||
|
||||
There is a deadline for how long it can take for the proposal to get executed. Again, as the proposal is necessarily something that has been agreed by the voters, it will be incentivized naturally to be executed.
|
||||
|
||||
See [tech-design/authority-token.md](./authority-tokens.md) for how effects take place after execution
|
||||
There will be a deadline before which a proposal's effects will have to be executed. As any passed proposal's effects will necessarily have been supported by the community, it can be presumed that community members will have be incentivised to ensure the effects are enacted soon after the proposal has been passed.
|
||||
|
|
|
|||
|
|
@ -1,66 +1,89 @@
|
|||
# StakingPool technical design
|
||||
# Stakes and staking pool technical design
|
||||
|
||||
| Spec Status | Impl Status | Last Revision |
|
||||
|-------------|-------------|---------------|
|
||||
| WIP | WIP | 2022-01-18 |
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-----------:|:-----------:|:-------------:|
|
||||
| WIP | WIP | 2022-02-07 |
|
||||
|
||||
--------------------
|
||||
---
|
||||
|
||||
**Spec Ownership:** [@Emily Martins]
|
||||
**Specification ownership:** [Emily Martins]
|
||||
|
||||
**Authors**: [@Emily Martins]
|
||||
**Authors**:
|
||||
|
||||
**Impl Owner:** [@Emily Martins]
|
||||
- [Emily Martins]
|
||||
- [Jack Hodgkinson]
|
||||
|
||||
[@Emily Martins]: https://github.com/emiflake
|
||||
**Implementation ownership:** [Emily Martins]
|
||||
|
||||
--------------------
|
||||
[Emily Martins]: https://github.com/emiflake
|
||||
|
||||
## The StakingPool
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
|
||||
In order to be able to count votes at all, some means of proving a user's skin in the game on-chain must exist. We propose having a central StakingPool contract which mints separate per-user UTXOs in which the governance token can be deposited. The MintingPolicy of the state threads ensures that it is paid to the script and with valid initial state. This circumvents the need for a central token, and makes the minting of such tokens concurrently possible.
|
||||
**Current status:** Originally written for Liqwid by [Emily Martins]. Rewritten by [Jack Hodgkinson]. Required review from [Emily Martins], especially the section on staking pools.
|
||||
|
||||
### Stake UTXOs
|
||||
---
|
||||
|
||||
A stake UTXO stores the information to allow accessing your staked GT as if it was a safe.
|
||||
## Stake UTXOs
|
||||
|
||||
A 'stake' records how much GT has been staked by a user, and on which proposals it has been locked against.
|
||||
|
||||
```haskell
|
||||
data Stake = Stake
|
||||
{ -- | Which proposals has this Stake been used to vote on?
|
||||
{ -- | Which proposals has this stake been used to vote on?
|
||||
lockedByProposals :: [(DatumHash, ProposalVote)]
|
||||
, -- | The amount staked by this utxo
|
||||
, -- | The amount of GT in the stake.
|
||||
stakedAmount :: GT
|
||||
, -- | Who owns this Stake
|
||||
, -- | The owner of the stake.
|
||||
owner :: PubKeyHash
|
||||
}
|
||||
```
|
||||
|
||||
When voting for a proposal, the Stake UTXO is used to witness the user's staked amount. As a result, the two following state transitions take place (pseudocode):
|
||||
When voting for a proposal, the stake UTXO is used to witness the user's staked amount. As a result, the two following state transitions take place:
|
||||
|
||||
```haskell
|
||||
proposal.votes += (stake.stakedAmount, vote)
|
||||
stake.lockedByProposals += (hash proposal.settings, vote)
|
||||
```
|
||||
|
||||
A sort of mutual binding between the proposal and the stake is created and undoing one undoes the other, which is exactly what we want!
|
||||
This forms a mutual binding between the proposal and the stake.
|
||||
|
||||
Depositing and withdrawing is made illegal when `stake.lockedByProposals` isn't empty. Withdrawing is illegal so that you can't have GT in a vote, without having it anymore, whereas Depositing is illegal so that you can't deposit after a vote and unvote it again in order to retract more than you originally voted. Thus preserving that
|
||||
A stake may be used to vote on an unlimited number of proposals. Consider a user staking 50GT. They may pledge that 50GT against a proposal `p` _and_ another proposal `p'`.
|
||||
|
||||
#### Delegating stake
|
||||
Altering the amount positioned in a stake is not possible, for as long as that stake is locked against any proposals. This is to prevent vote manipulation. Consider:
|
||||
|
||||
Most things like Cosigning sort of work trivially by just witnessing Stake, but delegation requires an extra step. We add a field to what `Stake` stores.
|
||||
- Ford stakes 100GT and votes in-favour of a proposal `p`. `p` now has +100GT in-favour.
|
||||
- Ford _increases_ his stake by 50GT to 150GT.
|
||||
- Ford retracts his vote from `p`. As his stake is 150GT, `p` deducts 150GT and `p` now has -50GT in-favour.
|
||||
|
||||
It should be clear how users could alter their stakes to reduce and manipulate the vote count. Preventing alteration of GT in stakes ensures that there is never a discrepancy between the amount of GT a user holds and the amount the system believes that they hold.
|
||||
|
||||
If a user wished to stake _more_ GT, they could always create a new stake that they would be free to lock on proposals. For this reason, it may be useful to include a method of 'merging' stakes, when they are not being locked against any proposals, to allow users to 'streamline' their GT portfolio.
|
||||
|
||||
## Delegating stake
|
||||
|
||||
Aspects of delegation, such as co-signing work through the trivial witnessing of a stake UTXO, however allowing a user to delegate their stakes requires an extra field:
|
||||
|
||||
```haskell
|
||||
data Stake = Stake
|
||||
{ -- | Which proposals has this Stake been used to vote on?
|
||||
{ -- | Which proposals has this stake been used to vote on?
|
||||
lockedByProposals :: [(DatumHash, ProposalVote)]
|
||||
, -- | The amount staked by this utxo
|
||||
, -- | The amount of GT in the stake.
|
||||
stakedAmount :: GT
|
||||
, -- | Who can spend our utxo for us when voting
|
||||
delegatedTo :: Maybe ValidatorHash
|
||||
, -- | Who owns this Stake
|
||||
, -- | The owner of the stake.
|
||||
owner :: PubKeyHash
|
||||
, -- | To whom this stake has been delegated.
|
||||
delegatedTo :: Maybe ValidatorHash
|
||||
}
|
||||
```
|
||||
|
||||
We simply link one stake to another. When voting now the voter can check which Stake utxos are delegated to them off-chain, and include them in the transaction for voting. **This will lock the delegators' utxos**, but that's no big deal because they can themselves unlock it just like usual. The validity of the hash provided to the Stake is irrelevant. It simply delegates its _authentication_ to the particular hash. Note, it only delegates authentication for _voting_ but not for example for withdrawing.
|
||||
When voting on a proposal, a user can check which stakes have delegated to them off-chain and include them in the voting transaction. _This will lock the delegator's stake_, however they will be themselves be able to unlock it as usual. It should be noted that delegation of stakes only extends to voting on proposals and not, for example, withdrawing GT from a stake.
|
||||
|
||||
## Staking pool
|
||||
|
||||
There are a number of reasons that a protocol would wish to track the global state of stakes in its system. For example, a protocol may wish to implement a proposal system where a certain proportion of the globally available GT must be staked in-favour of a proposal, in order to allow it to pass. This is the equivalent of mandating a certain voter turnout be met in a national referendum. The ability to do such a thing is conferred by the creation of a _staking pool_.
|
||||
|
||||
Whilst the ability to track stakes is a useful one, it is a complicated concept to implement on Cardano. A particular issue is _throughput and contention_: any purely on-chain solution is unlikely to be able to process data rapidly enough that the process of users creating stakes _and_ updating the staking pool is as seamless as desired.
|
||||
|
||||
One potential solution for this is an _escrow_ system, which implements a queueing solution by which users issue their stake and the system takes responsibility for updating the staking pool accordingly, with no further action required from the staker. This is a feature that is being considered for Agora v2.
|
||||
|
||||
Another implementation takes the burden of calculating the global state of user stakes _off-chain_. This allows the developers much more freedom in how they approach the solution, as they are no longer restricted by the complications of programming on a blockchain. What issue this solution _does_ have is one of **trust**. Any off-chain solution utilised by the protocol developers must demonstrate its fairness and accuracy to its users.
|
||||
|
|
|
|||
48
docs/tech-design/treasury.md
Normal file
48
docs/tech-design/treasury.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Treasury technical design
|
||||
|
||||
| Specification | Implementation | Last revision |
|
||||
|:-----------:|:--------------:|:-------------:|
|
||||
| WIP | WIP | v0.1 2022-02-07 |
|
||||
|
||||
---
|
||||
|
||||
**Specification ownership:** [Jack Hodgkinson]
|
||||
|
||||
**Authors**:
|
||||
|
||||
- [Jack Hodgkinson]
|
||||
|
||||
**Implementation ownership:** _unassigned_
|
||||
|
||||
[Jack Hodgkinson]: https://github.com/jhodgdev
|
||||
|
||||
[Emily Martins]: https://github.com/emiflake
|
||||
|
||||
**Current Status**:
|
||||
|
||||
Initial conceptual draft. Requires review from [Emily Martins].
|
||||
|
||||
---
|
||||
|
||||
Treasuries in Cardano governance systems serve two functions:
|
||||
|
||||
1. To serve as a community reserve or wallet.
|
||||
2. To allow users to redeem their allocated share of rewards.
|
||||
|
||||
## Community reserve
|
||||
|
||||
A decentralised autonomous organisation (DAO) may wish to source funds from its members to save for use at a later date. A treasury therefore serves as a form of 'community wallet', where members can contribute funds, knowing that they may only be released at the behest of the community.
|
||||
|
||||
Treasuries are not, by default, limited to the reserve of a single token and are indeed able to hold any supported Cardano tokens.
|
||||
|
||||
A treasury, as a community's reserves, will naturally need to interact with governance proposals. Indeed, the primary mechanism by which funds are able to be released by the treasury, will be the passing of an appropriate proposal.
|
||||
|
||||
## Reward holder
|
||||
|
||||
The treasury will further be the initial holder of all a governance system's GT. It is likely that any governance system will desire a method to distribute these GT through the community _over time_. The amount of GT a DAO member is eligible for at a given time can be termed that user's 'reward'. The specifics of any 'reward structure', namely:
|
||||
|
||||
1. Who is eligible for rewards?
|
||||
2. When may they receive those rewards?
|
||||
3. How much do they receive in their reward?
|
||||
|
||||
are all, naturally, protocol-specific. A simple method for creating such a bespoke reward structure is **not** considered in-scope for Agora v1. Agora v1 will offer a simple, prescribed reward structure, that allows the treasury to determine the reward eligibility of a user and allow them to redeem said amount.
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
# Vesting contract technical design
|
||||
|
||||
| Spec Status | Impl Status | Last Revision |
|
||||
|-------------|-------------|---------------|
|
||||
| WIP | WIP | 2022-01-18 |
|
||||
|
||||
--------------------
|
||||
|
||||
**Spec Ownership:** [@Emily Martins]
|
||||
|
||||
**Authors**: [@Emily Martins]
|
||||
|
||||
**Impl Owner:** [@Emily Martins]
|
||||
|
||||
[@Emily Martins]: https://github.com/emiflake
|
||||
|
||||
--------------------
|
||||
|
||||
## Vesting contract
|
||||
|
||||
In order to distribute governance tokens, one or more vesting contracts may be deployed.
|
||||
|
||||
First and foremost, there is a _schedule_ for the distribution of said tokens. Alongside this schedule, we keep track of how much we've distributed so far. This allows us to calculate how much is "due" at any particular time.
|
||||
|
||||
To gain intuition, you can think of it being implemented this way:
|
||||
|
||||
```haskell
|
||||
distributed :: Schedule -> Time -> Value
|
||||
distributed schedule time = scanl (+) mempty schedule !! time
|
||||
|
||||
due :: Schedule -> Value -> Time -> Value
|
||||
due schedule alreadyDistributed time = distributed schedule time - alreadyDistributed
|
||||
```
|
||||
|
||||
The vesting contract may require that only an address in a particular set can withdraw from it.
|
||||
|
||||
The vesting contract may have an optional escape hatch for trusted authority to recover from a potential DAO operation.
|
||||
72
flake.lock
generated
72
flake.lock
generated
|
|
@ -187,17 +187,17 @@
|
|||
"cardano-base": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1633939430,
|
||||
"narHash": "sha256-zbjq43Bnhv1/LhJCFlI8gdd61dGvVlkEa6wkCvLqEFg=",
|
||||
"lastModified": 1633088283,
|
||||
"narHash": "sha256-JKpOlruMX5sr9eaQ3AuOppCbBjQIRKwF4ny20tdPnUg=",
|
||||
"owner": "input-output-hk",
|
||||
"repo": "cardano-base",
|
||||
"rev": "4ea7e2d927c9a7f78ddc69738409a5827ab66b98",
|
||||
"rev": "654f5b7c76f7cc57900b4ddc664a82fc3b925fb0",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "input-output-hk",
|
||||
"repo": "cardano-base",
|
||||
"rev": "4ea7e2d927c9a7f78ddc69738409a5827ab66b98",
|
||||
"rev": "654f5b7c76f7cc57900b4ddc664a82fc3b925fb0",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
|
@ -220,17 +220,17 @@
|
|||
"cardano-crypto": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1621376239,
|
||||
"narHash": "sha256-oxIOVlgm07FAEmgGRF1C2me9TXqVxQulEOcJ22zpTRs=",
|
||||
"lastModified": 1604244485,
|
||||
"narHash": "sha256-2Fipex/WjIRMrvx6F3hjJoAeMtFd2wGnZECT0kuIB9k=",
|
||||
"owner": "input-output-hk",
|
||||
"repo": "cardano-crypto",
|
||||
"rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec",
|
||||
"rev": "f73079303f663e028288f9f4a9e08bcca39a923e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "input-output-hk",
|
||||
"repo": "cardano-crypto",
|
||||
"rev": "07397f0e50da97eaa0575d93bee7ac4b2b2576ec",
|
||||
"rev": "f73079303f663e028288f9f4a9e08bcca39a923e",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
|
@ -386,17 +386,17 @@
|
|||
"cardano-wallet": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1635781445,
|
||||
"narHash": "sha256-5IZuqlE/4aGH3TEuGYQsZwOpI/Q7DYzJ4q3stuqGpWc=",
|
||||
"lastModified": 1639607349,
|
||||
"narHash": "sha256-JuYH5pAF7gOsliES0Beo86PinoBmmKXWShXT3NqVlgQ=",
|
||||
"owner": "j-mueller",
|
||||
"repo": "cardano-wallet",
|
||||
"rev": "6be73ab852c0592713dfe78218856d4a8a0ee69e",
|
||||
"rev": "760140e238a5fbca61d1b286d7a80ece058dc729",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "j-mueller",
|
||||
"repo": "cardano-wallet",
|
||||
"rev": "6be73ab852c0592713dfe78218856d4a8a0ee69e",
|
||||
"rev": "760140e238a5fbca61d1b286d7a80ece058dc729",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
|
@ -1139,11 +1139,11 @@
|
|||
},
|
||||
"nixpkgs-2009": {
|
||||
"locked": {
|
||||
"lastModified": 1624271064,
|
||||
"narHash": "sha256-qns/uRW7MR2EfVf6VEeLgCsCp7pIOjDeR44JzTF09MA=",
|
||||
"lastModified": 1635350005,
|
||||
"narHash": "sha256-tAMJnUwfaDEB2aa31jGcu7R7bzGELM9noc91L2PbVjg=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "46d1c3f28ca991601a53e9a14fdd53fcd3dd8416",
|
||||
"rev": "1c1f5649bb9c1b0d98637c8c365228f57126f361",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -1353,17 +1353,17 @@
|
|||
"ouroboros-network": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1634917006,
|
||||
"narHash": "sha256-lwTgyoZBQAaU6Sh7BouGJGUvK1tSVrWhJP63v7MpwKA=",
|
||||
"lastModified": 1637082154,
|
||||
"narHash": "sha256-FNYcUjoy0ZpletEXUIAMbag2Hwb9K3bDRl793NyNy1E=",
|
||||
"owner": "input-output-hk",
|
||||
"repo": "ouroboros-network",
|
||||
"rev": "1f4973f36f689d6da75b5d351fb124d66ef1057d",
|
||||
"rev": "d613de3d872ec8b4a5da0c98afb443f322dc4dab",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "input-output-hk",
|
||||
"repo": "ouroboros-network",
|
||||
"rev": "1f4973f36f689d6da75b5d351fb124d66ef1057d",
|
||||
"rev": "d613de3d872ec8b4a5da0c98afb443f322dc4dab",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
|
@ -1393,17 +1393,17 @@
|
|||
"th-extras": "th-extras"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1643303963,
|
||||
"narHash": "sha256-Ta3PLyLX209Dj1LWljkp9ynlA+QPJyaI2g6oQgBeueM=",
|
||||
"lastModified": 1643799364,
|
||||
"narHash": "sha256-ud/YkMtBKcx0yrHOboA7uTPtGCt5LCOipF0m2W6LqxU=",
|
||||
"owner": "Plutonomicon",
|
||||
"repo": "plutarch",
|
||||
"rev": "d753dc34dfc30b144e94d6493c837ebd0c99b588",
|
||||
"rev": "1fd4db27152625184e559cfb465d225a0995a56b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Plutonomicon",
|
||||
"repo": "plutarch",
|
||||
"rev": "d753dc34dfc30b144e94d6493c837ebd0c99b588",
|
||||
"rev": "1fd4db27152625184e559cfb465d225a0995a56b",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
|
@ -1438,17 +1438,34 @@
|
|||
"plutus-apps": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1636122782,
|
||||
"narHash": "sha256-+T9TGzHEzyfixBysxLwy5VWVrL5xqKF5pcbRlHQr+wI=",
|
||||
"lastModified": 1642502716,
|
||||
"narHash": "sha256-UULYQppoNjj+EOcV75UT3DOwJF+d609FOYsZZFeAQcM=",
|
||||
"owner": "input-output-hk",
|
||||
"repo": "plutus-apps",
|
||||
"rev": "404af7ac3e27ebcb218c05f79d9a70ca966407c9",
|
||||
"rev": "34fe6eeff441166fee0cd0ceba68c1439f0e93d2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "input-output-hk",
|
||||
"repo": "plutus-apps",
|
||||
"rev": "404af7ac3e27ebcb218c05f79d9a70ca966407c9",
|
||||
"rev": "34fe6eeff441166fee0cd0ceba68c1439f0e93d2",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"plutus-extra": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1643739251,
|
||||
"narHash": "sha256-L7WSXvGWxfuqSP4ZNdbuT2AdW89mAJsE6+3mxO+1dx8=",
|
||||
"owner": "Liqwid-Labs",
|
||||
"repo": "plutus-extra",
|
||||
"rev": "bfeb0d2bb1bc18f147e58c200db2022f5c75eb60",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "Liqwid-Labs",
|
||||
"repo": "plutus-extra",
|
||||
"rev": "bfeb0d2bb1bc18f147e58c200db2022f5c75eb60",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
|
|
@ -1585,6 +1602,7 @@
|
|||
"plutarch": "plutarch",
|
||||
"plutus": "plutus_2",
|
||||
"plutus-apps": "plutus-apps",
|
||||
"plutus-extra": "plutus-extra",
|
||||
"purescript-bridge": "purescript-bridge",
|
||||
"servant-purescript": "servant-purescript"
|
||||
}
|
||||
|
|
|
|||
41
flake.nix
41
flake.nix
|
|
@ -10,18 +10,22 @@
|
|||
"github:input-output-hk/plutus?rev=65bad0fd53e432974c3c203b1b1999161b6c2dce";
|
||||
|
||||
inputs.plutarch.url =
|
||||
"github:Plutonomicon/plutarch?rev=d753dc34dfc30b144e94d6493c837ebd0c99b588";
|
||||
"github:Plutonomicon/plutarch?rev=1fd4db27152625184e559cfb465d225a0995a56b";
|
||||
|
||||
inputs.goblins.url =
|
||||
"github:input-output-hk/goblins?rev=cde90a2b27f79187ca8310b6549331e59595e7ba";
|
||||
inputs.goblins.flake = false;
|
||||
|
||||
inputs.plutus-extra.url =
|
||||
"github:Liqwid-Labs/plutus-extra?rev=bfeb0d2bb1bc18f147e58c200db2022f5c75eb60";
|
||||
inputs.plutus-extra.flake = false; # Could we set this to true?
|
||||
|
||||
inputs.cardano-node.url =
|
||||
"github:input-output-hk/cardano-node?rev=b6ca519f97a0e795611a63174687e6bb70c9f752";
|
||||
inputs.cardano-node.flake = false;
|
||||
|
||||
inputs.cardano-wallet.url =
|
||||
"github:j-mueller/cardano-wallet?rev=6be73ab852c0592713dfe78218856d4a8a0ee69e";
|
||||
"github:j-mueller/cardano-wallet?rev=760140e238a5fbca61d1b286d7a80ece058dc729";
|
||||
inputs.cardano-wallet.flake = false;
|
||||
|
||||
inputs.purescript-bridge.url =
|
||||
|
|
@ -33,7 +37,7 @@
|
|||
inputs.servant-purescript.flake = false;
|
||||
|
||||
inputs.plutus-apps.url =
|
||||
"github:input-output-hk/plutus-apps?rev=404af7ac3e27ebcb218c05f79d9a70ca966407c9";
|
||||
"github:input-output-hk/plutus-apps?rev=34fe6eeff441166fee0cd0ceba68c1439f0e93d2";
|
||||
inputs.plutus-apps.flake = false;
|
||||
|
||||
inputs.cardano-addresses.url =
|
||||
|
|
@ -45,7 +49,7 @@
|
|||
inputs.optparse-applicative.flake = false;
|
||||
|
||||
inputs.ouroboros-network.url =
|
||||
"github:input-output-hk/ouroboros-network?rev=1f4973f36f689d6da75b5d351fb124d66ef1057d";
|
||||
"github:input-output-hk/ouroboros-network?rev=d613de3d872ec8b4a5da0c98afb443f322dc4dab";
|
||||
inputs.ouroboros-network.flake = false;
|
||||
|
||||
inputs.cardano-ledger-specs.url =
|
||||
|
|
@ -61,11 +65,11 @@
|
|||
inputs.cardano-prelude.flake = false;
|
||||
|
||||
inputs.cardano-base.url =
|
||||
"github:input-output-hk/cardano-base?rev=4ea7e2d927c9a7f78ddc69738409a5827ab66b98";
|
||||
"github:input-output-hk/cardano-base?rev=654f5b7c76f7cc57900b4ddc664a82fc3b925fb0";
|
||||
inputs.cardano-base.flake = false;
|
||||
|
||||
inputs.cardano-crypto.url =
|
||||
"github:input-output-hk/cardano-crypto?rev=07397f0e50da97eaa0575d93bee7ac4b2b2576ec";
|
||||
"github:input-output-hk/cardano-crypto?rev=f73079303f663e028288f9f4a9e08bcca39a923e";
|
||||
inputs.cardano-crypto.flake = false;
|
||||
|
||||
inputs.flat.url =
|
||||
|
|
@ -91,6 +95,7 @@
|
|||
};
|
||||
|
||||
deferPluginErrors = true;
|
||||
plutarch-development = true;
|
||||
|
||||
projectFor = system:
|
||||
let pkgs = nixpkgsFor system;
|
||||
|
|
@ -224,6 +229,7 @@
|
|||
"lib/launcher"
|
||||
"lib/core-integration"
|
||||
"lib/cli"
|
||||
"lib/dbvar"
|
||||
"lib/shelley"
|
||||
];
|
||||
}
|
||||
|
|
@ -238,6 +244,7 @@
|
|||
"plutus-chain-index-core"
|
||||
"plutus-contract"
|
||||
"plutus-ledger"
|
||||
"plutus-ledger-constraints"
|
||||
"plutus-pab"
|
||||
"plutus-playground-server"
|
||||
"plutus-use-cases"
|
||||
|
|
@ -250,6 +257,19 @@
|
|||
subdirs =
|
||||
[ "cardano-api" "cardano-node" "cardano-cli" "cardano-config" ];
|
||||
}
|
||||
{
|
||||
src = inputs.plutus-extra;
|
||||
subdirs = [
|
||||
"tasty-plutus"
|
||||
"plutus-pretty"
|
||||
"plutus-numeric"
|
||||
"plutus-extra"
|
||||
"plutus-golden"
|
||||
"plutus-laws"
|
||||
"quickcheck-plutus-instances"
|
||||
|
||||
];
|
||||
}
|
||||
{
|
||||
src = inputs.plutus;
|
||||
subdirs = [
|
||||
|
|
@ -268,7 +288,12 @@
|
|||
];
|
||||
modules = [{
|
||||
packages = {
|
||||
|
||||
plutarch.flags.development = plutarch-development;
|
||||
marlowe.flags.defer-plugin-errors = deferPluginErrors;
|
||||
plutus-use-cases.flags.defer-plugin-errors = deferPluginErrors;
|
||||
plutus-ledger.flags.defer-plugin-errors = deferPluginErrors;
|
||||
plutus-contract.flags.defer-plugin-errors = deferPluginErrors;
|
||||
cardano-crypto-praos.components.library.pkgconfig =
|
||||
nixpkgs.lib.mkForce
|
||||
[ [ (import plutus { inherit system; }).pkgs.libsodium-vrf ] ];
|
||||
|
|
@ -296,7 +321,9 @@
|
|||
graphviz
|
||||
];
|
||||
|
||||
additional = ps: [ ps.plutarch ps.plutus-ledger ];
|
||||
additional = ps: [ ps.plutarch ps.plutus-ledger ps.plutus-extra ];
|
||||
|
||||
tools.haskell-language-server = { };
|
||||
};
|
||||
};
|
||||
in {
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
# This file is no longer useful for normal nix-shell, as it has
|
||||
# been superseded by flake.nix However, this is still useful for
|
||||
# lorri to use automatically.
|
||||
{ system ? builtins.currentSystem }:
|
||||
|
||||
(builtins.getFlake (toString ./.)).devShell.${system}
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
module Agora.AuthorityToken (
|
||||
authorityTokenPolicy,
|
||||
AuthorityToken (..),
|
||||
serialisedScriptSize,
|
||||
) where
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
@ -9,20 +8,6 @@ module Agora.AuthorityToken (
|
|||
import Prelude
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Codec.Serialise (serialise)
|
||||
import Data.ByteString qualified as BSS
|
||||
import Data.ByteString.Lazy qualified as BS
|
||||
import Data.ByteString.Short qualified as SBS
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Cardano.Api.Shelley (
|
||||
PlutusScript (PlutusScriptSerialised),
|
||||
PlutusScriptV1,
|
||||
serialiseToCBOR,
|
||||
)
|
||||
import Plutus.V1.Ledger.Scripts (Script)
|
||||
import Plutus.V1.Ledger.Value (AssetClass (..))
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
@ -86,17 +71,6 @@ passetClassValueOf =
|
|||
PNothing -> 0
|
||||
PJust v -> pfromData v
|
||||
|
||||
-- TODO: We should rely on plutus-extra instead of rolling our own,
|
||||
-- this is just quick and hacky.
|
||||
serialisedScriptSize :: Script -> Int
|
||||
serialisedScriptSize =
|
||||
BSS.length
|
||||
. serialiseToCBOR
|
||||
. PlutusScriptSerialised @PlutusScriptV1
|
||||
. SBS.toShort
|
||||
. BS.toStrict
|
||||
. serialise
|
||||
|
||||
authorityTokenPolicy ::
|
||||
AuthorityToken ->
|
||||
Term s (PData :--> PData :--> PScriptContext :--> PUnit)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue