Skip to content

Commit

Permalink
Pass through extraArgs from user to VRFV2PlusWrapper (#10816)
Browse files Browse the repository at this point in the history
* Pass through extraArgs from user to VRFV2PlusWrapper via VRFV2PlusWrapperConsumerBase

* Generate go wrappers and prettify

* Remove abi.decode, removeDomainSeparator and add a simpler checkPaymentMode

* Fix issue in VRFV2PlusWrapperLoadTestConsumer::makeRequests

* Fix comments

---------

Co-authored-by: Sri Kidambi <[email protected]>
Co-authored-by: Makram <[email protected]>
  • Loading branch information
3 people authored Oct 2, 2023
1 parent 6ae09dc commit 07d4038
Show file tree
Hide file tree
Showing 10 changed files with 95 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ interface VRFV2PlusWrapperInterface {
function requestRandomWordsInNative(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords
uint32 _numWords,
bytes memory extraArgs
) external payable returns (uint256 requestId);
}
43 changes: 38 additions & 5 deletions contracts/src/v0.8/dev/vrf/VRFV2PlusWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume

error LinkAlreadySet();
error FailedToTransferLink();
error IncorrectExtraArgsLength(uint16 expectedMinimumLength, uint16 actualLength);
error NativePaymentInOnTokenTransfer();
error LINKPaymentInRequestRandomWordsInNative();

/* Storage Slot 1: BEGIN */
// s_keyHash is the key hash to use when requesting randomness. Fees are paid based on current gas
Expand Down Expand Up @@ -104,6 +107,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume

// s_maxNumWords is the max number of words that can be requested in a single wrapped VRF request.
uint8 s_maxNumWords;

uint16 private constant EXPECTED_MIN_LENGTH = 36;
/* Storage Slot 8: END */

struct Callback {
Expand Down Expand Up @@ -358,10 +363,11 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
function onTokenTransfer(address _sender, uint256 _amount, bytes calldata _data) external onlyConfiguredNotDisabled {
require(msg.sender == address(s_link), "only callable from LINK");

(uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords) = abi.decode(
(uint32 callbackGasLimit, uint16 requestConfirmations, uint32 numWords, bytes memory extraArgs) = abi.decode(
_data,
(uint32, uint16, uint32)
(uint32, uint16, uint32, bytes)
);
checkPaymentMode(extraArgs, true);
uint32 eip150Overhead = getEIP150Overhead(callbackGasLimit);
int256 weiPerUnitLink = getFeedData();
uint256 price = calculateRequestPriceInternal(callbackGasLimit, tx.gasprice, weiPerUnitLink);
Expand All @@ -373,7 +379,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
requestConfirmations: requestConfirmations,
callbackGasLimit: callbackGasLimit + eip150Overhead + s_wrapperGasOverhead,
numWords: numWords,
extraArgs: "" // empty extraArgs defaults to link payment
extraArgs: extraArgs // empty extraArgs defaults to link payment
});
uint256 requestId = s_vrfCoordinator.requestRandomWords(req);
s_callbacks[requestId] = Callback({
Expand All @@ -384,11 +390,38 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
lastRequestId = requestId;
}

function checkPaymentMode(bytes memory extraArgs, bool isLinkMode) public pure {
// If extraArgs is empty, payment mode is LINK by default
if (extraArgs.length == 0) {
if (!isLinkMode) {
revert LINKPaymentInRequestRandomWordsInNative();
}
return;
}
if (extraArgs.length < EXPECTED_MIN_LENGTH) {
revert IncorrectExtraArgsLength(EXPECTED_MIN_LENGTH, uint16(extraArgs.length));
}
// ExtraArgsV1 only has struct {bool nativePayment} as of now
// The following condition checks if nativePayment in abi.encode of
// ExtraArgsV1 matches the appropriate function call (onTokenTransfer
// for LINK and requestRandomWordsInNative for Native payment)
bool nativePayment = extraArgs[35] == hex"01";
if (nativePayment && isLinkMode) {
revert NativePaymentInOnTokenTransfer();
}
if (!nativePayment && !isLinkMode) {
revert LINKPaymentInRequestRandomWordsInNative();
}
}

function requestRandomWordsInNative(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords
uint32 _numWords,
bytes calldata extraArgs
) external payable override returns (uint256 requestId) {
checkPaymentMode(extraArgs, false);

uint32 eip150Overhead = getEIP150Overhead(_callbackGasLimit);
uint256 price = calculateRequestPriceNativeInternal(_callbackGasLimit, tx.gasprice);
require(msg.value >= price, "fee too low");
Expand All @@ -399,7 +432,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
requestConfirmations: _requestConfirmations,
callbackGasLimit: _callbackGasLimit + eip150Overhead + s_wrapperGasOverhead,
numWords: _numWords,
extraArgs: VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true}))
extraArgs: extraArgs
});
requestId = s_vrfCoordinator.requestRandomWords(req);
s_callbacks[requestId] = Callback({
Expand Down
11 changes: 7 additions & 4 deletions contracts/src/v0.8/dev/vrf/VRFV2PlusWrapperConsumerBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,27 +73,30 @@ abstract contract VRFV2PlusWrapperConsumerBase {
function requestRandomness(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords
uint32 _numWords,
bytes memory extraArgs
) internal returns (uint256 requestId) {
LINK.transferAndCall(
address(VRF_V2_PLUS_WRAPPER),
VRF_V2_PLUS_WRAPPER.calculateRequestPrice(_callbackGasLimit),
abi.encode(_callbackGasLimit, _requestConfirmations, _numWords)
abi.encode(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs)
);
return VRF_V2_PLUS_WRAPPER.lastRequestId();
}

function requestRandomnessPayInNative(
uint32 _callbackGasLimit,
uint16 _requestConfirmations,
uint32 _numWords
uint32 _numWords,
bytes memory extraArgs
) internal returns (uint256 requestId) {
uint256 requestPrice = VRF_V2_PLUS_WRAPPER.calculateRequestPriceNative(_callbackGasLimit);
return
VRF_V2_PLUS_WRAPPER.requestRandomWordsInNative{value: requestPrice}(
_callbackGasLimit,
_requestConfirmations,
_numWords
_numWords,
extraArgs
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.8.6;

import "../VRFV2PlusWrapperConsumerBase.sol";
import "../../../shared/access/ConfirmedOwner.sol";
import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol";

contract VRFV2PlusWrapperConsumerExample is VRFV2PlusWrapperConsumerBase, ConfirmedOwner {
event WrappedRequestFulfilled(uint256 requestId, uint256[] randomWords, uint256 payment);
Expand All @@ -27,7 +28,8 @@ contract VRFV2PlusWrapperConsumerExample is VRFV2PlusWrapperConsumerBase, Confir
uint16 _requestConfirmations,
uint32 _numWords
) external onlyOwner returns (uint256 requestId) {
requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords);
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}));
requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs);
uint256 paid = VRF_V2_PLUS_WRAPPER.calculateRequestPrice(_callbackGasLimit);
s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false, native: false});
emit WrapperRequestMade(requestId, paid);
Expand All @@ -39,7 +41,8 @@ contract VRFV2PlusWrapperConsumerExample is VRFV2PlusWrapperConsumerBase, Confir
uint16 _requestConfirmations,
uint32 _numWords
) external onlyOwner returns (uint256 requestId) {
requestId = requestRandomnessPayInNative(_callbackGasLimit, _requestConfirmations, _numWords);
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true}));
requestId = requestRandomnessPayInNative(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs);
uint256 paid = VRF_V2_PLUS_WRAPPER.calculateRequestPriceNative(_callbackGasLimit);
s_requests[requestId] = RequestStatus({paid: paid, randomWords: new uint256[](0), fulfilled: false, native: true});
emit WrapperRequestMade(requestId, paid);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity ^0.8.6;
import "../VRFV2PlusWrapperConsumerBase.sol";
import "../../../shared/access/ConfirmedOwner.sol";
import "../../../ChainSpecificUtil.sol";
import {VRFV2PlusClient} from "../libraries/VRFV2PlusClient.sol";

