Skip to content

Commit

Permalink
VRFV2PlusWrapper config refactor (#12581)
Browse files Browse the repository at this point in the history
* VRFV2PlusWrapper config refactor

* Added changeset

* Prettier fix

* Updated tests and fixed lint warnings
  • Loading branch information
kidambisrinivas authored Mar 26, 2024
1 parent 684afa4 commit 6fcc739
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 93 deletions.
5 changes: 5 additions & 0 deletions .changeset/wicked-gorillas-sniff.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": minor
---

VRFV2PlusWrapper config refactor
5 changes: 5 additions & 0 deletions contracts/.changeset/eight-peas-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": minor
---

VRFV2PlusWrapper config refactor
51 changes: 27 additions & 24 deletions contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,15 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// charges for link payment.
uint32 private s_fulfillmentFlatFeeLinkDiscountPPM;

// s_wrapperNativePremiumPercentage is the premium ratio in percentage for native payment. For example, a value of 0
// indicates no premium. A value of 15 indicates a 15 percent premium.
uint8 private s_wrapperNativePremiumPercentage;
// s_coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for native payment.
// For example, a 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_coordinatorNativePremiumPercentage;

// s_wrapperLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a value of 0
// indicates no premium. A value of 15 indicates a 15 percent premium.
uint8 private s_wrapperLinkPremiumPercentage;
// s_coordinatorLinkPremiumPercentage is the premium ratio in percentage for link payment. For example, a
// 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;

// 10 bytes left
/* Storage Slot 6: END */
Expand Down Expand Up @@ -200,9 +202,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
* @param _coordinatorGasOverhead reflects the gas overhead of the coordinator's
* fulfillRandomWords function.
*
* @param _wrapperNativePremiumPercentage is the premium ratio in percentage for wrapper requests paid in native.
* @param _coordinatorNativePremiumPercentage is the coordinator's premium ratio in percentage for requests paid in native.
*
* @param _wrapperLinkPremiumPercentage is the premium ratio in percentage for wrapper requests paid in link.
* @param _coordinatorLinkPremiumPercentage is the coordinator's premium ratio in percentage for requests paid in link.
*
* @param _keyHash to use for requesting randomness.
* @param _maxNumWords is the max number of words that can be requested in a single wrapped VRF request
Expand All @@ -221,8 +223,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
function setConfig(
uint32 _wrapperGasOverhead,
uint32 _coordinatorGasOverhead,
uint8 _wrapperNativePremiumPercentage,
uint8 _wrapperLinkPremiumPercentage,
uint8 _coordinatorNativePremiumPercentage,
uint8 _coordinatorLinkPremiumPercentage,
bytes32 _keyHash,
uint8 _maxNumWords,
uint32 _stalenessSeconds,
Expand All @@ -233,17 +235,17 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
if (_fulfillmentFlatFeeLinkDiscountPPM > _fulfillmentFlatFeeNativePPM) {
revert LinkDiscountTooHigh(_fulfillmentFlatFeeLinkDiscountPPM, _fulfillmentFlatFeeNativePPM);
}
if (_wrapperNativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) {
revert InvalidPremiumPercentage(_wrapperNativePremiumPercentage, PREMIUM_PERCENTAGE_MAX);
if (_coordinatorNativePremiumPercentage > PREMIUM_PERCENTAGE_MAX) {
revert InvalidPremiumPercentage(_coordinatorNativePremiumPercentage, PREMIUM_PERCENTAGE_MAX);
}
if (_wrapperLinkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) {
revert InvalidPremiumPercentage(_wrapperLinkPremiumPercentage, PREMIUM_PERCENTAGE_MAX);
if (_coordinatorLinkPremiumPercentage > PREMIUM_PERCENTAGE_MAX) {
revert InvalidPremiumPercentage(_coordinatorLinkPremiumPercentage, PREMIUM_PERCENTAGE_MAX);
}

s_wrapperGasOverhead = _wrapperGasOverhead;
s_coordinatorGasOverhead = _coordinatorGasOverhead;
s_wrapperNativePremiumPercentage = _wrapperNativePremiumPercentage;
s_wrapperLinkPremiumPercentage = _wrapperLinkPremiumPercentage;
s_coordinatorNativePremiumPercentage = _coordinatorNativePremiumPercentage;
s_coordinatorLinkPremiumPercentage = _coordinatorLinkPremiumPercentage;
s_keyHash = _keyHash;
s_maxNumWords = _maxNumWords;
s_configured = true;
Expand All @@ -257,8 +259,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
emit ConfigSet(
_wrapperGasOverhead,
_coordinatorGasOverhead,
_wrapperNativePremiumPercentage,
_wrapperLinkPremiumPercentage,
_coordinatorNativePremiumPercentage,
_coordinatorLinkPremiumPercentage,
_keyHash,
_maxNumWords,
_stalenessSeconds,
Expand Down Expand Up @@ -324,8 +326,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
s_fulfillmentFlatFeeLinkDiscountPPM,
s_wrapperGasOverhead,
s_coordinatorGasOverhead,
s_wrapperNativePremiumPercentage,
s_wrapperLinkPremiumPercentage,
s_coordinatorNativePremiumPercentage,
s_coordinatorLinkPremiumPercentage,
s_keyHash,
s_maxNumWords
);
Expand Down Expand Up @@ -390,8 +392,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume

// coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied
// coordinator cost * premium multiplier + flat fee
uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * (s_wrapperNativePremiumPercentage + 100)) /
100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM));
uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei *
(s_coordinatorNativePremiumPercentage + 100)) / 100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM));

