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.

| improve this answer | |
  • 3
    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. – AnAllergyToAnalogy Aug 18 '18 at 13:20
  • 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. – Thorkil Værge 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.

| improve this answer | |
  • 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! – Yogesh - EtherAuthority.io Mar 24 '19 at 15:23
  • The answer is very good, in my opinion. Also the source is very respectablr. I would heed the warnings. – Rob Hitchens 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.

| improve this answer | |

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?

| improve this answer | |

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.