Issue in testing Raffle smart contract in forking chain #3305
Replies: 3 comments 9 replies
-
Please show your |
Beta Was this translation helpful? Give feedback.
-
Hi, I'm stuck with the same section but I think my problem is that I'm calling VRFCoordinatorV2_5Mock and that this leads to the test failing on Sepolia, but before I rewrite this and potentially create a huge mess can someone please confirm this being the issue here? So I'm getting this error in terminal: forge test --fork-url $SEPOLIA_RPC_URL -vvvv ─╯
[⠊] Compiling...
[⠑] Compiling 2 files with Solc 0.8.19
[⠘] Solc 0.8.19 finished in 2.75s
Compiler run successful with warnings:
Warning (5667): Unused function parameter. Remove or comment out the variable name to silence this warning.
--> src/Raffle.sol:165:9:
|
165 | uint256 requestId,
| ^^^^^^^^^^^^^^^^^
Ran 1 test for test/unit/RaffleTest.t.sol:RaffleTest
[FAIL: EvmError: Revert] setUp() (gas: 0)
Logs:
Adding consumer contract: 0xa4725D8EDA697d9B3CcD5Acdb3BCbFf7E473afD8
To VRF Coordinator: 0xD7f86b4b8Cae7D942340FF628F82735b7a20893a
On chain id: 11155111
Traces:
[33140186] RaffleTest::setUp()
├─ [21605499] → new DeployRaffle@0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f
│ └─ ← [Return] 107705 bytes of code
├─ [11452994] DeployRaffle::deployContract()
│ ├─ [4602171] → new HelperConfig@0x104fBc016F4bb334D775a19E8A6510109AC63E00
│ │ └─ ← [Return] 21877 bytes of code
│ ├─ [2239] HelperConfig::getConfig()
│ │ └─ ← [Return] NetworkConfig({ entranceFee: 10000000000000000 [1e16], interval: 30, vrfCoordinator: 0xD7f86b4b8Cae7D942340FF628F82735b7a20893a, gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae, subscriptionId: 56791896273763508949438815106474997201608599347730115153934960174154752396659 [5.679e76], callbackGasLimit: 500000 [5e5], link: 0x779877A7B0D9E8603169DdbD7836e478b4624789, account: 0xd22BFCA3DAb60c1a11b2f1d7C8e2CBa063716A38 })
│ ├─ [0] VM::startBroadcast(0xd22BFCA3DAb60c1a11b2f1d7C8e2CBa063716A38)
│ │ └─ ← [Return]
│ ├─ [825058] → new Raffle@0xa4725D8EDA697d9B3CcD5Acdb3BCbFf7E473afD8
│ │ └─ ← [Return] 3775 bytes of code
│ ├─ [0] VM::stopBroadcast()
│ │ └─ ← [Return]
│ ├─ [5900128] → new AddConsumer@0x037eDa3aDB1198021A9b2e88C22B464fD38db3f3
│ │ └─ ← [Return] 29354 bytes of code
│ ├─ [8758] AddConsumer::addConsumer(Raffle: [0xa4725D8EDA697d9B3CcD5Acdb3BCbFf7E473afD8], BeaconVRFConsumer: [0xD7f86b4b8Cae7D942340FF628F82735b7a20893a], 56791896273763508949438815106474997201608599347730115153934960174154752396659 [5.679e76], 0xd22BFCA3DAb60c1a11b2f1d7C8e2CBa063716A38)
│ │ ├─ [0] console::log("Adding consumer contract: ", Raffle: [0xa4725D8EDA697d9B3CcD5Acdb3BCbFf7E473afD8]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("To VRF Coordinator: ", BeaconVRFConsumer: [0xD7f86b4b8Cae7D942340FF628F82735b7a20893a]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] console::log("On chain id: ", 11155111 [1.115e7]) [staticcall]
│ │ │ └─ ← [Stop]
│ │ ├─ [0] VM::startBroadcast(0xd22BFCA3DAb60c1a11b2f1d7C8e2CBa063716A38)
│ │ │ └─ ← [Return]
│ │ ├─ [214] BeaconVRFConsumer::addConsumer(56791896273763508949438815106474997201608599347730115153934960174154752396659 [5.679e76], Raffle: [0xa4725D8EDA697d9B3CcD5Acdb3BCbFf7E473afD8])
│ │ │ └─ ← [Revert] EvmError: Revert
│ │ └─ ← [Revert] EvmError: Revert
│ └─ ← [Revert] EvmError: Revert
└─ ← [Revert] EvmError: Revert
Suite result: FAILED. 0 passed; 1 failed; 0 skipped; finished in 2.83s (0.00ns CPU time)
Ran 1 test suite in 4.28s (2.83s 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: EvmError: Revert] setUp() (gas: 0)
Encountered a total of 1 failing tests, 0 tests succeeded this would be my // SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Test} from "forge-std/Test.sol";
import {DeployRaffle} from "script/DeployRaffle.s.sol";
import {Raffle} from "src/Raffle.sol";
import {HelperConfig} from "script/HelperConfig.s.sol";
import {Vm} from "forge-std/Vm.sol";
import {VRFCoordinatorV2_5Mock} from "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2_5Mock.sol";
contract FailingReceiver {
fallback() external payable {
revert("I always fail!");
}
}
contract RaffleTest is Test {
Raffle public raffle;
HelperConfig public helperConfig;
FailingReceiver public failingReceiver;
address public PLAYER = makeAddr("player");
uint256 public constant STARTING_PLAYER_BALANCE = 10 ether;
event RaffleEntered(address indexed player);
event WinnerPicked(address indexed winner);
uint256 entranceFee;
uint256 interval;
address vrfCoordinator;
bytes32 gasLane;
uint256 subscriptionId;
uint32 callbackGasLimit;
function setUp() external {
DeployRaffle deployer = new DeployRaffle();
(raffle, helperConfig) = deployer.deployContract();
failingReceiver = new FailingReceiver();
HelperConfig.NetworkConfig memory config = helperConfig.getConfig();
entranceFee = config.entranceFee;
interval = config.interval;
vrfCoordinator = config.vrfCoordinator;
gasLane = config.gasLane;
subscriptionId = config.subscriptionId;
callbackGasLimit = config.callbackGasLimit;
vm.deal(address(failingReceiver), 1 ether);
vm.deal(PLAYER, STARTING_PLAYER_BALANCE);
}
function testRaffleInitializesInOpenState() public view {
assert(raffle.getRaffleState() == Raffle.RaffleState.OPEN);
}
modifier raffleEntered() {
vm.prank(PLAYER);
raffle.enterRaffle{value: entranceFee}();
vm.warp(block.timestamp + interval + 1);
vm.roll(block.number + 1);
_;
}
/*//////////////////////////////////////////////////////////////
ENTER RAFFLE
//////////////////////////////////////////////////////////////*/
function testRaffleRevertsWhenYouDontPayEnough() public {
// Arrange
vm.prank(PLAYER);
// Act / Assert
vm.expectRevert(Raffle.Raffle__SendMoreToEnterRaffle.selector);
raffle.enterRaffle();
}
function testRaffleRecordsPlayersWhenTheyEnter() public {
// Arrange
vm.prank(PLAYER);
// Act
raffle.enterRaffle{value: entranceFee}();
address playerRecorded = raffle.getPlayer(0);
// Assert
assert(playerRecorded == PLAYER);
}
function testEnteringRaffleEmitsEvent() public {
// Arrange
vm.prank(PLAYER);
// Act
vm.expectEmit(true, false, false, false, address(raffle));
emit RaffleEntered(PLAYER);
// Assert
raffle.enterRaffle{value: entranceFee}();
}
function testDontAllowPlayersToEnterWhileRaffleIsCalculating()
public
raffleEntered
{
// Arrange
raffle.performUpkeep();
// Act / Assert
vm.expectRevert(Raffle.Raffle__RaffleNotOpen.selector);
vm.prank(PLAYER);
raffle.enterRaffle{value: entranceFee}();
}
/*//////////////////////////////////////////////////////////////
CHECK UPKEEP
//////////////////////////////////////////////////////////////*/
function testCheckUpkeepReturnsFalseIfItHasNoBalance() public {
// Arrange
vm.warp(block.timestamp + interval + 1);
vm.roll(block.number + 1);
// Act
(bool upkeepNeeded, ) = raffle.checkUpkeep("");
assert(!upkeepNeeded);
}
function testCheckUpkeepReturnsFalseIfRaffleIsNotOpen()
public
raffleEntered
{
// Arrange
raffle.performUpkeep();
// Act
(bool upkeepNeeded, ) = raffle.checkUpkeep("");
assert(!upkeepNeeded);
}
function testCheckUpkeepRevertIfNotNeeded() public {
// Arrange
// --> Not doing anything so that the raffle is not open
// Act / Assert
vm.expectRevert(
abi.encodeWithSelector(
Raffle.Raffle__UpkeepNotNeeded.selector,
0, // balance
0, // playersLength
0 // raffleState
)
);
raffle.performUpkeep();
}
/*//////////////////////////////////////////////////////////////
PERFORM UPKEEP
//////////////////////////////////////////////////////////////*/
function testPerformUpkeepCanOnlyRunIfCheckUpkeepIsTrue()
public
raffleEntered
{
// Act / Assert
raffle.performUpkeep();
}
function testPerformUpkeepUpdatesRaffleStateAndEmitsRequestId()
public
raffleEntered
{
// Act
vm.recordLogs();
raffle.performUpkeep();
Vm.Log[] memory entries = vm.getRecordedLogs();
bytes32 requestId = entries[1].topics[1];
// Assert
Raffle.RaffleState raffleState = raffle.getRaffleState();
assert(uint256(requestId) > 0);
assert(uint256(raffleState) == 1);
}
/*//////////////////////////////////////////////////////////////
FULLFILLRANDOMWORDS
//////////////////////////////////////////////////////////////*/
function testFulfillRandomWordsCanOnlyBeCalledAfterPerformUpkeep(
uint256 randomRequestId
) public raffleEntered {
// Arrange / Act / Assert
vm.expectRevert(VRFCoordinatorV2_5Mock.InvalidRequest.selector);
VRFCoordinatorV2_5Mock(vrfCoordinator).fulfillRandomWords(
randomRequestId,
address(raffle)
);
}
function testFulfillRandomWordsReturnsRandomNumber() public raffleEntered {
// Arrange
raffle.performUpkeep();
// Act
uint256[] memory randomArr = new uint256[](1);
randomArr[0] = 123;
// Assert
vm.expectEmit(true, true, false, true);
emit WinnerPicked(PLAYER);
vm.prank(0x34A1D3fff3958843C43aD80F30b94c510645C316);
raffle.rawFulfillRandomWords(0, randomArr);
}
function testFulFillRandomWordsRevertsIfTransferFailed()
public
raffleEntered
{
// Arrange
vm.prank(address(failingReceiver));
raffle.enterRaffle{value: entranceFee}();
vm.warp(block.timestamp + interval + 1);
vm.roll(block.number + 1);
raffle.performUpkeep();
// Assert
vm.expectRevert(Raffle.Raffle__TransferFailed.selector);
vm.prank(vrfCoordinator);
uint256[] memory randomArr = new uint256[](1);
randomArr[0] = 123; // If s_players.length=1, 0 % 1 = 0 => failingReceiver is winner
raffle.rawFulfillRandomWords(0, randomArr);
}
function testFulfillRandomWordsPicksAWinnerResetsAndSendsMoney()
public
raffleEntered
{
// Arrange
uint256 additionalEntrants = 3; // 4 in total
uint256 startingIndex = 1;
address expectedWinner = address(1);
for (
uint256 i = startingIndex;
i < startingIndex + additionalEntrants;
i++
) {
address newPlayer = address(uint160(i));
hoax(newPlayer, 1 ether);
raffle.enterRaffle{value: entranceFee}();
}
uint256 startingTimeStamp = raffle.getLastTimeStamp();
uint256 winnerStartingBalance = expectedWinner.balance;
// Act
vm.recordLogs();
raffle.performUpkeep();
Vm.Log[] memory entries = vm.getRecordedLogs();
bytes32 requestId = entries[1].topics[1];
VRFCoordinatorV2_5Mock(vrfCoordinator).fulfillRandomWords(
uint256(requestId),
address(raffle)
);
// Assert
address recentWinner = raffle.getRecentWinner();
Raffle.RaffleState raffleState = raffle.getRaffleState();
uint256 winnerBalance = recentWinner.balance;
uint256 endingTimeStamp = raffle.getLastTimeStamp();
uint256 prize = entranceFee * (additionalEntrants + 1);
assert(recentWinner == expectedWinner);
assert(uint256(raffleState) == 0);
assert(winnerBalance == winnerStartingBalance + prize);
assert(endingTimeStamp > startingTimeStamp);
}
} Then, // SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Script} from "forge-std/Script.sol";
import {Raffle} from "src/Raffle.sol";
import {HelperConfig} from "script/HelperConfig.s.sol";
import {CreateSubscription, FundSubscription, AddConsumer} from "script/Interactions.s.sol";
contract DeployRaffle is Script {
function run() public {
deployContract();
}
function deployContract() public returns (Raffle, HelperConfig) {
HelperConfig helperConfig = new HelperConfig();
// local -> deploy mocks, get local config
// sepolia -> get sepolia config
HelperConfig.NetworkConfig memory config = helperConfig.getConfig();
if (config.subscriptionId == 0) {
CreateSubscription createSubscription = new CreateSubscription();
(config.subscriptionId, config.vrfCoordinator) = createSubscription
.createSubscription(config.vrfCoordinator, config.account);
// Fund it!
FundSubscription fundSubscription = new FundSubscription();
fundSubscription.fundSubscription(
config.vrfCoordinator,
config.subscriptionId,
config.link,
config.account
);
}
vm.startBroadcast(config.account);
Raffle raffle = new Raffle(
config.entranceFee,
config.interval,
config.vrfCoordinator,
config.gasLane,
config.subscriptionId,
config.callbackGasLimit
);
vm.stopBroadcast();
AddConsumer addConsumer = new AddConsumer();
// don't need to broadcast this
addConsumer.addConsumer(
address(raffle),
config.vrfCoordinator,
config.subscriptionId,
config.account
);
return (raffle, helperConfig);
}
} And // SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {Script} from "forge-std/Script.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 {
/* VRF Mock Values */
uint96 public MOCK_BASE_FEE = 0.25 ether;
uint96 public MOCK_GAS_PRICE_LINK = 1e9;
// LINK / ETH price
int256 public MOCK_WEI_PER_UINT_LINK = 4e15;
uint256 public constant ETH_SEPOLIA_CHAIN_ID = 11155111;
uint256 public constant LOCAL_CHAIN_ID = 31337;
}
contract HelperConfig is CodeConstants, Script {
error HelperConfig__InvalidChainId();
struct NetworkConfig {
uint256 entranceFee;
uint256 interval;
address vrfCoordinator;
bytes32 gasLane;
uint256 subscriptionId;
uint32 callbackGasLimit;
address link;
address account;
}
NetworkConfig public localNetworkConfig;
mapping(uint256 chainId => NetworkConfig) public networkConfigs;
constructor() {
networkConfigs[ETH_SEPOLIA_CHAIN_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
vrfCoordinator: 0xD7f86b4b8Cae7D942340FF628F82735b7a20893a,
gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae,
subscriptionId: 56791896273763508949438815106474997201608599347730115153934960174154752396659,
callbackGasLimit: 500000, // 500,000 gas
link: 0x779877A7B0D9E8603169DdbD7836e478b4624789,
account: 0xd22BFCA3DAb60c1a11b2f1d7C8e2CBa063716A38
});
}
function getOrCreateAnvilEthConfig() public returns (NetworkConfig memory) {
if (localNetworkConfig.vrfCoordinator != address(0)) {
return localNetworkConfig;
}
// Deploy mocks and such
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),
// gasLane & callbackGasLimit don't matter for mocks
gasLane: 0x787d74caea10b2b357790d5b5247c2f63d1d91572a9846f780606e4d953677ae,
callbackGasLimit: 500000, // 500,000 gas
subscriptionId: 0,
link: address(linkToken),
account: 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38
});
return localNetworkConfig;
}
} |
Beta Was this translation helpful? Give feedback.
-
sorry, I just realized that I was using the mainnet vrfCoordinator address. Upon checking and updating it to the sepolia address it's now working! |
Beta Was this translation helpful? Give feedback.
-
I'm currently facing an issue in Raffle smart contract, when I try to test my scripts in sepoliaEth forking chain I run into the
InvalidSubscription()
error. The traces are given below :The same test runs perfectly in local Anvil chain. Someone kindly help me to fix the issue, I'll share the test file and deploy script too.
Raffle.Test.t.sol
DeployRaffle.s.sol
Beta Was this translation helpful? Give feedback.
All reactions