Date: January 21, 2026 Created by: Ralph (Autonomous AI Development Agent) Status: Test files created, ready for implementation
Ralph has created comprehensive test suites for all Backroom smart contracts:
- council_tests.cljs - Tests for Council.sol and CouncilStakeBank.sol
- ari_oracle_tests.cljs - Tests for ARIOracle.sol
- power_plant_tests.cljs - Tests for PowerPlant.sol
These tests follow the existing ClojureScript testing patterns used in the district-registry codebase and provide comprehensive coverage of contract functionality.
File: test/district_registry/tests/smart_contracts/council_tests.cljs
Coverage:
- Council initialization (9 seats)
- Seat 8 immutability verification
- Council weight calculations
- Philosophy updates
- Seat flip mechanism
- Stake bank operations (stake, unstake, move)
- Checkpoint queries
- Integration between Council and StakeBank
Test Count: ~20 test cases
File: test/district_registry/tests/smart_contracts/ari_oracle_tests.cljs
Coverage:
- Oracle initialization and configuration
- Proposal creation (5 types)
- Proposal lifecycle (Pending → VetoPeriod → Approved/Vetoed → Executed)
- Veto detection (30% threshold)
- Veto period timing (3 days)
- Council weight snapshots
- Proposal execution
- Proposal cancellation
- ARI address management
- Oracle-PowerPlant integration
Test Count: ~30 test cases
File: test/district_registry/tests/smart_contracts/power_plant_tests.cljs
Coverage:
- PowerPlant initialization
- Treasury deposits (ETH + tokens)
- Treasury balance queries
- Bounty lifecycle (Create → Assign → Complete → Claim)
- Grant creation with vesting
- Grant vesting calculations (linear)
- Grant disbursement
- Treasury withdrawal (emergency)
- Multiple bounties and grants
- Oracle integration
Test Count: ~25 test cases
- Start local blockchain:
ganache-cli- Deploy contracts:
npx truffle migrate --network development- Start test environment:
# ClojureScript tests run via shadow-cljs or lein
# Check package.json for test script
# If using shadow-cljs:
npx shadow-cljs compile test
# If using lein:
lein doo node test once- ✅ Test files created - All 3 files with comprehensive test cases
- ⏳ Test contracts need creation - Helper contracts for tests (e.g.,
council.cljs,ari-oracle.cljs) - ⏳ Some tests commented out - Require contract deployment and helper functions
- ⏳ Integration tests need setup - Require multi-contract interactions
- Test structure and organization
- Test case definitions
- Error case coverage
- Integration test placeholders
- Documentation comments
- Create contract helper files in
src/district_registry/server/contract/ - Uncomment and complete test implementations
- Add test data setup/teardown
- Run tests against deployed contracts
- Fix any failures and edge cases
The tests reference contract helper modules that need to be created:
(ns district-registry.server.contract.council
(:require [district.server.smart-contracts :refer [contract-call instance]]))
(defn get-seat [contract-key seat-index]
(contract-call (instance contract-key) :get-seat seat-index))
(defn get-council-weights [contract-key]
(contract-call (instance contract-key) :get-council-weights))
(defn update-philosophy [contract-key seat-index philosophy-hash opts]
(contract-call (instance contract-key) :update-philosophy seat-index philosophy-hash opts))
(defn propose-new-mind [contract-key mind-id name philosophy-hash proposed-stake opts]
(contract-call (instance contract-key) :propose-new-mind mind-id name philosophy-hash proposed-stake opts))
(defn verify-stranger-immutable [contract-key]
(contract-call (instance contract-key) :verify-stranger-immutable))
(defn update-stake-cache [contract-key seat-index total-staked opts]
(contract-call (instance contract-key) :update-stake-cache seat-index total-staked opts))(ns district-registry.server.contract.council-stake-bank
(:require [district.server.smart-contracts :refer [contract-call instance]]))
(defn stake-on-seat [contract-key seat-index amount opts]
(contract-call (instance contract-key) :stake-on-seat seat-index amount opts))
(defn unstake-from-seat [contract-key seat-index amount opts]
(contract-call (instance contract-key) :unstake-from-seat seat-index amount opts))
(defn move-stake [contract-key from-seat to-seat amount opts]
(contract-call (instance contract-key) :move-stake from-seat to-seat amount opts))
(defn balance-of [contract-key seat-index staker]
(contract-call (instance contract-key) :balance-of seat-index staker))
(defn balance-of-at [contract-key seat-index staker block-number]
(contract-call (instance contract-key) :balance-of-at seat-index staker block-number))
(defn total-staked-for-seat-at [contract-key seat-index block-number]
(contract-call (instance contract-key) :total-staked-for-seat-at seat-index block-number))
(defn council [contract-key]
(contract-call (instance contract-key) :council))(ns district-registry.server.contract.ari-oracle
(:require [district.server.smart-contracts :refer [contract-call instance]]))
(defn create-proposal [contract-key proposal-type reasoning-hash amount recipient opts]
(contract-call (instance contract-key) :create-proposal proposal-type reasoning-hash amount recipient opts))
(defn start-veto-period [contract-key proposal-id opts]
(contract-call (instance contract-key) :start-veto-period proposal-id opts))
(defn check-veto [contract-key proposal-id]
(contract-call (instance contract-key) :check-veto proposal-id))
(defn execute-proposal [contract-key proposal-id opts]
(contract-call (instance contract-key) :execute-proposal proposal-id opts))
(defn cancel-proposal [contract-key proposal-id opts]
(contract-call (instance contract-key) :cancel-proposal proposal-id opts))
(defn get-proposal [contract-key proposal-id]
(contract-call (instance contract-key) :get-proposal proposal-id))
(defn veto-period-duration [contract-key]
(contract-call (instance contract-key) :veto-period-duration))
(defn veto-threshold-bps [contract-key]
(contract-call (instance contract-key) :veto-threshold-bps))
(defn dnt-token [contract-key]
(contract-call (instance contract-key) :dnt-token))
(defn ari-address [contract-key]
(contract-call (instance contract-key) :ari-address))
(defn set-ari-address [contract-key new-ari-addr opts]
(contract-call (instance contract-key) :set-ari-address new-ari-addr opts))(ns district-registry.server.contract.power-plant
(:require [district.server.smart-contracts :refer [contract-call instance]]))
(defn deposit [contract-key token amount opts]
(contract-call (instance contract-key) :deposit token amount opts))
(defn get-treasury-balance [contract-key token]
(contract-call (instance contract-key) :get-treasury-balance token))
(defn create-bounty [contract-key metadata-hash reward token deadline opts]
(contract-call (instance contract-key) :create-bounty metadata-hash reward token deadline opts))
(defn assign-bounty [contract-key bounty-id assignee opts]
(contract-call (instance contract-key) :assign-bounty bounty-id assignee opts))
(defn mark-bounty-complete [contract-key bounty-id opts]
(contract-call (instance contract-key) :mark-bounty-complete bounty-id opts))
(defn claim-bounty [contract-key bounty-id opts]
(contract-call (instance contract-key) :claim-bounty bounty-id opts))
(defn get-bounty [contract-key bounty-id]
(contract-call (instance contract-key) :get-bounty bounty-id))
(defn create-grant [contract-key recipient total-amount token vesting-duration metadata-hash opts]
(contract-call (instance contract-key) :create-grant recipient total-amount token vesting-duration metadata-hash opts))
(defn disburse-grant [contract-key grant-id opts]
(contract-call (instance contract-key) :disburse-grant grant-id opts))
(defn get-grant [contract-key grant-id]
(contract-call (instance contract-key) :get-grant grant-id))
(defn withdraw [contract-key token amount to opts]
(contract-call (instance contract-key) :withdraw token amount to opts))
(defn ari-oracle [contract-key]
(contract-call (instance contract-key) :ari-oracle))
(defn owner [contract-key]
(contract-call (instance contract-key) :owner))(deftest test-name
(async done
(go
(let [[owner addr1] (<! (web3-eth/accounts @web3))]
(testing "Test description"
(is condition "Assertion message"))
(done)))))(testing "Should reject invalid input"
(is (tx-error? (<! (contract-call ...)))
"Should reject with error"))(testing "State changes correctly"
(let [before (<! (get-state))
tx (<! (modify-state))
after (<! (get-state))]
(is (not= before after) "State should change")))(testing "Contracts interact correctly"
;; 1. Setup state in contract A
;; 2. Call function in contract B
;; 3. Verify state changed in contract A
)-
Seat 8 Immutability
(let [seat (<! (council/get-seat :council 8))] (is (:is-immutable seat) "Seat 8 MUST be immutable"))
Why Critical: Core requirement - newcomer advocacy seat cannot be changed
-
Council Weights Sum to 100%
(let [weights (<! (council/get-council-weights :council)) total (reduce + (:weights weights))] (is (= total 10000) "Weights must sum to 10000 basis points"))
Why Critical: Governance calculations depend on correct percentages
-
Stake Bank Notifies Council
(testing "Staking updates council cache" ;; Stake on seat ;; Verify council.totalStaked increased )
Why Critical: Council weights must reflect actual stakes
-
30% Veto Threshold
(testing "Veto triggers at exactly 30%" ;; Move 30% of stake ;; Verify proposal vetoed ;; Move 29.9% of stake ;; Verify proposal not vetoed )
Why Critical: Core governance mechanic
-
3-Day Veto Period
(let [veto-duration (<! (oracle/veto-period-duration :ari-oracle))] (is (= veto-duration 259200) "Must be exactly 3 days (259200 seconds)"))
Why Critical: Community needs time to respond
-
Only ARI Can Propose
(is (tx-error? (<! (oracle/create-proposal ... {:from non-ari-addr}))) "Non-ARI addresses must be rejected")
Why Critical: Prevents governance spam
-
Only Oracle Can Create Bounties/Grants
(is (tx-error? (<! (power-plant/create-bounty ... {:from non-oracle}))) "Only Oracle can create bounties")
Why Critical: Treasury security
-
Grant Vesting is Linear
(testing "50% vested after 50% time elapsed" ;; Create 100 DNT grant over 100 days ;; Wait 50 days ;; Disburse ;; Verify ~50 DNT disbursed )
Why Critical: Fair distribution
-
Cannot Claim Uncompleted Bounty
(is (tx-error? (<! (power-plant/claim-bounty bounty-id {:from assignee}))) "Cannot claim before marking complete")
Why Critical: Prevents theft
- Ganache running on port 8545
- All contracts compiled:
npx truffle compile - All contracts deployed:
npx truffle migrate --reset - Contract helper files created in
src/district_registry/server/contract/ - Smart contract addresses registered in test config
- Test DNT tokens minted for test accounts
- Run Council tests:
npx shadow-cljs compile test(or equivalent) - Run Oracle tests
- Run PowerPlant tests
- Run integration tests
- Check test coverage: aim for >80%
- Document any skipped tests (with reasons)
- Document known limitations
- Update @fix_plan.md with test status
- Create test report
- Tag commit with test milestone
Testing district-registry.tests.smart-contracts.council-tests
council-initialization
✓ Council initializes with 9 seats
✓ Seat 8 (The Stranger) is immutable
✓ Other seats are mutable
council-weights
✓ Council weights return correctly with zero stake
✓ All weights are equal when no stake exists
update-philosophy
✓ Owner can update philosophy
✓ Non-owner cannot update philosophy
✓ Cannot update with empty philosophy hash
✓ Cannot update invalid seat index
Ran 20 tests containing 45 assertions.
0 failures, 0 errors.
Testing district-registry.tests.smart-contracts.council-tests
immutability-verification
✗ Seat 8 (The Stranger) is immutable
Expected: true
Actual: false
FAILURE: Seat 8 is mutable! Critical bug in Council.sol
Fix: Review Council.sol line 69 - ensure isImmutable flag is set correctly
-
Create contract helper files (4 files, ~30 minutes each)
- council.cljs
- council_stake_bank.cljs
- ari_oracle.cljs
- power_plant.cljs
-
Deploy to local testnet (1 hour)
- Start Ganache
- Migrate contracts
- Verify deployment
-
Run initial tests (2 hours)
- Uncomment test implementations
- Fix any syntax errors
- Run test suite
- Document failures
-
Fix failing tests (4-8 hours)
- Debug contract issues
- Fix test assumptions
- Add missing functionality
-
Add integration tests (4 hours)
- Multi-contract scenarios
- End-to-end governance flow
- Edge cases
-
Achieve >80% coverage (4 hours)
- Add missing test cases
- Test error conditions
- Test event emissions
-
Testnet deployment (2-3 hours)
- Deploy to Sepolia/Goerli
- Run tests against testnet
- Verify in Etherscan
-
Gas optimization (4-6 hours)
- Profile gas usage
- Optimize expensive operations
- Re-test after optimizations
-
Security audit prep (8-12 hours)
- Comprehensive test documentation
- Known issues list
- Mitigation strategies
- HANDOFF_STATUS.md - Overall project status
- BACKROOM_IMPLEMENTATION_STATUS.md - Backend implementation details
- @fix_plan.md - Implementation roadmap
- contracts/Council.sol - Contract source with inline docs
- contracts/ARIOracle.sol - Contract source with inline docs
- contracts/PowerPlant.sol - Contract source with inline docs
- Time-dependent tests - Veto period timing requires time manipulation (use
ganache-clitime control) - Gas usage tests - Not yet profiled
- Event emission tests - Framework exists but tests commented out
- Fuzz testing - Random input testing not implemented
- Load testing - Multiple simultaneous transactions not tested
- Fresh blockchain state - Tests assume clean deployment
- Sufficient test ETH - All accounts need gas
- Minted DNT tokens - Staking tests need DNT
- Deterministic accounts - Tests use specific account indices
- ✅ All contracts deploy successfully
- ✅ Seat 8 immutability verified
- ✅ Council weights calculate correctly
- ✅ Veto threshold works (30%)
- ✅ Veto period is 3 days
- ✅ Only ARI can propose
- ✅ Only Oracle can call PowerPlant
- ✅ Bounty lifecycle completes
- ✅ Grant vesting works linearly
- ✅ No critical security issues
- All of above, plus:
-
80% code coverage
- All error cases tested
- Integration tests pass
- Gas optimization verified
- Event emissions correct
- Multi-user scenarios work
- Edge cases handled
If you're adding new contract functionality:
- Add tests first (TDD approach)
- Follow existing patterns (async, tx-error?, etc.)
- Test both success and failure cases
- Document why the test matters
- Run full test suite before committing
Status: Test files created, contract helpers needed, ready for implementation 🧪
Next Action: Create contract helper files and run first test suite
Estimated Time to Full Test Coverage: 12-20 hours of implementation + debugging
This test guide was created by Ralph on January 21, 2026 to ensure thorough testing of The Backroom smart contracts.