An address in Solidity can be an account or a contract (or other things, such as a transaction). When I have a variable x, holding an address, how can I test if it is a cont
The top-voted answer with the isContract function that uses EXTCODESIZE was discovered to be hackable.
The function will return false if it is invoked from a contract's constructor (because the contract has not been deployed yet).
The code should be used very carefully, if at all, to avoid security hacks such as:
https://www.reddit.com/r/ethereum/comments/916xni/how_to_pwn_fomo3d_a_beginners_guide (archive)
To repeat:
Do not use the EXTCODESIZE check to prevent smart contracts from calling a function. This is not foolproof, it can be subverted by a constructor call, due to the fact that while the constructor is running, EXTCODESIZE for that address returns 0.
See sample code for a contract that tricks EXTCODESIZE to return 0.
If you want to make sure that an EOA is calling your contract, a simple way is require(msg.sender == tx.origin). However, preventing a contract is an anti-pattern with security and interoperability considerations.
This will need revisiting when account abstraction is implemented.