Foundry101, raffle, lesson 39 one big test, debugging at the end of the lesson. #2655
-
I have a hard time debugging at the end of lesson 39 of the raffle. These tests and debugging the tests are probably the most confusing parts of the course for me. Here is the code to my function, in the RaffleTest.t.sol file: function testFulfillRandomWordsPicksAWinnerResetsAndSendsMoney() public raffleEntered {
//Arrange
//Add 3 more players to the raffle
uint256 additionalEntrants = 3; // 4 total players
uint256 startingIndex = 1;
address expectedWinner = address(1);
for (uint256 i = startingIndex; i < startingIndex + additionalEntrants; i++) {
address newPlayer = address(uint160(i));
hoax(newPlayer, 10 ether);
raffle.enterRaffle{value: entranceFee}();
}
uint256 startingTimeStamp = raffle.getLastTimeStamp();
uint256 winnerStartingBalance = expectedWinner.balance;
// Act
// We need to get the requestId from the fulfillRandomWords to call
// VRFCoordinatorV2_5Mock.fulfillRandomWords with the requestId
vm.recordLogs();
raffle.performUpkeep("");
Vm.Log[] memory entries = vm.getRecordedLogs();
bytes32 requestId = entries[1].topics[1];
// This line simulates the fulfillRandomWords call from the VRFCoordinator
// and passes in the requestId
VRFCoordinatorV2_5Mock(vrfCoordinator).fulfillRandomWords(uint256(requestId), address(raffle));
// Assert
address winner = raffle.getRecentWinner();
Raffle.RaffleState raffleState = raffle.getState();
uint256 winnerBalance = address(winner).balance;
uint256 endingTimeStamp = raffle.getLastTimeStamp();
uint256 prize = entranceFee * (additionalEntrants + 1);
assert(winner == expectedWinner);
assert (uint256(raffleState) == 0);
assert (winnerBalance == winnerStartingBalance + prize - entranceFee);
assert (endingTimeStamp > startingTimeStamp);
} Here is the error message I am getting when I try to run this test with -vvvv option: ~/CyfrinUpdraft/FoundryFoundations/cu-ff-s4-lottery$ forge test --mt testFulfillRandomWordsPicksAWinnerResetsAndSendsMoney -vvvv
[⠊] Compiling...
No files changed, compilation skipped
Ran 1 test for test/unit/RaffleTest.t.sol:RaffleTest
[FAIL: InvalidRequest()] testFulfillRandomWordsPicksAWinnerResetsAndSendsMoney() (gas: 329409)
Logs:
Creating subscription on chain ID: 31337
Subscription ID: 97767009708314305665643641779529925837712974602641641141825456487478243071475
Funding subscription ID: 97767009708314305665643641779529925837712974602641641141825456487478243071475
Using VRF coordinator: 0x90193C961A926261B756D1E5bb255e67ff9498A1
On chain ID: 31337
Adding consumer contract 0x50EEf481cae4250d252Ae577A09bF514f224C6C4
Using VRF coordinator: 0x90193C961A926261B756D1E5bb255e67ff9498A1
On chain ID: 31337
Traces:
[49990893] RaffleTest::setUp()
├─ [21045848] → new DeployRaffle@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
│ └─ ← [Return] 104915 bytes of code
├─ [24993922] DeployRaffle::deployContract()
│ ├─ [4488068] → new HelperConfig@0x104fBc016F4bb334D775a19E8A6510109AC63E00
│ │ └─ ← [Return] 21628 bytes of code
│ ├─ [3872341] HelperConfig::getConfig()
│ │ ├─ [0] VM::startBroadcast()
│ │ │ └─ ← [Return]
│ │ ├─ [2863541] → new VRFCoordinatorV2_5Mock@0x90193C961A926261B756D1E5bb255e67ff9498A1
│ │ │ ├─ emit ConfigSet()
│ │ │ └─ ← [Return] 13951 bytes of code
│ │ ├─ [797693] → new LinkToken@0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496
│ │ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: DefaultSender: [0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38], amount: 1000000000000000000000000 [1e24])
│ │ │ └─ ← [Return] 3524 bytes of code
│ │ ├─ [0] VM::stopBroadcast()
│ │ │ └─ ← [Return]
│ │ └─ ← [Return] NetworkConfig({ entranceFee: 10000000000000000 [1e16], interval: 30, vrfCoordinator: 0x90193C961A926261B756D1E5bb255e67ff9498A1, gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae, callbackGasLimit: 500000 [5e5], subscriptionId: 0, link: 0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496 })
│ ├─ [4748866] → new CreateSubscription@0x037eDa3aDB1198021A9b2e88C22B464fD38db3f3
│ │ └─ ← [Return] 23606 bytes of code
│ ├─ [126346] CreateSubscription::createSubscription(VRFCoordinatorV2_5Mock: [0x90193C961A926261B756D1E5bb255e67ff9498A1])
│ │ ├─ [0] console::log("Creating subscription on chain ID:", 31337 [3.133e4]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] VM::startBroadcast()
│ │ │ └─ ← [Return]
│ │ ├─ [120948] VRFCoordinatorV2_5Mock::createSubscription()
│ │ │ ├─ emit SubscriptionCreated(subId: 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], owner: DefaultSender: [0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38])
│ │ │ └─ ← [Return] 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76]
│ │ ├─ [0] VM::stopBroadcast()
│ │ │ └─ ← [Return]
│ │ ├─ [0] console::log("Subscription ID:", 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ └─ ← [Return] 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], VRFCoordinatorV2_5Mock: [0x90193C961A926261B756D1E5bb255e67ff9498A1]
│ ├─ [4940935] → new FundSubscription@0xDDc10602782af652bB913f7bdE1fD82981Db7dd9
│ │ └─ ← [Return] 24565 bytes of code
│ ├─ [49114] FundSubscription::fundSubscription(VRFCoordinatorV2_5Mock: [0x90193C961A926261B756D1E5bb255e67ff9498A1], 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], LinkToken: [0xA8452Ec99ce0C64f20701dB7dD3abDb607c00496])
│ │ ├─ [0] console::log("Funding subscription ID:", 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("Using VRF coordinator:", VRFCoordinatorV2_5Mock: [0x90193C961A926261B756D1E5bb255e67ff9498A1]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("On chain ID:", 31337 [3.133e4]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] VM::startBroadcast()
│ │ │ └─ ← [Return]
│ │ ├─ [45313] VRFCoordinatorV2_5Mock::fundSubscription(97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], 300000000000000000000 [3e20])
│ │ │ ├─ emit SubscriptionFunded(subId: 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], oldBalance: 0, newBalance: 300000000000000000000 [3e20])
│ │ │ └─ ← [Stop]
│ │ ├─ [0] VM::stopBroadcast()
│ │ │ └─ ← [Return]
│ │ └─ ← [Stop]
│ ├─ [0] VM::startBroadcast()
│ │ └─ ← [Return]
│ ├─ [849684] → new Raffle@0x50EEf481cae4250d252Ae577A09bF514f224C6C4
│ │ └─ ← [Return] 3898 bytes of code
│ ├─ [0] VM::stopBroadcast()
│ │ └─ ← [Return]
│ ├─ [5669586] → new AddConsumer@0x7FdB3132Ff7D02d8B9e221c61cC895ce9a4bb773
│ │ └─ ← [Return] 28203 bytes of code
│ ├─ [71039] AddConsumer::addConsumer(Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4], VRFCoordinatorV2_5Mock: [0x90193C961A926261B756D1E5bb255e67ff9498A1], 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76])
│ │ ├─ [0] console::log("Adding consumer contract", Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("Using VRF coordinator:", VRFCoordinatorV2_5Mock: [0x90193C961A926261B756D1E5bb255e67ff9498A1]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("On chain ID:", 31337 [3.133e4]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] VM::startBroadcast()
│ │ │ └─ ← [Return]
│ │ ├─ [67270] VRFCoordinatorV2_5Mock::addConsumer(97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4])
│ │ │ ├─ emit SubscriptionConsumerAdded(subId: 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], consumer: Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4])
│ │ │ └─ ← [Stop]
│ │ ├─ [0] VM::stopBroadcast()
│ │ │ └─ ← [Return]
│ │ └─ ← [Stop]
│ └─ ← [Return] Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4], HelperConfig: [0x104fBc016F4bb334D775a19E8A6510109AC63E00]
├─ [3734041] HelperConfig::getConfig()
│ ├─ [0] VM::startBroadcast()
│ │ └─ ← [Return]
│ ├─ [2863541] → new VRFCoordinatorV2_5Mock@0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809
│ │ ├─ emit ConfigSet()
│ │ └─ ← [Return] 13951 bytes of code
│ ├─ [797693] → new LinkToken@0xD718d5A27a29FF1cD22403426084bA0d479869a0
│ │ ├─ emit Transfer(from: 0x0000000000000000000000000000000000000000, to: DefaultSender: [0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38], amount: 1000000000000000000000000 [1e24])
│ │ └─ ← [Return] 3524 bytes of code
│ ├─ [0] VM::stopBroadcast()
│ │ └─ ← [Return]
│ └─ ← [Return] NetworkConfig({ entranceFee: 10000000000000000 [1e16], interval: 30, vrfCoordinator: 0xDEb1E9a6Be7Baf84208BB6E10aC9F9bbE1D70809, gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae, callbackGasLimit: 500000 [5e5], subscriptionId: 0, link: 0xD718d5A27a29FF1cD22403426084bA0d479869a0 })
├─ [0] VM::deal(player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C], 10000000000000000000 [1e19])
│ └─ ← [Return]
└─ ← [Stop]
[329409] RaffleTest::testFulfillRandomWordsPicksAWinnerResetsAndSendsMoney()
├─ [0] VM::prank(player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
│ └─ ← [Return]
├─ [47760] Raffle::enterRaffle{value: 10000000000000000}()
│ ├─ emit RaffleEntered(player: player: [0x44E97aF4418b7a17AABD8090bEA0A471a366305C])
│ └─ ← [Stop]
├─ [0] VM::warp(32)
│ └─ ← [Return]
├─ [0] VM::roll(2)
│ └─ ← [Return]
├─ [0] VM::deal(ECRecover: [0x0000000000000000000000000000000000000001], 10000000000000000000 [1e19])
│ └─ ← [Return]
├─ [0] VM::prank(ECRecover: [0x0000000000000000000000000000000000000001])
│ └─ ← [Return]
├─ [23860] Raffle::enterRaffle{value: 10000000000000000}()
│ ├─ emit RaffleEntered(player: ECRecover: [0x0000000000000000000000000000000000000001])
│ └─ ← [Stop]
├─ [0] VM::deal(SHA-256: [0x0000000000000000000000000000000000000002], 10000000000000000000 [1e19])
│ └─ ← [Return]
├─ [0] VM::prank(SHA-256: [0x0000000000000000000000000000000000000002])
│ └─ ← [Return]
├─ [23860] Raffle::enterRaffle{value: 10000000000000000}()
│ ├─ emit RaffleEntered(player: SHA-256: [0x0000000000000000000000000000000000000002])
│ └─ ← [Stop]
├─ [0] VM::deal(RIPEMD-160: [0x0000000000000000000000000000000000000003], 10000000000000000000 [1e19])
│ └─ ← [Return]
├─ [0] VM::prank(RIPEMD-160: [0x0000000000000000000000000000000000000003])
│ └─ ← [Return]
├─ [23860] Raffle::enterRaffle{value: 10000000000000000}()
│ ├─ emit RaffleEntered(player: RIPEMD-160: [0x0000000000000000000000000000000000000003])
│ └─ ← [Stop]
├─ [2325] Raffle::getLastTimeStamp() [staticcall]
│ └─ ← [Return] 1
├─ [0] VM::recordLogs()
│ └─ ← [Return]
├─ [144081] Raffle::performUpkeep(0x)
│ ├─ [115645] VRFCoordinatorV2_5Mock::requestRandomWords(RandomWordsRequest({ keyHash: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae, subId: 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], requestConfirmations: 3, callbackGasLimit: 500000 [5e5], numWords: 1, extraArgs: 0x92fd13380000000000000000000000000000000000000000000000000000000000000000 }))
│ │ ├─ emit RandomWordsRequested(keyHash: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae, requestId: 1, preSeed: 100, subId: 97767009708314305665643641779529925837712974602641641141825456487478243071475 [9.776e76], minimumRequestConfirmations: 3, callbackGasLimit: 500000 [5e5], numWords: 1, extraArgs: 0x92fd13380000000000000000000000000000000000000000000000000000000000000000, sender: Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4])
│ │ └─ ← [Return] 1
│ ├─ emit ReqestedRaffleWinner(requestId: 1)
│ └─ ← [Stop]
├─ [0] VM::getRecordedLogs()
│ └─ ← [Return] [([0xeb0e3652e0f44f417695e6e90f2f42c99b65cd7169074c5a654b16b9748c3a4e, 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae, 0xd8262aa171a788c591a5045080d466aa297809e6525646681b09fd4af97b95f3, 0x00000000000000000000000050eef481cae4250d252ae577a09bf514f224c6c4], 0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000640000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000007a120000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000002492fd1338000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000, 0x90193C961A926261B756D1E5bb255e67ff9498A1), ([0xeaaef190cda19dcc6c54a8cf34b736dfa9a8b92e6e8a7c457bdc7e6870661e89, 0x0000000000000000000000000000000000000000000000000000000000000001], 0x, 0x50EEf481cae4250d252Ae577A09bF514f224C6C4)]
├─ [4892] VRFCoordinatorV2_5Mock::fulfillRandomWords(1, Raffle: [0x50EEf481cae4250d252Ae577A09bF514f224C6C4])
│ └─ ← [Revert] InvalidRequest()
└─ ← [Revert] InvalidRequest()
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 4.39ms (340.20µs CPU time)
Ran 1 test suite in 756.70ms (4.39ms CPU time): 0 tests passed, 1 failed, 0 skipped (1 total tests)
Failing tests:
Encountered 1 failing test in test/unit/RaffleTest.t.sol:RaffleTest
[FAIL: InvalidRequest()] testFulfillRandomWordsPicksAWinnerResetsAndSendsMoney() (gas: 329409)
Encountered a total of 1 failing tests, 0 tests succeeded As far as I can see it is all well and good till the script goes on to call the fulfillRandomWords function in the VRFCoordinatorV2_5Mock file. Then somehow uint256 requestId (value=1) gets rejected as invalid. I have gone as far as trying to import console in the VRFCoordinatorV2_5Mock and get some logs in the output, but failed to do that. Somehow when I try to run the test with import line at the top, and a console.log entry in the fulfillRandomWords function, compiler cannot find .log function in the console library. Damn these imports... I have also watched the rest of the video and read the text lesson, made some changes to increase funding, substract the entrance fee in the last assert, but those didn't make any difference as well. I think my error is before that last part of the test. What am I missing? If you need the rest of the code I am working on, you can find them here: https://github.com/BowtiedHarpyEagle/cu-ff-s4-lottery/tree/d23cc42e63a12161db49194fea45d57e2cbee930 |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 13 replies
-
Please share your |
Beta Was this translation helpful? Give feedback.
-
Hello @BowtiedHarpyEagle, Please retry the test with the // SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Script} from "forge-std/Script.sol";
import {Raffle} from "../src/Raffle.sol";
import {VRFCoordinatorV2_5Mock} from "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol";
import {LinkToken} from "test/mocks/LinkToken.sol";
abstract contract CodeConstants {
uint256 public constant SEPOLIA_NETWORK_ID = 11155111;
uint256 public constant LOCAL_CHAIN_ID = 31337;
//Mock Contract Constants
uint96 public constant MOCK_BASE_FEE = 0.25 ether;
uint96 public constant MOCK_GAS_PRICE_LINK = 1e9;
int256 public constant MOCK_WEI_PER_UINT_LINK = 4e15;
}
contract HelperConfig is CodeConstants, Script {
error HelperConfig__InvalidChainId();
struct NetworkConfig {
uint256 entranceFee;
uint256 interval;
address vrfCoordinator;
bytes32 gasLane;
uint32 callbackGasLimit;
uint256 subscriptionId;
address link;
}
NetworkConfig public localNetworkConfig;
mapping(uint256 chainId => NetworkConfig) public networkConfigs;
constructor() {
networkConfigs[SEPOLIA_NETWORK_ID] = getSepoliaEthConfig();
}
function getConfigByChainId(
uint256 chainId
) public returns (NetworkConfig memory) {
if (networkConfigs[chainId].vrfCoordinator != address(0)) {
return networkConfigs[chainId];
} else if (chainId == LOCAL_CHAIN_ID) {
return getOrCreateAnvilEthConfig();
} else {
revert HelperConfig__InvalidChainId();
}
}
function getConfig() public returns (NetworkConfig memory) {
return getConfigByChainId(block.chainid);
}
function getSepoliaEthConfig() public pure returns (NetworkConfig memory) {
return
NetworkConfig({
entranceFee: 0.01 ether,
interval: 30, // 30 seconds so we can test quickly
vrfCoordinator: 0x9DdfaCa8183c41ad55329BdeeD9F6A8d53168B1B,
gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae,
callbackGasLimit: 500000, // 500,000 gas, plenty for testing
subscriptionId: 0,
link: 0x779877A7B0D9E8603169DdbD7836e478b4624789
});
}
function getOrCreateAnvilEthConfig() public returns (NetworkConfig memory) {
// check if we have already created the config
if (networkConfigs[LOCAL_CHAIN_ID].vrfCoordinator != address(0)) {
return localNetworkConfig;
}
// if not, create it using mock contract deployed on anvil
vm.startBroadcast();
VRFCoordinatorV2_5Mock vrfCoordinatorMock = new VRFCoordinatorV2_5Mock(
MOCK_BASE_FEE,
MOCK_GAS_PRICE_LINK,
MOCK_WEI_PER_UINT_LINK
);
LinkToken linkToken = new LinkToken();
vm.stopBroadcast();
localNetworkConfig = NetworkConfig({
entranceFee: 0.01 ether,
interval: 30, // 30 seconds
vrfCoordinator: address(vrfCoordinatorMock),
// gas doesn't matter in mock contract
gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae,
callbackGasLimit: 500000, // 500,000 gas
subscriptionId: 0, // we may need to fix this later
link: address(linkToken) }
);
networkConfigs[LOCAL_CHAIN_ID] = localNetworkConfig
return localNetworkConfig;
}
} |
Beta Was this translation helpful? Give feedback.
Hello @BowtiedHarpyEagle, Please retry the test with the
HelperConfig
below