Ethereum: Issue with tx.origin
and msg.sender
in Foundry testing
As part of my ongoing research on smart contracts, I was working on a test case of an Ethernaut Level 4 (phone) contract using Foundry. However, I encountered an unexpected issue that required troubleshooting.
Issue:
During testing, I noticed that the “tx.origin” and “msg.sender” fields in my contract were not behaving as expected. In particular, these fields seemed to return different values than I expected.
Issue:
After reviewing the contract code and understanding how it interacts with the blockchain, I realized there were two main issues:
tx.origin
: Thetx.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
: Themsg.sender
field contains the address of the account that called the contract function (i.e. the recipient). This value may differ from thetx.origin
value, especially if the transaction was sent via a different account.
Solution:
To solve this problem, I made some changes to the test code:
- Use
sender
instead oforigin
: In the Foundry test framework,
sender
seems to be the correct attribute when accessing the sender of a transaction.
- Use
contractAddress
as a fallback: Iftx.origin
andmsg.sender
are still different, I can fall back to the contract address (contractAddress
) as an alternative.
Here is an updated code snippet demonstrating these changes:
const { Ether } = require("Ether");
// Test case for phone contract
async function testTelephone() {
// Initialize contract and account
const phoneContract = new Ether.Contract(
"
ABI phoneContract,
ethers.Wallet.fromPrivateKey(
"YOUR_PRIVATE_KEY", // Replace it with your private key
)
);
// Create a transaction object
Constants tx = {
from: ethers.Wallet.fromPrivateKey("YOUR_PRIVATE_KEY"),
to: phoneContract.address, // The correct address for this contract
value: ethers.utils.parseEther("1"), // Set the transaction value
gasPrice: 20n, // Set gas price (optional)
gasLimit: 2000, // Set maximum gas limit
data: "0x", // Set the transaction data (in this case it is empty)
};
// Commit transaction
const result = await phoneContract.sendTransaction(tx);
console.log(result);
}
// Run the test function
testPhone();
Conclusion:
With these changes, I was able to resolve the issue with tx.origin and msg.sender in my phone contract test case. Now that the values are accurate, I can move on to further testing and analysis.
If you encounter similar issues or have any questions about this solution, feel free to ask!