Foundry Testing – How to Test Multiple Addresses in Foundry using Forge

forgefoundry

Is there any way to test with multiple addresses using forge like you can in Truffle or Hardhat? Like Truffle gives you an array of addresses you can call and that changes the msg.sender calling the function.

I'm trying to test these methods:

function addMember(address _member) public onlyOwner {
        balance[_member] = TOTAL_MEMBER_TOKENS;
        totalTokens += TOTAL_MEMBER_TOKENS;
    }

function addProposal(string calldata _proposal) public onlyMember {
        proposals.push(Proposal(_proposal, 0, 0));
        emit NewProposal(_proposal);
    }

I want to use the owner address to addMember then use the members address to call addProposal. How would I do that? If this can't be done then what is the address that I should pass to addMember to make the owner of the contract a member so I can test with only one address.

Best Answer

Foundry's anvil network provides you with a list of 10 addresses and their private keys:

Available Accounts
==================

(0) "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266" (10000.000000000000000000 ETH)
(1) "0x70997970C51812dc3A010C7d01b50e0d17dc79C8" (10000.000000000000000000 ETH)
(2) "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC" (10000.000000000000000000 ETH)
(3) "0x90F79bf6EB2c4f870365E785982E1f101E93b906" (10000.000000000000000000 ETH)
(4) "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65" (10000.000000000000000000 ETH)
(5) "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc" (10000.000000000000000000 ETH)
(6) "0x976EA74026E726554dB657fA54763abd0C3a0aa9" (10000.000000000000000000 ETH)
(7) "0x14dC79964da2C08b23698B3D3cc7Ca32193d9955" (10000.000000000000000000 ETH)
(8) "0x23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f" (10000.000000000000000000 ETH)
(9) "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720" (10000.000000000000000000 ETH)

Private Keys
==================

(0) 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
(1) 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d
(2) 0x5de4111afa1a4b94908f83103eb1f1706367c2e68ca870fc3fb9a804cdab365a
(3) 0x7c852118294e51e653712a81e05800f419141751be58f605c371e15141b007a6
(4) 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a
(5) 0x8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba
(6) 0x92db14e403b83dfe3df233f83dfa3a0d7096f21ca9b0d6d6b8d88b2b4ec1564e
(7) 0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356
(8) 0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97
(9) 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6

You can easily use these to test your functions.

Another solution you could use would be to simply use vm.prank with random addresses, such as address(0), address(1), and address(1337).

First you can test addMember() by calling it from the owner's address with a random address such as address(1).

For example:

function test_addMember() {
vm.prank(owner);
yourContract.addMember(address(1));
}

vm.prank allows you to change msg.sender for the next function call.

Now that address(1) is a member we can call addProposal() from that address:

function test_addProposal() {
vm.prank(address(1));
yourContract.addProposal(yourProposal);
}

You can add some conditional or assert after the function call to ensure it did what you expected it to.

You can read more about Foundry's anvil here and more about vm.prank here.