Let's say:

function transfer() public payable

 require(tx.origin == 0xb2930B35844a230f00E51431aCAe96Fe543a0347);  
msg.sender.call.value(1 ether)();


Ignore the address above I just copied it from etherscan it belongs to some mining pool...so the question is: how can this address get "spoofed" if at all? Isn't tx.origin more secure since the caller can never be contract? Thanx!

  • I'd say tx.origin cannot be "spoofed" in the usual sense. But if you call a malicious contract M it can call a "victim" contract V. If V only verifies tx.origin it will think it was called by you. There was a famous multisig wallet that was exploitable that way. – Ismael Dec 11 '19 at 19:55

I'm confused by your question title. You obviously can't use tx.origin to check whether msg.sender is some address, because they have different meanings. If you want to check msg.sender, you should check msg.sender.

'More secure' does not exist in the space of smart contracts. They either do what they're supposed to do, or they don't.

  • msg.sender is the address that called your contract. It can be either a human address (controlled by a private key) or a contract address.

  • tx.origin is the address that submitted the current transaction. It is never a contract address.

The fact that tx.origin is present in your contract does not mean it can't be called by another contract.

if (tx.origin != msg.sender)
    // This contract was called by another contract.
    // Therefore, msg.sender and tx.origin have different values:
    // - msg.sender is the other contract
    // - tx.origin is the original 'human' address that submitted the current transaction

msg.sender and tx.origin are not more or less secure than one another. They simply have a different meaning. I can tell you though, in almost 3 years of contract development I have never encountered a single use-case for tx.origin. You should use msg.sender.

| improve this answer | |
  • 1
    Thanks but what about the example I gave? Is this "hackable"? I googled this: medium.com/coinmonks/solidity-tx-origin-attacks-58211ad95514 - so this seems hackable but here tx.origin is owner and not any address? My question is: can any address be spoofed even the zero 0x0 or so? I guess not maybe still can't grasp the whole logic, should have a look at the sample in the link... – Robert Ggg Dec 11 '19 at 17:29
  • 1
    @RobertGgg msg.sender and tx.origin can never be 0x0. I don't know what your contract is supposed to do. The way you have written it now, any contract called by 0xb2930B... can take amounts of 1 ether from your contract. So yes, it's probably hackable. If you just use msg.sender instead of tx.origin, only 0xb2930B... will be able to take the 1 ether. – Jesbus Dec 11 '19 at 17:45
  • 1
    I see, I will try to replicate the example from the link...one more thing: it uses transfer and not call so maybe using "transfer" can save the day given the 2300 limitation of gas? As far as I know since Istanbul 2 days ago, transfer can send over 2300 gas and thus allow such things? will have to test on ropsten and see... – Robert Ggg Dec 11 '19 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.