🎓 A1Learner
🔍
0 of 48 lessons completed

Solidity Library vs Contract

The difference between a library and a contract is what each can own. A contract owns state and can receive ether, while a library only computes.

A contract owns state between calls

Counter stores its count. Each call changes the stored value.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
contract Counter {
    uint256 public count;

    function increment() public {
        count += 1;
    }
}

State lives in the contract, not the library

DoubleLib only computes. Score owns the stored value and changes it with the library result.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library DoubleLib {
    function double(uint256 x) internal pure returns (uint256) {
        return x * 2;
    }
}

contract Score {
    uint256 public score;

    function setScore(uint256 s) public {
        score = s;
    }

    function doubleScore() public {
        score = DoubleLib.double(score);
    }
}

A library cannot receive ether

A receive function inside a library fails to compile. Ether belongs in contracts.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library EtherLib {
    function double(uint256 x) internal pure returns (uint256) {
        return x * 2;
    }

    receive() external payable {}
}

Example

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
library InterestLib {
    function interest(uint256 amount, uint256 percent) internal pure returns (uint256) {
        return amount * percent / 100;
    }
}

contract Savings {
    uint256 public balance;

    function deposit(uint256 amount) public {
        balance += amount;
    }

    function applyInterest(uint256 percent) public {
        balance += InterestLib.interest(balance, percent);
    }
}

Key points

  • Contract: a deployable block that owns state and can receive ether.
  • Library: a block of functions with no state and no ether.
  • Use a contract when a value must be stored between calls.
  • Use a library when many contracts need the same computation.
  • A contract is deployed on its own, while an internal library is copied into its caller.

In this example, InterestLib computes interest and stores nothing. Savings owns the balance. Its deposit function grows the balance, and its applyInterest function adds the library interest to that balance.

Note

a library cannot receive ether, so ether always lands in a contract.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Remix IDE

Exercise

A computation is needed by ten contracts and stores nothing. What fits best?