1

I'm looking for a function that will tell me if an address is a contract address or an externally owned address / wallet address.

I tried with this function, however this only tells me if the address is payable (which could be both contract or wallet address).

function isPayable(address testAddress) private returns (bool) {
    if(payable(testAddress).send(0)) {
        return true;
        }
    return false;
    }

Is there any function to check is an address is a contract or a wallet address in solidity?

0

2 Answers 2

3

There is a library called Address in openzeppelin-contracts.

You can use isContract function to check whether the address is smart contract address.
Please read more details here. https://docs.openzeppelin.com/contracts/2.x/api/utils

1
1

The best way to check and make sure that an address is not a contract, is by comparing tx.origin with msg.sender. You could do a modifier for that.

    modifier onlyEoa() {
        require(tx.origin == msg.sender, "Not EOA");
        _;
    }

Smart contracts cannot execute on their own. Always a user's account needs to create a transaction to call a smart contract so that it executes. So, they are dependent on a user to start the execution.

Once they are running, they can call other contracts, and in this case, they themselves would be the 'sender' of this call, but they would still be executing in the context of the original transaction that the user sent.

In Solidity, we can check who originated the transaction in the first place, using 'tx.origin'. This will always show the address of the user that created the transaction. Also, we can check who called a contract using 'msg.sender'. This one can vary from call to call.

In the call to the first smart contract, 'msg.sender' will be the user that originated that call, the same as 'tx.origin'. But, if that smart contract calls another smart contract, then in the other smart contract the 'msg.sender' will be the address of the smart contract that called, but 'tx.origin' will always be the original user that sent the transaction, no matter what.

This is useful to check and make sure that is a user that is calling certain function and not a contract. In fact, this is the best way to check if the sender is a smart contract, by simply comparing tx.origin == msg.sender. If they are the same, then the caller is a regular user. If they are different, then the caller is a smart contract.

A quick way to see it would be like this: "Simple call chain A -> B -> C -> D, inside D msg.sender will be C, and tx.origin will be A."

1

Not the answer you're looking for? Browse other questions tagged or ask your own question.