How to write an onlyNonContract modifier (function can't be called by a contract)

Open zeppelin contracts have this solution for ‘isContract’ modifier

Implementation is based on EIP 1052 which seems not to be merged to the EVM yet.

Should this code be used in production code at all?

Still I see a warning in this that it will return false for the case that

  • “* - a contract in construction”
    So it can’t be used for onlyNonContract modifier.

In below article it is advised to use tx.origin for checking if a call is originating from a contract or non-contract address.

https://consensys.github.io/smart-contract-best-practices/recommendations/#avoid-using-extcodesize-to-check-for-externally-owned-accounts

But from other reads and best practices, it seems tx.origin might be deprecated at some stage.
Although there is no clear statement about that.

please advise how to create an onlyNonContract modifier.
thanks

1 Like

Hi @ilanD,

For an onlyNonContract your options appear to be:

I assume it comes down to your use case in what you are trying to prevent and if the option covers this (including any caveats on what it can detect/prevent).

I had a look through the Solidity issues to see if I could find discussions on potentially deprecating tx.origin. I only found this issue: https://github.com/ethereum/solidity/issues/683

Seems that isContract(address account) will not protect from calls from a contracts ctor.

thus will not give the required protection.

1 Like

Indeed, isContract can only be used to assert that an address is a contract, and should never be used to assert that an address is not a contract.

There is relevant discussion in Bypassing Smart Contract Timelocks. An alternative method proposed there is to require a signature from the address in order to verify that it is an EOA, and thus conclude it isn’t a contract.

1 Like