Skip to content

[Plan]: GoodDaoHouses MVP implementation outline #298

Description

@L03TJ3

Summary

Execution plan for the GoodDaoHouses.sol MVP requested in #297.

Execution plan

1. Contract placement and architecture

  • Add GoodDaoHouses.sol under contracts/governance/ next to CompoundVotingMachine.sol, GReputation.sol, and the staking contracts.
  • Keep the MVP as one contract with internal structs/enums for house membership, HoA eligibility, vote snapshots, ballots, finalized results, and FlowSplitter pool tracking.
  • Make the contract upgradeable and NameService-aware so it fits the existing governance deployment model.

2. Existing repo patterns to reuse

  • Reuse DAOUpgradeableContract + NameService lookup for protocol wiring and avatar-authorized upgrades.
  • Reuse OpenZeppelin AccessControlUpgradeable role patterns already used in Reputation.sol and Faucet.sol for committee/admin permissions.
  • Reuse snapshot-style governance ideas from CompoundVotingMachine.sol: explicit vote creation, stored start/end boundaries, and frozen voting eligibility at creation time.
  • Reuse staking UX from GoodDollarStaking.sol, especially the onTokenTransfer entrypoint for one-transaction staking.

3. Token and single-transaction staking path

  • Use the G$ token already exposed through NameService (GOODDOLLAR) and its existing transferAndCall / ERC677-style callback path.
  • Preferred registration flow: GoodDollar.transferAndCall(housesContract, amount, encodedRegistrationData) -> onTokenTransfer decodes house type + metadata and performs register-and-stake atomically.
  • Keep a plain registerAndStake / stake path only if needed for operational flexibility, but the primary MVP path should be ERC677-based because it already exists and is tested in this repo.
  • Do not base the MVP on ERC777 hooks; the repo’s proven staking pattern for G$ membership flows is transferAndCall.

4. Membership and registry model

  • Define enum House { Citizens, Alignment } and enum MemberStatus { None, Pending, Active, Revoked, Unstaked }.
  • Store per-member state: house, status, staked amount, joinedAt, updatedAt, unstakedAt, and metadata fields required by each house.
  • Store separate HoA eligibility records with isEligible, listedAt, updatedAt, and optional delisted timestamp.
  • Restrict HoA registration to eligible addresses only; HoC registration can activate immediately after staking.
  • Preserve historical participation through events and timestamps even after revocation or unstake.

5. Permission model

  • Use DEFAULT_ADMIN_ROLE for emergency/admin actions such as pausing and role management.
  • Use one broad GOVERNANCE_COMMITTEE_ROLE in the MVP for HoA eligibility management, HoA approval/revocation, vote creation, vote finalization, and result execution.
  • Defer finer-grained role splitting unless a reviewer explicitly wants operational separation; one committee role matches the stated MVP scope and keeps deployment simpler.
  • Add pause protection only on sensitive write paths: registration, approval/revocation, vote creation, vote casting updates, finalize, and execute.

6. AlignmentVote shape

  • Model a single AlignmentVote type with manual creation by committee for the quarterly cycle.
  • On creation, snapshot:
    • active HoA recipients
    • active HoA voters
    • active HoC voters
    • fixed per-house voting weights (40 HoA / 4 HoC)
    • vote open/close timestamps (default 7 days)
  • Store per-voter ballot totals so a voter can replace their allocation while the vote is open.
  • Finalization should compute and persist canonical results on-chain before any FlowSplitter call.
  • Execution must be a separate permissioned step, one-time only, and must not erase finalized results if downstream execution fails.

