Skip to content

Commit

Permalink
Set LINK native feed in VRFV2PlusWrapper to immutable (#12592)
Browse files Browse the repository at this point in the history
* Set LINK native feed in VRFV2PlusWrapper to immutable

* LINK native feed set to immutable, removed setter function
* both LINK token and LINK native feed can be set to zero addresses
* fixed Foundry tests

* Added solhint disable for LINK_NATIVE_FEED immutable var

* Added changesets

* Delete storage slot padding from VRFV2PlusWrapper

Co-authored-by: Lee Yik Jiun <yikjiun.lee@smartcontract.com>

* Renamed LINK_NATIVE_FEED to i_link_native_feed, generated Go wrappers

* Fixed linter issue

* Link native feed address variable set to internal

---------

Co-authored-by: Lee Yik Jiun <yikjiun.lee@smartcontract.com>
  • Loading branch information
ibrajer and leeyikjiun authored Mar 26, 2024
1 parent 50724c3 commit b512ef5
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 218 deletions.
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

0 comments on commit b512ef5

Please sign in to comment.