Smart Contract Security on Celo with Remix Static Analyzer

Smart Contract Security on Celo with Remix Static Analyzer https://celo.academy/uploads/default/optimized/2X/d/daad2dfeced04303b09a7f3d7a056b095a9b256b_2_1024x576.png
none 0.0 0

Introduction

Smart contracts are an integral part of decentralized applications where the logic resides. Solidity as a famous smart contract language provides us with constructs, global variables, semantics, and syntaxes for writing instructions for the EVM-like blockchains that are termed smart contracts. Even though the solidity documentation highlights some of the best practices to use while writing contracts that target layers of the EVM-compatible blockchain, developers are expected to research further to ensure the best is deployed.

Prerequisites​

In this guide, you will learn how to leverage one of the smart contracts analysis and security tools called Remix static analyzer to avoid cheap and common mistakes often made by smart contract developers. You must at least be an intermediate working with smart contracts using solidity. If you’re new in this field, I recommend starting from here and here.
I also assume you know how to deploy contracts to the Celo networks. If you’re new to it, please check the below tutorials.

Requirements​

For this tutorial, you do not need to install any library or CLI tool. We’ll be using an online Integrated Development Environment (IDE) known as Remix

Remix static analyzer

According to the Remix NPM publication, Remix analyzer is a tool used for performing static analysis on Solidity smart contracts to check security vulnerabilities and bad development practices. There are practices that are considered bad when writing smart contracts. They leave room for attackers to easily exploit and part away with the treasure.

The static analyzer tool works underneath Remix IDE “Solidity static analysis” plugin which is used to run an analysis for a compiled contract according to selected modules. To understand how the tool works, let’s examine what static analysis is.

Static analysis

Static analysis is a process of debugging solidity code by examining it for vulnerabilities or bad practices without actually executing the code. The tool uses the Solidity Static Analysis plugin under the hood to perform static analysis on smart contracts written in Solidity.
The tool will check for the following parameters in your contracts.

  • Transaction origin: It checks whether the tx.origin variable is used.
  • Check-Effect interaction: It searches for a potential reentrancy risk.
  • Inline assembly: Using inline assembly has fair advantages coupled with risks that caused it to be discouraged often.
  • Block timestamp: Since miners can influence timestamps to a certain degree, dependency on it is highly discouraged.
  • Low-level calls: Except you know what you’re doing or you’re an experienced developer, you should not be using low-level calls.
  • Blockhash: This is a global variable in Solidity whose usage as well is discouraged because it can be manipulated by the miner.
  • Self-destruct: It has been established that contracts using self-destruct can be broken hence you have to be extremely careful while using it.

Installation

To use the Remix Static Analyzer tool, you have to follow these simple steps.

  • Click on the plug-in icon on the left-hand pane as shown in the image above. Scroll till you find the Static Analyzer plugin and activate it.

  • Confirm it was added.

Transaction origin & Low-level calls

The code below displays where tx.origin was used and a low-level call made. There is a potential vulnerability in the withdraw function as the client could be deceived the owner only is authorized to withdraw from the contract. The attacker could send a call from another attacking contract acting on behalf of the client.

Secondly, we used a low-level interaction to forward the $Celo in the contract to the caller when they invoke the withdraw(). As an advanced solidity developer, I need to guard against the recipient account calling back into the contract should it not belong to them. You also want to ensure the call was successful by checking the first return value is not false since low-level calls do not revert the whole transaction if not successful.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract TxOrigin {
  uint public depositCounter;
  address payable owner;

  constructor(address payable client) {
    require(client != address(0), "Zero address");
    owner = client;
  }

  function deposit() public payable {
    require(msg.value > 0, "Please send some value");
    depositCounter ++;
  }

  function withdraw(address withdrawTo, uint amount) public {
    require(tx.origin == owner, "Disguised");
    (bool sent,) = withdrawTo.call{value: amount}("");
    require(sent);
  }

}

Report

Check-Effect interaction

A reentrancy attack is possible when we fail to balance the interactions between the changes we made and the storage. An example is displayed in the simple contract below.

  • The savings records users’ saving balances and the time it was made using structured data type.
  • The issues arose in the withdraw function. We first check that the user has enough savings to withdraw, and forwarded the requested amount before we later update their balances. If the recipient is a malicious contract account designed to steal from the Reentrancy contract, they would have succeeded even before the main call terminates.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract Reentrancy {

  struct Balances {
    uint value;
    uint depositTime;
  }

  mapping(address =>Balances) private savings;

  constructor() { }

  function deposit() public payable {
    uint amount = msg.value;
    require(amount > 0, "Please send some value");
    savings[msg.sender] = Balances(amount, _now());
  }

  function _now() internal view returns(uint) {
    return block.timestamp;
  }

  function withdraw(address withdrawTo, uint amount) public {
    require(savings[msg.sender].value > amount, "Disguised");
    require(_now() + 86400 > savings[msg.sender].depositTime, "Only after 24 hours");
    (bool sent,) = withdrawTo.call{value: amount}("");
    require(sent);
    savings[msg.sender].value -= amount;
  }

}

Report

Check the warnings on the left.

Inline assembly, Blockhash, and Selfdestruct

blockhash is used to access the last 256 block hashes, that is the aggregate hash for the hashes in a block. Miners are able to influence Blockhash to an extent. A miner could cleverly compute the block hash by simply adding up the information in the currently mined block to influence the outcome of a specific transaction in the current block.

The selfdestruct is able to block calling contracts unexpectedly. You need to exercise more care especially if this contract is meant to be used by other contracts such as library contracts. Be aware that the selfdestruct of the callee contract can leave callers in an inoperable state.

// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;

contract Example {
    function sumAsm(uint[] memory data) public pure returns (uint sum) {
        for (uint i = 0; i < data.length; ++i) {
            assembly {
                sum := add(sum, mload(add(add(data, 0x20), mul(i, 0x20))))
            }
        }
    }

    function getBlockHash() public view returns(bytes32 result) {
      result = blockhash(block.number);
    }

    function closeContract(address closeTo) public {
      selfdestruct(payable(closeTo));
    }
}

Report

Conclusion​

You would notice that without executing any of the contracts, the plug-in has already gone ahead to detect the unacceptable practices we had used in our contracts.

What next?

As a developer, building safe and secure dApps on the Celo blockchain is paramount. Start leveraging some of the sophisticated tools such as the Remix static analyzer to scrutinize your contracts code.
To learn how to deploy your dream project on the Celo blockchain, visit the Celo documentation

About the Author​

Isaac Jesse, aka Bobelr is an advanced smart contract/Web3 developer. He has been in the field since 2018. He’s been an ambassador for projects such as Algorand, AtomicWallet, DxChain, etc. as a content creator and developer ambassador. He has also contributed to Web3 projects.

References​

14 Likes

@Celo_Academy As stated in the announcement post, I’d like to pick this proposal.

Thank you again.

12 Likes

Hi @bobelr I’ll be reviewing your piece in 1 or 2 days

Ok good @Phenzic

9 Likes

@Phenzic It’s already 3 days and you are yet to review this post. I am therefore requesting 4undRaiser or @ishan.pathak2711 or Kunaldawar to review for me whoever responds first. Copied @Celo_Academy.

12 Likes

I can do that for you @bobelr

1 Like

Please go ahead @ishan.pathak2711

11 Likes

I’ll edit and untag the other reviewers I previously tagged. Thank you for prompt response.

11 Likes