@@ -11,11 +11,11 @@ import "./PulseErrors.sol";
11
11
abstract contract Pulse is IPulse , PulseState {
12
12
function _initialize (
13
13
address admin ,
14
- uint128 pythFeeInWei ,
14
+ uint96 pythFeeInWei ,
15
15
address pythAddress ,
16
16
address defaultProvider ,
17
17
bool prefillRequestStorage ,
18
- uint256 exclusivityPeriodSeconds
18
+ uint32 exclusivityPeriodSeconds
19
19
) internal {
20
20
require (admin != address (0 ), "admin is zero address " );
21
21
require (pythAddress != address (0 ), "pyth is zero address " );
@@ -44,11 +44,6 @@ abstract contract Pulse is IPulse, PulseState {
44
44
req.publishTime = 1 ;
45
45
req.callbackGasLimit = 1 ;
46
46
req.requester = address (1 );
47
- req.numPriceIds = 0 ;
48
- // Pre-warm the priceIds array storage
49
- for (uint8 j = 0 ; j < MAX_PRICE_IDS; j++ ) {
50
- req.priceIds[j] = bytes32 (0 );
51
- }
52
47
}
53
48
}
54
49
}
@@ -58,7 +53,7 @@ abstract contract Pulse is IPulse, PulseState {
58
53
address provider ,
59
54
uint64 publishTime ,
60
55
bytes32 [] calldata priceIds ,
61
- uint256 callbackGasLimit
56
+ uint32 callbackGasLimit
62
57
) external payable override returns (uint64 requestSequenceNumber ) {
63
58
require (
64
59
_state.providers[provider].isRegistered,
@@ -77,21 +72,29 @@ abstract contract Pulse is IPulse, PulseState {
77
72
}
78
73
requestSequenceNumber = _state.currentSequenceNumber++ ;
79
74
80
- uint128 requiredFee = getFee (provider, callbackGasLimit, priceIds);
75
+ uint96 requiredFee = getFee (provider, callbackGasLimit, priceIds);
81
76
if (msg .value < requiredFee) revert InsufficientFee ();
82
77
83
78
Request storage req = allocRequest (requestSequenceNumber);
84
79
req.sequenceNumber = requestSequenceNumber;
85
80
req.publishTime = publishTime;
86
81
req.callbackGasLimit = callbackGasLimit;
87
82
req.requester = msg .sender ;
88
- req.numPriceIds = uint8 (priceIds.length );
89
83
req.provider = provider;
90
- req.fee = SafeCast.toUint128 (msg .value - _state.pythFeeInWei);
84
+ req.fee = SafeCast.toUint96 (msg .value - _state.pythFeeInWei);
91
85
92
- // Copy price IDs to storage
86
+ // Create array with the right size
87
+ req.priceIdPrefixes = new bytes8 [](priceIds.length );
88
+
89
+ // Copy only the first 8 bytes of each price ID to storage
93
90
for (uint8 i = 0 ; i < priceIds.length ; i++ ) {
94
- req.priceIds[i] = priceIds[i];
91
+ // Extract first 8 bytes of the price ID
92
+ bytes32 priceId = priceIds[i];
93
+ bytes8 prefix;
94
+ assembly {
95
+ prefix := priceId
96
+ }
97
+ req.priceIdPrefixes[i] = prefix;
95
98
}
96
99
_state.accruedFeesInWei += _state.pythFeeInWei;
97
100
@@ -119,12 +122,21 @@ abstract contract Pulse is IPulse, PulseState {
119
122
120
123
// Verify priceIds match
121
124
require (
122
- priceIds.length == req.numPriceIds ,
125
+ priceIds.length == req.priceIdPrefixes. length ,
123
126
"Price IDs length mismatch "
124
127
);
125
- for (uint8 i = 0 ; i < req.numPriceIds; i++ ) {
126
- if (priceIds[i] != req.priceIds[i]) {
127
- revert InvalidPriceIds (priceIds[i], req.priceIds[i]);
128
+ for (uint8 i = 0 ; i < req.priceIdPrefixes.length ; i++ ) {
129
+ // Extract first 8 bytes of the provided price ID
130
+ bytes32 priceId = priceIds[i];
131
+ bytes8 prefix;
132
+ assembly {
133
+ prefix := priceId
134
+ }
135
+
136
+ // Compare with stored prefix
137
+ if (prefix != req.priceIdPrefixes[i]) {
138
+ // Now we can directly use the bytes8 prefix in the error
139
+ revert InvalidPriceIds (priceIds[i], req.priceIdPrefixes[i]);
128
140
}
129
141
}
130
142
@@ -222,31 +234,31 @@ abstract contract Pulse is IPulse, PulseState {
222
234
223
235
function getFee (
224
236
address provider ,
225
- uint256 callbackGasLimit ,
237
+ uint32 callbackGasLimit ,
226
238
bytes32 [] calldata priceIds
227
- ) public view override returns (uint128 feeAmount ) {
228
- uint128 baseFee = _state.pythFeeInWei; // Fixed fee to Pyth
239
+ ) public view override returns (uint96 feeAmount ) {
240
+ uint96 baseFee = _state.pythFeeInWei; // Fixed fee to Pyth
229
241
// Note: The provider needs to set its fees to include the fee charged by the Pyth contract.
230
242
// Ideally, we would be able to automatically compute the pyth fees from the priceIds, but the
231
243
// fee computation on IPyth assumes it has the full updated data.
232
- uint128 providerBaseFee = _state.providers[provider].baseFeeInWei;
233
- uint128 providerFeedFee = SafeCast.toUint128 (
244
+ uint96 providerBaseFee = _state.providers[provider].baseFeeInWei;
245
+ uint96 providerFeedFee = SafeCast.toUint96 (
234
246
priceIds.length * _state.providers[provider].feePerFeedInWei
235
247
);
236
- uint128 providerFeeInWei = _state.providers[provider].feePerGasInWei; // Provider's per-gas rate
248
+ uint96 providerFeeInWei = _state.providers[provider].feePerGasInWei; // Provider's per-gas rate
237
249
uint256 gasFee = callbackGasLimit * providerFeeInWei; // Total provider fee based on gas
238
250
feeAmount =
239
251
baseFee +
240
252
providerBaseFee +
241
253
providerFeedFee +
242
- SafeCast.toUint128 (gasFee); // Total fee user needs to pay
254
+ SafeCast.toUint96 (gasFee); // Total fee user needs to pay
243
255
}
244
256
245
257
function getPythFeeInWei ()
246
258
public
247
259
view
248
260
override
249
- returns (uint128 pythFeeInWei )
261
+ returns (uint96 pythFeeInWei )
250
262
{
251
263
pythFeeInWei = _state.pythFeeInWei;
252
264
}
@@ -367,9 +379,9 @@ abstract contract Pulse is IPulse, PulseState {
367
379
}
368
380
369
381
function registerProvider (
370
- uint128 baseFeeInWei ,
371
- uint128 feePerFeedInWei ,
372
- uint128 feePerGasInWei
382
+ uint96 baseFeeInWei ,
383
+ uint96 feePerFeedInWei ,
384
+ uint96 feePerGasInWei
373
385
) external override {
374
386
ProviderInfo storage provider = _state.providers[msg .sender ];
375
387
require (! provider.isRegistered, "Provider already registered " );
@@ -382,9 +394,9 @@ abstract contract Pulse is IPulse, PulseState {
382
394
383
395
function setProviderFee (
384
396
address provider ,
385
- uint128 newBaseFeeInWei ,
386
- uint128 newFeePerFeedInWei ,
387
- uint128 newFeePerGasInWei
397
+ uint96 newBaseFeeInWei ,
398
+ uint96 newFeePerFeedInWei ,
399
+ uint96 newFeePerGasInWei
388
400
) external override {
389
401
require (
390
402
_state.providers[provider].isRegistered,
@@ -396,9 +408,9 @@ abstract contract Pulse is IPulse, PulseState {
396
408
"Only provider or fee manager can invoke this method "
397
409
);
398
410
399
- uint128 oldBaseFee = _state.providers[provider].baseFeeInWei;
400
- uint128 oldFeePerFeed = _state.providers[provider].feePerFeedInWei;
401
- uint128 oldFeePerGas = _state.providers[provider].feePerGasInWei;
411
+ uint96 oldBaseFee = _state.providers[provider].baseFeeInWei;
412
+ uint96 oldFeePerFeed = _state.providers[provider].feePerFeedInWei;
413
+ uint96 oldFeePerGas = _state.providers[provider].feePerGasInWei;
402
414
_state.providers[provider].baseFeeInWei = newBaseFeeInWei;
403
415
_state.providers[provider].feePerFeedInWei = newFeePerFeedInWei;
404
416
_state.providers[provider].feePerGasInWei = newFeePerGasInWei;
@@ -437,7 +449,7 @@ abstract contract Pulse is IPulse, PulseState {
437
449
emit DefaultProviderUpdated (oldProvider, provider);
438
450
}
439
451
440
- function setExclusivityPeriod (uint256 periodSeconds ) external override {
452
+ function setExclusivityPeriod (uint32 periodSeconds ) external override {
441
453
require (
442
454
msg .sender == _state.admin,
443
455
"Only admin can set exclusivity period "
@@ -447,7 +459,7 @@ abstract contract Pulse is IPulse, PulseState {
447
459
emit ExclusivityPeriodUpdated (oldPeriod, periodSeconds);
448
460
}
449
461
450
- function getExclusivityPeriod () external view override returns (uint256 ) {
462
+ function getExclusivityPeriod () external view override returns (uint32 ) {
451
463
return _state.exclusivityPeriodSeconds;
452
464
}
453
465
0 commit comments