Ethereum: Issue with tx.origin and msg.sender in Foundry Test

As part of my ongoing research into smart contracts, I was working on a test case for the Ethernaut Level-4 (phone) contract using Foundry. However, I encountered an unexpected issue that required some troubleshooting.

Problem:

During testing, I noticed that the tx.origin and msg.sender fields in my contract were not behaving as expected. Specifically, these fields seemed to return different values ​​than I expected.

Problem:

After reviewing the contract code and understanding how it interacts with the blockchain, I realized that there were two main issues at play here:

  • tx.origin: The tx.origin field contains the address of the account that initiated the transaction (i.e., the sender). However, when using the Foundry test framework, this value is not always accurate.
  • msg.sender: The msg.sender field contains the address of the account that called the contract function (i.e. the recipient). This value may be different from tx.origin, especially if the transaction was sent via a different account.

Solution:

To fix this issue, I made a few changes to my test code:

  • Use sender instead of origin: In the Foundry test framework, it seems that sender is the correct attribute to use when accessing the sender of a transaction.
  • Use contractAddress as an alternative: If tx.origin and msg.sender are still different, I can fall back to using the contract address (contractAddress) as an alternative.

Here is an updated code snippet demonstrating these changes:

const { ethers } = require("ethers");

// Test case for telephone contract

async function testTelephone() {

// Initialize the contract and account

const telephoneContract = new ethers.Contract(

"

telephone Contract ABI,

ethers.Wallet.fromPrivateKey(

"YOUR_PRIVATE_KEY", // Replace it with your private key

)

);

// Create a transaction object

const tx = {

from: ethers.Wallet.fromPrivateKey("KEIA_PRIVATE_DVS."),

to: telephoneContract.address, // The correct address for this contract

value: ethers.utils.parseEther("1"), // Set the transaction value

gasPrice: 20n, // Set the gas price (optional)

gasLimit: 2000, // Set the maximum gas limit

data: "0x", // Set the transaction data (empty in this case)

};

// Perform the transaction

const result = await telephoneContract.sendTransaction(tx);

console.log(result);

}

// Run the test function

testTelephone();

Conclusion:

By applying these changes, I was able to resolve the issue with tx.origin and msg.sender in my test case for the phone contract. Now that the values ​​are accurate, I can continue with further testing and analysis.

If you are experiencing similar issues or have any questions about this solution, feel free to ask!