Skip to content

Commit

Permalink
Split coordinator gas overhead into link and native (#12911)
Browse files Browse the repository at this point in the history
* Split coordinator gas overhead into link and native

* Fix tests
  • Loading branch information
leeyikjiun authored Apr 23, 2024
1 parent 70c5a0b commit d2df811
Show file tree
Hide file tree
Showing 15 changed files with 150 additions and 75 deletions.
60 changes: 42 additions & 18 deletions contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
event FulfillmentTxSizeSet(uint32 size);
event ConfigSet(
uint32 wrapperGasOverhead,
uint32 coordinatorGasOverhead,
uint32 coordinatorGasOverheadNative,
uint32 coordinatorGasOverheadLink,
uint16 coordinatorGasOverheadPerWord,
uint8 coordinatorNativePremiumPercentage,
uint8 coordinatorLinkPremiumPercentage,
Expand Down Expand Up @@ -115,11 +116,18 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
/// @dev total data size = 4608 bits + 32 bits = 4640 bits = 580 bytes
uint32 public s_fulfillmentTxSizeBytes = 580;

// s_coordinatorGasOverhead reflects the gas overhead of the coordinator's fulfillRandomWords
// function. The cost for this gas is billed to the subscription, and must therefor be included
// s_coordinatorGasOverheadNative reflects the gas overhead of the coordinator's fulfillRandomWords
// function for native payment. The cost for this gas is billed to the subscription, and must therefor be included
// in the pricing for wrapped requests. This includes the gas costs of proof verification and
// payment calculation in the coordinator.
uint32 private s_coordinatorGasOverhead;
uint32 private s_coordinatorGasOverheadNative;

// s_coordinatorGasOverheadLink reflects the gas overhead of the coordinator's fulfillRandomWords
// function for link payment. The cost for this gas is billed to the subscription, and must therefor be included
// in the pricing for wrapped requests. This includes the gas costs of proof verification and
// payment calculation in the coordinator.
uint32 private s_coordinatorGasOverheadLink;

uint16 private s_coordinatorGasOverheadPerWord;

// s_fulfillmentFlatFeeLinkPPM is the flat fee in millionths of native that VRFCoordinatorV2
Expand All @@ -139,8 +147,6 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// value of 0 indicates no premium. A value of 15 indicates a 15 percent premium.
// Wrapper has no premium. This premium is for VRFCoordinator.
uint8 private s_coordinatorLinkPremiumPercentage;

// 4 bytes left
/* Storage Slot 5: END */

struct Callback {
Expand Down Expand Up @@ -199,7 +205,13 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
* @param _wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords
* function.
*
* @param _coordinatorGasOverhead reflects the gas overhead of the coordinator's
* @param _coordinatorGasOverheadNative reflects the gas overhead of the coordinator's
* fulfillRandomWords function for native payment.
*
* @param _coordinatorGasOverheadLink reflects the gas overhead of the coordinator's
* fulfillRandomWords function for link payment.
*
* @param _coordinatorGasOverheadPerWord reflects the gas overhead per word of the coordinator's
* fulfillRandomWords function.
*
* @param _coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for requests paid in native.
Expand All @@ -222,7 +234,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
*/
function setConfig(
uint32 _wrapperGasOverhead,
uint32 _coordinatorGasOverhead,
uint32 _coordinatorGasOverheadNative,
uint32 _coordinatorGasOverheadLink,
uint16 _coordinatorGasOverheadPerWord,
uint8 _coordinatorNativePremiumPercentage,
uint8 _coordinatorLinkPremiumPercentage,
Expand All @@ -244,7 +257,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
}

s_wrapperGasOverhead = _wrapperGasOverhead;
s_coordinatorGasOverhead = _coordinatorGasOverhead;
s_coordinatorGasOverheadNative = _coordinatorGasOverheadNative;
s_coordinatorGasOverheadLink = _coordinatorGasOverheadLink;
s_coordinatorGasOverheadPerWord = _coordinatorGasOverheadPerWord;
s_coordinatorNativePremiumPercentage = _coordinatorNativePremiumPercentage;
s_coordinatorLinkPremiumPercentage = _coordinatorLinkPremiumPercentage;
Expand All @@ -260,7 +274,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume

emit ConfigSet(
_wrapperGasOverhead,
_coordinatorGasOverhead,
_coordinatorGasOverheadNative,
_coordinatorGasOverheadLink,
_coordinatorGasOverheadPerWord,
_coordinatorNativePremiumPercentage,
_coordinatorLinkPremiumPercentage,
Expand Down Expand Up @@ -291,8 +306,11 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
* @return wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords
* function. The cost for this gas is passed to the user.
*
* @return coordinatorGasOverhead reflects the gas overhead of the coordinator's
* fulfillRandomWords function.
* @return coordinatorGasOverheadNative reflects the gas overhead of the coordinator's
* fulfillRandomWords function for native payment.
*
* @return coordinatorGasOverheadLink reflects the gas overhead of the coordinator's
* fulfillRandomWords function for link payment.
*
* @return coordinatorGasOverheadPerWord reflects the gas overhead per word of the coordinator's
* fulfillRandomWords function.
Expand All @@ -318,7 +336,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
uint32 fulfillmentFlatFeeNativePPM,
uint32 fulfillmentFlatFeeLinkDiscountPPM,
uint32 wrapperGasOverhead,
uint32 coordinatorGasOverhead,
uint32 coordinatorGasOverheadNative,
uint32 coordinatorGasOverheadLink,
uint16 coordinatorGasOverheadPerWord,
uint8 wrapperNativePremiumPercentage,
uint8 wrapperLinkPremiumPercentage,
Expand All @@ -332,7 +351,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
s_fulfillmentFlatFeeNativePPM,
s_fulfillmentFlatFeeLinkDiscountPPM,
s_wrapperGasOverhead,
s_coordinatorGasOverhead,
s_coordinatorGasOverheadNative,
s_coordinatorGasOverheadLink,
s_coordinatorGasOverheadPerWord,
s_coordinatorNativePremiumPercentage,
s_coordinatorLinkPremiumPercentage,
Expand Down Expand Up @@ -403,7 +423,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// coordinatorCostWei takes into account the L1 posting costs of the VRF fulfillment transaction, if we are on an L2.
// (wei/gas) * gas + l1wei
uint256 coordinatorCostWei = _requestGasPrice *
(_gas + _getCoordinatorGasOverhead(_numWords)) +
(_gas + _getCoordinatorGasOverhead(_numWords, true)) +
ChainSpecificUtil._getL1CalldataGasCost(s_fulfillmentTxSizeBytes);

// coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied
Expand All @@ -427,7 +447,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// coordinatorCostWei takes into account the L1 posting costs of the VRF fulfillment transaction, if we are on an L2.
// (wei/gas) * gas + l1wei
uint256 coordinatorCostWei = _requestGasPrice *
(_gas + _getCoordinatorGasOverhead(_numWords)) +
(_gas + _getCoordinatorGasOverhead(_numWords, false)) +
ChainSpecificUtil._getL1CalldataGasCost(s_fulfillmentTxSizeBytes);

// coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied
Expand Down Expand Up @@ -641,8 +661,12 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
return gas / 63 + 1;
}

function _getCoordinatorGasOverhead(uint32 numWords) internal view returns (uint32) {
return s_coordinatorGasOverhead + numWords * s_coordinatorGasOverheadPerWord;
function _getCoordinatorGasOverhead(uint32 numWords, bool nativePayment) internal view returns (uint32) {
if (nativePayment) {
return s_coordinatorGasOverheadNative + numWords * s_coordinatorGasOverheadPerWord;
} else {
return s_coordinatorGasOverheadLink + numWords * s_coordinatorGasOverheadPerWord;
}
}

/**
Expand Down
46 changes: 34 additions & 12 deletions contracts/src/v0.8/vrf/test/VRFV2PlusWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B;
bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528";
uint32 private wrapperGasOverhead = 100_000;
uint32 private coordinatorGasOverhead = 200_000;
uint32 private coordinatorGasOverheadNative = 200_000;
uint32 private coordinatorGasOverheadLink = 220_000;
uint256 private s_wrapperSubscriptionId;

ExposedVRFCoordinatorV2_5 private s_testCoordinator;
Expand Down Expand Up @@ -84,10 +85,24 @@ contract VRFV2PlusWrapperTest is BaseTest {

function setConfigWrapper() internal {
vm.expectEmit(false, false, false, true, address(s_wrapper));
emit ConfigSet(wrapperGasOverhead, coordinatorGasOverhead, 0, 0, 0, vrfKeyHash, 10, 1, 50000000000000000, 0, 0);
emit ConfigSet(
wrapperGasOverhead,
coordinatorGasOverheadNative,
coordinatorGasOverheadLink,
0,
0,
0,
vrfKeyHash,
10,
1,
50000000000000000,
0,
0
);
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
coordinatorGasOverhead, // coordinator gas overhead
coordinatorGasOverheadNative, // coordinator gas overhead native
coordinatorGasOverheadLink, // coordinator gas overhead link
0, // coordinator gas overhead per word
0, // native premium percentage,
0, // link premium percentage
Expand All @@ -104,15 +119,17 @@ contract VRFV2PlusWrapperTest is BaseTest {
,
,
uint32 _wrapperGasOverhead,
uint32 _coordinatorGasOverhead,
uint32 _coordinatorGasOverheadNative,
uint32 _coordinatorGasOverheadLink,
uint16 _coordinatorGasOverheadPerWord,
uint8 _coordinatorNativePremiumPercentage,
uint8 _coordinatorLinkPremiumPercentage,
bytes32 _keyHash,
uint8 _maxNumWords
) = s_wrapper.getConfig();
assertEq(_wrapperGasOverhead, wrapperGasOverhead);
assertEq(_coordinatorGasOverhead, coordinatorGasOverhead);
assertEq(_coordinatorGasOverheadNative, coordinatorGasOverheadNative);
assertEq(_coordinatorGasOverheadLink, coordinatorGasOverheadLink);
assertEq(0, _coordinatorGasOverheadPerWord);
assertEq(0, _coordinatorNativePremiumPercentage);
assertEq(0, _coordinatorLinkPremiumPercentage);
Expand All @@ -137,7 +154,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
event FulfillmentTxSizeSet(uint32 size);
event ConfigSet(
uint32 wrapperGasOverhead,
uint32 coordinatorGasOverhead,
uint32 coordinatorGasOverheadNative,
uint32 coordinatorGasOverheadLink,
uint16 coordinatorGasOverheadPerWord,
uint8 coordinatorNativePremiumPercentage,
uint8 coordinatorLinkPremiumPercentage,
Expand Down Expand Up @@ -241,7 +259,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
requestId = s_consumer.makeRequestNative(callbackGasLimit, 0, 1);

(uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId);
uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverhead;
uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadNative;
uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, 0, tx.gasprice);
uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, 0);
assertEq(paid, expectedPaid);
Expand Down Expand Up @@ -277,7 +295,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
vm.expectRevert(abi.encodeWithSelector(VRFV2PlusWrapper.LinkDiscountTooHigh.selector, uint32(501), uint32(500)));
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
coordinatorGasOverhead, // coordinator gas overhead
coordinatorGasOverheadNative, // coordinator gas overhead native
coordinatorGasOverheadLink, // coordinator gas overhead link
0, // coordinator gas overhead per word
0, // native premium percentage,
0, // link premium percentage
Expand All @@ -294,7 +313,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
// Test that setting link discount flat fee equal to native flat fee does not revert
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
coordinatorGasOverhead, // coordinator gas overhead
coordinatorGasOverheadNative, // coordinator gas overhead native
coordinatorGasOverheadLink, // coordinator gas overhead link
0, // coordinator gas overhead per word
0, // native premium percentage,
0, // link premium percentage
Expand All @@ -314,7 +334,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
);
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
coordinatorGasOverhead, // coordinator gas overhead
coordinatorGasOverheadNative, // coordinator gas overhead native
coordinatorGasOverheadLink, // coordinator gas overhead link
0, // coordinator gas overhead per word
156, // native premium percentage,
0, // link premium percentage
Expand All @@ -334,7 +355,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
);
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
coordinatorGasOverhead, // coordinator gas overhead
coordinatorGasOverheadNative, // coordinator gas overhead native
coordinatorGasOverheadLink, // coordinator gas overhead link
0, // coordinator gas overhead per word
15, // native premium percentage,
202, // link premium percentage
Expand Down Expand Up @@ -377,7 +399,7 @@ contract VRFV2PlusWrapperTest is BaseTest {

// Assert that the request was made correctly.
(uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId);
uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverhead) * 2;
uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadLink) * 2;
uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, 0, tx.gasprice);
uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, 0);
assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/native ratio
Expand Down
16 changes: 10 additions & 6 deletions contracts/src/v0.8/vrf/test/VRFV2PlusWrapper_Migration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest {
uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 ETH
bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528";
uint32 private wrapperGasOverhead = 10_000;
uint32 private coordinatorGasOverhead = 20_000;
uint32 private coordinatorGasOverheadNative = 20_000;
uint32 private coordinatorGasOverheadLink = 40_000;
uint256 private s_wrapperSubscriptionId;

ExposedVRFCoordinatorV2_5 private s_testCoordinator;
Expand Down Expand Up @@ -101,7 +102,8 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest {
function setConfigWrapper() internal {
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
coordinatorGasOverhead, // coordinator gas overhead
coordinatorGasOverheadNative, // coordinator gas overhead native
coordinatorGasOverheadLink, // coordinator gas overhead link
0, // coordinator gas overhead per word
0, // native premium percentage,
0, // link premium percentage
Expand All @@ -118,15 +120,17 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest {
,
,
uint32 _wrapperGasOverhead,
uint32 _coordinatorGasOverhead,
uint32 _coordinatorGasOverheadNative,
uint32 _coordinatorGasOverheadLink,
uint16 _coordinatorGasOverheadPerWord,
uint8 _coordinatorNativePremiumPercentage,
uint8 _coordinatorLinkPremiumPercentage,
bytes32 _keyHash,
uint8 _maxNumWords
) = s_wrapper.getConfig();
assertEq(_wrapperGasOverhead, wrapperGasOverhead);
assertEq(_coordinatorGasOverhead, coordinatorGasOverhead);
assertEq(_coordinatorGasOverheadNative, coordinatorGasOverheadNative);
assertEq(_coordinatorGasOverheadLink, coordinatorGasOverheadLink);
assertEq(0, _coordinatorGasOverheadPerWord);
assertEq(0, _coordinatorNativePremiumPercentage);
assertEq(0, _coordinatorLinkPremiumPercentage);
Expand Down Expand Up @@ -229,7 +233,7 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest {
assertEq(requestId, 1);

(uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId);
uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverhead) * 2;
uint32 expectedPaid = (callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadLink) * 2;
uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, 0, tx.gasprice);
uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit, 0);
assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/native ratio
Expand Down Expand Up @@ -344,7 +348,7 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest {
assertEq(requestId, 1);

(uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId);
uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverhead;
uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverheadNative;
uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, 0, tx.gasprice);
uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit, 0);
assertEq(paid, expectedPaid);
Expand Down
Loading

0 comments on commit d2df811

Please sign in to comment.