feat: implement 5 CosmWasm contracts (M008, M001-ENH, M011, M014, M015)#78
feat: implement 5 CosmWasm contracts (M008, M001-ENH, M011, M014, M015)#78brawlaphant wants to merge 4 commits intoregen-network:mainfrom
Conversation
Implements the M009 Service Provision Escrow mechanism as a CosmWasm smart contract with milestone-based payment release, dispute resolution, and governance-tunable parameters per the SPEC. Key features: - Service agreement lifecycle: Proposed -> Funded -> InProgress -> Completed - Sequential milestone management with deliverable IRI tracking - Provider bond locking (configurable 5-25% of escrow) - Platform fees on milestone approval + completion (configurable 0-5%) - Cancellation with fee from Funded state (configurable 0-10%) - Three-way dispute resolution: ClientWins, ProviderWins, Split - Arbiter DAO gating on dispute resolution - Milestone revision tracking with configurable max revisions - Paginated query endpoints for agreements, milestones, escrow balance, disputes - Admin-gated config updates with parameter bounds validation 37 unit tests covering: - Happy path (3 milestones through completion) - All three dispute resolution outcomes - Cancellation from Proposed and Funded states - Authorization guards on all execute messages - Milestone ordering enforcement - Revision limits - Escrow balance tracking after partial approvals - Pagination and status filtering - Parameter validation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…M015 Complete the on-chain mechanism layer — all 6 contracts now implemented: - M008 attestation-bonding: economic skin-in-the-game for ecological data claims with bond/challenge/slash lifecycle (7 tests) - M001-ENH credit-class-voting: agent pre-screening + governance voting for credit class approvals with deposit escrow (15 tests) - M011 marketplace-curation: curator bonding, quality scoring, and challenge disputes for credit batch collections (10 tests) - M015 contribution-rewards: activity-weighted distribution from community pool with stability tier locking at 6% annual (8 tests) - M014 validator-governance: PoA validator set management with 3-category composition, performance scoring, and compensation (10 tests) All contracts compile to wasm32, 384-468KB each. 50 unit tests passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Code Review
This pull request introduces a suite of CosmWasm smart contracts for the Regen Network, including modules for attestation bonding, contribution rewards, credit class voting, marketplace curation, service escrow, and validator governance. The review feedback identifies several critical scalability issues, specifically regarding unbounded range queries and iterative 'push' distribution models in the rewards and governance contracts that could lead to gas limit failures as the system scales. Additionally, the feedback points out a logic error in the credit class voting contract where slashed funds remain locked without a transfer mechanism, and an inefficient O(N) operation in the marketplace curation contract when updating quality scores.
| let mut bank_msgs = vec![]; | ||
| if !activity_pool.is_zero() && !total_score.is_zero() { | ||
| for (addr, score) in &participant_scores { | ||
| let reward = activity_pool.multiply_ratio(score.u128(), total_score.u128()); | ||
| if !reward.is_zero() { | ||
| bank_msgs.push(BankMsg::Send { | ||
| to_address: addr.to_string(), | ||
| amount: vec![Coin { | ||
| denom: config.denom.clone(), | ||
| amount: reward, | ||
| }], | ||
| }); | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
The current implementation of execute_trigger_distribution attempts to send rewards to all participants in a single transaction using a loop of BankMsg::Send. This approach is not scalable and will likely fail due to gas limits or chain-specific message count restrictions as the number of participants grows. Smart contracts should generally use a "pull" model where participants claim their own rewards, or a multi-step "push" model that supports pagination.
| let total_committed: Uint128 = COMMITMENTS | ||
| .range(storage, None, None, Order::Ascending) | ||
| .filter_map(|r| r.ok()) | ||
| .filter(|(_, c)| c.status == CommitmentStatus::Committed) | ||
| .map(|(_, c)| c.amount) | ||
| .fold(Uint128::zero(), |acc, a| acc + a); |
There was a problem hiding this comment.
The calculate_stability_allocation function performs an unbounded range query over all commitments to calculate the total committed principal. As the number of historical commitments grows, this operation will become increasingly expensive and eventually exceed the gas limit, preventing distributions from being triggered. A more efficient approach would be to maintain a total_committed counter in the contract state that is updated during commitment and withdrawal actions.
| let all_collections: Vec<(u64, Collection)> = COLLECTIONS | ||
| .range(deps.storage, None, None, Order::Ascending) | ||
| .collect::<StdResult<Vec<_>>>()?; | ||
|
|
||
| for (cid, mut coll) in all_collections { | ||
| if let Some(pos) = coll.batches.iter().position(|b| b == &batch_denom) { | ||
| coll.batches.remove(pos); | ||
| COLLECTIONS.save(deps.storage, cid, &coll)?; | ||
| removed_from.push(cid); | ||
| } |
There was a problem hiding this comment.
In execute_submit_quality_score, the contract iterates over all existing collections to remove a batch if its score falls below the threshold. This O(N) operation across all collections is not scalable and will cause the transaction to fail once the number of collections grows large. Consider enforcing quality thresholds at the time of trade or batch addition, or maintaining an index of batch-to-collections to avoid full table scans.
| .multiply_ratio(EXPIRE_SLASH_BPS, 10_000u128); | ||
| let refund = proposal.deposit_amount - slash; |
There was a problem hiding this comment.
Slashed funds are calculated but never transferred out of the contract. These funds will remain locked in the contract's balance indefinitely with no mechanism to recover them. The contract should define a destination for slashed funds (such as a community pool or treasury) and include a BankMsg::Send to transfer the slashed portion during finalization.
| let active_validators: Vec<AuthorityValidator> = VALIDATORS | ||
| .range(deps.storage, None, None, Order::Ascending) | ||
| .filter_map(|r| r.ok()) | ||
| .map(|(_, v)| v) | ||
| .filter(|v| v.status == ValidatorStatus::Active) | ||
| .collect(); |
There was a problem hiding this comment.
The execute_distribute_compensation function iterates over all validators in the system to filter for active ones. As the history of candidates and former validators grows, this range query will become increasingly expensive and could eventually hit gas limits. Consider maintaining a separate state item or prefix for currently active validators to ensure this operation remains efficient regardless of the total number of historical validator records.
…on tests Major repo hardening push: - Cargo workspace: unified build for all 6 contracts + integration-tests - GitHub Actions CI: Rust build/test/clippy/wasm, TypeScript typecheck, spec verification, PR wasm size comments - AGENT-001 Registry Reviewer: full standalone implementation with 3 workflows (class screening, project validation, batch review), mirrors AGENT-002 pattern exactly, TypeScript clean - ElizaOS runtime: dual-mode bootstrap (ElizaOS when available, standalone OODA loop fallback), MCP plugins registered as proper ElizaOS plugins - Integration tests: 5 cross-contract cw-multi-test scenarios covering attestation→curation, credit class approval, service escrow lifecycle, validator governance + rewards, and full ecosystem flow 92 tests passing (87 unit + 5 integration). All contracts workspace-dep consolidated. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- contribution-rewards: switch from push to pull reward distribution model (ClaimRewards msg), add total_committed_principal counter to eliminate unbounded range query in stability allocation - credit-class-voting: slashed funds now transfer to community_pool (or admin fallback) via BankMsg::Send on reject/expire/auto-reject - marketplace-curation: add BATCH_COLLECTIONS reverse index to replace O(N) collection scan in quality score auto-removal - validator-governance: add ACTIVE_VALIDATORS index for O(1) lookup in compensation distribution, queries, and composition checks 98 tests passing (6 new tests added for the fixes). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Completes the on-chain mechanism layer — all 6 CosmWasm contracts now implemented with full lifecycle logic, fund handling, and unit tests:
Total: 9,149 lines of Rust across 30 files. 50 unit tests passing. All compile to wasm32 (384-468KB each).
Contract Status
Key Design Decisions
cw-storage-plus2.0 maps with paginationmust_pay()helper enforces single-denom paymentsMockApi::default().addr_make()for proper bech32 in CosmWasm 2.2Test plan
cargo testpasses for all 6 contracts (50 tests total)cargo build --release --target wasm32-unknown-unknownsucceeds for all contracts🤖 Generated with Claude Code