6

I am trying to create a basic inheritance hierarchy with abstract/virtual formalisms. Consider the following two contracts:
Abstract Contract (IUser.sol):

contract IUser {
    function addUser (address a) returns (bool) {}
}

Virtual Contract (User.sol):

import "./IUser.sol";  
contract User {
    address[] userList;
    function addUser (address a) returns (bool) {
        userList.push(a);
    }

When I try deploying both the contracts, first the IUser.sol and next the User.sol, using truffle, I get an error "IUser is not defined". Any suggestions? Also, how do we use interfaces in 0.4.11 and deploy the same using truffle migrate?

1 Answer 1

14

You don't try to deploy the abstract interface contract IUser.

contract User is IUser {}

You deploy (migrate) User. Other contracts can use the abstraction to understand the interface to User. User is IUser protects you from certain kinds of developer errors such as failing to define a function in the interface.

Hope it helps.

Some clarification to respond to comments below

You can't deploy a contract with an abstract (undefined) function. It will react similarly to a constructor failure and won't be deployed.

Abstract (a.k.a. Interface) contracts for keeping the overhead low when contracts need to communicate. It's a matter of taste, but I've found it useful for implementations to inherit from interfaces as way to catch errors.

Consider a pair of largish contracts for a storefront and a shipper that need to communicate. For example, the store needs to arrange shipping. This would be huge:

import "./Shipping.sol";

contract Store {

  Shipping s;

  ...
}

In fact, if one tackles things this way, the block gasLimit is going to be a problem during deployment. Good news: The store doesn't need to know the internal workings of the shipping contract, only the interface. So ...

contract ShippingInterface {
  function shipStuff(bytes32 itemId, uint qty, bytes32 streetAddressId) public returns(bytes32 waybillId);
}

contract Store {

  ShippingInterface s;
  ...
}

In the first case, Store inherits all the bytecode for Shipping. In the second case, it inherits only the critical ABI information, so it's much smaller. In both cases, the contract can be instantiated by the constructor or some other function.

This will work:

function Store(address shippingContract) public {
  Shipping s = Shipping(shippingContract);
}

but so will this (second case)

function Store(address shippingContract) public {
  ShippingInterface s = ShippingInterface(shippingContract);
}

The second way is much more compact. Note that an actual shipping contract is deployed in both cases. The methods differ only in the way Store is informed about it.

As a matter of style, it can be handy to have the compiler report inconsistencies that creep into the code as you go. This style works in a lot of cases.

Shipping.sol

contract ShippingInterface {
  function doStuff() ... ;
}

contract Shipping is ShippingInterface {
  function doStuff() .. { // define it }
}

Store.sol

import "./Shipping.sol";

contract Store {

  ShippingInterface s; 
  ...
}

You would deploy a Shipping and a Store. You would never deploy a ShippingInterface - it's just a way of describing the interface to the real thing. And, the compiler is going to complain if there is something described in the Interface and it's not defined in the contract you're trying to deploy, which is a good thing.

Hope it helps.

6
  • This is helpful! Thanks for the update - I have another related question. When I tried to deploy a contract that is inheriting from another contract (which has modifiers) and I am getting a "contract code couldn't be stored. please check the gas amount" error. Any suggestions?
    – skarred14
    Commented Sep 18, 2017 at 23:41
  • Sounds like the constructor decided to throw. Try deploying it manually and troubleshoot from there, I guess. Commented Sep 19, 2017 at 1:14
  • thanks - so as to not mix around the questions, I ll post this as a separate question on the forum
    – skarred14
    Commented Sep 19, 2017 at 1:24
  • @skarred14: did you get this sorted? I've similar issue with truffle migrate, it throws contract code couldn't be stored when I try to deploy a contract which implements an interface
    – szerte
    Commented Dec 13, 2017 at 12:27
  • @szerte based on my understanding so far, cannot be deployed to ethereum platform- they are more so for governance around the maintenance of the smart contracts. Ensuring that a contract is inherited from an abstract contract helps prevent erroneous development and inclusion/exclusion of functionalities
    – skarred14
    Commented Dec 13, 2017 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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