2

I'm building a project which has the following artifacts:

  1. the complete code for Oraclize API, inline, (1329 lines of code including comments and description)
  2. SafeMath Library, inline, (114 lines of code)
  3. a contract called Ownable which has codes to change owner, modifiers related to owner etc. this contract is small (around 80 lines)
  4. the main project contract which is large (around 1300 lines of code, including comments and function description)

all these four artifacts are inline in the same file called ProjectName.sol.

I'm unable to deploy this project using truffle as I believe the size limit of the project has been exceeded (24576 bytes). Can you please tell me what would be the industry standard (best practice) to break this code into multiple contracts?

1

I solved this problem in my project by moving all code logic to libraries. My contract only contains boiler-plate code that calls library functions. You can update state variables by storing them in a struct and passing that struct (by reference) to your library functions. The struct will need to be stored in a separate library that all other libraries import.

// AnimalContract.sol (imports StorageLib, LionLib, and CatLib)
contract AnimalContract{

    StorageLib.StorageStruct storage;

    function roar() public{
        LionLib.roar(storage);
    }

    function meow(uint256 someValue) public{
       CatLib.meow(storage, someValue);
    }  
}

//LionLib.sol (imports StorageLib)
function roar(StorageLib.StorageStruct storage storageStruct) public{
    storageStruct.hasRoared = true;
}
0

Having all contracts in a single file is most probably not the problem. It looks like your contract with 1300 lines of code is too large.

Moreover, you should look for your new statements, since they will include all the code of the contract to be instantiated. Factory pattern is a possibility to navigate around this.

contract A {}

contract AFactory {
    function createA() public returns(A) {
        return new A();
    }
}

contract B {
    AFactory fac;
    constructor(AFactory _fac) {fac = _fac;}
    ...
        fac.createA()
    ...
}

This will reduce the code size of the B contract since A code is not included, because new statement is in AFactory.

UPDATE another way to reduce the code size of a contract is to use delegation instead of inheritance. See https://refactoring.guru/replace-inheritance-with-delegation

It's difficult to tell more without seeing the code.

  • there are no 'new' statements in my code pertaining to instantiating another contract. my main contract inherits usingOraclize and Ownable, and the SafeMath library is inherited by the statement: "using SafeMath for uint256;". – Kombo Jan 8 at 6:39
  • Did you check the size of the compiled bytecode? – ivicaa Jan 8 at 7:39
  • could you tell me how to find the size of the compiled bytecode? I tried to copy the value of the "object" key in bytecode section of remix, to a new txt file. the size of the txt file is showing as 90kb. – Kombo Jan 8 at 7:54
  • In Remix, in the compile panel, there is a "Details" button under the contract. If you open this you can see bytecode in it's raw form in hex representation (object field). If you divide the string length by 2 you get the size in bytes. – ivicaa Jan 8 at 18:58
  • I did what you asked. The size in bytes is coming to around 46015 bytes. – Kombo Jan 9 at 2:14

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.