Skip to content

Commit 352f4ad

Browse files
committed
Gold-pegged posting fee activates claims and contributes to VS; add oracle submodules
1 parent 4f3e2ee commit 352f4ad

16 files changed

Lines changed: 293 additions & 232 deletions

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,19 @@ foundry.lock
1515
# Node (in case tests/scripts install tooling later)
1616
node_modules/
1717

18+
# misc
19+
modules/
20+
objects/
21+
22+
# Allow tracked submodules
23+
lib/*
24+
!lib/
25+
!lib/chainlink
26+
!lib/chainlink-brownie-contract
27+
1828
# OS
1929
.DS_Store
2030
Thumbs.db
31+
32+
# misc
33+
audits

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
11
[submodule "lib/forge-std"]
22
path = lib/forge-std
33
url = https://github.com/foundry-rs/forge-std
4+
[submodule "lib/chainlink"]
5+
path = lib/chainlink
6+
url = https://github.com/smartcontractkit/chainlink
7+
[submodule "lib/chainlink-brownie-contracts"]
8+
path = lib/chainlink-brownie-contracts
9+
url = https://github.com/smartcontractkit/chainlink-brownie-contracts

foundry.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ optimizer_runs = 200
88
via_ir = true
99

1010
remappings = [
11-
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
11+
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
12+
"@chainlink/contracts/=lib/chainlink-brownie-contracts/contracts/"
1213
]
1314

1415
[rpc_endpoints]

lib/chainlink

Submodule chainlink added at 776d01f

lib/chainlink-brownie-contracts

src/ProtocolViews.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
pragma solidity ^0.8.20;
33

44
import "./PostRegistry.sol";
5-
import "./StakeEngine.sol";
65
import "./LinkGraph.sol";
76
import "./ScoreEngine.sol";
7+
import "./interfaces/IStakeEngine.sol";
88

99
/// @title ProtocolViews
1010
/// @notice Read-only aggregation layer for UI/indexers.
1111
contract ProtocolViews {
1212
PostRegistry public immutable registry;
13-
StakeEngine public immutable stake;
13+
IStakeEngine public immutable stake;
1414
LinkGraph public immutable graph;
1515
ScoreEngine public immutable score;
1616

@@ -31,7 +31,7 @@ contract ProtocolViews {
3131
address score_
3232
) {
3333
registry = PostRegistry(registry_);
34-
stake = StakeEngine(stake_);
34+
stake = IStakeEngine(stake_);
3535
graph = LinkGraph(graph_);
3636
score = ScoreEngine(score_);
3737
}

src/ScoreEngine.sol

Lines changed: 49 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -3,42 +3,25 @@ pragma solidity ^0.8.20;
33

44
import "./PostRegistry.sol";
55
import "./LinkGraph.sol";
6-
import "./StakeEngine.sol";
6+
import "./interfaces/IStakeEngine.sol";
77

88
/// @title ScoreEngine
9-
/// @notice Computes base and effective Veracity Scores (VS) for claims.
9+
/// @notice Computes base and effective Verity Scores (VS) for claims.
1010
/// VS is represented as signed ray (1e18 = +1.0).
11-
///
12-
/// RULES:
13-
/// - baseVS depends only on direct stake
14-
/// - effectiveVS propagates recursively over links
15-
/// - a link contributes ONLY IF:
16-
/// * IC is economically active (totalStake >= postingFeeThreshold)
17-
/// * DC is economically active (totalStake >= postingFeeThreshold)
18-
/// * link itself is economically active (totalStake >= postingFeeThreshold)
19-
/// - symmetry preserved: negative VS propagates normally
20-
///
21-
/// NEW (3.6+ incentive change):
22-
/// - Incoming effect is NOT just icVS * linkVS.
23-
/// - Instead, an IC exports its (effectiveVS(IC)) “mass” across ALL of its outgoing links
24-
/// proportional to each link’s stake (conservation / no amplification):
25-
///
26-
/// let S = sum_{outgoing links of IC} totalStake(link)
27-
/// share(link) = totalStake(link) / S
28-
///
29-
/// incomingEffect(link -> DC) = linkVS * icVS * share(link)
30-
///
31-
/// (and then flipped if edge.isChallenge, which negates linkVS)
3211
contract ScoreEngine {
3312
PostRegistry public immutable registry;
34-
StakeEngine public immutable stake;
13+
IStakeEngine public immutable stake;
3514
LinkGraph public immutable graph;
3615

3716
int256 internal constant RAY = 1e18;
3817

39-
constructor(address registry_, address stake_, address graph_) {
18+
constructor(
19+
address registry_,
20+
address stake_,
21+
address graph_
22+
) {
4023
registry = PostRegistry(registry_);
41-
stake = StakeEngine(stake_);
24+
stake = IStakeEngine(stake_);
4225
graph = LinkGraph(graph_);
4326
}
4427

@@ -47,14 +30,20 @@ contract ScoreEngine {
4730
// ---------------------------------------------------------------------
4831

4932
/// @notice Base VS = (2A / (A + D)) - 1 (ray-scaled)
33+
/// @dev Posting fee is injected into A *only when active*
5034
function baseVSRay(uint256 postId) public view returns (int256) {
5135
(uint256 A, uint256 D) = stake.getPostTotals(postId);
36+
uint256 postingFee = stake.postingFeeThreshold();
37+
5238
uint256 T = A + D;
53-
if (T == 0) return 0;
39+
if (T < postingFee) return 0;
40+
41+
// Inject posting fee as virtual support
42+
uint256 Aeff = A + postingFee;
43+
uint256 Teff = Aeff + D;
5444

55-
// ray math: ((2A / T) - 1) * 1e18
56-
int256 num = int256(2 * A) * RAY;
57-
int256 vs = (num / int256(T)) - RAY;
45+
int256 num = int256(2 * Aeff) * RAY;
46+
int256 vs = (num / int256(Teff)) - RAY;
5847

5948
return _clampRay(vs);
6049
}
@@ -67,19 +56,17 @@ contract ScoreEngine {
6756
return _effectiveVSRay(claimPostId, 0);
6857
}
6958

70-
function _effectiveVSRay(uint256 claimPostId, uint256 depth) internal view returns (int256) {
71-
// recursion safety
59+
function _effectiveVSRay(uint256 claimPostId, uint256 depth)
60+
internal
61+
view
62+
returns (int256)
63+
{
7264
if (depth > 32) return 0;
7365

74-
uint256 threshold = stake.postingFeeThreshold();
66+
uint256 postingFee = stake.postingFeeThreshold();
67+
if (!_isActive(claimPostId, postingFee)) return 0;
7568

76-
// DC must be economically active to have meaningful effectiveVS
77-
if (!_isActive(claimPostId, threshold)) {
78-
return 0;
79-
}
80-
81-
int256 baseVS = baseVSRay(claimPostId);
82-
int256 acc = baseVS;
69+
int256 acc = baseVSRay(claimPostId);
8370

8471
LinkGraph.IncomingEdge[] memory inc = graph.getIncoming(claimPostId);
8572

@@ -89,39 +76,23 @@ contract ScoreEngine {
8976
uint256 ic = e.fromClaimPostId;
9077
uint256 linkPostId = e.linkPostId;
9178

92-
// IC must be economically active
93-
if (!_isActive(ic, threshold)) continue;
94-
95-
// Link post must be economically active
96-
if (!_isActive(linkPostId, threshold)) continue;
79+
if (!_isActive(ic, postingFee)) continue;
80+
if (!_isActive(linkPostId, postingFee)) continue;
9781

98-
// IC effectiveVS (recursive)
9982
int256 icVS = _effectiveVSRay(ic, depth + 1);
10083
if (icVS == 0) continue;
10184

102-
// Compute sum of ALL outgoing link stakes from IC (distribution denominator)
103-
uint256 sumOutgoingLinkStake = _sumOutgoingLinkStake(ic, threshold);
104-
if (sumOutgoingLinkStake == 0) continue;
85+
uint256 sumOutgoing = _sumOutgoingLinkStake(ic, postingFee);
86+
if (sumOutgoing == 0) continue;
10587

106-
// This particular link stake (numerator)
10788
uint256 linkStake = _totalStake(linkPostId);
108-
if (linkStake == 0) continue;
89+
if (linkStake < postingFee) continue;
10990

110-
// Link "vote" is the link's own VS (based on its own stake queues)
111-
// (Links don't have incoming claim-links, so baseVS == effectiveVS for links.)
11291
int256 linkVS = baseVSRay(linkPostId);
92+
if (e.isChallenge) linkVS = -linkVS;
11393

114-
// challenge edge flips semantic polarity
115-
if (e.isChallenge) {
116-
linkVS = -linkVS;
117-
}
118-
119-
// incomingEffect = linkVS * icVS * (linkStake / sumOutgoingLinkStake)
120-
// Keep ray precision:
121-
// (linkVS * icVS) / RAY => ray
122-
// then * linkStake / sumOutgoing => ray
12394
int256 contrib = (linkVS * icVS) / RAY;
124-
contrib = (contrib * int256(linkStake)) / int256(sumOutgoingLinkStake);
95+
contrib = (contrib * int256(linkStake)) / int256(sumOutgoing);
12596

12697
acc += contrib;
12798
}
@@ -138,28 +109,23 @@ contract ScoreEngine {
138109
return s + d;
139110
}
140111

141-
function _isActive(uint256 postId, uint256 threshold) internal view returns (bool) {
142-
uint256 t = _totalStake(postId);
143-
if (threshold == 0) {
144-
return t > 0;
145-
}
146-
return t >= threshold;
112+
function _isActive(uint256 postId, uint256 threshold)
113+
internal
114+
view
115+
returns (bool)
116+
{
117+
return _totalStake(postId) >= threshold;
147118
}
148119

149-
/// @dev Sum stakes of ALL outgoing links from IC. (Optional: only count links that are economically active.)
150-
function _sumOutgoingLinkStake(uint256 icClaimPostId, uint256 threshold) internal view returns (uint256 sum) {
151-
LinkGraph.Edge[] memory outs = graph.getOutgoing(icClaimPostId);
120+
function _sumOutgoingLinkStake(uint256 ic, uint256 threshold)
121+
internal
122+
view
123+
returns (uint256 sum)
124+
{
125+
LinkGraph.Edge[] memory outs = graph.getOutgoing(ic);
152126
for (uint256 i = 0; i < outs.length; i++) {
153-
uint256 linkPostId = outs[i].linkPostId;
154-
uint256 t = _totalStake(linkPostId);
155-
156-
// Only include links that are active; prevents dust from diluting distribution.
157-
if (threshold == 0) {
158-
if (t == 0) continue;
159-
} else {
160-
if (t < threshold) continue;
161-
}
162-
127+
uint256 t = _totalStake(outs[i].linkPostId);
128+
if (t < threshold) continue;
163129
sum += t;
164130
}
165131
}
@@ -170,3 +136,4 @@ contract ScoreEngine {
170136
return x;
171137
}
172138
}
139+

0 commit comments

Comments
 (0)