From e728bac992c41f2f2c35d10db8b04e5e8998e219 Mon Sep 17 00:00:00 2001 From: Chris <104409744+vreff@users.noreply.github.com> Date: Fri, 1 Sep 2023 10:13:24 -0400 Subject: [PATCH 1/5] Update test coverage for trusted blockhash store --- .../foundry/vrf/TrustedBlockhashStore.t.sol | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol b/contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol index d2f52552e43..47fff7ea900 100644 --- a/contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol +++ b/contracts/test/v0.8/foundry/vrf/TrustedBlockhashStore.t.sol @@ -48,6 +48,7 @@ contract TrustedBlockhashStoreTest is BaseTest { assertEq(blockhash(unreachableBlock), 0); // Store blockhash from whitelisted address; + uint256[] memory invalidBlockNums = new uint256[](0); uint256[] memory blockNums = new uint256[](1); blockNums[0] = unreachableBlock; bytes32[] memory blockhashes = new bytes32[](1); @@ -64,9 +65,25 @@ contract TrustedBlockhashStoreTest is BaseTest { vm.expectRevert("Only callable by owner"); bhs.setWhitelist(new address[](0)); - // Should store unreachable blocks via whitelisted address. + // Should not store for a mismatched list of block numbers and hashes. changePrank(LINK_WHALE); + vm.expectRevert(TrustedBlockhashStore.InvalidTrustedBlockhashes.selector); + bhs.storeTrusted(invalidBlockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + + // Should store unreachable blocks via whitelisted address. bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); assertEq(bhs.getBlockhash(unreachableBlock), unreachableBlockhash); + + // Change whitelist. Assert that the old whitelisted address can no longer store, + // but the new one can. + address[] memory newWhitelist = new address[](1); + newWhitelist[0] = LINK_WHALE_2; + bhs.setWhitelist(newWhitelist); + + vm.expectRevert(TrustedBlockhashStore.NotInWhitelist.selector); + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); + + changePrank(LINK_WHALE_2); + bhs.storeTrusted(blockNums, blockhashes, recentBlockNumber, blockhash(recentBlockNumber)); } } From 4f268b97d26a5c133e171786cb916b4b9d6449f1 Mon Sep 17 00:00:00 2001 From: Chris <104409744+vreff@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:05:18 -0400 Subject: [PATCH 2/5] Add wrapper coverage and update snapshot --- contracts/gas-snapshots/vrf.gas-snapshot | 7 +- .../test/v0.8/foundry/vrf/VRFV2Wrapper.t.sol | 69 +++++++++++++++++++ 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/contracts/gas-snapshots/vrf.gas-snapshot b/contracts/gas-snapshots/vrf.gas-snapshot index ff95ebd8afe..58783c28659 100644 --- a/contracts/gas-snapshots/vrf.gas-snapshot +++ b/contracts/gas-snapshots/vrf.gas-snapshot @@ -1,5 +1,5 @@ TrustedBlockhashStoreTest:testGenericBHSFunctions() (gas: 53507) -TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 49536) +TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 92594) VRFCoordinatorV2Plus_Migration:testDeregister() (gas: 101083) VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 29377) VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19877) @@ -12,5 +12,6 @@ VRFV2Plus:testRegisterProvingKey() (gas: 101019) VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755125) VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705549) VRFV2Plus:testSetConfig() (gas: 73057) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 390063) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 290612) \ No newline at end of file +VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 389773) +VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 320270) +VRFV2PlusWrapperTest:testSetLinkAndLinkEthFeed() (gas: 3182869) \ No newline at end of file diff --git a/contracts/test/v0.8/foundry/vrf/VRFV2Wrapper.t.sol b/contracts/test/v0.8/foundry/vrf/VRFV2Wrapper.t.sol index 4b506bb8c50..33bc72998f8 100644 --- a/contracts/test/v0.8/foundry/vrf/VRFV2Wrapper.t.sol +++ b/contracts/test/v0.8/foundry/vrf/VRFV2Wrapper.t.sol @@ -5,6 +5,7 @@ import {VRF} from "../../../../src/v0.8/vrf/VRF.sol"; import {MockLinkToken} from "../../../../src/v0.8/mocks/MockLinkToken.sol"; import {MockV3Aggregator} from "../../../../src/v0.8/tests/MockV3Aggregator.sol"; import {ExposedVRFCoordinatorV2Plus} from "../../../../src/v0.8/dev/vrf/testhelpers/ExposedVRFCoordinatorV2Plus.sol"; +import {VRFV2PlusWrapperConsumerBase} from "../../../../src/v0.8/dev/vrf/VRFV2PlusWrapperConsumerBase.sol"; import {VRFV2PlusWrapperConsumerExample} from "../../../../src/v0.8/dev/vrf/testhelpers/VRFV2PlusWrapperConsumerExample.sol"; import {VRFCoordinatorV2Plus} from "../../../../src/v0.8/dev/vrf/VRFCoordinatorV2Plus.sol"; import {VRFV2PlusWrapper} from "../../../../src/v0.8/dev/vrf/VRFV2PlusWrapper.sol"; @@ -70,6 +71,21 @@ contract VRFV2PlusWrapperTest is BaseTest { vrfKeyHash, // keyHash 10 // max number of words ); + ( + , + , + , + uint32 _wrapperGasOverhead, + uint32 _coordinatorGasOverhead, + uint8 _wrapperPremiumPercentage, + bytes32 _keyHash, + uint8 _maxNumWords + ) = s_wrapper.getConfig(); + assertEq(_wrapperGasOverhead, wrapperGasOverhead); + assertEq(_coordinatorGasOverhead, coordinatorGasOverhead); + assertEq(0, _wrapperPremiumPercentage); + assertEq(vrfKeyHash, _keyHash); + assertEq(10, _maxNumWords); } event RandomWordsRequested( @@ -84,11 +100,42 @@ contract VRFV2PlusWrapperTest is BaseTest { address indexed sender ); + function testSetLinkAndLinkEthFeed() public { + VRFV2PlusWrapper wrapper = new VRFV2PlusWrapper(address(0), address(0), address(s_testCoordinator)); + + // Set LINK and LINK/ETH feed on wrapper. + wrapper.setLINK(address(s_linkToken)); + wrapper.setLinkEthFeed(address(s_linkEthFeed)); + assertEq(address(wrapper.s_link()), address(s_linkToken)); + assertEq(address(wrapper.s_linkEthFeed()), address(s_linkEthFeed)); + + // Revert for subsequent assignment. + vm.expectRevert(VRFV2PlusWrapper.LinkAlreadySet.selector); + wrapper.setLINK(address(s_linkToken)); + + // Consumer can set LINK token. + VRFV2PlusWrapperConsumerExample consumer = new VRFV2PlusWrapperConsumerExample(address(0), address(wrapper)); + consumer.setLinkToken(address(s_linkToken)); + + // Revert for subsequent assignment. + vm.expectRevert(VRFV2PlusWrapperConsumerBase.LINKAlreadySet.selector); + consumer.setLinkToken(address(s_linkToken)); + } + function testRequestAndFulfillRandomWordsNativeWrapper() public { // Fund subscription. s_testCoordinator.fundSubscriptionWithEth{value: 10 ether}(s_wrapper.SUBSCRIPTION_ID()); vm.deal(address(s_consumer), 10 ether); + // Get type and version. + assertEq(s_wrapper.typeAndVersion(), "VRFV2Wrapper 1.0.0"); + + // Cannot make request while disabled. + s_wrapper.disable(); + vm.expectRevert("wrapper is disabled"); + s_consumer.makeRequestNative(500_000, 0, 1); + s_wrapper.enable(); + // Request randomness from wrapper. uint32 callbackGasLimit = 1_000_000; vm.expectEmit(true, true, true, true); @@ -114,7 +161,11 @@ contract VRFV2PlusWrapperTest is BaseTest { (uint256 paid, bool fulfilled, bool native) = s_consumer.s_requests(requestId); uint32 expectedPaid = callbackGasLimit + wrapperGasOverhead + coordinatorGasOverhead; + uint256 wrapperNativeCostEstimate = s_wrapper.estimateRequestPriceNative(callbackGasLimit, tx.gasprice); + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPriceNative(callbackGasLimit); assertEq(paid, expectedPaid); + assertEq(uint256(paid), wrapperNativeCostEstimate); + assertEq(wrapperNativeCostEstimate, wrapperCostCalculation); assertEq(fulfilled, false); assertEq(native, true); assertEq(address(s_consumer).balance, 10 ether - expectedPaid); @@ -129,6 +180,13 @@ contract VRFV2PlusWrapperTest is BaseTest { (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); assertEq(nowFulfilled, true); assertEq(storedWords[0], 123); + + // Withdraw funds from wrapper. + changePrank(LINK_WHALE); + uint256 priorWhaleBalance = LINK_WHALE.balance; + s_wrapper.withdrawNative(LINK_WHALE, paid); + assertEq(LINK_WHALE.balance, priorWhaleBalance + paid); + assertEq(address(s_wrapper).balance, 0); } function testRequestAndFulfillRandomWordsLINKWrapper() public { @@ -162,7 +220,11 @@ 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; + uint256 wrapperCostEstimate = s_wrapper.estimateRequestPrice(callbackGasLimit, tx.gasprice); + uint256 wrapperCostCalculation = s_wrapper.calculateRequestPrice(callbackGasLimit); assertEq(paid, expectedPaid); // 1_030_000 * 2 for link/eth ratio + assertEq(uint256(paid), wrapperCostEstimate); + assertEq(wrapperCostEstimate, wrapperCostCalculation); assertEq(fulfilled, false); assertEq(native, false); assertEq(s_linkToken.balanceOf(address(s_consumer)), 10 ether - expectedPaid); @@ -177,5 +239,12 @@ contract VRFV2PlusWrapperTest is BaseTest { (, bool nowFulfilled, uint256[] memory storedWords) = s_consumer.getRequestStatus(requestId); assertEq(nowFulfilled, true); assertEq(storedWords[0], 456); + + // Withdraw funds from wrapper. + changePrank(LINK_WHALE); + uint256 priorWhaleBalance = s_linkToken.balanceOf(LINK_WHALE); + s_wrapper.withdraw(LINK_WHALE, paid); + assertEq(s_linkToken.balanceOf(LINK_WHALE), priorWhaleBalance + paid); + assertEq(s_linkToken.balanceOf(address(s_wrapper)), 0); } } From ae52651561c0b3c9261ca1e9dc525bca00e66d95 Mon Sep 17 00:00:00 2001 From: Chris <104409744+vreff@users.noreply.github.com> Date: Fri, 1 Sep 2023 16:40:31 -0400 Subject: [PATCH 3/5] Update gas snapshot --- contracts/gas-snapshots/vrf.gas-snapshot | 26 +++++++++++++----------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/contracts/gas-snapshots/vrf.gas-snapshot b/contracts/gas-snapshots/vrf.gas-snapshot index 6b15a770007..1a6c799fcd8 100644 --- a/contracts/gas-snapshots/vrf.gas-snapshot +++ b/contracts/gas-snapshots/vrf.gas-snapshot @@ -1,17 +1,19 @@ TrustedBlockhashStoreTest:testGenericBHSFunctions() (gas: 53507) TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 92594) VRFCoordinatorV2Plus_Migration:testDeregister() (gas: 101083) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 29377) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19877) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenPendingFulfillment() (gas: 237679) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenReentrant() (gas: 361358) -VRFCoordinatorV2Plus_Migration:testMigration() (gas: 471429) -VRFV2Plus:testCreateSubscription() (gas: 181121) -VRFV2Plus:testGetActiveSubscriptionIds() (gas: 3465607) -VRFV2Plus:testRegisterProvingKey() (gas: 101019) -VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755125) -VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705549) -VRFV2Plus:testSetConfig() (gas: 73057) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 29421) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19855) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenPendingFulfillment() (gas: 237702) +VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenReentrant() (gas: 354749) +VRFCoordinatorV2Plus_Migration:testMigration() (gas: 471631) +VRFCoordinatorV2Plus_Migration:testMigrationNoLink() (gas: 431052) +VRFV2Plus:testCancelSubWithNoLink() (gas: 160261) +VRFV2Plus:testCreateSubscription() (gas: 181127) +VRFV2Plus:testGetActiveSubscriptionIds() (gas: 3453659) +VRFV2Plus:testRegisterProvingKey() (gas: 101025) +VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755178) +VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705581) +VRFV2Plus:testSetConfig() (gas: 73032) VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 389773) VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 320270) -VRFV2PlusWrapperTest:testSetLinkAndLinkEthFeed() (gas: 3182869) +VRFV2PlusWrapperTest:testSetLinkAndLinkEthFeed() (gas: 3182869) \ No newline at end of file From 13e453a198ba88f358cf4402dca5a6bd2f0fe5b3 Mon Sep 17 00:00:00 2001 From: Chris Cushman <104409744+vreff@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:11:44 -0400 Subject: [PATCH 4/5] Update vrf.gas-snapshot --- contracts/gas-snapshots/vrf.gas-snapshot | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/contracts/gas-snapshots/vrf.gas-snapshot b/contracts/gas-snapshots/vrf.gas-snapshot index efab34218ae..e11f2dbee08 100644 --- a/contracts/gas-snapshots/vrf.gas-snapshot +++ b/contracts/gas-snapshots/vrf.gas-snapshot @@ -1,5 +1,5 @@ TrustedBlockhashStoreTest:testGenericBHSFunctions() (gas: 53507) -TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 92594) +TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 98989) VRFCoordinatorV2Plus_Migration:testDeregister() (gas: 101083) VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 33190) VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19877) @@ -14,6 +14,6 @@ VRFV2Plus:testRegisterProvingKey() (gas: 101085) VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755144) VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705591) VRFV2Plus:testSetConfig() (gas: 73032) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 389773) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 320270) -VRFV2PlusWrapperTest:testSetLinkAndLinkEthFeed() (gas: 3182869) +VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 394916) +VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 325457) +VRFV2PlusWrapperTest:testSetLinkAndLinkEthFeed() (gas: 3182891) From fdf411ac28a47c12f2fae39afe51d50801884ecb Mon Sep 17 00:00:00 2001 From: Chris Cushman <104409744+vreff@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:51:26 -0400 Subject: [PATCH 5/5] Delete contracts/gas-snapshots/vrf.gas-snapshot --- contracts/gas-snapshots/vrf.gas-snapshot | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 contracts/gas-snapshots/vrf.gas-snapshot diff --git a/contracts/gas-snapshots/vrf.gas-snapshot b/contracts/gas-snapshots/vrf.gas-snapshot deleted file mode 100644 index e11f2dbee08..00000000000 --- a/contracts/gas-snapshots/vrf.gas-snapshot +++ /dev/null @@ -1,19 +0,0 @@ -TrustedBlockhashStoreTest:testGenericBHSFunctions() (gas: 53507) -TrustedBlockhashStoreTest:testTrustedBHSFunctions() (gas: 98989) -VRFCoordinatorV2Plus_Migration:testDeregister() (gas: 101083) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCaller() (gas: 33190) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenInvalidCoordinator() (gas: 19877) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenPendingFulfillment() (gas: 237679) -VRFCoordinatorV2Plus_Migration:testMigrateRevertsWhenReentrant() (gas: 357765) -VRFCoordinatorV2Plus_Migration:testMigration() (gas: 471605) -VRFCoordinatorV2Plus_Migration:testMigrationNoLink() (gas: 431075) -VRFV2Plus:testCancelSubWithNoLink() (gas: 160279) -VRFV2Plus:testCreateSubscription() (gas: 181127) -VRFV2Plus:testGetActiveSubscriptionIds() (gas: 3453681) -VRFV2Plus:testRegisterProvingKey() (gas: 101085) -VRFV2Plus:testRequestAndFulfillRandomWordsLINK() (gas: 755144) -VRFV2Plus:testRequestAndFulfillRandomWordsNative() (gas: 705591) -VRFV2Plus:testSetConfig() (gas: 73032) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsLINKWrapper() (gas: 394916) -VRFV2PlusWrapperTest:testRequestAndFulfillRandomWordsNativeWrapper() (gas: 325457) -VRFV2PlusWrapperTest:testSetLinkAndLinkEthFeed() (gas: 3182891)