Skip to content

Commit af0bc62

Browse files
committed
Added tests for IC mass distribution
1 parent 9670f02 commit af0bc62

2 files changed

Lines changed: 150 additions & 57 deletions

File tree

test/EconomicInvariants.t.sol

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -152,33 +152,42 @@ contract EconomicInvariantsTest is Test {
152152
assertTrue(e >= -1e18 && e <= 1e18, "effectiveVS out of bounds");
153153
}
154154

155-
function test_MultiHop_Propagation_Chain3() public {
156-
// A -> B -> C
157-
uint256 A = registry.createClaim("A");
158-
uint256 B = registry.createClaim("B");
159-
uint256 C = registry.createClaim("C");
155+
function test_MultiHop_Propagation_Chain3() public {
156+
// A -> B -> C
157+
uint256 A = registry.createClaim("A");
158+
uint256 B = registry.createClaim("B");
159+
uint256 C = registry.createClaim("C");
160160

161-
// Activate B and C (otherwise effectiveVS gated to 0)
162-
stake.stake(B, 0, 1);
163-
stake.stake(C, 0, 1);
161+
// Activate B and C (otherwise effectiveVSRay returns 0 for gated posts)
162+
stake.stake(B, 0, 1);
163+
stake.stake(C, 0, 1);
164164

165-
uint256 AB = registry.createLink(A, B, false);
166-
uint256 BC = registry.createLink(B, C, false);
165+
uint256 AB = registry.createLink(A, B, false);
166+
uint256 BC = registry.createLink(B, C, false);
167167

168-
stake.stake(AB, 0, 50);
169-
stake.stake(BC, 0, 50);
168+
// Make links heavy so routing is meaningful
169+
stake.stake(AB, 0, 500);
170+
stake.stake(BC, 0, 500);
170171

171-
stake.stake(A, 0, 100);
172-
int256 eC1 = score.effectiveVSRay(C);
172+
// Case 1: A strongly positive
173+
stake.stake(A, 0, 300);
174+
int256 eC1 = score.effectiveVSRay(C);
173175

174-
stake.stake(A, 1, 300);
175-
int256 eC2 = score.effectiveVSRay(C);
176+
// Case 2: flip A strongly negative
177+
stake.stake(A, 1, 1200);
178+
int256 eC2 = score.effectiveVSRay(C);
179+
180+
// Expect downstream changes
181+
assertTrue(eC1 != eC2, "downstream did not change");
182+
183+
// Directional expectation
184+
assertTrue(eC2 < eC1, "downstream did not move downward");
185+
186+
// Still bounded
187+
assertTrue(eC1 >= -1e18 && eC1 <= 1e18, "eC1 out of bounds");
188+
assertTrue(eC2 >= -1e18 && eC2 <= 1e18, "eC2 out of bounds");
189+
}
176190

177-
assertTrue(eC1 >= -1e18 && eC1 <= 1e18);
178-
assertTrue(eC2 >= -1e18 && eC2 <= 1e18);
179-
assertTrue(eC1 >= -1e18 && eC1 <= 1e18, "eC1 out of bounds");
180-
assertTrue(eC2 >= -1e18 && eC2 <= 1e18, "eC2 out of bounds");
181-
}
182191

183192
function test_Cycle_Reverts_IfEnforced() public {
184193
uint256 A = registry.createClaim("A");
@@ -271,3 +280,4 @@ contract TestVSP is IVSPToken {
271280
}
272281
}
273282

283+

test/ScoreEngine.t.sol

