4

For deployment I am using remix. When I deploy Hello.sol the compiler typically merges SafeMath.sol as a part of the main contract (Hello.sol) and deploys. This adds up library and main contract's deployment cost as whole. I want to do this operation separately in order to divide deployment cost in to multiple operations.

[Q] Is there any way to first deploy the library contract separately from the main contract and than link it to the main contract on remix? Should I use Truffle or follow different approach for this?

I have following simple contract, remix deploys Hello.sol as as single contract which also includes SafeMath.sol:

SafeMath.sol

pragma solidity ^0.5.0;

library SafeMath {
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "addition overflow");

        return c;
    }
}

Hello.sol

pragma solidity ^0.5.0;

import "./SafeMath.sol";

contract Hello {
    using SafeMath for uint256;
    uint value;

    constructor() public
    {
        value = value.add(100);
    }    
}

enter image description here

4 Answers 4

5
+50

It seems that Remix does this automatically.

Library code:

pragma solidity ^0.5.10;

library Foo {
    struct F {
        uint256 x;
    }

    function foo (F storage f) external {
        f.x = 123456789;
    }
}

Main contract code:

pragma solidity ^0.5.10;

import './Foo.sol';

contract Bar {
    Foo.F public f;

    function bar () public {
        Foo.foo (f);
    }
}

When I tell Remix to deploy Bar contract, it actually executes two separate transactions: the first to deploy Foo library and the second to deploy Bar contract linked to the Foo library:

enter image description here

Though this way you cannot link library that is already deployed.

5
  • Why the same approach does not work on the code piece that I shared on my question, where remix does not separate contract and library? In order to deploy Library separately should it has its own storage? @Mikhail Vladimirov
    – alper
    Commented Jul 16, 2019 at 23:16
  • 1
    This is because you call internal function from the library, and internal functions cannot be called externally, so compiler had no other option than to embed the function into calling smart contract. Commented Jul 17, 2019 at 5:41
  • If I replace the interval keyword with public and keep those previously internal functions in the Library, will those cause additional gas usage? @Mikhail Vladimirov
    – alper
    Commented Jul 17, 2019 at 9:36
  • 1
    It is a tradeoff. Internal functions are cheaper to call but increase deployment cost of the contract. External library functions are more expensive to call, but allow to keep byte code size and deployment cost lower. Commented Jul 17, 2019 at 17:29
  • I assume external can only be called as though it's calling another contract or library, so additional 2,000 gas for the jump @Mikhail Vladimirov
    – alper
    Commented Jul 18, 2019 at 13:04
1

in truffle you can do something like this:

const ConvertLib = artifacts.require("ConvertLib");
const MetaCoin = artifacts.require("MetaCoin");

module.exports = function(deployer) {
  deployer.deploy(ConvertLib);
  deployer.link(ConvertLib, MetaCoin);
  deployer.deploy(MetaCoin);
};

from

https://github.com/truffle-box/metacoin-box/blob/master/migrations/2_deploy_contracts.js

I'm not aware if that is possible with remix :/

1
  • Remix will just go ahead and link the contracts so contracts with libraries work when using the JavsScript VM. I suspect the process works with Injected Web3 but I haven't tried it. Commented Jul 9, 2019 at 18:50
1

I deployed the library as contract (and also change the function to public) and linked the “contract-library” like this SafeMath safeMath = SafeMath(0xF2fD4E3A5b94f0B4D8EE74C009E12F698906420b);.

Here is the code of the contract Hello:

pragma solidity ^0.5.10;

contract SafeMath {
    function add(uint256 a, uint256 b) public pure returns (uint256);
}

contract Hello {
    SafeMath safeMath = SafeMath(0xF2fD4E3A5b94f0B4D8EE74C009E12F698906420b);

    uint public value;

    constructor() public
    {
        value = safeMath.add(value, 100);
    }    
}

(Technically I think it’s a solution for your issue but it’s not very elegant.)

See https://kovan.etherscan.io/address/0x031c90e551c760c895cdf7d14e940e83578f9cc0#code for the contract. And see https://kovan.etherscan.io/address/0xF2fD4E3A5b94f0B4D8EE74C009E12F698906420b#code for the “contract-library”.

0

I had this similar issue before, and finally got it work like this

const ConvertLib = artifacts.require("ConvertLib");
const MetaCoin = artifacts.require("MetaCoin");

module.exports = function(deployer) {
  ConvertLib.address = "0xabce987676...";
  deployer.link(ConvertLib, MetaCoin);
  deployer.deploy(MetaCoin);
};

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.