7. Read/write/event surface to plan for

  • Reads: member records, HoA eligibility, stake requirement config, active-member checks, vote config, vote snapshots, ballot state, finalized allocations, execution status, FlowSplitter pool config, FlowSplitter pool id, and FlowSplitter pool address.
  • Writes: add/remove HoA eligibility, register via callback, approve/revoke HoA member, unstake, create vote, cast/update vote, finalize vote, execute results, configure FlowSplitter, create the FlowSplitter pool, sync pool metadata, pause/unpause.
  • Events: eligibility added/removed, member registered, member approved, member revoked, unstaked, vote created, vote updated, vote finalized, vote executed, FlowSplitter config changed, FlowSplitter pool created.

8. FlowSplitter integration boundary

  • Use the published IFlowSplitter contract shape from Flowstate docs/Git source, not an ad-hoc local interface.
  • The exact contract support needed is:
    • createPool(ISuperToken, PoolConfig, PoolERC20Metadata, Member[], address[], string) returns (ISuperfluidPool)
    • updateMembersUnits(uint256, Member[])
    • updatePoolMetadata(uint256, string)
    • isPoolAdmin(uint256, address)
    • getPoolById(uint256) for verification/recovery reads
    • optional admin sync through addPoolAdmin, removePoolAdmin, or updatePoolAdmins if operational ownership needs to change later
  • Mirror the external data types exactly when integrating:
    • Member { address account; uint128 units; }
    • Admin { address account; AdminStatus status; }
    • Pool { uint256 id; address poolAddress; address token; string metadata; bytes32 adminRole; }
    • PoolConfig { bool transferabilityForUnitsOwner; bool distributionFromAnyAddress; }
    • PoolERC20Metadata { string name; string symbol; uint8 decimals; }
  • The integration must persist enough state to keep updating the same pool after creation: FlowSplitter contract address, pool id, pool address, metadata, and whether the pool has already been initialized.
  • Because FlowSplitter admin permissions are address-based, GoodDaoHouses itself should be registered as a pool admin if it is the contract that will perform future updateMembersUnits calls; GovCo authorization should stay enforced inside GoodDaoHouses rather than by making rotating EOAs the direct FlowSplitter admins.
  • Pool creation should use the GoodDollar SuperToken and custom pool metadata. The contract should create the pool once on first successful execution, then reuse updateMembersUnits on subsequent executions rather than recreating the pool.
  • The finalized vote output has to be converted into FlowSplitter uint128 units. Since allocations are defined as votePercentage * totalUnits, the implementation should normalize every recipient into deterministic units against totalUnits before calling createPool or updateMembersUnits.
  • Unstaking or approval removal should send an explicit Member(account, 0) unit update so the recipient’s incoming stream allocation is cleared.
  • Metadata should remain plain strings and be propagated through createPool(..., _metadata) and updatePoolMetadata as needed.
  • Recommended pool configuration for the governance-controlled MVP is transferabilityForUnitsOwner = false and distributionFromAnyAddress = false, so unit ownership and stream distribution stay under governance-controlled execution.

9. Deployment and test conventions

  • Follow the repo’s upgradeable deployment pattern used by governance contracts and multichain deploy scripts.
  • Register the deployed contract through NameService / release metadata like the existing governance components.
  • Add governance tests under test/governance/ using createDAO() fixtures and loadFixture(...).
  • Cover at minimum:
    • HoA eligibility gating
    • ERC677 register+stake flow
    • HoC immediate activation
    • HoA pending -> active approval flow
    • revocation / unstake state transitions
    • vote snapshot correctness
    • weighted vote replacement logic
    • finalize-before-execute guarantee
    • single-execution and failed-execution persistence
    • FlowSplitter pool creation on first execution
    • FlowSplitter member unit updates on re-execution
    • zero-unit update on unstake / HoA approval removal
    • role and pause enforcement

10. Resolved implementation requirements

  • Minimum stake amounts should be configurable per house by the GovCo role.
  • Unstaking should fully clear HoA approval and update units so the affected recipient’s incoming stream is set to 0.
  • Metadata should be stored as plain strings on-chain for now.
  • FlowSplitter execution should use the GoodDollar SuperToken, with allocations calculated as votePercentage * totalUnits.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions