2

I'm trying to understand the correct way to Deploy and then Import multiple Smart-Contracts and a Library when creating one big project.

As an example, the project will have the following Library and three Smart-Contracts.

We begin with:

The Library

pragma solidity >=0.4.0 <0.8.0;

library PizzaLib {

    struct Pizza {
       uint256 pieSize;
       string ingredients;
    }

    function mix(Pizza calldata pizza, uint256 pSize, string theIngredients) external pure returns (Pizza memory) {
        Pizza memory newPizza = pizza;
        newPizza.pieSize = pSize;
        newPizza.ingredients = theIngredients;

        return newPizza;
    }
}

This library will be used by all three upcoming smart-contracts (and perhaps more contracts to come) so I'm therefore going to deploy it independently. That way it's sitting in it's own address on the Blockchain and any contract can access it (which I believe is how this should work - but if I'm wrong even about this much, please let me know.)

Next is: Contract # 1

// Note that I'm putting an "import" statement here for the Library I just created, 
// but do I actually need this statement? Or will my migration/deployment 
// file - below - take care of linking the Library to this Contract 
// anyway? (That's question #1)
// 
// For now I'll put the import statement in:

import "PizzaLib.sol"; 

using PizzaLib for PizzaLib.Pizza;

contract MakePizza {
   // -Has functions to make various Types of Pizza
   // etc.
}

Now we move on to Contract # 2
This contract will also need to use the 'library', so question # 1 applies here as well (do I import or not?)
But here I have an additional question - question #2 - which is: this contract needs to not only access the 'library', but also contract # 1 (MakePizza), which was deployed independently, meaning it too resides in its own unique address on the Blockchain.
So, how do I instantiate MakePizza here, in the following DeliverPizza contract?

I'm thinking that at this point I need to NOT use import statements and NOT use the is syntax, as follows:

import "MakePizza.sol";

contract DeliverPizza is MakePizza {
 . . . 
}

Instead, I should just create the contract as follows - omitting both the import and is MakePizza statements:

contract DeliverPizza  {
    // This contract only handles the Deliveries of Pizzas. So it:
    // 1. Defines a “Customer” Struct (customer’s name, phone number, etc.)
    // 2. Defines a “CustomerAddress” Struct (street address, city, zip-code, etc.) 
    // 3. Has “delivery” type functions
}

Up next is Contract # 3
This guy needs to reference/instantiate everything we've done up until now: the PizzaLib library and the MakePizza and DeliverPizza contracts:

Contract HandleTheMoney   {
    // Defines all things having to do with funds:
    // 1. Acceptable Payment methods
    // 2. Defines various Fees
    // 3. Declares the Permissions re who’s allowed to withdraw funds from the contract, etc.
}

Question here again is: how do I instantiate / reference those other contracts in this contract?

The last contract is Contract # 4
Same thing. It needs to reference everything we spoke of up until now. Usually I would use the is syntax, as follows....

contract JoesPizzaShop is MakePizza, DeliverPizza, HandleTheMoney {
    // The “master” contract, bringing everything together
}

...but I don't think that's the way to go what with all the contracts being deployed independently, so it'd just be:

contract JoesPizzaShop {
    // Need to instantiate all the other contracts here...
}

FINALLY, we have the migration file - which I'm pretty sure I've got right:

module.exports = async function(deployer, network, accounts) {
  await deployer.deploy(PizzaLib, { overwrite: false });

  await deployer.link(PizzaLib, [MakePizza, DeliverPizza, HandleTheMoney, JoesPizzaShop]);
  
  await deployer.deploy(MakePizza);
  await deployer.deploy(DeliverPizza);
  await deployer.deploy(HandleTheMoney);
  await deployer.deploy(JoesPizzaShop);
}

Here's what I'm doing there:

  1. Deploying the PizzaLib first. Then,
  2. Linking it to all my contracts - which are listed in an array. And finally,
  3. Deploying each and every one of those contracts, one at a time.



So to recap my questions:

  1. Do I use import or not?
  2. Do I need to put the using PizzaLib for PizzaLib.Pizza; in every contract?
  3. Do I need the is statement in all my contract declaration statements or not?
  4. How do I reference / instantiate the different contracts in each-other so I can call methods from one in another?
3
  • If the library definition is in a separate file it is required to import when you use it, if you don't use the library you don't need to import it. The syntax using NN for xx is only allowed inside a contract. Also it is just a syntax sugar for writing obj.func(param) instead of library.func(obj, param). I suggest writing examples and asking here if you have found a problem that can't solve.
    – Ismael
    Commented Dec 16, 2020 at 4:05
  • Any update/learnings on the project? Perhaps you can answer your own question, it could certainly help the community, and me!
    – whamsicore
    Commented Jun 13, 2021 at 22:11
  • To get instance of the contract within another contract, you have to pass an address of this contract, usually over constructor. It would look like constructor(address myContractAddr) { _myContractInstance = MyContractInstance(myContractAddr) }
    – Gleichmut
    Commented Jan 16, 2023 at 8:23

1 Answer 1

1

I think the main question here is how do you want to structure your code:

  • your master contract to inherit all functionality and manage everything from a single contract's state
  • have separate contracts and states (i.e you could make pizza without using the master contract)

If you want to use different levels of complexity (inheriting), then:

  • use is when you want to inherit
  • there is no need to deploy all contracts
  • import and link the library to those contracts that use it
  • only deploy the library and the last contract

If you want to have separate contracts that can also be used individually:

  • don't use is
  • deploy library and link it to well the contracts that use it
  • import the library in all the contracts that use it
  • you can find out how to reference the contracts' functions from another contract here

For more info on how to deal with libraries: https://blockheroes.dev/import-external-contracts-libraries/

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.