2

The modifier used to check if a contract calls a function in Solidity used the assembly code extsize. I wonder why this is done. Using assembly seems very "hackish" to me (why does solidity not have a 'normal' function to check this?). The code in question is

modifier noContract(address _addr){
  uint32 size;
  assembly {
    size := extcodesize(_addr)
  }
  require (size == 0);
  _;
}

(edited from https://ethereum.stackexchange.com/a/15642/33191)

Why not use msg.sender == tx.orgin as check? Is there a loophole in this?

Is the reason for using extsize that this might use (slightly) less gas?

4
  • Could you share some links as to what code you are talking about? Commented Mar 28, 2018 at 19:11
  • I wiill edit my question. But here is a source. ethereum.stackexchange.com/questions/15641/…
    – JBrouwer
    Commented Mar 28, 2018 at 19:12
  • FYI, that's not a modifier. It's a function.
    – user19510
    Commented Mar 28, 2018 at 20:49
  • You are right, didn't check code I copied.
    – JBrouwer
    Commented Mar 28, 2018 at 20:50

1 Answer 1

1

tx.origin should be used in EXTREMELY rare circumstances. When you checktx.origin you are checking who the call originated from, so if used improperly it can open up extreme vulnerabilities, or possibly break functionality in your contract.

person a -> contract-a -> contract-b if you check tx.origin on contract-b it will resolve to the address of person a not the address of contract-a. If you check msg.sender it will be contract-a.

The reason why assembly is used, as you point out, is that there currently exists no solidity built in functions to handle that. Solidity is still quite a young language, so it's not surprising.

with regards to not having a contract being able to call itself

There's only a few ways this can happen:

1) Specifically programming functions or logic that forces the contract to call itself

2) Making call to unknown contracts that can trigger fallback code execution

Option 1 isn't really a problem since that's very easy to control, but Option 2 can open you up to hacking attempts on your contract since the unknown contract you're calling could conceivably implement a fallback function which would trigger calls to your contract.

I think your problem would better be resolved by findings which functions allow the contract to call itself, and change those functions, while removing any calls to unknown contracts that could trigger code execution for which you don't know the outcome. You could implement some assembly wizardry to prevent this from happening, but to me that sounds like it opens you up to potential vulnerabilities.

6
  • Let's see if I get it correctly. When using your modified modifier (no pun intended) you can prevent the contract from calling itself (via a CALL code). But this is already prevented by using either the tx.orgin method or the extcodesize method? Why use both? I think I miss something here.
    – JBrouwer
    Commented Mar 28, 2018 at 21:47
  • You also don't want the current contract to call itself? In that case I would update your original post to make that clear since it's not clear that that is what you're looking for. That can never be prevented by tx.origin since a call can never originate from a contract account, it always has to originate from an EOA (for now at least, until account abstraction). You shouldn't really ever use tx.origin it's dangerous and should be used under extrm circumstances. It sounds like what you're looking for can be solved by contract redesign, as opposed to trying to implement a hackish solution.
    – hextet
    Commented Mar 28, 2018 at 22:22
  • No, that was not my question. I don't understand what you mean by "but that would only check that the call originated from that account.". Why would you add the qrequire(msg.sender==tx.origin)` to the modifier? Isn't this always true if extcodesize is 0?
    – JBrouwer
    Commented Mar 28, 2018 at 23:34
  • Yes you're right my apologies for the confusion. It will always be true yes. If you're wondering why not use one or the other, that's entirely up to you. However the intent behind each is different. tx.origin is to look up the sender of the call, while extcodesize is to look up the size of the code in storage. I would reckon extcodesize with assembly would probably be slightly cheaper than using tx.origin
    – hextet
    Commented Mar 28, 2018 at 23:57
  • Alright, this clears up my question. I was indeed wondering if their results would be different in any way.
    – JBrouwer
    Commented Mar 29, 2018 at 0:07

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