Skip to content

Commit ba9705d

Browse files
committed
Set attestation lastUpdated based on block number
Update Scorer interface Update tests Changes after CR Changes after CR Changes after CR
1 parent 8218e83 commit ba9705d

File tree

6 files changed

+115
-70
lines changed

6 files changed

+115
-70
lines changed

abis/SLIOracle.json

Lines changed: 35 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -266,41 +266,29 @@
266266
"internalType": "CommonTypes.FilActorId"
267267
},
268268
{
269-
"name": "attestation",
269+
"name": "slis",
270270
"type": "tuple",
271-
"internalType": "struct SLITypes.Attestation",
271+
"internalType": "struct SLITypes.SLIThresholds",
272272
"components": [
273273
{
274-
"name": "lastUpdate",
275-
"type": "uint256",
276-
"internalType": "uint256"
274+
"name": "retrievabilityPct",
275+
"type": "uint8",
276+
"internalType": "uint8"
277277
},
278278
{
279-
"name": "slis",
280-
"type": "tuple",
281-
"internalType": "struct SLITypes.SLIThresholds",
282-
"components": [
283-
{
284-
"name": "retrievabilityPct",
285-
"type": "uint8",
286-
"internalType": "uint8"
287-
},
288-
{
289-
"name": "bandwidthMbps",
290-
"type": "uint16",
291-
"internalType": "uint16"
292-
},
293-
{
294-
"name": "latencyMs",
295-
"type": "uint16",
296-
"internalType": "uint16"
297-
},
298-
{
299-
"name": "indexingPct",
300-
"type": "uint8",
301-
"internalType": "uint8"
302-
}
303-
]
279+
"name": "bandwidthMbps",
280+
"type": "uint16",
281+
"internalType": "uint16"
282+
},
283+
{
284+
"name": "latencyMs",
285+
"type": "uint16",
286+
"internalType": "uint16"
287+
},
288+
{
289+
"name": "indexingPct",
290+
"type": "uint8",
291+
"internalType": "uint8"
304292
}
305293
]
306294
}
@@ -443,10 +431,16 @@
443431
"indexed": true,
444432
"internalType": "CommonTypes.FilActorId"
445433
},
434+
{
435+
"name": "lastUpdate",
436+
"type": "uint256",
437+
"indexed": false,
438+
"internalType": "uint256"
439+
},
446440
{
447441
"name": "slis",
448442
"type": "tuple",
449-
"indexed": true,
443+
"indexed": false,
450444
"internalType": "struct SLITypes.SLIThresholds",
451445
"components": [
452446
{
@@ -540,11 +534,21 @@
540534
"name": "FailedCall",
541535
"inputs": []
542536
},
537+
{
538+
"type": "error",
539+
"name": "InvalidAdmin",
540+
"inputs": []
541+
},
543542
{
544543
"type": "error",
545544
"name": "InvalidInitialization",
546545
"inputs": []
547546
},
547+
{
548+
"type": "error",
549+
"name": "InvalidOracle",
550+
"inputs": []
551+
},
548552
{
549553
"type": "error",
550554
"name": "NotInitializing",

src/SLIOracle.sol

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,16 @@ import {SLITypes} from "./types/SLITypes.sol";
1414
* @notice
1515
*/
1616
contract SLIOracle is ISLIOracle, Initializable, AccessControlUpgradeable, UUPSUpgradeable, MulticallUpgradeable {
17+
/**
18+
* @notice Thrown when an invalid oracle address is provided
19+
*/
20+
error InvalidOracle();
21+
22+
/**
23+
* @notice Thrown when an invalid admin address is provided
24+
*/
25+
error InvalidAdmin();
26+
1727
/**
1828
* @notice Upgradable role which allows for contract upgrades
1929
*/
@@ -24,12 +34,12 @@ contract SLIOracle is ISLIOracle, Initializable, AccessControlUpgradeable, UUPSU
2434
*/
2535
bytes32 public constant ORACLE_ROLE = keccak256("ORACLE_ROLE");
2636

27-
// @custom:storage-location erc7201:slioracle.storage.SLIOracleStorage
37+
/// @custom:storage-location erc7201:slioracle.storage.SLIOracleStorage
2838
struct SLIOracleStorage {
2939
mapping(CommonTypes.FilActorId provider => SLITypes.Attestation attestation) attestations;
3040
}
3141

32-
/// @custom:storage-location erc7201:slioracle.storage.SLIOracleStorage
42+
// keccak256(abi.encode(uint256(keccak256("slioracle.storage.SLIOracleStorage")) - 1)) & ~bytes32(uint256(0xff))
3343
bytes32 private constant SLIORACLE_STORAGE_LOCATION =
3444
0x0e62b9471a0c1cf5755a696ad58de1a3aec2ce3013fbd703781a8b7b7bd90100;
3545

@@ -49,9 +59,12 @@ contract SLIOracle is ISLIOracle, Initializable, AccessControlUpgradeable, UUPSU
4959
/**
5060
* @notice Emitted when SLI values are updated for a provider
5161
* @param provider ID of the provider
62+
* @param lastUpdate The block numer of last update
5263
* @param slis New SLI values
5364
*/
54-
event SLIAttestationUpdate(CommonTypes.FilActorId indexed provider, SLITypes.SLIThresholds indexed slis);
65+
event SLIAttestationUpdate(
66+
CommonTypes.FilActorId indexed provider, uint256 lastUpdate, SLITypes.SLIThresholds slis
67+
);
5568

5669
/**
5770
* @notice Disabled constructor (proxy pattern)
@@ -66,6 +79,8 @@ contract SLIOracle is ISLIOracle, Initializable, AccessControlUpgradeable, UUPSU
6679
* @param oracle Address that will get ORACLE_ROLE
6780
*/
6881
function initialize(address admin, address oracle) external initializer {
82+
if (admin == address(0)) revert InvalidAdmin();
83+
if (oracle == address(0)) revert InvalidOracle();
6984
__AccessControl_init();
7085
__Multicall_init();
7186
_grantRole(DEFAULT_ADMIN_ROLE, admin);
@@ -76,15 +91,15 @@ contract SLIOracle is ISLIOracle, Initializable, AccessControlUpgradeable, UUPSU
7691
/**
7792
* @notice Sets SLI values for a provider
7893
* @param provider ID of the provider
79-
* @param attestation New attestation values
94+
* @param slis New slis values for a provider
8095
*/
81-
function setSLI(CommonTypes.FilActorId provider, SLITypes.Attestation calldata attestation)
96+
function setSLI(CommonTypes.FilActorId provider, SLITypes.SLIThresholds calldata slis)
8297
external
8398
onlyRole(ORACLE_ROLE)
8499
{
85-
emit SLIAttestationUpdate(provider, attestation.slis);
86-
SLIOracleStorage storage $ = s();
87-
$.attestations[provider] = attestation;
100+
uint256 currentEpoch = block.number;
101+
s().attestations[provider] = SLITypes.Attestation({lastUpdate: currentEpoch, slis: slis});
102+
emit SLIAttestationUpdate(provider, currentEpoch, slis);
88103
}
89104

90105
/**

src/SLIScorer.sol

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,25 +7,35 @@ import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/U
77
import {CommonTypes} from "filecoin-solidity/v0.8/types/CommonTypes.sol";
88
import {SLIOracle} from "./SLIOracle.sol";
99
import {SLITypes} from "./types/SLITypes.sol";
10+
import {ISLIScorer} from "./interfaces/ISLIScorer.sol";
1011

1112
/**
1213
* @title SLA Registry
1314
* @notice Upgradeable contract for managing SLA deals with role-based access control
1415
*/
15-
contract SLIScorer is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
16-
/// @notice Thrown when an invalid oracle address is provided
16+
contract SLIScorer is ISLIScorer, Initializable, AccessControlUpgradeable, UUPSUpgradeable {
17+
/**
18+
* @notice Thrown when an invalid oracle address is provided
19+
*/
1720
error InvalidOracle();
1821

19-
/// @notice Thrown when an invalid admin address is provided
22+
/**
23+
*@notice Thrown when an invalid admin address is provided
24+
*/
2025
error InvalidAdmin();
2126

22-
/// @notice Thrown when no attestation exists for the given provider
23-
/// @param provider The FilActor ID of the provider without attestation
27+
/**
28+
*@notice Thrown when no attestation exists for the given provider
29+
* @param provider The FilActor ID of the provider without attestation
30+
*/
2431
error NoAttestation(CommonTypes.FilActorId provider);
2532

26-
/// @notice Thrown when an attestation has expired for the given provider
27-
/// @param provider The FilActor ID of the provider with expired attestation
33+
/**
34+
*@notice Thrown when an attestation has expired for the given provider
35+
*@param provider The FilActor ID of the provider with expired attestation
36+
*/
2837
error AttestationExpired(CommonTypes.FilActorId provider);
38+
2939
/**
3040
* @notice Upgradable role which allows for contract upgrades
3141
*/
@@ -37,12 +47,12 @@ contract SLIScorer is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
3747
*/
3848
uint256 private constant EPOCHS_IN_MONTH = 86_400;
3949

40-
// @custom:storage-location erc7201:sliscorer.storage.SLIScorerStorage
50+
/// @custom:storage-location erc7201:sliscorer.storage.SLIScorerStorage
4151
struct SLIScorerStorage {
4252
SLIOracle oracle;
4353
}
4454

45-
/// @custom:storage-location erc7201:sliscorer.storage.SLIScorerStorage
55+
// keccak256(abi.encode(uint256(keccak256("sliscorer.storage.SLIScorerStorage")) - 1)) & ~bytes32(uint256(0xff))
4656
bytes32 private constant SLISCORER_STORAGE_LOCATION =
4757
0xfc214f7b8d05a80223ac984f4c5d514cbee885916c0eb499aae1223022938a00;
4858

@@ -126,7 +136,7 @@ contract SLIScorer is Initializable, AccessControlUpgradeable, UUPSUpgradeable {
126136

127137
if (required.latencyMs != 0) {
128138
slasDefined++;
129-
if (required.latencyMs <= attestation.slis.latencyMs) slasMet++;
139+
if (required.latencyMs >= attestation.slis.latencyMs) slasMet++;
130140
}
131141

132142
if (required.indexingPct != 0) {

src/interfaces/ISLIOracle.sol

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,20 @@ import {SLITypes} from "../types/SLITypes.sol";
66

77
/**
88
* @title ISLIOracle
9-
* @notice Interface for retrieving measured SLI values for storage providers
9+
* @notice Interface for managing and retrieving SLI values for storage providers
1010
*/
1111
interface ISLIOracle {
1212
/**
13-
* @notice Get measured SLI values for a provider
14-
* @param provider The storage provider actor ID
15-
* @return attestation for a provider
13+
* @notice Sets SLI values for a provider
14+
* @param provider ID of the provider
15+
* @param slis New slis values for a provider
16+
*/
17+
function setSLI(CommonTypes.FilActorId provider, SLITypes.SLIThresholds calldata slis) external;
18+
19+
/**
20+
* @notice Retrieves the SLI values for a provider
21+
* @param provider ID of the provider
22+
* @return attestation The attestation values for the provider
1623
*/
1724
function getAttestation(CommonTypes.FilActorId provider)
1825
external

test/SLIOracle.t.sol

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,12 @@ contract SLIOracleTest is Test {
1313
SLIOracle public sliOracle;
1414
address public oracle = address(0x123);
1515
CommonTypes.FilActorId public provider = CommonTypes.FilActorId.wrap(1000);
16-
SLITypes.Attestation public attestation = SLITypes.Attestation({
17-
lastUpdate: block.number,
18-
slis: SLITypes.SLIThresholds({retrievabilityPct: 80, bandwidthMbps: 500, latencyMs: 200, indexingPct: 90})
19-
});
16+
SLITypes.SLIThresholds public slis =
17+
SLITypes.SLIThresholds({retrievabilityPct: 80, bandwidthMbps: 500, latencyMs: 200, indexingPct: 90});
2018

2119
function setUp() public {
2220
SLIOracle impl = new SLIOracle();
23-
bytes memory initData = abi.encodeWithSignature("initialize(address,address)", address(this), oracle);
21+
bytes memory initData = abi.encodeCall(SLIOracle.initialize, (address(this), oracle));
2422
ERC1967Proxy proxy = new ERC1967Proxy(address(impl), initData);
2523
sliOracle = SLIOracle(address(proxy));
2624
}
@@ -49,23 +47,34 @@ contract SLIOracleTest is Test {
4947

5048
function testSLIAttestationEvent() public {
5149
vm.expectEmit(true, true, false, false);
52-
emit SLIOracle.SLIAttestationUpdate(provider, attestation.slis);
50+
emit SLIOracle.SLIAttestationUpdate(provider, block.number, slis);
5351
vm.prank(oracle);
54-
sliOracle.setSLI(provider, attestation);
52+
sliOracle.setSLI(provider, slis);
5553
}
5654

5755
function testSetSLIAttestation() public {
5856
vm.prank(oracle);
59-
sliOracle.setSLI(provider, attestation);
57+
sliOracle.setSLI(provider, slis);
6058

6159
SLITypes.Attestation memory storedAttestation = sliOracle.getAttestation(provider);
62-
// Compare lastUpdate is set correctly in storage
63-
assertEq(storedAttestation.lastUpdate, attestation.lastUpdate);
64-
// Compare that last update is set to current block number
6560
assertEq(storedAttestation.lastUpdate, block.number);
66-
assertEq(storedAttestation.slis.retrievabilityPct, attestation.slis.retrievabilityPct);
67-
assertEq(storedAttestation.slis.latencyMs, attestation.slis.latencyMs);
68-
assertEq(storedAttestation.slis.indexingPct, attestation.slis.indexingPct);
69-
assertEq(storedAttestation.slis.bandwidthMbps, attestation.slis.bandwidthMbps);
61+
assertEq(storedAttestation.slis.retrievabilityPct, slis.retrievabilityPct);
62+
assertEq(storedAttestation.slis.latencyMs, slis.latencyMs);
63+
assertEq(storedAttestation.slis.indexingPct, slis.indexingPct);
64+
assertEq(storedAttestation.slis.bandwidthMbps, slis.bandwidthMbps);
65+
}
66+
67+
function testInitializeRevertInvalidAdmin() public {
68+
SLIOracle impl = new SLIOracle();
69+
bytes memory initData = abi.encodeCall(SLIOracle.initialize, (address(0), oracle));
70+
vm.expectRevert(abi.encodeWithSelector(SLIOracle.InvalidAdmin.selector));
71+
new ERC1967Proxy(address(impl), initData);
72+
}
73+
74+
function testInitializeRevertInvalidOracle() public {
75+
SLIOracle impl = new SLIOracle();
76+
bytes memory initData = abi.encodeCall(SLIOracle.initialize, (address(this), address(0)));
77+
vm.expectRevert(abi.encodeWithSelector(SLIOracle.InvalidOracle.selector));
78+
new ERC1967Proxy(address(impl), initData);
7079
}
7180
}

test/SLIScorer.t.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ contract SLIScorerTest is Test {
6060

6161
function testCalculateScoreIsNonZeroForSLI() public {
6262
vm.prank(client);
63-
oracle.setAttestations(1000, 100, 100, 80, 80);
63+
oracle.setAttestations(1000, 100, 100, 100, 80);
6464
vm.roll(1001);
6565
uint256 score = sliScorer.calculateScore(provider, sliParams);
6666
assertEq(score, 50);
6767
}
6868

6969
function testCalculateScore() public {
7070
vm.prank(client);
71-
oracle.setAttestations(1000, 100, 100, 100, 100);
71+
oracle.setAttestations(1000, 100, 100, 95, 100);
7272
vm.roll(1001);
7373
uint256 score = sliScorer.calculateScore(provider, sliParams);
7474
assertEq(score, 100);

0 commit comments

Comments
 (0)