Explorar o código

feat(entropy): More ergonomic v2 interface (#2632)

* rename method signature

* comments

* docs
Jayant Krishnamurthy hai 6 meses
pai
achega
d8c2d25edd

+ 53 - 5
target_chains/ethereum/contracts/contracts/entropy/Entropy.sol

@@ -243,7 +243,7 @@ abstract contract Entropy is IEntropy, EntropyState {
         providerInfo.sequenceNumber += 1;
 
         // Check that fees were paid and increment the pyth / provider balances.
-        uint128 requiredFee = getFeeForGas(provider, callbackGasLimit);
+        uint128 requiredFee = getFeeV2(provider, callbackGasLimit);
         if (msg.value < requiredFee) revert EntropyErrors.InsufficientFee();
         uint128 providerFee = getProviderFee(provider, callbackGasLimit);
         providerInfo.accruedFeesInWei += providerFee;
@@ -295,6 +295,32 @@ abstract contract Entropy is IEntropy, EntropyState {
         }
     }
 
+    function requestV2()
+        external
+        payable
+        override
+        returns (uint64 assignedSequenceNumber)
+    {
+        assignedSequenceNumber = requestV2(getDefaultProvider(), random(), 0);
+    }
+
+    function requestV2(
+        uint32 gasLimit
+    ) external payable override returns (uint64 assignedSequenceNumber) {
+        assignedSequenceNumber = requestV2(
+            getDefaultProvider(),
+            random(),
+            gasLimit
+        );
+    }
+
+    function requestV2(
+        address provider,
+        uint32 gasLimit
+    ) external payable override returns (uint64 assignedSequenceNumber) {
+        assignedSequenceNumber = requestV2(provider, random(), gasLimit);
+    }
+
     // As a user, request a random number from `provider`. Prior to calling this method, the user should
     // generate a random number x and keep it secret. The user should then compute hash(x) and pass that
     // as the userCommitment argument. (You may call the constructUserCommitment method to compute the hash.)
@@ -334,14 +360,14 @@ abstract contract Entropy is IEntropy, EntropyState {
         bytes32 userRandomNumber
     ) public payable override returns (uint64) {
         return
-            requestWithCallbackAndGasLimit(
+            requestV2(
                 provider,
                 userRandomNumber,
                 0 // Passing 0 will assign the request the provider's default gas limit
             );
     }
 
-    function requestWithCallbackAndGasLimit(
+    function requestV2(
         address provider,
         bytes32 userRandomNumber,
         uint32 gasLimit
@@ -720,10 +746,20 @@ abstract contract Entropy is IEntropy, EntropyState {
     function getFee(
         address provider
     ) public view override returns (uint128 feeAmount) {
-        return getFeeForGas(provider, 0);
+        return getFeeV2(provider, 0);
+    }
+
+    function getFeeV2() external view override returns (uint128 feeAmount) {
+        return getFeeV2(getDefaultProvider(), 0);
+    }
+
+    function getFeeV2(
+        uint32 gasLimit
+    ) external view override returns (uint128 feeAmount) {
+        return getFeeV2(getDefaultProvider(), gasLimit);
     }
 
-    function getFeeForGas(
+    function getFeeV2(
         address provider,
         uint32 gasLimit
     ) public view override returns (uint128 feeAmount) {
@@ -1041,4 +1077,16 @@ abstract contract Entropy is IEntropy, EntropyState {
         // a randomness request with sequence number 0.
         return req.sequenceNumber != 0;
     }
+
+    function random() internal returns (bytes32) {
+        _state.seed = keccak256(
+            abi.encodePacked(
+                block.timestamp,
+                block.difficulty,
+                msg.sender,
+                _state.seed
+            )
+        );
+        return _state.seed;
+    }
 }

+ 2 - 0
target_chains/ethereum/contracts/contracts/entropy/EntropyState.sol

@@ -37,6 +37,8 @@ contract EntropyInternalStructs {
         // proposedAdmin is the new admin's account address proposed by either the owner or the current admin.
         // If there is no pending transfer request, this value will hold `address(0)`.
         address proposedAdmin;
+        // Seed for in-contract PRNG. This seed is used to generate user random numbers in some callback flows.
+        bytes32 seed;
     }
 }
 

+ 20 - 18
target_chains/ethereum/contracts/forge-test/Entropy.t.sol

@@ -1695,9 +1695,9 @@ contract EntropyTest is Test, EntropyTestUtils, EntropyEvents, EntropyEventsV2 {
         // Test larger than max value reverts with expected error
         uint32 exceedsGasLimit = uint32(type(uint16).max) * 10000 + 1;
         vm.expectRevert(EntropyErrors.MaxGasLimitExceeded.selector);
-        random.getFeeForGas(provider1, exceedsGasLimit);
+        random.getFeeV2(provider1, exceedsGasLimit);
         vm.expectRevert(EntropyErrors.MaxGasLimitExceeded.selector);
-        random.requestWithCallbackAndGasLimit{value: 10000000000000}(
+        random.requestV2{value: 10000000000000}(
             provider1,
             bytes32(uint(42)),
             exceedsGasLimit
@@ -1722,18 +1722,14 @@ contract EntropyTest is Test, EntropyTestUtils, EntropyEvents, EntropyEventsV2 {
     ) internal {
         // Create a request with callback
         bytes32 userRandomNumber = bytes32(uint(42));
-        uint fee = random.getFeeForGas(provider1, gasLimit);
+        uint fee = random.getFeeV2(provider1, gasLimit);
         assertEq(fee - random.getPythFee(), expectedProviderFee);
 
         // Passing 1 wei less than the expected fee causes a revert.
         vm.deal(user1, fee);
         vm.prank(user1);
         vm.expectRevert(EntropyErrors.InsufficientFee.selector);
-        random.requestWithCallbackAndGasLimit{value: fee - 1}(
-            provider1,
-            userRandomNumber,
-            gasLimit
-        );
+        random.requestV2{value: fee - 1}(provider1, userRandomNumber, gasLimit);
 
         EntropyStructsV2.ProviderInfo memory providerInfo = random
             .getProviderInfoV2(provider1);
@@ -1749,9 +1745,11 @@ contract EntropyTest is Test, EntropyTestUtils, EntropyEvents, EntropyEventsV2 {
             bytes("")
         );
         vm.prank(user1);
-        uint64 sequenceNumber = random.requestWithCallbackAndGasLimit{
-            value: fee
-        }(provider1, userRandomNumber, gasLimit);
+        uint64 sequenceNumber = random.requestV2{value: fee}(
+            provider1,
+            userRandomNumber,
+            gasLimit
+        );
 
         assertEq(
             random.getProviderInfoV2(provider1).accruedFeesInWei -
@@ -1796,7 +1794,7 @@ contract EntropyTest is Test, EntropyTestUtils, EntropyEvents, EntropyEventsV2 {
     ) internal {
         // Create a request with callback
         bytes32 userRandomNumber = bytes32(uint(42));
-        uint fee = random.getFeeForGas(provider1, gasLimit);
+        uint fee = random.getFeeV2(provider1, gasLimit);
 
         vm.deal(user1, fee);
         vm.prank(user1);
@@ -1981,9 +1979,11 @@ contract EntropyConsumer is IEntropyConsumer {
         bytes32 randomNumber
     ) public payable returns (uint64 sequenceNumber) {
         address _provider = IEntropy(entropy).getDefaultProvider();
-        sequenceNumber = IEntropy(entropy).requestWithCallback{
-            value: msg.value
-        }(_provider, randomNumber);
+        sequenceNumber = IEntropy(entropy).requestV2{value: msg.value}(
+            _provider,
+            randomNumber,
+            0
+        );
     }
 
     function requestEntropyWithGasLimit(
@@ -1991,9 +1991,11 @@ contract EntropyConsumer is IEntropyConsumer {
         uint32 gasLimit
     ) public payable returns (uint64 sequenceNumber) {
         address _provider = IEntropy(entropy).getDefaultProvider();
-        sequenceNumber = IEntropy(entropy).requestWithCallbackAndGasLimit{
-            value: msg.value
-        }(_provider, randomNumber, gasLimit);
+        sequenceNumber = IEntropy(entropy).requestV2{value: msg.value}(
+            _provider,
+            randomNumber,
+            gasLimit
+        );
     }
 
     function getEntropy() internal view override returns (address) {

+ 104 - 23
target_chains/ethereum/entropy_sdk/solidity/IEntropy.sol

@@ -29,6 +29,96 @@ interface IEntropy is EntropyEvents, EntropyEventsV2 {
     // balance of fees in the contract).
     function withdrawAsFeeManager(address provider, uint128 amount) external;
 
+    /// @notice Request a random number using the default provider with default gas limit
+    /// @return assignedSequenceNumber A unique identifier for this request
+    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
+    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
+    /// the generated random number.
+    ///
+    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
+    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
+    /// by the provider's configured default limit.
+    ///
+    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2()`) as msg.value.
+    /// Note that the fee can change over time. Callers of this method should explicitly compute `getFeeV2()`
+    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
+    ///
+    /// Note that this method uses an in-contract PRNG to generate the user's portion of the random number.
+    /// Users must trust this PRNG in order to prove the result is random. If you wish to avoid this trust assumption,
+    /// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
+    function requestV2()
+        external
+        payable
+        returns (uint64 assignedSequenceNumber);
+
+    /// @notice Request a random number using the default provider with specified gas limit
+    /// @param gasLimit The gas limit for the callback function.
+    /// @return assignedSequenceNumber A unique identifier for this request
+    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
+    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
+    /// the generated random number.
+    ///
+    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
+    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
+    /// by the provider's configured default limit.
+    ///
+    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(gasLimit)`) as msg.value.
+    /// Note that the fee can change over time. Callers of this method should explicitly compute `getFeeV2(gasLimit)`
+    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
+    ///
+    /// Note that this method uses an in-contract PRNG to generate the user's portion of the random number.
+    /// Users must trust this PRNG in order to prove the result is random. If you wish to avoid this trust assumption,
+    /// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
+    function requestV2(
+        uint32 gasLimit
+    ) external payable returns (uint64 assignedSequenceNumber);
+
+    /// @notice Request a random number from a specific provider with specified gas limit
+    /// @param provider The address of the provider to request from
+    /// @param gasLimit The gas limit for the callback function
+    /// @return assignedSequenceNumber A unique identifier for this request
+    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
+    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
+    /// the generated random number.
+    ///
+    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
+    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
+    /// by the provider's configured default limit.
+    ///
+    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(provider, gasLimit)`) as msg.value.
+    /// Note that provider fees can change over time. Callers of this method should explicitly compute `getFeeV2(provider, gasLimit)`
+    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
+    ///
+    /// Note that this method uses an in-contract PRNG to generate the user's portion of the random number.
+    /// Users must trust this PRNG in order to prove the result is random. If you wish to avoid this trust assumption,
+    /// call a variant of `requestV2` that accepts a `userRandomNumber` parameter.
+    function requestV2(
+        address provider,
+        uint32 gasLimit
+    ) external payable returns (uint64 assignedSequenceNumber);
+
+    /// @notice Request a random number from a specific provider with a user-provided random number and gas limit
+    /// @param provider The address of the provider to request from
+    /// @param userRandomNumber A random number provided by the user for additional entropy
+    /// @param gasLimit The gas limit for the callback function
+    /// @return assignedSequenceNumber A unique identifier for this request
+    /// @dev The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
+    /// The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
+    /// the generated random number.
+    ///
+    /// `entropyCallback` will be run with the `gasLimit` provided to this function.
+    /// The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
+    /// by the provider's configured default limit.
+    ///
+    /// This method will revert unless the caller provides a sufficient fee (at least `getFeeV2(provider, gasLimit)`) as msg.value.
+    /// Note that provider fees can change over time. Callers of this method should explicitly compute `getFeeV2(provider, gasLimit)`
+    /// prior to each invocation (as opposed to hardcoding a value). Further note that excess value is *not* refunded to the caller.
+    function requestV2(
+        address provider,
+        bytes32 userRandomNumber,
+        uint32 gasLimit
+    ) external payable returns (uint64 assignedSequenceNumber);
+
     // As a user, request a random number from `provider`. Prior to calling this method, the user should
     // generate a random number x and keep it secret. The user should then compute hash(x) and pass that
     // as the userCommitment argument. (You may call the constructUserCommitment method to compute the hash.)
@@ -60,26 +150,6 @@ interface IEntropy is EntropyEvents, EntropyEventsV2 {
         bytes32 userRandomNumber
     ) external payable returns (uint64 assignedSequenceNumber);
 
-    // Request a random number from `provider`, getting a callback with the result.
-    // The caller must specify a provider to fulfill the request -- `getDefaultProvider()` is a sane default --
-    // and a `userRandomNumber` to combine into the result. The method returns a sequence number which callers
-    // should save to correlate the request with the callback.
-    //
-    // The address calling this function should be a contract that inherits from the IEntropyConsumer interface.
-    // The `entropyCallback` method on that interface will receive a callback with the returned sequence number and
-    // the generated random number. `entropyCallback` will be run with the `gasLimit` provided to this function.
-    // The `gasLimit` will be rounded up to a multiple of 10k (e.g., 19000 -> 20000), and furthermore is lower bounded
-    // by the provider's configured default limit.
-    //
-    // This method will revert unless the caller provides a sufficient fee (at least `getFeeForGas(provider, gasLimit)`) as msg.value.
-    // Note that provider fees can change over time. Thus, callers of this method should explictly compute `getFeeForGas(provider, gasLimit)`
-    // prior to each invocation (as opposed to  hardcoding a value). Further note that excess value is *not* refunded to the caller.
-    function requestWithCallbackAndGasLimit(
-        address provider,
-        bytes32 userRandomNumber,
-        uint32 gasLimit
-    ) external payable returns (uint64 assignedSequenceNumber);
-
     // Fulfill a request for a random number. This method validates the provided userRandomness and provider's proof
     // against the corresponding commitments in the in-flight request. If both values are validated, this function returns
     // the corresponding random number.
@@ -132,11 +202,22 @@ interface IEntropy is EntropyEvents, EntropyEventsV2 {
     ) external view returns (EntropyStructsV2.Request memory req);
 
     // Get the fee charged by provider for a request with the default gasLimit (`request` or `requestWithCallback`).
-    // If you are calling `requestWithCallbackAndGasLimit`, please use `getFeeForGas`.
+    // If you are calling any of the `requestV2` methods, please use `getFeeV2`.
     function getFee(address provider) external view returns (uint128 feeAmount);
 
-    // Get the fee charged by `provider` for a request with a specific `gasLimit` (`requestWithCallbackAndGasLimit`).
-    function getFeeForGas(
+    // Get the fee charged by the default provider for the default gas limit.
+    // Use this function to determine the fee to pass to `requestV2`.
+    function getFeeV2() external view returns (uint128 feeAmount);
+
+    // Get the fee charged by the default provider for the specified gas limit.
+    // Use this function to determine the fee to pass to `requestV2`.
+    function getFeeV2(
+        uint32 gasLimit
+    ) external view returns (uint128 feeAmount);
+
+    // Get the fee charged by `provider` for a request with a specific `gasLimit`.
+    // Use this function to determine the fee to pass to `requestV2`.
+    function getFeeV2(
         address provider,
         uint32 gasLimit
     ) external view returns (uint128 feeAmount);

+ 94 - 6
target_chains/ethereum/entropy_sdk/solidity/abis/IEntropy.json

@@ -991,7 +991,39 @@
         "type": "uint32"
       }
     ],
-    "name": "getFeeForGas",
+    "name": "getFeeV2",
+    "outputs": [
+      {
+        "internalType": "uint128",
+        "name": "feeAmount",
+        "type": "uint128"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "getFeeV2",
+    "outputs": [
+      {
+        "internalType": "uint128",
+        "name": "feeAmount",
+        "type": "uint128"
+      }
+    ],
+    "stateMutability": "view",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "uint32",
+        "name": "gasLimit",
+        "type": "uint32"
+      }
+    ],
+    "name": "getFeeV2",
     "outputs": [
       {
         "internalType": "uint128",
@@ -1368,6 +1400,25 @@
     "stateMutability": "payable",
     "type": "function"
   },
+  {
+    "inputs": [
+      {
+        "internalType": "uint32",
+        "name": "gasLimit",
+        "type": "uint32"
+      }
+    ],
+    "name": "requestV2",
+    "outputs": [
+      {
+        "internalType": "uint64",
+        "name": "assignedSequenceNumber",
+        "type": "uint64"
+      }
+    ],
+    "stateMutability": "payable",
+    "type": "function"
+  },
   {
     "inputs": [
       {
@@ -1376,12 +1427,25 @@
         "type": "address"
       },
       {
-        "internalType": "bytes32",
-        "name": "userRandomNumber",
-        "type": "bytes32"
+        "internalType": "uint32",
+        "name": "gasLimit",
+        "type": "uint32"
       }
     ],
-    "name": "requestWithCallback",
+    "name": "requestV2",
+    "outputs": [
+      {
+        "internalType": "uint64",
+        "name": "assignedSequenceNumber",
+        "type": "uint64"
+      }
+    ],
+    "stateMutability": "payable",
+    "type": "function"
+  },
+  {
+    "inputs": [],
+    "name": "requestV2",
     "outputs": [
       {
         "internalType": "uint64",
@@ -1410,7 +1474,31 @@
         "type": "uint32"
       }
     ],
-    "name": "requestWithCallbackAndGasLimit",
+    "name": "requestV2",
+    "outputs": [
+      {
+        "internalType": "uint64",
+        "name": "assignedSequenceNumber",
+        "type": "uint64"
+      }
+    ],
+    "stateMutability": "payable",
+    "type": "function"
+  },
+  {
+    "inputs": [
+      {
+        "internalType": "address",
+        "name": "provider",
+        "type": "address"
+      },
+      {
+        "internalType": "bytes32",
+        "name": "userRandomNumber",
+        "type": "bytes32"
+      }
+    ],
+    "name": "requestWithCallback",
     "outputs": [
       {
         "internalType": "uint64",