Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set LINK native feed in VRFV2PlusWrapper to immutable #12592

Merged
merged 7 commits into from
Mar 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/odd-mugs-divide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"chainlink": patch
---

Set LINK native feed in VRFV2PlusWrapper to immutable
5 changes: 5 additions & 0 deletions contracts/.changeset/strange-actors-do.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@chainlink/contracts": patch
---

Set LINK native feed in VRFV2PlusWrapper to immutable
39 changes: 11 additions & 28 deletions contracts/src/v0.8/vrf/dev/VRFV2PlusWrapper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i
uint256 public immutable SUBSCRIPTION_ID;
LinkTokenInterface internal immutable i_link;
AggregatorV3Interface internal immutable i_link_native_feed;

error LinkAlreadySet();
error LinkDiscountTooHigh(uint32 flatFeeLinkDiscountPPM, uint32 flatFeeNativePPM);
Expand Down Expand Up @@ -80,13 +81,6 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// fallback to fallbackWeiPerUnitLink.
uint32 private s_stalenessSeconds;

AggregatorV3Interface public s_linkNativeFeed;

/// @dev padding to make sure that the next variable is at a new storage slot
uint64 private s_padding;
/* Storage Slot 5: END */

/* Storage Slot 6: BEGIN */
// s_wrapperGasOverhead reflects the gas overhead of the wrapper's fulfillRandomWords
// function. The cost for this gas is passed to the user.
uint32 private s_wrapperGasOverhead;
Expand Down Expand Up @@ -125,8 +119,8 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// Wrapper has no premium. This premium is for VRFCoordinator.
uint8 private s_coordinatorLinkPremiumPercentage;

// 10 bytes left
/* Storage Slot 6: END */
// 6 bytes left
/* Storage Slot 5: END */

struct Callback {
address callbackAddress;
Expand All @@ -137,24 +131,19 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
// GasPrice is unlikely to be more than 14 ETH on most chains
uint64 requestGasPrice;
}
/* Storage Slot 7: BEGIN */
/* Storage Slot 6: BEGIN */
mapping(uint256 => Callback) /* requestID */ /* callback */ public s_callbacks;
/* Storage Slot 7: END */
/* Storage Slot 6: END */

constructor(
address _link,
address _linkNativeFeed,
address _coordinator,
uint256 _subId
) VRFConsumerBaseV2Plus(_coordinator) {
if (_link == address(0)) {
revert ZeroAddress();
}
i_link = LinkTokenInterface(_link);
i_link_native_feed = AggregatorV3Interface(_linkNativeFeed);

if (_linkNativeFeed != address(0)) {
s_linkNativeFeed = AggregatorV3Interface(_linkNativeFeed);
}
if (_subId == 0) {
revert SubscriptionIdMissing();
}
Expand All @@ -170,16 +159,6 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
SUBSCRIPTION_ID = _subId;
}

/**
* @notice set link native feed to be used by this wrapper
* @param linkNativeFeed address of the link native feed
*/
function setLinkNativeFeed(address linkNativeFeed) external onlyOwner {
s_linkNativeFeed = AggregatorV3Interface(linkNativeFeed);

emit LinkNativeFeedSet(linkNativeFeed);
}

/**
* @notice setFulfillmentTxSize sets the size of the fulfillment transaction in bytes.
* @param size is the size of the fulfillment transaction in bytes.
Expand Down Expand Up @@ -599,10 +578,14 @@ contract VRFV2PlusWrapper is ConfirmedOwner, TypeAndVersionInterface, VRFConsume
return address(i_link);
}

function linkNativeFeed() external view override returns (address) {
return address(i_link_native_feed);
}

function _getFeedData() private view returns (int256 weiPerUnitLink, bool isFeedStale) {
uint32 stalenessSeconds = s_stalenessSeconds;
uint256 timestamp;
(, weiPerUnitLink, , timestamp, ) = s_linkNativeFeed.latestRoundData();
(, weiPerUnitLink, , timestamp, ) = i_link_native_feed.latestRoundData();
// solhint-disable-next-line not-rely-on-time
isFeedStale = stalenessSeconds > 0 && stalenessSeconds < block.timestamp - timestamp;
if (isFeedStale) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.0;

interface IVRFV2PlusWrapper {
event LinkNativeFeedSet(address linkNativeFeed);
event FulfillmentTxSizeSet(uint32 size);
event ConfigSet(
uint32 wrapperGasOverhead,
Expand Down Expand Up @@ -90,4 +89,5 @@ interface IVRFV2PlusWrapper {
) external payable returns (uint256 requestId);

function link() external view returns (address);
function linkNativeFeed() external view returns (address);
}
25 changes: 6 additions & 19 deletions contracts/test/v0.8/foundry/vrf/VRFV2PlusWrapper.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ contract VRFV2PlusWrapperTest is BaseTest {
address(s_testCoordinator),
uint256(s_wrapperSubscriptionId)
);
assertEq(address(s_linkToken), address(s_wrapper.link()));
assertEq(address(s_linkNativeFeed), address(s_wrapper.linkNativeFeed()));

// Add wrapper as a consumer to the wrapper's subscription.
s_testCoordinator.addConsumer(uint256(s_wrapperSubscriptionId), address(s_wrapper));
Expand Down Expand Up @@ -156,14 +158,14 @@ contract VRFV2PlusWrapperTest is BaseTest {

function testVRFV2PlusWrapperZeroAddress() public {
vm.expectRevert(VRFConsumerBaseV2Plus.ZeroAddress.selector);
new VRFV2PlusWrapper(address(s_linkToken), address(0), address(0), uint256(0));
new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(0), uint256(0));
}

function testCreationOfANewVRFV2PlusWrapper() public {
// second wrapper contract will simply add itself to the same subscription
VRFV2PlusWrapper nextWrapper = new VRFV2PlusWrapper(
address(s_linkToken),
address(0),
address(s_linkNativeFeed),
address(s_testCoordinator),
s_wrapperSubscriptionId
);
Expand All @@ -172,27 +174,12 @@ contract VRFV2PlusWrapperTest is BaseTest {

function testVRFV2PlusWrapperWithZeroSubscriptionId() public {
vm.expectRevert(VRFV2PlusWrapper.SubscriptionIdMissing.selector);
new VRFV2PlusWrapper(address(s_linkToken), address(0), address(s_testCoordinator), uint256(0));
new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(0));
}

function testVRFV2PlusWrapperWithInvalidSubscriptionId() public {
vm.expectRevert(SubscriptionAPI.InvalidSubscription.selector);
new VRFV2PlusWrapper(address(s_linkToken), address(0), address(s_testCoordinator), uint256(123456));
}

function testSetLinkAndLinkNativeFeed() public {
VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper(
address(s_linkToken),
address(0),
address(s_testCoordinator),
uint256(s_wrapperSubscriptionId)
);

// Set LINK/Native feed on wrapper.
vm.expectEmit(false, false, false, true, address(wrapper));
emit LinkNativeFeedSet(address(s_linkNativeFeed));
wrapper.setLinkNativeFeed(address(s_linkNativeFeed));
assertEq(address(wrapper.s_linkNativeFeed()), address(s_linkNativeFeed));
new VRFV2PlusWrapper(address(s_linkToken), address(s_linkNativeFeed), address(s_testCoordinator), uint256(123456));
}

function testSetFulfillmentTxSize() public {
Expand Down
Loading
Loading