Skip to content
Basic math operations on Ethereum with overflow protection
HTML JavaScript CSS Shell
Branch: master
Clone or download

Latest commit

Fetching latest commit…
Cannot retrieve the latest commit at this time.

Files

Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
build/contracts
contracts
coverage
migrations
test
.gitignore
README.md
coverage.json
package-lock.json
package.json
run_test.sh
truffle.js

README.md

BasicMathLib

Build Status Discord

A utility library provided by Modular to protect math operations from overflow and invalid outputs.

Library Address

Main Ethereum Network: 0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC
Rinkeby Test Network: 0xa83b336F5501e6b6A3273c7c39dfCC5B18002733

License and Warranty

Be advised that while we strive to provide professional grade, tested code we cannot guarantee its fitness for your application. This is released under The MIT License (MIT) and as such we will not be held liable for lost funds, etc. Please use your best judgment and note the following:

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Installation and Usage

How to install

npm install ethereum-libraries-basic-math

How to link

This process will allow you to both link your contract to the current on-chain library as well as deploy it in your local environment for development.

Amend the deployment .js file in your truffle migrations/ directory as follows:

var BasicMathLib = require("ethereum-libraries-basic-math/build/contracts/BasicMathLib.json";
var OtherLibs = artifacts.require("./OtherLibs.sol");
var YourOtherContract = artifacts.require("./YourOtherContract.sol");
...

module.exports = function(deployer) {
  deployer.deploy(BasicMathLib, {overwrite: false});
  deployer.link(BasicMathLib, YourOtherContract);
  deployer.deploy(YourOtherContract);
};

Note: If you have not created a second deployment .js file in the migrations/ directory, this needs to be done first. You cannot use the 1_initial_migration.js file for your migrations.

Note: The .link() function should be called before you .deploy(YourOtherContract). Also, be sure to include the {overwrite: false} when writing the deployer i.e. .deploy(BasicMathLib, {overwrite: false}). This prevents deploying the library onto the main network or Rinkeby test network at your cost and uses the library already on the blockchain. The function should still be called however because it allows you to use it in your development environment. See below

Testing

Test: npm run test

Test Coverage: npm run test:coverage

solc Installation

version 0.4.21

For direction and instructions on how the Solidity command line compiler works see the documentation.

With standard JSON input

The Standard JSON Input provides an easy interface to include libraries. Include the following as part of your JSON input file:

{
  "language": "Solidity",
  "sources":
  {
    "YourContract.sol": {
      ...
      ...
    },
    "BasicMathLib.sol": {
      "content": "[Contents of BasicMathLib.sol]"
    }
  },
  "settings":
  {
    ...
    "libraries": {
      "YourContract.sol": {
        "BasicMathLib": "0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC"
      }
    }
  }
}

Note: The library name should match the name used in your contract.

solc without standard JSON input

When creating unlinked binary, the compiler currently leaves special substrings in the compiled bytecode in the form of 'LibraryName____' which leaves a 20 byte space for the library's address. In order to include the deployed library in your bytecode add the following flag to your command:

--libraries "BasicMathLib:0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC"

Additionally, if you have multiple libraries, you can create a file with one library string per line and include this library as follows:

"BasicMathLib:0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC"

then add the following flag to your command:

--libraries filename

Finally, if you have an unlinked binary already stored with the 'LibraryName____' placeholder, you can run the compiler with the --link flag and also include the following flag:

--libraries "BasicMathLib:0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC"

solc documentation

See the solc documentation for further information.

solc-js Installation

version 0.4.21

Solc-js provides javascript bindings for the Solidity compiler and can be found here. Please refer to their documentation for detailed use.

This version of Solc-js also uses the standard JSON input to compile a contract. The entry function is compileStandardWrapper() and you can create a standard JSON object explained under the solc section and incorporate it as follows:

var solc = require('solc');
var fs = require('fs');

var file = fs.readFileSync('/path/to/YourContract.sol','utf8');
var lib = fs.readFileSync('./path/to/BasicMathLib.sol','utf8');

var input = {
  "language": "Solidity",
  "sources":
  {
    "YourContract.sol": {
      "content": file
    },
    "BasicMathLib.sol": {
      "content": lib
    }
  },
  "settings":
  {
    ...
    "libraries": {
      "YourContract.sol": {
        "BasicMathLib": "0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC"
      }
    }
    ...
  }
}

var output = JSON.parse(solc.compileStandardWrapper(JSON.stringify(input)));

//Where the output variable is a standard JSON output object.

Solc-js Installation via Linking

Solc-js also provides a linking method if you have compiled binary code already with the placeholder. To link this library the call would be:

var linker = require('solc/linker')

bytecode = linker.linkBytecode(bytecode, { 'BasicMathLib': '0xc8Bc467B9A70A5824b7E71BE9D65906C72f13dDC' })

Solc-js documentation

See the Solc-js documentation for further information.

Basic Usage

Disclaimer: While we make every effort to produce professional grade code we can not guarantee the security and performance of these libraries in your smart contracts. Please use good judgement and security practices while developing, we do not take responsibility for any issues you, your customers, or your applications encounter when using these open source resources.

For a detailed explanation on how libraries are used please read the following from the Solidity documentation:

The BasicMathLib library does the four basic math functions for unsigned 256-bit integers and protects for overflow, underflow, and from dividing by 0 (yes, we know Solidity throws when dividing by zero but keep reading.) Each function returns two variables, the first being a boolean variable which indicates true if there is an error and false if there is no error. Error being an under/overflow condition or dividing by 0. The second variable is the result of the operation or 0 if there is an error.

When there is an error condition, BasicMathLib does not throw,invalid, or revert. This is important to understand for your smart contract workflow. The con to this is that any state changes your contract has made up to this point will need to be handled by you, no state changes will be reverted by the library if there is an error condition.

The results parallel javascript callback functions such that every return will have (err, result). This allows you to handle returns such as:

(err, res) = a.times(b);
if(err)
  //handle the error
else
  //there is no error, use res

Note: You can handle the error without throwing such as reverting yourself, this library gives you the flexibility to decide that tradeoff yourself.

In order to use the BasicMathLib library, import it into your contract and then bind it as follows:

Usage Example

pragma solidity ^0.4.21;

import "example-libraries-basic-math/contracts/BasicMathLib.sol";

contract YourContract {
  using BasicMathLib for uint256;

  //Then in your function you can call [first argument].function([second argument])
  //Your arguments should be of the same type you bound the library to
  function multiplyTwoNumbers(uint256 a, uint256 b) returns (bool,uint256){
    return a.times(b);
  }

  function divideTwoNumbers(uint256 a, uint256 b) returns (string success){
    bool err;
    uint256 res;
    (err, res) = a.dividedBy(b);
    if(!err)
      success = "I divided a number!"
  }
}

Binding the library allows you to call the function in the format [firstParameter].function(secondParameter)

Usage Note

All of the functions only accept uint256 types.

WORD OF CAUTION! If the function overflows or underflows, ie you subtract below zero, the function will return 0 as the result. If you operate on a variable but wish to preserve the value, you need to use a temporary variable to hold that value until checks pass. Consider the following code:

pragma solidity ^0.4.21;

import "ethereum-libraries-basic-math/contracts/BasicMathLib.sol";

contract YourContract {
  using BasicMathLib for uint256;

  uint256 a; //a is a state variable
  ...
  function badSubtract(uint256 b) returns (bool){
    bool err;
    (err, a) = a.minus(b);
    if(err)
      return false;
    //You have changed your state variable to zero
  }

  function goodSubtract(uint256 b) returns (bool){
    bool err;
    uint256 temp;
    (err, temp) = a.minus(b);
    if(err)
      return false;
    //Checks then effects
    a = temp;
  }
  ...
}

Functions

The following is the list of functions available to use in your smart contract.

times(numberOne, numberTwo) public pure returns (bool, uint256)

(BasicMathLib.sol, line 38)

Multiply two numbers. Checks for overflow.

Arguments

uint256 a
uint256 b

Returns

bool err uint256 res

dividedBy(uint256, uint256) public pure returns (bool, uint256)

(BasicMathLib.sol, line 55)

Divide two numbers. Checks for 0 divisor.

Arguments

uint256 a
uint256 b

Returns

bool err uint256 res

plus(uint256, uint256) public pure returns (bool, uint256)

(BasicMathLib.sol, line 78)

Add two numbers. Checks for overflow.

Arguments

uint256 a
uint256 b

Returns

bool err uint256 res

minus(uint256, uint256) public pure returns (bool, uint256)

(BasicMathLib.sol, line 95)

Subtract two numbers. Checks for underflow.

Arguments

uint256 a
uint256 b

Returns

bool err uint256 res

You can’t perform that action at this time.