@@ -1034,13 +1034,14 @@ contract ProperQFBranchCoverageTest is Test {
10341034
10351035 // _processVote: valid vote (success path - contributes to branch coverage of all checks passing)
10361036 function test_processVote_validVote_succeeds () public {
1037- // contribution = 10000 , sqrt(10000 ) = 100 , voteWeight = 100
1038- qf.exposed_processVote (1 , 10000 , 100 );
1037+ // contribution = 10000e18 , sqrt(10000e18 ) = 100e9 , voteWeight = 100e9
1038+ qf.exposed_processVote (1 , 10000e18 , 100e9 );
10391039
1040- // Verify it was recorded
1040+ // Verify it was recorded (sumContributions is lossy due to quantization)
1041+ uint256 step = uint256 (1 ) << 32 ;
10411042 ProperQF.Project memory project = qf.projects (1 );
1042- assertEq (project.sumContributions, 10000 );
1043- assertEq (project.sumSquareRoots, 100 );
1043+ assertApproxEqAbs (project.sumContributions, 10000e18 , step );
1044+ assertEq (project.sumSquareRoots, 100e9 );
10441045 }
10451046
10461047 // _calculateOptimalAlpha: quadraticSum == linearSum exactly (edge case)
@@ -1098,7 +1099,7 @@ contract ProperQFBranchCoverageTest is Test {
10981099
10991100 // totalFunding getter
11001101 function test_totalFunding_afterVotes () public {
1101- qf.exposed_processVote (1 , 10000 , 100 );
1102+ qf.exposed_processVote (1 , 10000e18 , 100e9 );
11021103 assertTrue (qf.totalFunding () > 0 );
11031104 }
11041105}
@@ -1990,6 +1991,7 @@ contract QVMBranchCoverageTest is Test {
19901991 uint256 constant QUORUM = 10 ;
19911992 uint256 constant TIMELOCK_DELAY = 1 days ;
19921993 uint256 constant GRACE_PERIOD = 7 days ;
1994+ uint256 constant W = 65536 ;
19931995
19941996 function _tam () internal view returns (TokenizedAllocationMechanism) {
19951997 return TokenizedAllocationMechanism (address (mechanism));
@@ -2009,7 +2011,7 @@ contract QVMBranchCoverageTest is Test {
20092011 symbol: "QVB " ,
20102012 votingDelay: VOTING_DELAY,
20112013 votingPeriod: VOTING_PERIOD,
2012- quorumShares: QUORUM,
2014+ quorumShares: QUORUM * W * W ,
20132015 timelockDelay: TIMELOCK_DELAY,
20142016 gracePeriod: GRACE_PERIOD,
20152017 owner: address (0 )
@@ -2060,7 +2062,7 @@ contract QVMBranchCoverageTest is Test {
20602062
20612063 vm.warp (block .timestamp + VOTING_DELAY + 1 );
20622064 vm.prank (alice);
2063- _tam ().castVote (pid, TokenizedAllocationMechanism.VoteType.For, 20 , recipient1);
2065+ _tam ().castVote (pid, TokenizedAllocationMechanism.VoteType.For, 20 * W , recipient1);
20642066
20652067 // Call calculateOptimalAlpha through the mechanism
20662068 (, uint256 den ) = mechanism.calculateOptimalAlpha (50_000e18 , DEPOSIT);
@@ -2082,7 +2084,7 @@ contract QVMBranchCoverageTest is Test {
20822084
20832085 vm.prank (alice);
20842086 vm.expectRevert (abi.encodeWithSelector (TokenizedAllocationMechanism.InvalidProposal.selector , 0 ));
2085- _tam ().castVote (0 , TokenizedAllocationMechanism.VoteType.For, 10 , recipient1);
2087+ _tam ().castVote (0 , TokenizedAllocationMechanism.VoteType.For, 10 * W , recipient1);
20862088 }
20872089
20882090 // ===== getProposalFunding: canceled proposal returns zeros =====
@@ -2094,7 +2096,7 @@ contract QVMBranchCoverageTest is Test {
20942096
20952097 vm.warp (block .timestamp + VOTING_DELAY + 1 );
20962098 vm.prank (alice);
2097- _tam ().castVote (pid, TokenizedAllocationMechanism.VoteType.For, 10 , recipient1);
2099+ _tam ().castVote (pid, TokenizedAllocationMechanism.VoteType.For, 10 * W , recipient1);
20982100
20992101 // Cancel the proposal
21002102 vm.prank (alice);
@@ -2116,7 +2118,7 @@ contract QVMBranchCoverageTest is Test {
21162118
21172119 vm.warp (block .timestamp + VOTING_DELAY + 1 );
21182120 vm.prank (alice);
2119- _tam ().castVote (pid, TokenizedAllocationMechanism.VoteType.For, 20 , recipient1);
2121+ _tam ().castVote (pid, TokenizedAllocationMechanism.VoteType.For, 20 * W , recipient1);
21202122
21212123 (uint256 sumC , uint256 sumSq , uint256 qf , uint256 lf ) = mechanism.getProposalFunding (pid);
21222124 assertTrue (sumC > 0 , "Should have contributions " );
@@ -3013,35 +3015,40 @@ contract ProperQFDeepBranchTest is Test {
30133015
30143016 // ===== _processVote: exact boundary - voteWeight^2 == contribution (success) =====
30153017 function test_processVote_exactSqrt_succeeds () public {
3016- qf.exposed_processVote (1 , 100 , 10 );
3018+ // 100e18 = (10e9)^2
3019+ qf.exposed_processVote (1 , 100e18 , 10e9 );
30173020
3021+ uint256 step = uint256 (1 ) << 32 ;
30183022 ProperQF.Project memory project = qf.projects (1 );
3019- assertEq (project.sumContributions, 100 );
3020- assertEq (project.sumSquareRoots, 10 );
3023+ assertApproxEqAbs (project.sumContributions, 100e18 , step );
3024+ assertEq (project.sumSquareRoots, 10e9 );
30213025 }
30223026
30233027 // ===== _processVote: voteWeight at lower tolerance boundary =====
30243028 function test_processVote_voteWeightAtLowerTolerance () public {
3025- qf.exposed_processVote (1 , 10000 , 90 );
3029+ // sqrt(10000e18) = 100e9, tolerance = 100e9/10 = 10e9, lower = 90e9
3030+ qf.exposed_processVote (1 , 10000e18 , 90e9 );
30263031
30273032 ProperQF.Project memory project = qf.projects (1 );
3028- assertEq (project.sumSquareRoots, 90 );
3033+ assertEq (project.sumSquareRoots, 90e9 );
30293034 }
30303035
30313036 // ===== _processVote: voteWeight below lower tolerance =====
30323037 function test_processVote_voteWeightBelowLowerTolerance_reverts () public {
30333038 vm.expectRevert (ProperQF.VoteWeightOutsideTolerance.selector );
3034- qf.exposed_processVote (1 , 10000 , 89 );
3039+ qf.exposed_processVote (1 , 10000e18 , 89e9 );
30353040 }
30363041
30373042 // ===== _processVote: multiple votes on same project =====
30383043 function test_processVote_multipleVotesSameProject () public {
3039- qf.exposed_processVote (1 , 10000 , 100 );
3040- qf.exposed_processVote (1 , 40000 , 200 );
3044+ qf.exposed_processVote (1 , 10000e18 , 100e9 );
3045+ qf.exposed_processVote (1 , 40000e18 , 200e9 );
30413046
3047+ uint256 step = uint256 (1 ) << 32 ;
30423048 ProperQF.Project memory project = qf.projects (1 );
3043- assertEq (project.sumContributions, 50000 );
3044- assertEq (project.sumSquareRoots, 300 );
3049+ // 2 votes: tolerance = 2 * STEP
3050+ assertApproxEqAbs (project.sumContributions, 50000e18 , 2 * step);
3051+ assertEq (project.sumSquareRoots, 300e9 );
30453052 }
30463053}
30473054
@@ -3359,7 +3366,7 @@ contract ProperQFUnderflowBranchTest is Test {
33593366 qf.exposed_setAlpha (50 , 100 );
33603367
33613368 // Process a vote - this internally calls _calculateWeightedTotalFunding
3362- qf.exposed_processVote (1 , 10000 , 100 );
3369+ qf.exposed_processVote (1 , 10000e18 , 100e9 );
33633370
33643371 // totalFunding should be updated
33653372 uint256 totalFunding = qf.totalFunding ();
@@ -3909,29 +3916,32 @@ contract ProperQFStorageUnderflowTest is Test {
39093916 // ===== ProperQF line 156: QuadraticSumUnderflow =====
39103917 // When totalQuadraticSum < oldQuadraticFunding (project.sumSquareRoots^2)
39113918 function test_processVoteUnchecked_quadraticSumUnderflow_reverts () public {
3919+ uint256 step = uint256 (1 ) << 32 ;
39123920 // Set up a project with sumSquareRoots = 10, so oldQuadraticFunding = 100
3913- qf.setProject (1 , 100 , 10 );
3921+ // sumContributions must be step-aligned for exact round-trip
3922+ qf.setProject (1 , 100 * step, 10 );
39143923 // Set totalQuadraticSum to a value less than 100
39153924 qf.setTotalQuadraticSum (50 );
3916- qf.setTotalLinearSum (200 );
3925+ qf.setTotalLinearSum (200 * step );
39173926
39183927 // Now calling _processVoteUnchecked should trigger QuadraticSumUnderflow
39193928 // because totalQuadraticSum (50) < oldQuadraticFunding (10*10 = 100)
39203929 vm.expectRevert (ProperQF.QuadraticSumUnderflow.selector );
3921- qf.exposed_processVoteUnchecked (1 , 400 , 20 );
3930+ qf.exposed_processVoteUnchecked (1 , 400 * step , 20 );
39223931 }
39233932
39243933 // ===== ProperQF line 157: LinearSumUnderflow =====
39253934 // When totalLinearSum < project.sumContributions
39263935 function test_processVoteUnchecked_linearSumUnderflow_reverts () public {
3927- // Set up a project with sumContributions = 500, sumSquareRoots = 10
3928- qf.setProject (1 , 500 , 10 );
3936+ uint256 step = uint256 (1 ) << 32 ;
3937+ // Set up a project with sumContributions = 500*STEP, sumSquareRoots = 10
3938+ qf.setProject (1 , 500 * step, 10 );
39293939 // Set totalQuadraticSum correctly (>= 10^2 = 100) but totalLinearSum too low
39303940 qf.setTotalQuadraticSum (200 );
3931- qf.setTotalLinearSum (100 ); // 100 < 500 = project.sumContributions
3941+ qf.setTotalLinearSum (100 * step ); // 100*STEP < 500*STEP = project.sumContributions
39323942
39333943 vm.expectRevert (ProperQF.LinearSumUnderflow.selector );
3934- qf.exposed_processVoteUnchecked (1 , 400 , 20 );
3944+ qf.exposed_processVoteUnchecked (1 , 400 * step , 20 );
39353945 }
39363946
39373947 // ===== ProperQF: alphaNumerator() view function coverage =====
0 commit comments