Skip to content

feat: O.U.R.COOP artist-cooperative governance on the crowdstake stack#131

Open
RonTuretzky wants to merge 5 commits into
mainfrom
RonTuretzky/cova-coin-custom-impl
Open

feat: O.U.R.COOP artist-cooperative governance on the crowdstake stack#131
RonTuretzky wants to merge 5 commits into
mainfrom
RonTuretzky/cova-coin-custom-impl

Conversation

@RonTuretzky

Copy link
Copy Markdown
Contributor

Adds src/cova/ — a custom O.U.R.COOP artist-cooperative built entirely on the BreadKit/CrowdStake abstractions and deployed via CrowdStakeFactory: CovaDollarYield (USD-pegged yield-bearing AbstractToken over an ERC-4626 vault), CovaProjectRegistry (AbstractRecipientRegistry + full/minimum-viable budgets), OnePersonOneVotePower (IVotingPowerStrategy, one member = one equal vote), CovaPointsVotingModule (AbstractVotingModule, raw 100-point ballots), CovaArtFundStrategy (AbstractDistributionStrategy single-round top-N allocation with minimum-viable redistribution, driven per cycle by AbstractDistributionManager + AbstractCycleModule so funding is cycle-gated and non-drainable), and CovaWithdrawals (four-fund propose/vote/close governance). Includes Sepolia mocks (MockUSD, MockUSDVault) so the yield token works on testnet, script/DeployCova.s.sol wiring the whole system through the factory, and test/cova/CovaCrowdstake.t.sol covering the end-to-end flows (the spec's worked example matches exactly). foundry.toml enables the optimizer (contracts exceed EIP-170 without it) and .gitignore now excludes broadcast/ deployment artifacts. No existing protocol files are modified — this is purely additive on top of v0.0.1.

RonTuretzky and others added 5 commits May 19, 2026 17:30
Custom cooperative built on the BreadKit/CrowdStake abstractions, all deployed
via CrowdStakeFactory:

- CovaDollarYield: USD-pegged yield-bearing AbstractToken over an ERC-4626 vault
- CovaProjectRegistry: AbstractRecipientRegistry + full/min-viable budgets
- OnePersonOneVotePower: IVotingPowerStrategy (one member, one equal vote)
- CovaPointsVotingModule: AbstractVotingModule, raw 100-point ballots
- CovaArtFundStrategy: AbstractDistributionStrategy with single-round top-N
  allocation + minimum-viable redistribution, driven per cycle by the
  AbstractDistributionManager + AbstractCycleModule (cycle-gated, no drain)
- CovaWithdrawals: four-fund propose/vote/close governance
- Sepolia mocks (MockUSD, MockUSDVault) so the yield token works on testnet
- DeployCova.s.sol wires the full system via the factory
- CovaCrowdstake.t.sol covers the end-to-end flows (worked example exact)
- foundry.toml: enable optimizer (EIP-170 size); .gitignore: ignore broadcast/
…l' into RonTuretzky/cova-coin-custom-impl

# Conflicts:
#	test/VotingStreakNFTModule.t.sol

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new src/cova/ feature slice that composes existing CrowdStake/BreadKit abstractions into an O.U.R.COOP artist-cooperative governance system (yield token + project registry + voting + distribution strategy + withdrawals), plus a Sepolia deployment script and end-to-end Foundry tests. Also includes minor formatting/cleanup changes in existing tests/contracts and enables the Foundry optimizer.

Changes:

  • Introduces COVA modules: one-person-one-vote power, raw 100-point voting, project registry with budgets/metadata, Art Fund distribution strategy, and a withdrawals governance module.
  • Adds Sepolia mocks (MockUSD, MockUSDVault), a DeployCova script, and an end-to-end CovaCrowdstake integration test.
  • Enables Foundry optimizer and applies small formatting/cleanup tweaks across a few existing files.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
test/VotingStreakNFTModule.t.sol Formatting cleanup in test assertions / tuple destructuring.
test/mocks/MockCrowdstakeNFT.sol Removes trailing whitespace/line; no logic change.
test/fuzz/VotingModuleFuzz.t.sol Formatting cleanup for EIP-712 hash construction and tuple destructuring.
test/fuzz/TWVPFuzz.t.sol Formatting cleanup for fuzz test signature and braces.
test/fuzz/RecipientRegistryFuzz.t.sol Formatting cleanup for fuzz test signature and braces.
test/fuzz/DistributionFuzz.t.sol Formatting cleanup for fuzz test signatures and layout.
test/FactoryModuleDeployment.t.sol Formatting cleanup for vm.mockCall and initializer payload encoding.
test/DistributionCycleIntegration.t.sol Formatting cleanup for init payload and vm.mockCall usage.
test/cova/CovaCrowdstake.t.sol New end-to-end tests covering token yield, distribution cycle gating, voting constraints, and withdrawals flow.
src/interfaces/ICrowdstakeNFT.sol Trailing whitespace cleanup.
src/implementation/VotingStreakNFTModule.sol Formatting cleanup; no apparent behavior change.
src/implementation/strategies/VotingDistributionStrategy.sol Formatting cleanup for initializer signature.
src/implementation/strategies/EqualDistributionStrategy.sol Formatting cleanup for initializer signature.
src/cova/OnePersonOneVotePower.sol New curated membership-based IVotingPowerStrategy (1 member = 1 vote unit).
src/cova/mocks/MockUSDVault.sol New minimal ERC-4626-style vault mock with yield simulation for Sepolia/testing.
src/cova/mocks/MockUSD.sol New faucet-mintable USD ERC20 mock for Sepolia/testing.
src/cova/interfaces/ICovaProjectRegistry.sol New interface extending recipient registry with project metadata + budgets.
src/cova/CovaWithdrawals.sol New four-fund governance withdrawals module (propose/vote/close).
src/cova/CovaProjectRegistry.sol New recipient registry implementation with project metadata (budgets/title/summary).
src/cova/CovaPointsVotingModule.sol New raw 100-point ballot voting module (membership-gated, recast supported).
src/cova/CovaDollarYield.sol New AbstractToken yield wrapper over an ERC-4626 USD vault.
src/cova/CovaArtFundStrategy.sol New top-N, capped, min-viable redistribution distribution strategy driven by votes/budgets.
src/base/BasisPointsVotingModule.sol Minor signature keyword ordering change (virtual override).
src/abstract/AbstractDistributionStrategy.sol Formatting cleanup for initializer helpers.
script/DeployCova.s.sol New deployment script wiring COVA modules through CrowdStakeFactory and seeding demo data.
foundry.toml Enables optimizer + sets optimizer runs.
.gitignore Ignores broadcast/ deployment artifacts.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +89 to +94
function initialize(address token_, address membership_, address coordinator_) external initializer {
__Ownable_init(coordinator_);
Store storage $ = _s();
$.token = IERC20(token_);
$.membership = IMembership(membership_);
}
Comment on lines +120 to +125
if (fund >= FUND_COUNT) revert InvalidFund();
Store storage $ = _s();
if (amount == 0 || amount > $.funds[fund]) revert InvalidAmount();
id = $.withdrawals.length;
$.withdrawals.push(Withdrawal(msg.sender, fund, amount, recipient, purpose, Status.Voting, 0, 0));
emit WithdrawalProposed(id, msg.sender, fund, amount, recipient, purpose);
Comment on lines +145 to +149
if (w.amount > $.funds[w.fund]) revert InvalidAmount();
w.status = Status.Approved;
$.funds[w.fund] -= w.amount;
$.token.safeTransfer(w.recipient, w.amount);
emit Movement(_name(w.fund), "recipient", w.amount, "withdrawal", w.purpose);
Comment on lines +13 to +15
/// use. The queued add/remove + `processQueue` cycle semantics of the
/// base registry apply (changes land at the cycle boundary).
contract CovaProjectRegistry is AbstractRecipientRegistry, ICovaProjectRegistry {
Comment thread foundry.toml
Comment on lines +5 to +6
optimizer = true
optimizer_runs = 200
Comment on lines +257 to +265
function test_withdrawalFlow() public {
_mintCusd(5350 * E);
tok.approve(address(wd), 5350 * E);
wd.allocateInflow([uint256(1200 * E), 800 * E, 950 * E, 2400 * E], "Quarterly");
assertEq(wd.getFunds()[1], 800 * E);

vm.prank(m1);
uint256 id = wd.proposeWithdrawal(1, 300 * E, address(0xCAFE), "Workshop");
vm.prank(m2);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants