# System Design In the [Requirements](./requirements.md) section, we identified the need for the following smart contracts: Reputation, Bench, Forum, Work, Proposal, and Rollup. We also identified the need for a mechanism for coordinating Rollup Post validation. To address this need, we introduce [Matrix](https://matrix.org), a federated messaging protocol. Our application uses the Client-Server protocol to communicate with a Matrix Homeserver. ## Contracts The following is a dependency graph, where the arrows represent one contract calling another. ```mermaid flowchart BT subgraph Core Contracts Reputation Bench Forum end subgraph Business Logic Work Proposal Rollup end Bench --> Reputation Proposal --> Bench Proposal --> Reputation Work --> Reputation Work --> Bench Work --> Rollup Work --> Proposal Forum --> Reputation Bench --> Forum Rollup --> Bench ``` Reputation, Forum, and Bench can be considered core contracts. Together they provide the necessary primitives for a DAO to carry out its business. Work, Proposal, and Rollup can be considered business logic. They allow the DAO to support arbitrarily complex use cases, according to its needs. [Future work](./future-work.md) may include utilizing the process defined by the Proposal contract to govern features of the core contracts themselves. ### Reputation We can achieve the requirements of the Reputation contract as follows: 1. Reputation may be implemented as an ERC20 token contract. 1. `transfer` and `transferFrom` methods must be disabled, so that REP may not be transferred. 1. Reputation internal methods (`mint`, `burn`, `update`) may be called only by the Bench and Forum contracts. ### Bench To achieve the Bench requirements, the contract must do the following: 1. Define a minimum quorum 1. Define a minimum and maximum VP duration 1. Keep a record of Validation Pools 1. Implement a method for initiating a Validation Pool (VP) 1. This should be a payable contract call. The value transferred is the fee for this VP. 1. The VP shall mint an amount of REP equal to `valueTransferred * mintingRatio` 1. **`mintingRatio`** may be set statically, or may be taken as a parameter when initiating a VP. Taking `mintingRatio` as a parameter enables greater flexibility, but increases overhead cost per transaction. This makes `mintingRatio` a good candidate for being governed by a Proposal process, outlined in [Future Work](./future-work.md). 1. Half of the minted REP shall be staked in favor of the VP, and the other half shall be staked against the VP. 1. This ratio could be taken as a parameter or governed by a Proposal to increase the flexibility of the DAO; see [Future Work](./future-work.md). 1. Implement a method for receiving REP stakes for/against the VP 1. Stake should be rejected if the VP `duration` has already elapsed. 1. Staking REP means that a DAO member makes an allowance for the given amount of REP to be withdrawn from their balance. The amount of the shall be recorded along with the boolean `inFavor`, but the REP is not to be withdraws from the sender's balance until certain conditions are met durint the evaluation of the VP outcome (explained below). 1. Implement a method for evaluating the outcome of a Validation Pool 1. Outcome may not be evaluated until VP `duration` has elapsed 1. An exception can be made if `totalStakedFor + totalStakedAgainst == totalSupply`. In thise case the DAO is all-in, and there's no reason to wait before evaluating the outcome. 1. The quorum is met if `(totalStakedFor + totalStakedAgainst) * quorum[denominator] >= totalSupply * quorum[numerator]` 1. The vote passes if `totalStakedFor * winRatio[denominator] >= (totalStakedFor + totalStakedAgainst) * winRatio[numerator]` 1. If the vote passes and the quorum is met, 1. If `redistributeLosingStakes` is true, then `(bindingPercent / 100) * totalStakedAgainst` shall be distributed among the accounts who staked against the VP, in proportion to their stakes. 1. The REP that was staked in favor of the VP during its initiation, shall be transferred to the Target Post, and propagated via the Forum Reference mechanism to the authors of the Post and its referenced Posts. 1. If provided, `callbackOnValidate` should be executed, and should be passed the results of the VP. **`totalSupply`** refers to the total amount of REP held by all DAO members. **`ValdiationPoolResult`** Fields | Name | Type | | --- | --- | | `sender` | wallet address | | `votePasses` | boolean | | `quorumMet` | boolean | **`InitiateValidationPool`** Parameters | Name | Type | | --- | --- | | `postId` | string identifying the Target Post| | `duration` | positive integer number of seconds | | `quorum` | integer numerator, integer denominator | | `winRatio` | integer numerator, integer denominator | | `bindingPercent` | integer | | `redistributeLosingStakes` | boolean | | `callbackOnValidate` | function(`ValidationPoolResult`, `callbackData`) | Optional callback to be executed when the VP is concluded | | `callbackData` | bytes | Opaque data to be passed back to `callbackOnValidate` | ### Forum To achieve the Forum requirements, the contract must do the following: 1. Keep a record of Posts, indexed by Post ID 1. Implement a method to add a Post 1. Implement a recursive method to distribute Reputation to a Post's references and authors. 1. This method must be called only by the Bench, when a Validation Pool is accepted. ### Proposal To achieve the Proposals requirements, the contract must do the following: 1. Define an attestation threshold 1. Keep a record of Proposals 1. Implement a method to initiate a Proposal 1. The caller should be able to provide an optional callback to be executed when and if the Proposal is accepted 1. Implement a method for a DAO member to attest to a Proposal 1. Implement a method to evaluate the attestation for a given Proposal 1. If the attestation threshold is met, begin the referendum process 1. Implement the referendum process 1. Initiate the VP for the current stage referendum 1. Provide a callback to be executed when each referendum VP concludes, that advances the Proposal through the referenda stages according to the requirements. 1. If the Proposal passes all referenda stages, and a callback was provided, the callback should be executed. ### Availability For convenience, we can define an Availability contract, as a base contract that other contracts may extend. Work contracts as well as the Rollup contract need to use this Availability mechanism. To achieve the requirements, the Availability contract must do the following: 1. Keep a record of Worker availability stakes 1. Implement a method to accept Worker availability stakes 1. Implement a method to select a Worker by random weighted selection, weighted by the amount each Worker staked. ### Work To achieve the Work Smart Contract requirements, a work contract must do the following: 1. Inherit from the Availability contract 1. Define a price for the work 1. Optionally, implement a method to initate a Proposal to change the price 1. Implement a method for a Customer to request work 1. Implement a method for a Worker to submit Work Evidence (WEV) 1. Implement a method for a Customer to submit work approval/disapproval 1. Once approval/disapproval is submitted, either initiate a Validation Pool tarageting the WEV, or submit the fee and worker's REP stakes to the Rollup contract instead (explained below). ### Rollup Rather than submit every Post on-chain and conduct every Validation Pool on-chain, it is more efficient to keep a collection of Posts off-chain, and add a single Rollup Post on-chain representing multiple off-chain Posts. With this Rollup Post, we have the opportunity to attribute credit to multiple authors, with a weight assigned to each author. We can express this weight as parts per million (PPM), for a balance between numerical precision, and ease of visual recognition. The Rollup Post can weight authorship in accordance with the off-chain Validation Pools that have taken place. The off-chain system can fully model the Forum and Bench outlined in the [Requirements](./requirements.md) section. For demonstration purposes, our prototype makes some simplifying assumptions. Work Evidence Posts (WEV) are assumed to contain no references to prior Posts. In reality, we want WEV to be able to reference prior Posts, such as those representing policies of the DAO, prior work by other DAO members, prior art outside the DAO, and so on. So, a proper implementation of this system should account for these references, just as the Forum contract must. To achieve the Rollup requirements, the contract must do the following: 1. Inherit from the Availability contract 1. Keep a queue of items to be batched 1. Implement a method to add an item to the queue of items to be batched 1. Implement a method for the current batch worker to initiate a Validation Pool targeting a Rollup Post that represents items from the batch queue. 1. Items must be submitted in order without skipping any items 1. Implement a method to select a new batch worker 1. If this method is called to replace a batch worker who has failed to submit the next batch, a Validation Pool should be initiated and the batch worker's stakes submitted in favor of the VP. The DAO members may then stake against this VP, punishing the worker who failed to submit the batch. ## Off-chain Operations As outlined in the Rollup section above, we need to define processes for handling off-chain Posts and Validation Pools. On-chain, Posts are represented by a unique identifier, but the Post content is always stored off-chain. So, every on-chain Post must have a corresponding off-chain Post. These off-chain posts should be visible to the public. To achieve this, we introduce a Forum API, that supports writing and reading off-chain Posts. Moreover, each Forum API instance must also function as a Matrix client to send, receive, and query for messages. ### Write Parameters | Name | Type | | --- | --- | | `sender` | Wallet address | | `authors` | Array of tuples: (Wallet address, weight) | | `content` | String | | `references` | Array of tuples: (Post ID, weight) | | `embeddedData` | Object | | `signature` | Sender or author signature of `content` and `embeddedData` | In order to protect the integrity of the off-chain Forum, the API should verify that the Post is signed by one of its authors, or by the sender. The reason for allowing the Post to be signed by the sender rather than by an author, is to support the use case of adding a Post on behalf of its author(s). The API should compute a hash of all input parameters except for `references`, and use this hash as the key for storing the Post. The hash should also be returned to the caller. The reason for excluding `references` from the hash, is to support the use case of importing Posts from an existing data source. If we included the references, then to import any Posts from an existing data source, we would have to import every referenced Post, starting with the earliest, in order to compute the entire tree of references made by a given Post. By omitting references from the hash, it becomes possible to precompute the hash (a.k.a. ID) of referenced Posts that have not yet been imported. The reason for excluding `references` from the signature, is to reduce the number of queries that must be made to an existing data source when importing a Post. (Specifically, when importing from the [Semantic Scholar API](https://api.semanticscholar.org/api-docs).) If we had to include the references in the signature, there is an "N + 1 problem" to the query pattern. For each paper, we would need to perform an additional query for each of its references. A single query can't ask for the references of the references of a paper. Note that because `references` is not included in the hash or signature, there is a replay attack vulnerability. Someone could read an existing Post, modify the `references`, and write the modified Post back to the API. The signatures will still be valid even though the references have changed, and the new references will overwrite the previous references. Note that this would only affect the off-chain record of the Post's references. If the Post is published to the on-chain Forum, it is not subject to such modification, as a Post with a given ID can only be added once. To mitigate this vulnerabliity in the off-chain Forum, we should reject a write attempt if a Post with the given ID already exists. When a Post is written, the Forum API should send an `io.dgov.forum.post` event to the Matrix room. Peer nodes should listen for events of this type from other peers. When an `io.dgov.forum.post` event is received, the recipient should write the Post to storage just as they would if the `write` endpoint were called directly. Each Forum API node should keep track of the most recent `io.dgov.forum.post` event received. On startup, each Forum API node should query the Matrix Homeserver for any newer `io.dgov.forum.post` events. ### Read The `read` endpoint should accept a Post ID argument, and retrieve the corresponding Post from storage. Before sending the Post to the caller, the Forum API should verify the hash and signature, to ensure the integrity of the record. ## Automated Staking To achieve the Autonomy requirement for the DAO, Validation Pools targeting Work Evidence Posts or Rollup Posts should be automatically validated, without human intervention. This means the rules for validating a given VP and its target Post must be represented in code. Our prototype demonstrates the simplest possible type of rule that can be applied: a Work Evidence Post is considered valid if it starts with a specific string, "This is a work evidence post". ### Validation Pool ### Rollup ## User Interface ### Web App ### Widget ## Other - Register Matrix Identity - Imprt from Semantic Scholar - Import from Matrix - Bot Commands