@@ -103,7 +103,7 @@ abstract contract Entropy is IEntropy, EntropyState {
103103            for  (uint8  i =  0 ; i <  NUM_REQUESTS; i++ ) {
104104                EntropyStructs.Request storage  req =  _state.requests[i];
105105                req.provider =  address (1 );
106-                 req.blockNumber  =  1234 ;
106+                 req.blockNumberOrGasLimit  =  1234 ;
107107                req.commitment =  hex "0123 " ;
108108            }
109109        }
@@ -222,14 +222,12 @@ abstract contract Entropy is IEntropy, EntropyState {
222222        providerInfo.sequenceNumber +=  1 ;
223223
224224        // Check that fees were paid and increment the pyth / provider balances. 
225-         uint128  requiredFee =  getFee (provider);
225+         uint128  requiredFee =  getFeeForGas (provider, callbackGasLimit );
226226        if  (msg .value  <  requiredFee) revert  EntropyErrors.InsufficientFee ();
227-         providerInfo.accruedFeesInWei +=  getProviderFee (
228-             provider,
229-             callbackGasLimit
230-         );
227+         uint128  providerFee =  getProviderFee (provider, callbackGasLimit);
228+         providerInfo.accruedFeesInWei +=  providerFee;
231229        _state.accruedPythFeesInWei +=  (SafeCast.toUint128 (msg .value ) - 
232-             providerInfo.feeInWei );
230+             providerFee );
233231
234232        // Store the user's commitment so that we can fulfill the request later. 
235233        // Warning: this code needs to overwrite *every* field in the request, because the returned request can be 
@@ -257,16 +255,19 @@ abstract contract Entropy is IEntropy, EntropyState {
257255        } else  if  (isRequestWithCallback) {
258256            req.isRequestWithCallback =  isRequestWithCallback;
259257            if  (callbackGasLimit ==  0 ) {
260-                 req.blockNumber  =  providerInfo.defaultGasLimit;
258+                 req.blockNumberOrGasLimit  =  providerInfo.defaultGasLimit;
261259            } else  {
262-                 req.blockNumber  =  callbackGasLimit;
260+                 req.blockNumberOrGasLimit  =  callbackGasLimit;
263261            }
264262            req.useBlockhash =  false ;
265263        } else  {
266264            req.isRequestWithCallback =  false ;
267-             req.blockNumber  =  SafeCast.toUint64 (block .number );
265+             req.blockNumberOrGasLimit  =  SafeCast.toUint64 (block .number );
268266            req.useBlockhash =  useBlockhash;
269267        }
268+ 
269+         req.callbackFailed =  false ;
270+         req.reentryGuard =  false ;
270271    }
271272
272273    // As a user, request a random number from `provider`. Prior to calling this method, the user should 
@@ -376,9 +377,9 @@ abstract contract Entropy is IEntropy, EntropyState {
376377
377378        blockHash =  bytes32 (uint256 (0 ));
378379        if  (req.useBlockhash) {
379-             bytes32  _blockHash =  blockhash (req.blockNumber );
380+             bytes32  _blockHash =  blockhash (req.blockNumberOrGasLimit );
380381
381-             // The `blockhash` function will return zero if the req.blockNumber  is equal to the current 
382+             // The `blockhash` function will return zero if the req.blockNumberOrGasLimit  is equal to the current 
382383            // block number, or if it is not within the 256 most recent blocks. This allows the user to 
383384            // select between two random numbers by executing the reveal function in the same block as the 
384385            // request, or after 256 blocks. This gives each user two chances to get a favorable result on 
@@ -451,7 +452,7 @@ abstract contract Entropy is IEntropy, EntropyState {
451452    }
452453
453454    // Fulfill a request for a random number. This method validates the provided userRandomness and provider's proof 
454-     // against the corresponding commitments in the in-flight request. If both values are validated, this function  returns 
455+     // against the corresponding commitments in the in-flight request. If both values are validated, this method  returns 
455456    // the corresponding random number. 
456457    // 
457458    // Note that this function can only be called once per in-flight request. Calling this function deletes the stored 
@@ -520,7 +521,7 @@ abstract contract Entropy is IEntropy, EntropyState {
520521        }
521522        // Invariant check: all callback requests should have useBlockhash set to false. 
522523        if  (req.useBlockhash) {
523-             revert  EntropyErrors.InvalidRevealCall ();
524+             revert  EntropyErrors.AssertionFailure ();
524525        }
525526
526527        if  (req.reentryGuard) {
@@ -537,11 +538,16 @@ abstract contract Entropy is IEntropy, EntropyState {
537538
538539        address  callAddress =  req.requester;
539540
540-         if  (req.blockNumber !=  0  &&  ! req.callbackAttempted) {
541+         // blockNumberOrGasLimit holds the gas limit in the callback case. 
542+         // If the gas limit is 0, then the provider hasn't configured their default limit, 
543+         // so we default to the prior entropy flow (where there is no failure state). 
544+         // Similarly, if the request has already failed, we fall back to the prior flow so that 
545+         // recovery attempts can provide more gas / directly see the revert reason. 
546+         if  (req.blockNumberOrGasLimit !=  0  &&  ! req.callbackFailed) {
541547            // TODO: need to validate that we have enough gas left to forward (?) 
542548            // Or at least that we forwarded enough gas before marking the callback as failed 
543549            /* 
544-             if (gasleft() < req.blockNumber ) { 
550+             if (gasleft() < req.blockNumberOrGasLimit ) { 
545551
546552            } 
547553            */ 
@@ -550,7 +556,7 @@ abstract contract Entropy is IEntropy, EntropyState {
550556            bool  success;
551557            bytes  memory  ret;
552558            (success, ret) =  callAddress.excessivelySafeCall (
553-                 req.blockNumber ,
559+                 req.blockNumberOrGasLimit ,
554560                0 ,
555561                32 ,
556562                abi.encodeWithSelector (
@@ -582,7 +588,7 @@ abstract contract Entropy is IEntropy, EntropyState {
582588                    sequenceNumber,
583589                    errorReason
584590                );
585-                 req.callbackAttempted  =  true ;
591+                 req.callbackFailed  =  true ;
586592            }
587593        } else  {
588594            emit  RevealedWithCallback (
@@ -600,11 +606,13 @@ abstract contract Entropy is IEntropy, EntropyState {
600606            }
601607
602608            if  (len !=  0 ) {
609+                 req.reentryGuard =  true ;
603610                IEntropyConsumer (callAddress)._entropyCallback (
604611                    sequenceNumber,
605612                    provider,
606613                    randomNumber
607614                );
615+                 req.reentryGuard =  false ;
608616            }
609617        }
610618    }
@@ -652,6 +660,8 @@ abstract contract Entropy is IEntropy, EntropyState {
652660            providerAddr
653661        ];
654662        if  (gasLimit >  provider.defaultGasLimit) {
663+             // This calculation rounds down the fee, which means that users can get some gas in the callback for free. 
664+             // However, the value of the free gas is < 1 wei, which is insignificant. 
655665            uint128  additionalFee =  ((gasLimit -  provider.defaultGasLimit) * 
656666                provider.feeInWei) /  provider.defaultGasLimit;
657667            return  provider.feeInWei +  additionalFee;
0 commit comments