Lines changed: 119 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@ contract ScoreEngineTest is Test {
7979
StakeEngine stake;
8080
ScoreEngine score;
8181

82+
int256 internal constant RAY = 1e18;
83+
8284
function setUp() public {
8385
registry = new PostRegistry();
8486

@@ -95,100 +97,181 @@ contract ScoreEngineTest is Test {
9597
vsp.approve(address(stake), type(uint256).max);
9698
}
9799

98-
/// A -> B -> C
99-
/// Under the activation rule, B and C must have nonzero stake for their effectiveVS to be computed.
100+
// ---------------------------------------------------------------------
101+
// A -> B -> C : propagation should be positive and attenuate with hops.
102+
// Under gating rules, B and C must have nonzero stake or effectiveVS=0.
103+
// ---------------------------------------------------------------------
100104
function test_MultiHopEffectiveVS_LinearChain() public {
101105
uint256 A = registry.createClaim("A");
102106
uint256 B = registry.createClaim("B");
103107
uint256 C = registry.createClaim("C");
104108

105-
// Activate B and C (so effectiveVS(B) and effectiveVS(C) are not gated to 0)
109+
// Activate B & C so effectiveVS is computed
106110
stake.stake(B, stake.SIDE_SUPPORT(), 1);
107111
stake.stake(C, stake.SIDE_SUPPORT(), 1);
108112

109-
// Make A strongly positive
110-
stake.stake(A, stake.SIDE_SUPPORT(), 100);
113+
// Strong A support
114+
stake.stake(A, stake.SIDE_SUPPORT(), 200);
111115

112-
// Create links and stake the link posts so they contribute
116+
// Links A->B, B->C
113117
uint256 AB = registry.createLink(A, B, false);
114118
uint256 BC = registry.createLink(B, C, false);
115119

116-
stake.stake(AB, stake.SIDE_SUPPORT(), 50);
117-
stake.stake(BC, stake.SIDE_SUPPORT(), 50);
120+
// Give links meaningful mass so routed influence exists
121+
stake.stake(AB, stake.SIDE_SUPPORT(), 200);
122+
stake.stake(BC, stake.SIDE_SUPPORT(), 200);
118123

119124
int256 evsA = score.effectiveVSRay(A);
120125
int256 evsB = score.effectiveVSRay(B);
121126
int256 evsC = score.effectiveVSRay(C);
122127

123-
// A should be > 0
124-
assertGt(evsA, 0);
128+
assertGt(evsA, 0, "A should be positive");
129+
assertGt(evsB, 0, "B should receive routed influence");
130+
assertGt(evsC, 0, "C should receive routed influence");
125131

126-
// B and C should be > 0 due to propagation
127-
assertGt(evsB, 0);
128-
assertGt(evsC, 0);
132+
// Multi-hop should not amplify: downstream should not exceed upstream in a simple chain
133+
assertGe(evsA, evsB, "A should be >= B in simple chain");
134+
assertGe(evsB, evsC, "B should be >= C in simple chain");
129135

130-
// Typically B should be >= C in a simple chain (attenuation)
131-
assertGe(evsB, evsC);
136+
// Still bounded
137+
assertTrue(evsC >= -RAY && evsC <= RAY, "bounded");
132138
}
133139

134-
/// IC challenge propagation sanity.
140+
// ---------------------------------------------------------------------
141+
// Challenge link should invert contribution polarity.
142+
// Here: A -> B support, B -> C challenge.
143+
// Expect: C pulled away from B, potentially negative depending on weights.
144+
// ---------------------------------------------------------------------
135145
function test_MultiHopWithChallengePropagation() public {
136146
uint256 A = registry.createClaim("A");
137147
uint256 B = registry.createClaim("B");
138148
uint256 C = registry.createClaim("C");
139149

140-
// Activate B and C
150+
// Activate B & C
141151
stake.stake(B, stake.SIDE_SUPPORT(), 1);
142152
stake.stake(C, stake.SIDE_SUPPORT(), 1);
143153

144-
// A positive
145-
stake.stake(A, stake.SIDE_SUPPORT(), 100);
154+
// Strong A support
155+
stake.stake(A, stake.SIDE_SUPPORT(), 200);
146156

147-
// A -> B (support), B -> C (challenge)
157+
// A -> B support, B -> C challenge
148158
uint256 AB = registry.createLink(A, B, false);
149159
uint256 BC = registry.createLink(B, C, true);
150160

151-
// Stake both links
152-
stake.stake(AB, stake.SIDE_SUPPORT(), 50);
153-
stake.stake(BC, stake.SIDE_SUPPORT(), 50);
161+
// Make both links strong enough to matter
162+
stake.stake(AB, stake.SIDE_SUPPORT(), 200);
163+
stake.stake(BC, stake.SIDE_SUPPORT(), 200);
154164

155165
int256 evsB = score.effectiveVSRay(B);
156166
int256 evsC = score.effectiveVSRay(C);
157167

158-
// B should be positive
159-
assertGt(evsB, 0);
168+
assertGt(evsB, 0, "B should be positive");
169+
assertTrue(evsC < evsB, "challenge should pull C below B");
160170

161-
// Challenge link should invert contribution, pushing C negative (or at least away from B)
162-
assertLt(evsC, evsB);
171+
// Depending on your exact math, evsC may or may not go negative.
172+
// But it MUST remain bounded.
173+
assertTrue(evsC >= -RAY && evsC <= RAY, "bounded");
163174
}
164175

165-
/// Mixed influence: flipping upstream should change downstream (requires downstream activated).
176+
// ---------------------------------------------------------------------
177+
// Mixed influence: flipping upstream should MOVE downstream if routing is strong enough.
178+
// Do NOT require a full sign flip; require a meaningful delta and direction.
179+
// ---------------------------------------------------------------------
166180
function test_MultiHopMixedInfluence() public {
167181
uint256 A = registry.createClaim("A");
168182
uint256 B = registry.createClaim("B");
169183
uint256 C = registry.createClaim("C");
170184

171-
// Activate B and C
185+
// Activate B & C (otherwise effectiveVS=0)
172186
stake.stake(B, stake.SIDE_SUPPORT(), 1);
173187
stake.stake(C, stake.SIDE_SUPPORT(), 1);
174188

175189
// Links A->B, B->C (support)
176190
uint256 AB = registry.createLink(A, B, false);
177191
uint256 BC = registry.createLink(B, C, false);
178192

179-
stake.stake(AB, stake.SIDE_SUPPORT(), 50);
180-
stake.stake(BC, stake.SIDE_SUPPORT(), 50);
193+
// Make routing strong
194+
stake.stake(AB, stake.SIDE_SUPPORT(), 400);
195+
stake.stake(BC, stake.SIDE_SUPPORT(), 400);
181196

182197
// Case 1: A positive
183-
stake.stake(A, stake.SIDE_SUPPORT(), 100);
198+
stake.stake(A, stake.SIDE_SUPPORT(), 300);
184199
int256 eC1 = score.effectiveVSRay(C);
185200

186-
// Case 2: flip A strongly negative by overwhelming challenge
187-
stake.stake(A, stake.SIDE_CHALLENGE(), 400);
201+
// Case 2: overwhelm A with challenge to flip A negative hard
202+
stake.stake(A, stake.SIDE_CHALLENGE(), 1200);
188203
int256 eC2 = score.effectiveVSRay(C);
189204

190-
assertTrue(eC1 >= -1e18 && eC1 <= 1e18);
191-
assertTrue(eC2 >= -1e18 && eC2 <= 1e18);
205+
assertTrue(eC1 >= -RAY && eC1 <= RAY, "eC1 bounded");
206+
assertTrue(eC2 >= -RAY && eC2 <= RAY, "eC2 bounded");
207+
208+
// Must respond
209+
assertTrue(eC1 != eC2, "C should change when upstream flips (with strong routing)");
210+
211+
// Directional expectation: after flipping A negative, C should move downward
212+
assertTrue(eC2 < eC1, "C should move down when A flips negative");
213+
}
214+
215+
// ---------------------------------------------------------------------
216+
// NEW: IC mass distribution across multiple outgoing links.
217+
// Equal link mass => equal downstream influence.
218+
// ---------------------------------------------------------------------
219+
function test_ICMass_DistributesEvenlyAcrossEqualLinks() public {
220+
uint256 IC = registry.createClaim("IC");
221+
uint256 D1 = registry.createClaim("D1");
222+
uint256 D2 = registry.createClaim("D2");
223+
224+
// Activate DCs
225+
stake.stake(D1, stake.SIDE_SUPPORT(), 1);
226+
stake.stake(D2, stake.SIDE_SUPPORT(), 1);
227+
228+
// Strong IC
229+
stake.stake(IC, stake.SIDE_SUPPORT(), 500);
230+
231+
uint256 L1 = registry.createLink(IC, D1, false);
232+
uint256 L2 = registry.createLink(IC, D2, false);
233+
234+
// Equal link stake/mass
235+
stake.stake(L1, stake.SIDE_SUPPORT(), 200);
236+
stake.stake(L2, stake.SIDE_SUPPORT(), 200);
237+
238+
int256 v1 = score.effectiveVSRay(D1);
239+
int256 v2 = score.effectiveVSRay(D2);
240+
241+
// They should be very close. Exact equality may not hold due to integer division,
242+
// but should be within a tiny tolerance.
243+
int256 diff = v1 - v2;
244+
if (diff < 0) diff = -diff;
245+
246+
assertLe(uint256(int256(diff)), 1e12, "equal links should yield ~equal influence");
247+
}
248+
249+
// ---------------------------------------------------------------------
250+
// NEW: Larger link mass should receive more IC mass.
251+
// ---------------------------------------------------------------------
252+
function test_ICMass_StrongerLinkGetsMoreInfluence() public {
253+
uint256 IC = registry.createClaim("IC");
254+
uint256 D1 = registry.createClaim("D1");
255+
uint256 D2 = registry.createClaim("D2");
256+
257+
// Activate DCs
258+
stake.stake(D1, stake.SIDE_SUPPORT(), 1);
259+
stake.stake(D2, stake.SIDE_SUPPORT(), 1);
260+
261+
// Strong IC
262+
stake.stake(IC, stake.SIDE_SUPPORT(), 500);
263+
264+
uint256 L1 = registry.createLink(IC, D1, false);
265+
uint256 L2 = registry.createLink(IC, D2, false);
266+
267+
// Unequal link mass
268+
stake.stake(L1, stake.SIDE_SUPPORT(), 400);
269+
stake.stake(L2, stake.SIDE_SUPPORT(), 100);
270+
271+
int256 v1 = score.effectiveVSRay(D1);
272+
int256 v2 = score.effectiveVSRay(D2);
273+
274+
assertGt(v1, v2, "heavier link should route more IC mass");
192275
}
193276
}
194277

0 commit comments

Comments
 (0)