I’m trying to understand the correct way to
Deploy
and thenImport
multipleSmart-Contracts
and aLibrary
when creating one big project.As an example, the project will have the following
Library
and threeSmart-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 Iimport
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 instantiateMakePizza
here, in the followingDeliverPizza
contract?I’m thinking that at this point I need to NOT use
import
statements and NOT use theis
syntax, as follows:import "MakePizza.sol"; contract DeliverPizza is MakePizza { . . . }
Instead, I should just create the contract as follows – omitting both the
import
andis 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: thePizzaLib
library and theMakePizza
andDeliverPizza
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 theis
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:
- Deploying the
PizzaLib
first. Then,Linking
it to all mycontracts
– which are listed in anarray
. And finally,- Deploying each and every one of those
contracts
, one at a time.So to recap my questions:
- Do I use
import
or not?- Do I need to put the
using PizzaLib for PizzaLib.Pizza;
in everycontract
?- Do I need the
is
statement in all mycontract
declaration statements or not?- How do I reference / instantiate the different
contracts
in each-other so I can call methods from one in another?
Answer
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/
Attribution
Source : Link , Question Author : Mark55 , Answer Author : Ioana Roceanu