I have a function in one contract that that takes a different user defined contract as the parameter and then does something with it. When I make an RPC call externally I can provide virtually any address as the parameter regardless if it matches the contract interface of my user defined contract type. I'm assuming this is by design since I think in the ABI user defined types just become address.


contract MyContract is MyParentContract {
   string private foo;

   function MyContract(string _foo) {
       foo = _foo;

   function getFoo() public returns (string) {
       return foo;

contract ExternalContract {
    MyParentContract private myParentContract;

    function ExternalContract(MyParentContract _myParentContract) {
        myParentContract = _myParentContract;

    function setMyParentContract(MyParentContract _myParentContract) external {
        myParentContract = _myParentContract;

If I am to send a transaction to ExternalContract.setTestParentContract() I can provide the address of any contract regardless of whether it is a MyParentContract contract or even matches the interface of that contract.

I am wondering if anyone has come up with a solution to disallow incompatible contracts? Or if there are solidity/ethereum changes in the works to solve this issue?


Yes. It's by design.

It's possible to check make arrangements to check compatibility before doing something like changing a name registry or owner.

There are a few solutions around. For example: https://github.com/ethereum/EIPs/issues/165

We can also imagine a simple system of self-identification. Suppose A wants to be sure it only talks to instances of B; not some random contract lacking the correct interface. Example below.

A caution item: If the "users" who provide the contract addresses are untrusted, then preventing errors won't be enough.

A common pattern is an onlyOwner modifier that restricts access to a changeOwner() function. The changeOwner() function can be further protect itself from admin errors by checking the newOwner for an acceptable response and possibly confirming the admin has control of it; so one can't accidentally transfer ownership out of reach.

Hope it helps.

contract A {

  B b;

  event LogIsB(bool allOkay);

  function A() {
    b = new B();

  function doSomething()
    returns(bool success)

    // first, check "b" really is a "B"
    if(b.bSig() != sha3("Supports B Interface ver 1")) throw;
    return true;


contract B {

  // Response shows that B is "designed" to produce the expected response.
  // Extremely unlikely this will happen by accident. 
  // There is no assurance that an adversary can't spoof this. 

  function bSig() 
    returns(bytes32 fingerprint) 
        return sha3("Supports B Interface ver 1");

| improve this answer | |
  • Thank you for your response! The link to the discussion on interfaces is very helpful and I appreciate the simple example. – d0ck Feb 28 '17 at 15:30

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.