This code snippet is correct, although it seems important to note that EXTCODESIZE
will return 0 when called within the constructor
of a contract, since the contract is not created yet. Hence, if msg.sender
is a contract, the isContract()
modifier could return false if your contract's function is called within the constructor of the msg.sender
contract. This attack vector has been used on various occasions, such as draining the FoMo3D's ETH "airdrop pot".
A solution to this would be to (A) require msg.sender
to provide an ECDSA signature for their first function call, (B) require msg.sender
to call your contract on two separate blocks or (C) add require(msg.sender == tx.origin)
. The latter would be the cheapest, followed by ECDSA and the most expensive would be the 2 step process.