0
0
Blockchain / Solidityprogramming~20 mins

Transaction context (tx.origin vs msg.sender) in Blockchain / Solidity - Practice Questions

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
Transaction Context Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
Output of msg.sender vs tx.origin in nested calls

Consider two contracts: A calls B. What will be the output of msg.sender and tx.origin inside contract B when A calls B?

Blockchain / Solidity
contract B {
    function check() public view returns (address, address) {
        return (msg.sender, tx.origin);
    }
}

contract A {
    B b;
    constructor(address _b) {
        b = B(_b);
    }
    function callB() public view returns (address, address) {
        return b.check();
    }
}
Amsg.sender is the original external caller's address; tx.origin is A's address
Bmsg.sender is A's address; tx.origin is the original external caller's address
CBoth msg.sender and tx.origin are the original external caller's address
DBoth msg.sender and tx.origin are A's address
Attempts:
2 left
💡 Hint

Remember that msg.sender is the immediate caller, while tx.origin is the original external account that started the transaction.

Predict Output
intermediate
1:30remaining
Detecting phishing with tx.origin

What will be the output of the following Solidity function if called by an external user directly?

function isOwner() public view returns (bool) {
    return tx.origin == owner;
}
Blockchain / Solidity
address owner = 0x1234567890123456789012345678901234567890;

function isOwner() public view returns (bool) {
    return tx.origin == owner;
}
AReturns true if the external caller is the owner
BReturns true if the immediate caller is the owner
CAlways returns false
DCauses a compilation error
Attempts:
2 left
💡 Hint

tx.origin is the original external account that started the transaction.

🔧 Debug
advanced
2:30remaining
Why does this contract allow phishing via tx.origin?

Consider this contract snippet:

function withdraw() public {
    require(tx.origin == owner, "Not owner");
    payable(msg.sender).transfer(address(this).balance);
}

What is the security risk here?

AAn attacker can trick the owner into calling a malicious contract that calls withdraw, bypassing the check
BThe require statement will always fail because tx.origin is never the owner
CThe contract will run out of gas due to infinite recursion
DThere is no risk; tx.origin is safe to use here
Attempts:
2 left
💡 Hint

Think about how tx.origin can be manipulated by intermediate contracts.

📝 Syntax
advanced
1:30remaining
Identify the error in this Solidity function using tx.origin

Which option correctly fixes the syntax error in this function?

function checkOrigin() public view returns (bool) {
    if tx.origin == owner {
        return true;
    } else {
        return false;
    }
}
AChange function to external instead of public
BReplace tx.origin with msg.sender
CRemove the else block entirely
DAdd parentheses around the condition: if (tx.origin == owner) { ... }
Attempts:
2 left
💡 Hint

Check the syntax for if statements in Solidity.

🚀 Application
expert
3:00remaining
Design a secure authorization check avoiding tx.origin pitfalls

You want to restrict a function so only the contract owner can call it. Which approach is the most secure?

AUse <code>require(tx.origin != owner)</code> to block the owner
BUse <code>require(msg.sender != owner)</code> to block the owner
CUse <code>require(msg.sender == owner)</code> to check the immediate caller
DUse <code>require(tx.origin == owner)</code> to check the original transaction sender
Attempts:
2 left
💡 Hint

Consider how intermediate contracts affect msg.sender and tx.origin.