Ethereum Solidity Security - Safe Math

in #utopian-io5 years ago

Repository

https://github.com/igormuba/EthereumSolidityClasses/tree/master/SafeMath

What Will I Learn?

  • Implementing safe math and how does it work
  • Using safe math

Requirements

  • Internet connection
  • Code editor
  • Browser

Difficulty

  • Basic

Tutorial Contents

This tutorial is designed to be a standalone and disconnected from the main "Ethereum/Solidity" ones. On many of the other tutorials I have written, I have mentioned the importance of security. On the last class I have covered a little bit of security on a "multisig" contract (multisig, on that situation, meant that the majority of token holders had to vote). Before I get started with the next contract I want to teach, I need to introduce you to safe math operations.

The next tutorial will be interesting and will have many of real world uses, and you might need to do something like that at some point, if you are an Ethereal developer. But without safe math, the next tutorials will be useless because security will be very important.

Safe math is not hard to implement or to use, but it requires attention to details, and also require you to be up to date with the latest security news of smart contracts. Most security breaches of Ethereum smart contracts are mathematical exploits. For example, an user somehow manages to withdraw more tokens than he has, in this case, if the contract can't predict and handle such situation, the user will have "unlimited" balance, as his credit on the contract will underflow.

The contract

The contract will hold functions that will replace the basic mathematical operations. So, in another contract, when you need to sum two numbers, you won't say "x+y", but actually use the functions from the math contract to handle security the operation.

To get both of us on the same boat I will tell you what is my development environment. However, if you are more familiar with something else, like Truffle, for example, that is ok, you just need to understand what is happing and apply on your environment. Mine is:

The name of my file is safeMath.sol, the name is important because, just need to remember the name, because it is required to import to another contract(though it does not need to be the same name as mine).

The skeleton of my contract:

pragma solidity ^0.5.0;

contract safeMath{
    
}

Safe add

This function will check and guarantee that no overflow happens on the operation:

function safeAdd(uint _a, uint _b) public pure returns(uint){
    uint c = _a+_b;
    require(c>=_a && c>=_b);
    return c;
}

The function is pure, meaning it does not access/write anything on/to the Ethereum blockchain, all the operations happen on memory using the variables given to it. You are not forced to use the pure keyword, but by doing so you reduce the transaction costs! On big contract, like the one from the previous class, this kind of things add up!

Also, we are using the require keyword, instead of the assert because the require keyword throws an error and refund the remaining gas, while assert consumes all gas! If your user used 1ETH to pay for the gas, he will have a very bad time...

Many old contracts still use throw and assert, but to me, it seems like a bad practice, because at the time most of those contract were written the require keyword did not exist.

The important line of this operation is:

require(c>=_a && c>=_b);

It ensures that the result of the sum is never less than the arguments, this means that if an overflow happens it will throw an error. An overflow is when a sum goes over the "roof" of how big a number can be, and it starts again from zero. If an overflow happens the result will be less than one of the 2 arguments passed into it.

Safe sub

The safe sub function will check if a subtraction operating will underflow:

function safeSub(uint _a, uint _b) public pure returns (uint){
    require(_b<=_a);
    return _a-_b;
}

I will use mathematical jargon here, but you might remember it form the elementary math classes (are those things taught on elementary?...).

If the subtrahend of an operation is bigger than the minuend, the difference will be a negative number. It is a common exploit on smart contracts because if a user withdraws a negative number he will actually add balance to an account (a negative negative is a positive). Also, in the case of Ethereum, it will underflow and the result will actually be a HUGE number, allowing the user to have infinite balance!

So, in case the subtrahend (second parameter, or _b), is bigger than the minuend (first parameter, or _a), an error will be thrown and the remaining gas will be refunded.

Safe multiplication

Multiplication is probably a bit less intuitive than the previous two operations. Again, I will use mathematical jargon, illustrated with an image so you can understand what am I talking about.

And here is the code, before I explain it:

function safeMul(uint _a, uint _b) public pure returns(uint){
    uint c = _a * _b;
    require(_a==0 || c/_a==_b);
    return c;
}

First, we store the result in a variable c, so that we can later return it, and also use on the require.

First thing we check on the require function, is whether _a is equals to zero or not, if it is, that is ok and the operation continues because anything multiplied by zero is zero, so there would not be any mathematical abnormalities on the operation. Also, by checking first if _a is zero, thus true, we don't go into the next checking on the require statement, because if it is zero and we execute the next operation we will fall into the dividing by zero paradox.

If it is not zero, we then check the inverse operation, dividing the result for the multiplier factor, which should be equal to the multiplicand factor if the operating worked correctly, it will throw an error otherwise.

Safe division

The last of the four basic operations is division. Hovewer, notice that we are working with integers, and the remainder will be thrown away. Keep that in mind as the logic to get the remainder should be applied on the main contract that will be using the safe math.

Again, here is the structure of the division operating and the names:

And the code for Solidity 5:

function safeDiv(uint _a, uint _b) public pure returns (uint) {
    require(_b > 0);
    uint c = _a / _b;
    require(_a == _b * c + _a % _b);
    return c;
}

The first thing is that we require that the divisor is greater than zero, to avoid the problem of division by zero described in a previous section.

The other require checks the inverse operation, taking into consideration the remainder, though the remainder is not given to the caller.

Testing

To demonstrate how the implementation should work, I will use only the safeSub function, as the implementation for every function is very similar to each other, and the division function is easier to get an error with (div is easy too), as the other require HUGE numbers to get an overflow error!

Here is the code of my safeMathTest.sol file:

pragma solidity ^0.5.0;
import "browser/safeMath.sol";

contract safeMathTest is safeMath{
    function subtraction(uint _a, uint _b) public pure returns(uint){
        return safeSub(_a, _b);
    }
}

You need, first, to import the safeMath contract in order to work with it, however, you don't need to compile and run the safe math contract!

Then, what you need to do is to make the new contract inherit from the safeMath one with the keyword is.

After compiling and deploying, if you test the contract by doing a normal operating, the kind that we expected, which the second argument is equal or less than the first, it will work normally:

Captura de Tela 20190122 às 15.55.03.png

But if we try to do something that is not considered a "safe operation" it will throw is an error:

Captura de Tela 20190122 às 15.58.30.png

I have tagged this tutorial as for beginners, so I expect that beginners on Solidity will read it, however, most of my previous tutorials were advanced, as I am not very used to writing beginners tutorials. Though I have tried to make it as friendly and easy as possible, if the didactics of this one were not enough for you, as a beginners, to fully understand, I will be very happy to answer your questions on the comments.

Curriculum

This is supposed to be a standalone tutorial to help anyone interest in
Solidity to understand and use safe maths, however, if you are interested in mastering solidity, here is the main Ethereum smart contract development series:

First tutorial

Latest tutorial

Beneficiaries

This post has as beneficiaries

using the SteemPeak beneficiary tool

Captura de Tela 20190122 às 16.07.11.png

Sort:  

Thank you for your contribution @igormuba.

Good information in this tutorial, thanks for your work!

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Chat with us on Discord.

[utopian-moderator]

Thank you for your review, @portugalcoin! Keep up the good work!

ǝɹǝɥ sɐʍ ɹoʇɐɹnƆ pɐW ǝɥ┴

Hi @igormuba!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @igormuba!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!

Coin Marketplace

STEEM 0.19
TRX 0.14
JST 0.030
BTC 60115.50
ETH 3192.77
USDT 1.00
SBD 2.45