# tx.origin vs msg.sender — Security के लिए क्यों Important है
Solidity में सबसे common security mistakes में से एक है authentication के लिए tx.origin का उपयोग करना। यह seemingly innocent choice आपके contract को phishing attacks के लिए expose कर सकता है जो user funds drain कर सकते हैं।
इस article में, हम tx.origin और msg.sender के बीच के difference को clarify करेंगे, vulnerability demonstrate करेंगे, और establish करेंगे कि कब किसका उपयोग करें।
Difference क्या है
msg.sender
Current function का immediate caller।
- अगर user आपके contract को directly call करता है:
msg.sender= user का address
- अगर contract A, contract B को call करता है:
msg.sender= contract A का address
- Call chain में हर call पर change होता है
tx.origin
Original external account जिसने transaction initiate की।
- हमेशा वह EOA (Externally Owned Account) जिसने transaction sign की
- कभी contract address नहीं होता
- पूरे call chain में constant रहता है
Visual Example
User (0xUser) → Contract A → Contract B → Contract C
| | |
msg.sender: 0xUser A B
tx.origin: 0xUser 0xUser 0xUser
Contract C पर:
msg.sender= Contract B का address
tx.origin= 0xUser (original EOA)
Vulnerability: Phishing Attack
Vulnerable Contract
contract VulnerableWallet {
address public owner;
constructor() {
owner = msg.sender;
}
// VULNERABLE: tx.origin का उपयोग authentication के लिए
function transfer(address payable to, uint256 amount) public {
require(tx.origin == owner, "Not owner");
to.transfer(amount);
}
receive() external payable {}
}
Attack
Attacker एक malicious contract बनाता है:
contract MaliciousContract {
address payable public attacker;
VulnerableWallet public wallet;
constructor(address _wallet) {
attacker = payable(msg.sender);
wallet = VulnerableWallet(payable(_wallet));
}
// Innocent-looking function
function claimAirdrop() public {
// Victim के wallet को call करता है
wallet.transfer(attacker, address(wallet).balance);
}
}
Attack Flow
MaliciousContract deploy करता हैclaimAirdrop() call करने के लिए convince करता है (phishing के through)MaliciousContract.claimAirdrop() call करता हैVulnerableWallet.transfer() को call करता है - tx.origin = victim का address ✅ (check pass होता है!)
- msg.sender = MaliciousContract का address
क्यों काम करता है: Victim ने transaction initiate की, इसलिए पूरे call chain में tx.origin owner के equal है।
Secure Implementation
msg.sender का उपयोग
contract SecureWallet {
address public owner;
constructor() {
owner = msg.sender;
}
// SECURE: msg.sender का उपयोग
function transfer(address payable to, uint256 amount) public {
require(msg.sender == owner, "Not owner");
to.transfer(amount);
}
receive() external payable {}
}
अब attack fail हो जाता है:
msg.sender= MaliciousContract का address ❌ (check fail)
- Transaction revert हो जाता है funds steal होने से पहले
कब कौन सा उपयोग करें
msg.sender का उपयोग करें:
✅ Authentication/Authorization के लिए
modifier onlyOwner() {
require(msg.sender == owner, "Not authorized");
_;
}
✅ Access Control के लिए
mapping(address => bool) public whitelist;
function restrictedAction() external {
require(whitelist[msg.sender], "Not whitelisted");
}
✅ Sender-Specific Logic
mapping(address => uint256) public balances;
function deposit() external payable {
balances[msg.sender] += msg.value;
}
tx.origin का उपयोग करें:
⚠️ Rare legitimate cases:
function expensiveOperation() external {
// Complex computation
// Original user को gas refund (intermediate contract को नहीं)
payable(tx.origin).transfer(gasRefund);
}
event Action(address indexed user, address indexed caller);
function logAction() external {
emit Action(tx.origin, msg.sender);
}
function onlyEOA() external {
require(tx.origin == msg.sender, "No contract calls");
// Direct user interaction ensure करता है
}
Warning: Contracts को block करना account abstraction और future composability को prevent करता है।
Real-World Impact
THORChain Vulnerability (2021)
Early version में tx.origin checks थे जिन्हें router contracts के through exploit किया जा सकता था। Fortunately, launch से पहले audit में catch हो गया।
OpenZeppelin Recommendation
OpenZeppelin team explicitly tx.origin के against warn करती है:
> "Authorization के लिए tx.origin का उपयोग करना phishing attacks का कारण बन सकता है जहाँ malicious contract users को transactions approve करने के लिए trick करता है।"
EIP-3074 Implications
Future Ethereum improvements जैसे EIP-3074 (transaction sponsorship) tx.origin behavior को change कर सकते हैं, जिससे इस पर rely करना और भी risky हो जाता है।
Detection और Prevention
Slither Detection
Slither automatically tx.origin usage को flag करता है:
slither . --detect tx-origin
Output:
VulnerableWallet.transfer() (contracts/Wallet.sol#8-11) uses tx.origin for authorization:
- require(bool)(tx.origin == owner) (contracts/Wallet.sol#9)
Reference: https://github.com/crytic/slither/wiki/Detector-Documentation#dangerous-usage-of-txorigin
Code Review Checklist
✅ सभी tx.origin occurrences justified हैं
✅ Authorization के लिए require() में कोई tx.origin नहीं
✅ Access control modifiers में कोई tx.origin नहीं
✅ सभी authentication के लिए msg.sender उपयोग किया गया
Testing
Tests लिखें जो malicious intermediaries को simulate करें:
// Foundry test
function testPhishingAttack() public {
// User के owned wallet को deploy करें
vm.prank(user);
VulnerableWallet wallet = new VulnerableWallet();
vm.deal(address(wallet), 10 ether);
// Malicious contract deploy करें
MaliciousContract attacker = new MaliciousContract(address(wallet));
// User phishing में फंस जाता है, malicious contract को call करता है
vm.prank(user);
attacker.claimAirdrop();
// अब attacker के पास funds हैं
assertEq(address(attacker).balance, 10 ether);
}
Summary Table
| Aspect | msg.sender | tx.origin |
|--------|---------------|--------------|
| Value | Immediate caller | Original EOA |
| Contract हो सकता है | Yes | No |
| Call chain में changes | Yes | No |
| Authentication के लिए | ✅ Safe | ❌ Dangerous |
| Access control के लिए | ✅ Recommended | ❌ Vulnerable |
| Logging के लिए | ✅ दोनों उपयोग करें | ✅ Acceptable |
| Phishing risk | ❌ No | ✅ High |
Best Practices
msg.sender उपयोग करें — यह लगभग हमेशा वही होता है जो आपको चाहिएtx.origin उपयोग न करें — कोई exception नहींtx.origin occurrence को audit करें — इसकी necessity justify करेंConclusion
tx.origin और msg.sender के बीच का choice सिर्फ technical detail नहीं है — यह critical security decision है।
Rule simple है: Authentication और authorization के लिए msg.sender उपयोग करें। tx.origin को rare edge cases के लिए reserve करें जहाँ आपको genuinely original transaction signer चाहिए, और कभी security-critical checks के लिए नहीं।
Solingo पर secure authentication patterns master करें — हमारे exercises में phishing attack simulations और real-time feedback शामिल हैं जो आपको इन dangerous pitfalls से बचने में help करते हैं।