HydroBlockchain / community-brainstorming

A place for the Hydro Community to discuss ideas for the HCDP
1 stars 0 forks source link

Minimum viable decentralization for Hydro DAs #39

Open AnuragHydro opened 5 years ago

AnuragHydro commented 5 years ago

There's been a lot of talk about moving the DAs in a decentralized route. Here, I've proposed a minimum viable specification for decentralization of Hydro DAs. This just covers the necessary functionality; the process itself can and probably should be done using an external tool like Aragon (#27 ) but anyways, I just wanted to put something out to make it easier for the DAs to get started on this kind of initiative and spark some thought.

Overview

DAO purpose:

Global community committed to building core and associated infrastructure to advance the Hydro roadmap and support its implementations.

Points of note

Some or all DAs should be part of the foundation DAO should be managed by a smart contract - high priority All discussion can continue to happen off-chain through slack, etc; finalization of votes can occur through smart contract. Foundation should run through

SC requirements

Allows DAs to set corresponding variables to enforce multisig schemes for: Adding/removing DAs Setting roles for DAs and corresponding disbursement amounts Changing DAs/roles Changing required signatures for a given variable Unlocks ability to disburse DA funds on a monthly basis; enforces that these funds, once unlocked, can only go to the appropriate DAs in amounts as determined by their role Allows anybody to make the actual transfer for unlocked funds

Framework for SC structure for multisig DA contract

Contract variables

daRoles (bytes32[] - array of hashes of each role) daRoleAmounts (uint[] - each corresponds to each role) existingDas (address[] or uint[] if you want to get fancy with EINs) disbursementDate disbursementAmountByRole (array of uints corresponding to roles) signaturesToAdd (uint) signaturesToRemove (uint) signaturesToAddRole (uint) signaturesToRemoveRole (uint) signaturesToChangeRole (uint - also consists of changing the corresponding amount) signaturesToChangeRoleOfDa (uint) signaturesToChangeDaAddress (uint) signaturesToChangeRequiredSignatures (uint) signaturesRequiredToTransferFunds (uint) signaturesRequiredForCompleteTransfer (uint) signaturesRequiredToUpgradeDaMultisig (uint)

Mappings:

Address => bytes32; (or uint[] if you’re using EINs) roleByAddress Bytes32 => uint payoutByRole

Constructor

Sets existing DAs in contract Sets all starting variables as determined off-chain by DAs

Functions:

disbursementTrigger - can be called by any address: //verify timestamp Require that current time >= disbursementDate // make sure that the contract has enough balance to make the payment Set variable uint totalDisbursementAmount = 0; Loop through existingDas to get each of their roles; after each one, set totalDisbursementAmount = totalDisbursementAmount + (daRoleAmount for the given role). At the end, require that totalDisbursementAmount <= contract balance // set date of next disbursement Call setDisbursementDate //pay DAs Calls Disburse

Disburse (internal - called by disbursement trigger): //loop through all DAs, figure out how much they’re owed, and pay them For (i = 0, i<existingDas.length(), i++){ payOut(existingDas[i])}

payOut (internal - called by Disburse) Get bytes32[] role of existingDas[i] from mapping Determine payoutByRole for the given role from mapping transfer corresponding amount of HYDRO to address at i

setDisbursementDate internal() disbursementDate = disbursementDate + 1 month

Function addDas(_newDaAddresses address[], _daRoles bytes32[], _vSignatures bytes32[], _rSignatures bytes32[], _sSignatures bytes32[]) Require v, r, and s length are all >= signaturesToAdd Require checkSignatures pans out for all passed signatures Add the passed array of newDaAddresses to existingDas Loop through the DAs being added, update the roleByAddress mapping to reflect their roles

Function removeDas ( analogous to addDas above)

Function addRole (bytes32 _roleName, uint _roleAmount, _vSignatures bytes32[], _rSignatures bytes32[], _sSignatures bytes32[]) Require v, r, and s signatures are all >= signaturesToAddRole Require checkSignatures pans out for all passed signatures Add the new role to daRoles[] Update payoutByRole mapping to reflect _roleAmount

Function removeRole (analogous to addRole above)

Function fundContract payable() // this is so you can fund the contract intermittently instead of funding the whole thing at once // probably want to drive signature requirements as a percentage

Function checkSignatures (internal -- has logic to check signatures against list of DAs - accepts array of signatures) // common logic for checking signatures - probably want to treat requiredSignatures as a proportion of total DAs rather than overall.

Function upgradeDaMultisig Pass existingDas[], roles, etc as arguments Check all signatures Send complete HYDRO balance of the contract to a new passed contract address

/**

mitdralla commented 5 years ago

Hey @AnuragHydro, I really like the details you included here for making DA's and their functions more decentralized. I believe this covers the bases on what we would need to get up and running.

Question: "Setting roles for DAs and corresponding disbursement amounts" is the dispersement amount per DA? or per role? There is an instance where one DA could be compensated differently from another so I just wanted to get your thoughts on where / how this data would or could be stored.

AnuragHydro commented 5 years ago

@mitdralla great :) happy to work through any additional functionality with you guys as well or anything that comes up in the build process.

The way I've got it set up rn involves assigning a role for each DA and setting an amount-per-role. i.e. all DAs with a given role would receive the same amount (roles can be dev, bizdev, etc or more specific: pres, treasurer, etc). That's just one way to do it though, so if you guys want to send every DA the same exact amount, or customize amounts per-DA, etc any of those structures could be implemented instead! I know you guys currently do 444,444 per DA per month, so in this implementation we'd set the role of "DA" for every single DA and set the amount for anyone with the role of "DA" as 444,444. That way, if you ever wanted to add more distinction between roles in the future, you'd be able to do so.

jzafrap commented 5 years ago

Hello, FYI, OpenZeppelin has prototype contracts for Roles, TokenVesting and others that could be useful for this purposes, or as a reference: OpenZeppelin.

AnuragHydro commented 5 years ago

Yep yep! I'm certain there's no need to build this from scratch given all the existing tools out there - more wanted to focus the discussion around the specific features and implementation of a roles-based token release contract, and the mechanisms by which Hydro DAs can self-govern through the contract as an organization. The OpenZepelin prototype definitely provides a good structure for releasing to a beneficiary as defined by the owner of the contract. Our focus here should be modifying the "owner" structure to a defined governance structure among DAs who are perpetually being added and removed from the contract.