contract VRFV2PlusWrapperLoadTestConsumer is VRFV2PlusWrapperConsumerBase, ConfirmedOwner {
uint256 public s_responseCount;
Expand Down Expand Up @@ -42,7 +43,8 @@ contract VRFV2PlusWrapperLoadTestConsumer is VRFV2PlusWrapperConsumerBase, Confi
uint16 _requestCount
) external onlyOwner {
for (uint16 i = 0; i < _requestCount; i++) {
uint256 requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords);
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: false}));
uint256 requestId = requestRandomness(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs);
s_lastRequestId = requestId;

uint256 requestBlockNumber = ChainSpecificUtil.getBlockNumber();
Expand Down Expand Up @@ -70,7 +72,8 @@ contract VRFV2PlusWrapperLoadTestConsumer is VRFV2PlusWrapperConsumerBase, Confi
uint16 _requestCount
) external onlyOwner {
for (uint16 i = 0; i < _requestCount; i++) {
uint256 requestId = requestRandomnessPayInNative(_callbackGasLimit, _requestConfirmations, _numWords);
bytes memory extraArgs = VRFV2PlusClient._argsToBytes(VRFV2PlusClient.ExtraArgsV1({nativePayment: true}));
uint256 requestId = requestRandomnessPayInNative(_callbackGasLimit, _requestConfirmations, _numWords, extraArgs);
s_lastRequestId = requestId;

uint256 requestBlockNumber = ChainSpecificUtil.getBlockNumber();
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

40 changes: 31 additions & 9 deletions core/gethwrappers/generated/vrfv2plus_wrapper/vrfv2plus_wrapper.go

Large diffs are not rendered by default.

Loading

0 comments on commit 07d4038

Please sign in to comment.