0

When I use vm.prank(PLAYER), the assertion fails because PLAYER and playerRecorded are different.

function testRaffleUpdatesPlayersWhenTheyEnter() public {
    // Arrange
    vm.prank(PLAYER);
    console.log(PLAYER);
    // Act
    uint256 entranceFee = raffle.getEntranceFee();
    raffle.enterRaffle{value: entranceFee}();
    // Assert
    address playerRecorded = raffle.getPlayer(0);
    assert(playerRecorded == PLAYER);
    console.log(playerRecorded);
}

But, when I use vm.startPrank(PLAYER), the test passes and PLAYER and playerRecorded are the same, how come?

function testRaffleUpdatesPlayersWhenTheyEnter() public {
    // Arrange
    vm.startPrank(PLAYER);
    console.log(PLAYER);
    // Act
    uint256 entranceFee = raffle.getEntranceFee();
    raffle.enterRaffle{value: entranceFee}();
    // Assert
    address playerRecorded = raffle.getPlayer(0);
    assert(playerRecorded == PLAYER);
    console.log(playerRecorded);
    vm.stopPrank();
}

1 Answer 1

1

It's happening because vm.prank is setting msg.sender to PLAYER address only for the getEntranceFee() call, after that it's getting reset to the "foundry default caller".

As, you can read in the description given in the Foundry doc:

vm.prank sets msg.sender to the specified address for the next call. “The next call” includes static calls as well, but not calls to the cheat code address.

So, the pranked address is utilized by the static call to raffle.getEntranceFee(). That's why, the address which is used to enter the raffle (i.e., the msg.sender of raffle.enterRaffle()) is not the PLAYER address, but the address corresponding to the "foundry default caller" (i.e., 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38), resulting in the failure of the assert.

Whereas, when you're using vm.startPrank, then it is setting msg.sender for all subsequent calls until vm.stopPrank is called. So, the msg.sender is set to the PLAYER address for raffle.getEntranceFee() as well as for raffle.enterRaffle(), resulting in the success of the assert.

So, if you want to use vm.prank in your testRaffleUpdatesPlayersWhenTheyEnter test, then you can use it right before the raffler.enterRaffle(), like:

function testRaffleUpdatesPlayersWhenTheyEnter_1() public {
    // Arrange and Act
    uint256 entranceFee = raffle.getEntranceFee();

    // Using `vm.prank` after raffle.getEntranceFee() and before raffle.enterRaffle()
    vm.prank(PLAYER); 
    console.log(PLAYER);
    raffle.enterRaffle{value: entranceFee}();

    // Assert
    address playerRecorded = raffle.getPlayer(0);
    assert(playerRecorded == PLAYER);
    console.log(playerRecorded);
}
1
  • 1
    Thank you so much, this worked. I also tried using entrance fee as a constant in test contract now instead of using a getter function to retrieve it from the main contract Commented Aug 24 at 22:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.