Is it possible, from within a contract written in Solidity, to check if a contract is placed on a specific address or if this address does not contain any code?


This works:

function isContract(address _addr) private returns (bool isContract){
  uint32 size;
  assembly {
    size := extcodesize(_addr)
  return (size > 0);

The assembly language that all Ethereum contracts compile down to contains an opcode for this precise operation: EXTCODESIZE. This opcode returns the size of the code on an address. If the size is larger than zero, the address is a contract. But you need to write assembly code within the contract to access this opcode since the Solidity compiler does not support it directly at the moment. The above code creates a private method that you can call from within your contract to check if another address contains code. If you don't want a private method, remove the private keyword from the function header.

Edit: EXTCODESIZE returns 0 if it is called from the constructor of a contract. So if you are using this in a security sensitive setting, you would have to consider if this is a problem.

  • 7
    As far as I'm aware, this is the best method we have for checking whether an address is a contract right now. But anyone using this solution should also know that it's possible for a contract to return 0 from EXTCODESIZE if the function call was made from within that contracts constructor. This means that you can't blindly use EXCODESIZE to prevent other contracts from interacting with yours, it must be used with caution. Aug 18 '18 at 13:20
  • 1
    I originally needed this since I had created my own ERC20 token contracts and some financial contracts that transferred these tokens. When the financial contracts where settled, they were deleted by calling selfdestruct. As a security measure, I did not want the ERC20 to be transfer funds to deleted financial contracts so I introduced this check. For this use case, this check works but for other use cases, the Rob Hitchens B9lab warning should be heeded. Feb 2 '19 at 14:29

Full credit to @AnAllergyToAnalogy for the caution item.

I made an example to demonstrate that a constructor will trick this method. Posting for others who might come across this thread.

In practice, isContract can't reliably detect an attacker calling from a constructor.

pragma solidity 0.4.25;

contract Victim {

    function isContract() public view returns(bool){
      uint32 size;
      address a = msg.sender;
      assembly {
        size := extcodesize(a)
      return (size > 0);


contract Attacker {
    bool public iTrickedIt;
    Victim v;
    constructor(address _v) public {
        v = Victim(_v);
        // addrss(this) doesn't have code, yet
        iTrickedIt = !v.isContract();
  • deploy Victim
  • deploy Attacker with Victim address
  • check iTrickedIt in Attacker

Hope it helps.


Address.sol in OpenZeppelin/contracts/utility has function isContract that works on the principle described. Same warning applies. Use with awareness.

  • 1
    As @eth below says, we can use require(msg.sender == tx.origin). Many says it has security vulnerabilities. I am sure it would be for other cases. But in my case, I just want to know caller is contract or not. I dont want other contracts from interacting with my contract whatsoever. so is it safe to use this, just for this use case? Thank again in advance for your time! Mar 24 '19 at 15:23
  • 1
    The answer is very good, in my opinion. Also the source is very respectablr. I would heed the warnings. Mar 24 '19 at 17:00

Since this is security related, it's helpful to emphasize https://stackoverflow.com/questions/37644395/how-to-find-out-if-an-ethereum-address-is-a-contract:

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.


I'm working on this as well. There is an opcode called extcodehash. It says

The EXTCODEHASH of the account without code is c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 what is the keccack256 hash of empty data

So I think there is a possibility to check isContract by using this extcodehash combined with the c5d2460186f72...

function isContract(address addr) internal view returns (bool) {
    bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;

    bytes32 codehash;
    assembly {
        codehash := extcodehash(addr)
    return (codehash != 0x0 && codehash != accountHash);

This means, if the code hash does not equal to 0 nor c5d2460186f72..., we can conclude this is the contract address?


One obvious point not emphasized in previously posted answers is that, YES, requiring

assembly {
size := extcodesize(_addr)

will guarantee that only a contract can make it past the check if size > 0.

However, the opposite check to see that a sender is NOT a contract (but an EOA) is much more complicated and requires a signature verification scheme in order to prove. There are 2 approaches, which you can read up on more here and here.

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.