diff --git a/sputnikdao2/README.md b/sputnikdao2/README.md
index 440bb00a3..47004ca5f 100644
--- a/sputnikdao2/README.md
+++ b/sputnikdao2/README.md
@@ -1,133 +1,262 @@
# Sputnik DAO v2
-## Proposals
+> Building on the functionality of v1, Sputnik DAO v2 offers even more features and enhanced configuration ability.
-Proposals is the main way to interact with the DAO.
-Each action on the DAO is done by creating and approving proposal.
+## Overview
-## Token voting
+| Name | Description |
+| --------------------------------------------- | --------------------------------------------------------------------- |
+| [Setup](#setup) | Step-by-step guide to deploy a DAO factory and DAO contracts. |
+| [Roles & Permissions](#roles-and-permissions) | Setup roles and define permissions for each role. |
+| [Proposals](#proposals) | Each action on the DAO is done by creating and approving a proposal. |
+| [Voting](#voting) | Configure policies, setup governance tokens, and vote on proposals. |
+| [Bounties](#bounties) | Add and configure bounties. |
+| [Blob Storage](#blob-storage) | Store large data blobs and content and index them by the data's hash. |
+| [Upgradability](#upgradability) | Upgrade the DAO to different contract code versions. |
-DAO votes to select some token to become voting token (only can be done once, can't change later).
+---
-User flow is next:
-- User's deposit the token into the DAO.
-- They can then choose who to delegate these tokens. It can be to themself or to other users to increase their vote weight.
-- When users vote for proposals, their vote is weighted by all the delegations to them.
-- Undelegating will block delegating / withdrawing until one voting period passes.
-- Undelegated tokens can be withdrawn by the user.
+## Setup
-## Bounties
+### Prerequisites
-The lifecycle of a bounty is the next:
+1. [NEAR Account](https://wallet.testnet.near.org)
+2. [NEAR-CLI](https://docs.near.org/docs/tools/near-cli#setup)
+3. [Rust](https://www.rust-lang.org)
- - Anyone with permission can add proposal `AddBounty` which contains the bounty information, including `token` to pay the reward in and `amount` to pay it out.
- - This proposal gets voted in by the current voting policy
- - After proposal passed, the bounty get added. Now it has an `id` in the bounty list. Which can be queries via `get_bounties`
- - Anyone can claim a bounty by calling `bounty_claim(id, deadline)` up to `repeat` times which was specified in the bounty. This allows to have repeatative bounties or multiple working collaboratively. `deadline` specifies how long it will take the sender to complete the bounty.
- - If claimer decides to give up, they can call `bounty_giveup(id)`, and within `forgiveness_period` their claim bond will be returned. After this period, their bond is kept in the DAO.
- - When bounty is complete, call `bounty_done(id)`, which will start add a proposal `BountyDone` that when voted will pay to whoever done the bounty.
+
+3-Step Rust Installation.
+
-## Blob storage
+1. Install Rustup:
+
+```
+curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
+```
-DAO supports storing larger blobs of data and content indexing them by hash of the data.
-This is done to allow upgrading the DAO itself and other contracts.
+[_(Taken from official installation guide)_](https://www.rust-lang.org/tools/install)
-Blob lifecycle:
- - Store blob in the DAO
- - Create upgradability proposal
- - Proposal passes or fails
- - Remove blob and receive funds locked for storage back
+2. Configure your current shell:
-Blob can be removed only by the original storer.
+```
+source $HOME/.cargo/env
+```
-## Upgradability
+3. Add Wasm target to your toolchain:
-There are two major ways to upgrade the DAO:
- - Self upgrade by storing blob on the DAO contract and then voting to UpgradeSelf
- - Upgrade from the factory - factory stores new contract and then if allowed upgrades DAO by calling `upgrade(code)`.
+```
+rustup target add wasm32-unknown-unknown
+```
-DAO contracts can explicitly vote to disable factory auto upgrades and require to pull the upgrade themself from factory.
+
+
-## Testing
+---
-To test the sputnik2 DAO you will need a testnet account. If you don't have one yet create it in https://wallet.testnet.near.org/.
+
+1. Login with your account.
+
-Lets assume your account is 'sputnik2.testnet', and you want to deploy your first DAO in 'genesis.sputnik2.testnet'
+Using [`near-cli`](https://docs.near.org/docs/tools/near-cli#near-login), login to your account which will save your credentials locally:
-#### Step 1. Login with your account:
-```
+```bash
near login
```
-#### Step 2. Deploy factory:
+
+
-Use `export CONTRACT_ID=sputnik2.testnet` in the terminal to set the account where to deploy the factory. Then, execute the following command from the root of this repository.
+
+2. Clone repository.
+
-```
-near deploy $CONTRACT_ID --wasmFile=sputnikdao_factory2/res/sputnikdao_factory2.wasm
+```bash
+git clone https://github.com/near-daos/sputnik-dao-contract
```
-#### Step 3. Initialize factory:
-```
-near call $CONTRACT_ID new --accountId $CONTRACT_ID
+
+
+
+
+3. Build factory contract.
+
+
+```bash
+cd sputnik-dao-contract/sputnikdao-factory2 && ./build.sh
```
-#### Step 4. Define the parameters of the new DAO, its council and create it:
+
+
-Define the council of your DAO: `export COUNCIL='["councilmember.testnet", "sputnik2.testnet"]'`
+
+4. Deploy factory.
+
+- Create an env variable replacing `YOUR_ACCOUNT.testnet` with the name of the account you logged in with earlier:
+
+```bash
+export CONTRACT_ID=YOUR_ACCOUNT.testnet
```
-# bash
-ARGS=`echo '{"config": {"name": "genesis", "symbol": "GENESIS", "decimals": 24, "purpose": "test", "bond": "1000000000000000000000000", "metadata": ""}, "policy": '$COUNCIL'}' | base64 -w 0`
-# fish
-set ARGS (echo '{"config": {"name": "genesis", "symbol": "GENESIS", "decimals": 24, "purpose": "test", "bond": "1000000000000000000000000", "metadata": ""}, "policy": '$COUNCIL'}' | base64 -w 0)
+- Deploy factory contract by running the following command from your current directory _(`sputnik-dao-contract/sputnikdao-factory2`)_:
-# Create a new DAO with the given parameters.
-near call $CONTRACT_ID create "{\"name\": \"genesis\", \"args\": \"$ARGS\"}" --accountId $CONTRACT_ID --amount 5 --gas 150000000000000
+```bash
+near deploy $CONTRACT_ID --wasmFile=res/sputnikdao_factory2.wasm --accountId $CONTRACT_ID
```
-Set `export SPUTNIK_ID=genesis.$CONTRACT_ID`.
+
+
-Validate that it went through, and that it correctly set the policy:
-```
-near view $SPUTNIK_ID get_policy
+
+5. Initialize factory.
+
+
+```bash
+near call $CONTRACT_ID new --accountId $CONTRACT_ID
```
-#### Step 5. Create a proposal and interact with it:
+
+
-Lets use a third user, called `another-account.testnet` to create a proposal. The proposal asks for `another-account.testnet` they joins the council. The proposal will be votable for only a minute (`"submission_time":"60000000000"`).
+
+6. Define the parameters of the new DAO, its council, and create it.
+
-```
-near call $SPUTNIK_ID add_proposal '{"proposal": {"description": "test", "submission_time":"60000000000", "kind": {"AddMemberToRole": {"member_id": "another-account.testnet", "role": "council"}}}}' --accountId another-account.testnet --amount 1
-```
+- Define the council of your DAO:
-Vote "Approve" using the **council members**:
+```bash
+export COUNCIL='["council-member.testnet", "YOUR_ACCOUNT.testnet"]'
```
-near call $SPUTNIK_ID act_proposal '{"id": 0, "action": "VoteApprove"}' --accountId sputnik2.testnet
-near call $SPUTNIK_ID act_proposal '{"id": 0, "action": "VoteApprove"}' --accountId councilmember.testnet
+
+- Configure the name, purpose, and initial council members of the DAO and convert the arguments in base64:
+
+```bash
+export ARGS=`echo '{"config": {"name": "genesis", "purpose": "Genesis DAO", "metadata":""}, "policy": '$COUNCIL'}' | base64`
```
-View proposal:
+- Create the new DAO!:
+
+```bash
+near call $CONTRACT_ID create "{\"name\": \"genesis\", \"args\": \"$ARGS\"}" --accountId $CONTRACT_ID --amount 5 --gas 150000000000000
```
-near view $SPUTNIK_ID get_proposal '{"id": 0}'
+
+**Example Response:**
+
+```bash
+Scheduling a call: sputnik-v2.testnet.create({"name": "genesis", "args": "eyJjb25maWciOiB7Im5hbWUiOiAiZ2VuZXNpcyIsICJwdXJwb3NlIjogIkdlbmVzaXMgREFPIiwgIm1ldGFkYXRhIjoiIn0sICJwb2xpY3kiOiBbImNvdW5jaWwtbWVtYmVyLnRlc3RuZXQiLCAiWU9VUl9BQ0NPVU5ULnRlc3RuZXQiXX0K"}) with attached 5 NEAR
+Transaction Id 5beqy8ZMkzpzw7bTLPMv6qswukqqowfzYXZnMAitRVS7
+To see the transaction in the transaction explorer, please open this url in your browser
+https://explorer.testnet.near.org/transactions/5beqy8ZMkzpzw7bTLPMv6qswukqqowfzYXZnMAitRVS7
+true
```
-After one minute, the user "another-account.testnet" will be added to the council
+**Note:** If you see `false` at the bottom (after the transaction link) something went wrong. Check your arguments passed and target contracts and re-deploy.
+
+
+
+
+
+7. Verify successful deployment and policy configuration.
+
+
+The DAO deployment will create a new [sub-account](https://docs.near.org/docs/concepts/account#subaccounts) ( `genesis.YOUR_ACCOUNT.testnet` ) and deploy a Sputnik v2 DAO contract to it.
+
+- Setup another env variable for your DAO contract:
+
+```bash
+export SPUTNIK_ID=genesis.$CONTRACT_ID
```
+
+- Now call `get_policy` on this contract using [`near view`](https://docs.near.org/docs/tools/near-cli#near-view)
+
+```bash
near view $SPUTNIK_ID get_policy
```
-View first 10 proposals:
-```
-near view $SPUTNIK_ID get_proposals '{"from_index": 0, "limit": 10}'
+- Verify that the name, purpose, metadata, and council are all configured correctly. Also note the following default values:
+
+```json
+{
+ "roles": [
+ {
+ "name": "all",
+ "kind": "Everyone",
+ "permissions": ["*:AddProposal"],
+ "vote_policy": {}
+ },
+ {
+ "name": "council",
+ "kind": { "Group": ["council-member.testnet", "YOUR_ACCOUNT.testnet"] },
+ "permissions": [
+ "*:Finalize",
+ "*:AddProposal",
+ "*:VoteApprove",
+ "*:VoteReject",
+ "*:VoteRemove"
+ ],
+ "vote_policy": {}
+ }
+ ],
+ "default_vote_policy": {
+ "weight_kind": "RoleWeight",
+ "quorum": "0",
+ "threshold": [1, 2]
+ },
+ "proposal_bond": "1000000000000000000000000",
+ "proposal_period": "604800000000000",
+ "bounty_bond": "1000000000000000000000000",
+ "bounty_forgiveness_period": "86400000000000"
+}
```
+
+
-## Proposal Kinds
+---
-Each kind of proposal represents an operation the DAO can perform. Proposal kinds are:
-```
+## Roles and Permissions
+
+> The DAO can have several roles, each of which allows for permission configuring. These permissions are a combination of [`proposal_kind`](#proposal-types) and `VotingAction`. Due to this combination these permissions can be scoped to be very specific or you can use wildcards to grant greater access.
+
+**Examples:**
+
+- A role with: `["transfer:VoteReject","transfer:VoteRemove"]` means they can only vote to _reject_ or _remove_ a `transfer` proposal but they can't vote to approve.
+
+- A role with: `["transfer:*"]` can perform any vote action on `transfer` proposals.
+
+- A role with: `["*:*"]` has _unlimited_ permission. Normally, the `council` role has `*:*` as its permission so they can perform _any_ vote action on _any_ kind of proposal.
+
+**Here is a list of actions:**
+
+- `AddProposal` - _Adds given proposal to the DAO (this is the primary mechanism for getting things done)._
+- `RemoveProposal` - _Removes given proposal (this is used for immediate deletion in special cases)._
+- `VoteApprove` - _Votes to approve given proposal or bounty._
+- `VoteReject` - _Votes to reject given proposal or bounty._
+- `VoteRemove` - _Votes to remove given proposal or bounty (this may be because the proposal is spam or otherwise invalid)._
+- `Finalize` - _Finalizes proposal which is cancelled when proposal has expired (this action also returns funds)._
+- `MoveToHub` - _Moves a proposal to the hub (this is used to move a proposal into another DAO)._
+
+---
+
+## Proposals
+
+> Proposals are the main way to interact with the DAO. Each action on the DAO is performed by creating and approving a proposal.
+
+| Contents |
+| --------------------------------------------------- |
+| [Proposal types](#proposal-types) |
+| [Add proposal](#add-proposal) |
+| [View proposal](#view-proposal) |
+| [View multiple proposals](#view-multiple-proposals) |
+| [Approve proposal](#approve-proposal) |
+
+---
+
+### Proposal types
+
+> Each kind of proposal represents an operation the DAO can perform. Here are the kinds of proposals:
+
+```rs
ProposalKind::ChangeConfig { .. },
ProposalKind::ChangePolicy { .. },
ProposalKind::AddMemberToRole { .. },
@@ -142,43 +271,306 @@ ProposalKind::BountyDone { .. },
ProposalKind::Vote,
ProposalKind::FactoryInfoUpdate { .. },
```
-### Voting Policy
-You can set a different vote policy for each one of the proposal kinds.
+- **ChangeConfig** - used to change the configuration of the DAO
+- **ChangePolicy** - used to change the policy of the DAO
+- **AddMemberToRole** - used to add a member to a role in the DAO
+- **RemoveMemberFromRole** - used to remove a member from a role in the DAO
+- **FunctionCall** - used to a call a function on any valid account on the network including the DAO itself, any other DAO, or any other contract. This is a useful mechanism for extending the capabilities of the DAO without modifying or complicating the DAO contract code. One can imagine a family of contracts built specifically to serve the DAO as agents, proxies, oracles and banks, for example.
+- **UpgradeSelf** - used to upgrade the DAO contract itself.
+- **UpgradeRemote** - used to upgrade other contracts. For DAOs that are governing other protocols, this type of proposal will allow to upgrade another contract with its newer version.
+- **Transfer** - used to move assets from this DAO to another account on the network. Supports both `NEAR` and any `NEP-141` token that this DAO has.
+- **SetStakingContract** - used to set the staking contract of the DAO to help users delegate their tokens.
+- **AddBounty** - used to add a bounty to encourage members of the DAO community to contribute their time and attention to the needs of the DAO
+- **BountyDone** - used to mark the completion of an available bounty
+- **Vote** - used to create polls. Vote proposal doesn't have any action.
+- **FactoryInfoUpdate** - used for changing permissions of the factory that created the DAO. By default, the factory has permission to upgrade the DAO, but this can be modified by using `FactoryInfoUpdate`.
+
+---
+
+### Add proposal
+
+> Adds a proposal to the DAO contract and returns the index number of the proposal or "proposal ID". By default, anyone can add a proposal but it requires a minimum 1 Ⓝ bond (attached deposit).
+
+- method: `add_proposal`
+- params:
+ - `proposal`
+ - `description`
+ - `kind`
+- proposer account ID
+- attached deposit (minimum 1 Ⓝ)
+
+
+Example argument structure:
+
+
+```json
+{
+ "proposal": {
+ "description": "Add New Council",
+ "kind": {
+ "AddMemberToRole": {
+ "member_id": "council_member_3.testnet",
+ "role": "council"
+ }
+ }
+ }
+}
+```
+
+
+
+
+
+Example near-cli command:
+
+
+```bash
+near call genesis.sputnik-v2.testnet add_proposal \
+'{"proposal": {"description": "Add New Council", "kind": {"AddMemberToRole": {"member_id": "council_member_3.testnet", "role": "council"}}}}' \
+--accountId proposer.testnet \
+--amount 1
+```
+
+
+
+
+
+Example response:
+
+
+```bash
+Transaction Id HbJdK9AnZrvjuuoys2z1PojdkyFiuWBvrDbXsAf5ndvu
+To see the transaction in the transaction explorer, please open this url in your browser
+https://explorer.testnet.near.org/transactions/HbJdK9AnZrvjuuoys2z1PojdkyFiuWBvrDbXsAf5ndvu
+0
+```
+
+**Note:** The number under the transaction link is the proposal ID.
+
+
+
+
+---
+
+### View proposal
+
+> Returns proposal details by passing the ID or index of a given proposal.
+
+- method: `get_proposal`
+ - params: `id`
+
+
+Example near-cli command:
+
+
+```bash
+near view genesis.sputnik-v2.testnet get_proposal '{"id": 0}'
+```
+
+
+
+
+
+Example response:
+
+
+```json
+{
+ "id": 0,
+ "proposer": "near-example.testnet",
+ "description": "Add New Council",
+ "kind": {
+ "AddMemberToRole": {
+ "member_id": "council_member_3.testnet",
+ "role": "council"
+ }
+ },
+ "status": "InProgress",
+ "vote_counts": {},
+ "votes": {},
+ "submission_time": "1624947631810665051"
+}
+```
+
+
+
+
+---
+
+### View multiple proposals
+
+> Returns multiple proposal details by passing the index ("ID") starting point and a limit of how many records you would like returned.
+
+- method: `get_proposals`
+- params:
+ - `from_index`
+ - `limit`
+
+
+Example near-cli command:
+
+
+```bash
+near view genesis.sputnik-v2.testnet get_proposals '{"from_index": 1, "limit": 2}'
+```
+
+
+
+
+
+Example response:
+
+
+```js
+[
+ {
+ id: 1,
+ proposer: 'near-example.testnet',
+ description: 'Add New Council',
+ kind: {
+ AddMemberToRole: { member_id: 'council_member_4.testnet', role: 'council' }
+ },
+ status: 'InProgress',
+ vote_counts: {},
+ votes: {},
+ submission_time: '1624947785010147691'
+ },
+ {
+ id: 2,
+ proposer: 'near-example.testnet',
+ description: 'Add New Council',
+ kind: {
+ AddMemberToRole: { member_id: 'council_member_5.testnet', role: 'council' }
+ },
+ status: 'InProgress',
+ vote_counts: {},
+ votes: {},
+ submission_time: '1624947838518330827'
+ }
+]
+```
+
+
+
+
+---
+
+### Approve proposal
+
+> Approves proposal by ID. Only council members can approve a proposal
+
+- method: `act_proposal`
+- params:
+ - `id`
+ - `action`
+- account ID that is a council member.
+
+
+Example near-cli command:
+
+
+```bash
+near call genesis.sputnik-v2.testnet act_proposal '{"id": 0, "action": "VoteApprove"}' \
+--accountId council_member_1.testnet
+```
+
+
+
+
+
+Example response:
+
+
+```bash
+Receipts: 3mkSgRaHsd46FHkf9AtTcPbNXkYkxMCzPfJFHsHk8NPm, GjJ6hmoAhxt2a7si4hVPYZiL9CWeM5fmSEzMTpC7URxV
+ Log [genesis.sputnik-v2.testnet]: ["council"]
+Transaction Id BZPHxNoBpyMG4seCojzeNrKpr685vWPynDMTdg1JACa7
+To see the transaction in the transaction explorer, please open this url in your browser
+https://explorer.testnet.near.org/transactions/BZPHxNoBpyMG4seCojzeNrKpr685vWPynDMTdg1JACa7
+''
+```
+
+
+
+
+---
+
+## Voting
+
+>
+
+### Vote on a proposal
+
+> Only council members are allowed to vote on a proposal.
+
+---
+
+### Voting policy
+
+> You can set a different vote policy for each one of the proposal kinds.
Vote policy can be: `TokenWeight`, meaning members vote with tokens, or `RoleWeight(role)` where all users with such role (e.g."council") can vote.
-Also a vote policy has a "threshold". The threshold could be a ratio. e.g. `threshold:[1,2]` => 1/2 or 50% of the votes approve the proposal, or the threshold could be a fixed number (weight), so you can say that you need 3 votes to approve a proposal disregarding the amount of people in the rol, and you can say that you need 1m tokens to approve a proposal disregarding total token supply.
+Also a vote policy has a "threshold". The threshold could be a ratio. e.g. `threshold:[1,2]` => 1/2 or 50% of the votes approve the proposal, or the threshold could be a fixed number (weight), so you can say that you need 3 votes to approve a proposal disregarding the amount of people in the role, and you can say that you need 1m tokens to approve a proposal disregarding total token supply.
When vote policy is `TokenWeight`, vote % is measured against total toke supply, and each member vote weight is based on tokens owned. So if threshold is 1/2 you need half the token supply to vote "yes" to pass a proposal.
When vote policy is `RoleWeight(role)`, vote % is measured against the count of people with that role, and each member has one vote. So if threshold is 1/2 you need half the members with the role to vote "yes" to pass a proposal.
-## Roles & Permissions
+---
-The DAO can have several roles, and you can define permissions for each role. A permission is a combination of `proposal_kind:VotingAction` so they can become very specific.
+### Token voting
-Actions are:
-```
-/// Action to add proposal. Used internally.
-AddProposal,
-/// Action to remove given proposal. Used for immediate deletion in special cases.
-RemoveProposal,
-/// Vote to approve given proposal or bounty.
-VoteApprove,
-/// Vote to reject given proposal or bounty.
-VoteReject,
-/// Vote to remove given proposal or bounty (because it's spam).
-VoteRemove,
-/// Finalize proposal, called when it's expired to return the funds
-/// (or in the future can be used for early proposal closure).
-Finalize,
-/// Move a proposal to the hub to shift into another DAO.
-MoveToHub
-```
+> DAO votes to select some token to become voting token (only can be done once, can't change later).
-so, for example a role with: `["mint:VoteReject","mint:VoteRemove"]` means the users with that role can only vote to *reject or remove a mint proposal*, but they can't vote to approve.
+User flow to vote with selected token:
-You can use `*` as a wildcard, so for example a role with `mint:*` can perform any vote action on mint proposals.
+- Users deposit the desired amount of the token to the separate staking contract defined by the DAO.
+- They can then choose who to delegate these tokens. It can be to themselves or to other users to increase their vote weight.
+- When users vote for proposals, their vote is weighted by all the delegations to them.
+- Undelegating will block delegating / withdrawing until one voting period passes.
+- Undelegated tokens can be withdrawn by the user.
+
+---
+
+## Bounties
+
+> Add and configure bounties using `AddBounty` proposal.
+
+The lifecycle of a bounty is the next:
+
+- Anyone with permission can add proposal `AddBounty` which contains the bounty information including `token` to pay the reward in and `amount` to pay it out.
+- This proposal gets voted in by the current voting policy.
+- After proposal is passed, the bounty gets added. Now it has an `id` in the bounty list which can be queried via `get_bounties`.
+- Anyone can claim a bounty by calling `bounty_claim(id, deadline)` up to `repeat` times which was specified in the bounty. This allows to have repetitive bounties or multiple working collaboratively.
+- `deadline` specifies how long it will take the sender to complete the bounty.
+- If claimer decides to give up, they can call `bounty_giveup(id)`, and within `forgiveness_period` their claim bond will be returned. After this period, their bond is forfeited and is kept in the DAO.
+- When a bounty is complete, call `bounty_done(id)`, which will add a proposal `BountyDone` that, when voted, will pay to whoever completed the bounty.
+
+---
+
+## Blob storage
+
+> DAO supports storing larger blobs of data and content indexing them by hash of the data. This is done to allow upgrading the DAO itself and other contracts.
+
+Blob lifecycle:
+
+- Store blob in the DAO.
+- Create upgradability proposal.
+- Proposal passes or fails.
+- Remove blob and receive funds locked for storage back.
+
+Blob can be removed only by the original storer.
+
+---
+
+## Upgradability
+
+> Allow the DAO to be upgraded to different contract code versions. This allows the DAO to use a newer, more stable and faster version of the contract code. New versions usually include new features, bug fixes and improvements in performance. Downgrade to an older version is also possible.
+
+There are two major ways to upgrade the DAO:
+ - Self upgrade by storing blob on the DAO contract and then voting to UpgradeSelf
+ - Upgrade from the factory - factory stores new contract and then, if allowed, it upgrades the DAO by calling `upgrade(code)`.
-You can also use `*:*` for unlimited permission, normally the `council` role has `*:*` as its configured permission so they can perform any vote action on any kind of proposal.
+DAOs can explicitly vote to disable factory auto upgrades and can pull the upgrade themselves from the factory.