Open AnuragHydro opened 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.
@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.
Hello, FYI, OpenZeppelin has prototype contracts for Roles, TokenVesting and others that could be useful for this purposes, or as a reference: OpenZeppelin.
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.
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:
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
/**