7

When a base class uses a library, do derived classes also use the same library?

For example:

contract A {
    using SafeMath for uint256;
    ...
}
contract B is A {
    //is code here using SafeMath for uint256? 
}

4 Answers 4

5

No.

In Solidity 0.7.0 and later versions, the effect of using ... for is no longer inherited.

Quoting from the 0.7.0 changelog:

using A for B only affects the contract it is mentioned in. Previously, the effect was inherited. Now, you have to repeat the using statement in all derived contracts that make use of the feature.

1

You are right

pragma solidity ^0.4.24;

library Bytes32 {
    function toString(bytes32) public pure returns (string) {
        return "1";
    }
}

contract Parent {
    using Bytes32 for bytes32;

    function bar() public pure returns(string) {
        return bytes32(0).toString();              // returns "1"
    }
}

contract Child is Parent {
    function foo() public pure returns(string) {
        return bytes32(0).toString();              // returns "1"
    }
}
1
  • Note that this example will throw an error when compiled with solc ^0.7.0 May 29, 2021 at 2:26
1

Caveat: This answer is outdated and incorrect when used with solc compiler ^0.7.0.

Yes.

As noted in the official docs,

When a contract inherits from multiple contracts, only a single contract is created on the blockchain, and the code from all the base contracts is copied into the created contract.

This copying of code includes using...for statements, which apply to the contract as a whole rather than specific functions.

You can verify this for yourself by testing contract B for the behavior that the library provides to contract A. In this example you can try to cause an overflow in a test on contract B and see that it throws an error instead, if the library is properly included and linked with B's parent type, contract A.

You can also see this in OpenZeppelin's implementation of ERC20 tokens.

0

Answer is no for anything above 0.7.0 as as mentioned by others. Here is an appropriate use-case on why this is helpful. When you have UUPS contract that's upgradeable, if you had used libraries in parent contract and a need to upgrade any of those functions, would require you to update the library.

library MyTypes {

  struct DiamondType {
       string name;
       uint age;
  }

}

library MyLogic { 
   
   function age(MyTypes.DiamondType state) returns (uint) (
      return state.age;
   }


   function name(MyTypes.DiamondType state) returns (string) (
      return state.name;
   }

} 
       

contract MyContract is UUPSUpgradeable {

   using MyLogic for MyTypes.DiamondType;
   MyTypes.DiamondType state;
   
   function age() public returns (uint) (
      return state.age();
   }

  
   function name() public returns (string) (
      return state.name();
   }

}

now if you have to update the age function such that it returns Korean age which is usually 1 or 2 years more than international age.

library MyLogicV2 { 
   
   function age(MyTypes.DiamondType state) returns (uint) (
      return state.age + 1;
   }

} 


contract MyContractV2 is MyContract {

   using MyLogicV2 for MyTypes.DiamondType;
     
   function age() public returns (uint) (
      return state.age();
   }

}

This allows the MyContractV2 to still make use of all existing functions of MyLogic but yet be able to upgrade only few functions defined as MyLogicV2.

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.