return wrapperCostWei + coordinatorCostWithPremiumAndFlatFeeWei;
}
Expand All @@ -413,8 +415,9 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume

// coordinatorCostWithPremiumAndFlatFeeWei is the coordinator cost with the percentage premium and flat fee applied
// coordinator cost * premium multiplier + flat fee
uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei * (s_wrapperLinkPremiumPercentage + 100)) /
100) + (1e12 * uint256(s_fulfillmentFlatFeeNativePPM - s_fulfillmentFlatFeeLinkDiscountPPM));
uint256 coordinatorCostWithPremiumAndFlatFeeWei = ((coordinatorCostWei *
(s_coordinatorLinkPremiumPercentage + 100)) / 100) +
(1e12 * uint256(s_fulfillmentFlatFeeNativePPM - s_fulfillmentFlatFeeLinkDiscountPPM));

// requestPrice is denominated in juels (link)
// (1e18 juels/link) * wei / (wei/link) = juels
Expand Down
4 changes: 2 additions & 2 deletions contracts/src/v0.8/vrf/dev/interfaces/IVRFV2PlusWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ interface IVRFV2PlusWrapper {
event ConfigSet(
uint32 wrapperGasOverhead,
uint32 coordinatorGasOverhead,
uint8 wrapperNativePremiumPercentage,
uint8 wrapperLinkPremiumPercentage,
uint8 coordinatorNativePremiumPercentage,
uint8 coordinatorLinkPremiumPercentage,
bytes32 keyHash,
uint8 maxNumWords,
uint32 stalenessSeconds,
Expand Down
54 changes: 26 additions & 28 deletions contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper.t.sol
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "../BaseTest.t.sol";
import {VRF} from "../../../../src/v0.8/vrf/VRF.sol";
import {BaseTest} from "../BaseTest.t.sol";
import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol";
import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol";
import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol";
import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol";
import {VRFV2PlusWrapperConsumerBase} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol";
import {VRFV2PlusWrapperConsumerExample} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol";
import {VRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol";
import {VRFConsumerBaseV2Plus} from "../../../../src/v0.8/vrf/dev/VRFConsumerBaseV2Plus.sol";
import {VRFV2PlusWrapper} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol";
import {VRFV2PlusClient} from "../../../../src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";
import {console} from "forge-std/console.sol";

contract VRFV2PlusWrapperTest is BaseTest {
address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B;
bytes32 vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528";
uint32 wrapperGasOverhead = 10_000;
uint32 coordinatorGasOverhead = 20_000;
uint256 s_wrapperSubscriptionId;
bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528";
uint32 private wrapperGasOverhead = 10_000;
uint32 private coordinatorGasOverhead = 20_000;
uint256 private s_wrapperSubscriptionId;

ExposedVRFCoordinatorV2_5 s_testCoordinator;
MockLinkToken s_linkToken;
MockV3Aggregator s_linkNativeFeed;
VRFV2PlusWrapper s_wrapper;
VRFV2PlusWrapperConsumerExample s_consumer;
ExposedVRFCoordinatorV2_5 private s_testCoordinator;
MockLinkToken private s_linkToken;
MockV3Aggregator private s_linkNativeFeed;
VRFV2PlusWrapper private s_wrapper;
VRFV2PlusWrapperConsumerExample private s_consumer;

function setUp() public override {
BaseTest.setUp();
Expand Down Expand Up @@ -104,15 +102,15 @@ contract VRFV2PlusWrapperTest is BaseTest {
,
uint32 _wrapperGasOverhead,
uint32 _coordinatorGasOverhead,
uint8 _wrapperNativePremiumPercentage,
uint8 _wrapperLinkPremiumPercentage,
uint8 _coordinatorNativePremiumPercentage,
uint8 _coordinatorLinkPremiumPercentage,
bytes32 _keyHash,
uint8 _maxNumWords
) = s_wrapper.getConfig();
assertEq(_wrapperGasOverhead, wrapperGasOverhead);
assertEq(_coordinatorGasOverhead, coordinatorGasOverhead);
assertEq(0, _wrapperNativePremiumPercentage);
assertEq(0, _wrapperLinkPremiumPercentage);
assertEq(0, _coordinatorNativePremiumPercentage);
assertEq(0, _coordinatorLinkPremiumPercentage);
assertEq(vrfKeyHash, _keyHash);
assertEq(10, _maxNumWords);
}
Expand All @@ -135,8 +133,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
event ConfigSet(
uint32 wrapperGasOverhead,
uint32 coordinatorGasOverhead,
uint8 wrapperNativePremiumPercentage,
uint8 wrapperLinkPremiumPercentage,
uint8 coordinatorNativePremiumPercentage,
uint8 coordinatorLinkPremiumPercentage,
bytes32 keyHash,
uint8 maxNumWords,
uint32 stalenessSeconds,
Expand All @@ -156,7 +154,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
// SubscriptionAPI events
event SubscriptionConsumerAdded(uint256 indexed subId, address consumer);

function testVRFV2PlusWrapper_ZeroAddress() public {
function testVRFV2PlusWrapperZeroAddress() public {
vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector);
new VRFV2PlusWrapper(address(s_linkToken), address(0), address(0), uint256(0));
}
Expand Down Expand Up @@ -205,7 +203,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
assertEq(s_wrapper.s_fulfillmentTxSizeBytes(), fulfillmentTxSize);
}

function testSetCoordinator_ZeroAddress() public {
function testSetCoordinatorZeroAddress() public {
vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector);
s_wrapper.setCoordinator(address(0));
}
Expand Down Expand Up @@ -283,7 +281,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
assertEq(address(s_wrapper).balance, 0);
}

function testSetConfig_FulfillmentFlatFee_LinkDiscountTooHigh() public {
function testSetConfigFulfillmentFlatFee_LinkDiscountTooHigh() public {
// Test that setting link discount flat fee higher than native flat fee reverts
vm.expectRevert(abi.encodeWithSelector(VRFV2PlusWrapper.LinkDiscountTooHigh.selector, uint32(501), uint32(500)));
s_wrapper.setConfig(
Expand All @@ -300,7 +298,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
);
}

function testSetConfig_FulfillmentFlatFee_LinkDiscountEqualsNative() public {
function testSetConfigFulfillmentFlatFee_LinkDiscountEqualsNative() public {
// Test that setting link discount flat fee equal to native flat fee does not revert
s_wrapper.setConfig(
wrapperGasOverhead, // wrapper gas overhead
Expand All @@ -316,7 +314,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
);
}

function testSetConfig_NativePremiumPercentage_InvalidPremiumPercentage() public {
function testSetConfigNativePremiumPercentageInvalidPremiumPercentage() public {
// Test that setting native premium percentage higher than 155 will revert
vm.expectRevert(
abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(156), uint8(155))
Expand All @@ -335,7 +333,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
);
}

function testSetConfig_LinkPremiumPercentage_InvalidPremiumPercentage() public {
function testSetConfigLinkPremiumPercentageInvalidPremiumPercentage() public {
// Test that setting LINK premium percentage higher than 155 will revert
vm.expectRevert(
abi.encodeWithSelector(VRFCoordinatorV2_5.InvalidPremiumPercentage.selector, uint8(202), uint8(155))
Expand Down Expand Up @@ -415,7 +413,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0);
}

function testRequestRandomWordsLINKWrapper_FallbackWeiPerUnitLinkUsed() public {
function testRequestRandomWordsLINKWrapperFallbackWeiPerUnitLinkUsed() public {
// Fund subscription.
s_linkToken.transferAndCall(address(s_testCoordinator), 10 ether, abi.encode(s_wrapper.SUBSCRIPTION_ID()));
s_linkToken.transfer(address(s_consumer), 10 ether);
Expand Down Expand Up @@ -452,7 +450,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
s_consumer.makeRequest(callbackGasLimit, 0, 1);
}

function testRequestRandomWordsInNative_NotConfigured() public {
function testRequestRandomWordsInNativeNotConfigured() public {
VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper(
address(s_linkToken),
address(s_linkNativeFeed),
Expand All @@ -464,7 +462,7 @@ contract VRFV2PlusWrapperTest is BaseTest {
wrapper.requestRandomWordsInNative(500_000, 0, 1, "");
}

function testRequestRandomWordsInNative_Disabled() public {
function testRequestRandomWordsInNativeDisabled() public {
s_wrapper.disable();

vm.expectRevert("wrapper is disabled");
Expand Down
35 changes: 16 additions & 19 deletions contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper_Migration.t.sol
Original file line number Diff line number Diff line change
@@ -1,34 +1,31 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "../BaseTest.t.sol";
import {VRF} from "../../../../src/v0.8/vrf/VRF.sol";
import {BaseTest} from "../BaseTest.t.sol";
import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol";
import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol";
import {ExposedVRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/testhelpers/ExposedVRFCoordinatorV2_5.sol";
import {VRFCoordinatorV2Plus_V2Example} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFCoordinatorV2Plus_V2Example.sol";
import {VRFV2PlusWrapperConsumerBase} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapperConsumerBase.sol";
import {VRFV2PlusWrapperConsumerExample} from "../../../../src/v0.8/vrf/dev/testhelpers/VRFV2PlusWrapperConsumerExample.sol";
import {SubscriptionAPI} from "../../../../src/v0.8/vrf/dev/SubscriptionAPI.sol";
import {VRFCoordinatorV2_5} from "../../../../src/v0.8/vrf/dev/VRFCoordinatorV2_5.sol";
import {VRFV2PlusWrapper} from "../../../../src/v0.8/vrf/dev/VRFV2PlusWrapper.sol";
import {VRFV2PlusClient} from "../../../../src/v0.8/vrf/dev/libraries/VRFV2PlusClient.sol";

contract VRFV2PlusWrapper_MigrationTest is BaseTest {
address internal constant LINK_WHALE = 0xD883a6A1C22fC4AbFE938a5aDF9B2Cc31b1BF18B;
uint256 internal constant DEFAULT_NATIVE_FUNDING = 7 ether; // 7 ETH
uint256 internal constant DEFAULT_LINK_FUNDING = 10 ether; // 10 ETH
bytes32 vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528";
uint32 wrapperGasOverhead = 10_000;
uint32 coordinatorGasOverhead = 20_000;
uint256 s_wrapperSubscriptionId;
bytes32 private vrfKeyHash = hex"9f2353bde94264dbc3d554a94cceba2d7d2b4fdce4304d3e09a1fea9fbeb1528";
uint32 private wrapperGasOverhead = 10_000;
uint32 private coordinatorGasOverhead = 20_000;
uint256 private s_wrapperSubscriptionId;

ExposedVRFCoordinatorV2_5 s_testCoordinator;
MockLinkToken s_linkToken;
MockV3Aggregator s_linkNativeFeed;
VRFV2PlusWrapper s_wrapper;
VRFV2PlusWrapperConsumerExample s_consumer;
ExposedVRFCoordinatorV2_5 private s_testCoordinator;
MockLinkToken private s_linkToken;
MockV3Aggregator private s_linkNativeFeed;
VRFV2PlusWrapper private s_wrapper;
VRFV2PlusWrapperConsumerExample private s_consumer;

VRFCoordinatorV2Plus_V2Example s_newCoordinator;
VRFCoordinatorV2Plus_V2Example private s_newCoordinator;

event CoordinatorRegistered(address coordinatorAddress);
event MigrationCompleted(address newCoordinator, uint256 subId);
Expand Down Expand Up @@ -121,15 +118,15 @@ contract VRFV2PlusWrapper_MigrationTest is BaseTest {
,
uint32 _wrapperGasOverhead,
uint32 _coordinatorGasOverhead,
uint8 _wrapperNativePremiumPercentage,
uint8 _wrapperLinkPremiumPercentage,
uint8 _coordinatorNativePremiumPercentage,
uint8 _coordinatorLinkPremiumPercentage,
bytes32 _keyHash,
uint8 _maxNumWords
) = s_wrapper.getConfig();
assertEq(_wrapperGasOverhead, wrapperGasOverhead);
assertEq(_coordinatorGasOverhead, coordinatorGasOverhead);
assertEq(0, _wrapperNativePremiumPercentage);
assertEq(0, _wrapperLinkPremiumPercentage);
assertEq(0, _coordinatorNativePremiumPercentage);
assertEq(0, _coordinatorLinkPremiumPercentage);
assertEq(vrfKeyHash, _keyHash);
assertEq(10, _maxNumWords);
}
Expand Down
Loading

0 comments on commit 6fcc739

Please sign in to comment.