Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
clarus committed Jul 5, 2024
1 parent 71e411f commit 77824e8
Show file tree
Hide file tree
Showing 3 changed files with 181 additions and 6 deletions.
12 changes: 6 additions & 6 deletions blog/2024-06-28-coq-of-solidity-1.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ authors: []

[Solidity](https://soliditylang.org/) is the most widely used **smart contract language** on the blockchain. As smart contracts are **critical software** handling a lot of money, there is a huge interest in finding **all possible bugs** before putting them into production.

:::info AlephZero

_We are happy to be working with [AlephZero](https://alephzero.org/) to develop tools to bring more security for the audit of Solidity smart contracts, thanks to the use of formal verification and the interactive theorem prover [Coq](https://coq.inria.fr/). We thank the Aleph Zero Foundation for their support._

:::

**Formal verification** is a technique to test a program on all possible entries, even when there are **infinitely many**. This contrasts with the traditional test techniques, which can only execute a finite set of scenarios. As such, it appears to be an ideal way to bring more security to smart contract audits.

<!-- Many companies, like [Certora](https://certora.com/) and [CertiK](https://www.certik.io/), are already providing formal verification services for Solidity. -->
Expand All @@ -27,6 +21,12 @@ The code is available in our fork of the Solidity compiler at [github.com/formal

<!-- truncate -->

:::info AlephZero

_We are happy to be working with [AlephZero](https://alephzero.org/) to develop tools to bring more security for the audit of Solidity smart contracts, thanks to the use of formal verification and the interactive theorem prover [Coq](https://coq.inria.fr/). We thank the Aleph Zero Foundation for their support._

:::

<figure>
![Ethereum in forest](2024-06-28/ethereum-in-forest.webp)
</figure>
Expand Down
175 changes: 175 additions & 0 deletions blog/2024-07-03-coq-of-solidity-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
---
title: 🪨 Coq of Solidity – part 2
tags: [formal verification, Coq, Solidity, Yul]
authors: []
---

We present how we develop a formal verification framework for [Solidity](https://soliditylang.org/) smart contracts with the [Coq](https://coq.inria.fr/) proof assistant. We use the [coq-of-solidity](https://github.com/formal-land/solidity) tool to translate Solidity code to Coq that we presented in our previous blog post [🪨 Coq of Solidity – part 1](/blog/2024/06/28/coq-of-solidity-1).

We will take the example of an [ERC-20 smart contract](https://en.wikipedia.org/wiki/Ethereum#ERC20) implementation and show that it is equivalent to a purely functional definition in Coq acting as a specification.

<!-- truncate -->

:::info AlephZero

_We are happy to be working with [AlephZero](https://alephzero.org/) to develop tools to bring more security for the audit of Solidity smart contracts, thanks to the use of formal verification and the interactive theorem prover [Coq](https://coq.inria.fr/). We thank the Aleph Zero Foundation for their support._

:::

<figure>
![ERC-20 smart contract in forest](2024-07-03/erc20-jungle.webp)
</figure>

## Simplifying the code

We take the ERC-20 smart contract given in the tests of the Solidity compiler: [test/libsolidity/semanticTests/various/erc20.sol](https://github.com/ethereum/solidity/blob/develop/test/libsolidity/semanticTests/various/erc20.sol). It contains around **100 lines of Solidity**. We translate it with `coq-of-solidity` to the file [CoqOfSolidity/test/libsolidity/semanticTests/various/erc20/ERC20.v](https://github.com/formal-land/solidity/blob/guillaume-claret%40experiments-with-yul/CoqOfSolidity/test/libsolidity/semanticTests/various/erc20/ERC20.v) of **6,662 lines of Coq**. These lines are generated but this is still a large increase in terms of code size, more than sixty times. Looking at the Yul code of the contrat, the intermediate representation of the Solidity code that we use to make a translation to Coq, we get around **1,000 lines of Yul** when pretty-printed with the `--ir-optimized` option of the Solidity compiler. This is the actual size of the code that we need to analyze, once we remove the verbosity due to our Coq notations.

The beginning of the contract in Solidity looks like this:

```solidity
pragma solidity >=0.4.0 <0.9.0;
contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
constructor() {
_mint(msg.sender, 20);
}
// ...
```

Here is the constructor of the contract, calling the function `_mint` defined below. In Yul we get for the code of the constructor:

```go
object "ERC20_403" {
code {
{
/// @src 0:33:3484 "contract ERC20 {..."
mstore(64, memoryguard(0x80))
if callvalue()
{
revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
}
constructor_ERC20()
let _1 := allocate_unbounded()
codecopy(_1, dataoffset("ERC20_403_deployed"), datasize("ERC20_403_deployed"))
return(_1, datasize("ERC20_403_deployed"))
}
function allocate_unbounded() -> memPtr
{ memPtr := mload(64) }
function revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb()
{ revert(0, 0) }
function cleanup_rational_by(value) -> cleaned
{ cleaned := value }
function cleanup_uint256(value) -> cleaned
{ cleaned := value }
// ...
```
As we can see there is a lot of small intermediate functions that are introduced and for many of them they are very simple, or even doing nothing. The translation in Coq is the following:
```coq
(* Generated by coq-of-solidity *)
Require Import CoqOfSolidity.CoqOfSolidity.

Module ERC20.
Definition code : Code.t := {|
Code.name := "ERC20_403";
Code.hex_name := 0x45524332305f3430330000000000000000000000000000000000000000000000;
Code.functions :=
[
Code.Function.make (
"allocate_unbounded",
[],
["memPtr"],
M.scope (
do* ltac:(M.monadic (
M.assign (|
["memPtr"],
Some (M.call (|
"mload",
[
[Literal.number 64]
]
|))
|)
)) in
M.pure BlockUnit.Tt
)
);
Code.Function.make (
"revert_error_ca66f745a3ce8ff40e2ccaf1ad45db7774001b90d25810abd9040049be7bf4bb",
[],
[],
M.scope (
do* ltac:(M.monadic (
M.expr_stmt (|
M.call (|
"revert",
[
[Literal.number 0];
[Literal.number 0]
]
|)
|)
)) in
M.pure BlockUnit.Tt
)
);
Code.Function.make (
"cleanup_rational_by",
["value"],
["cleaned"],
M.scope (
do* ltac:(M.monadic (
M.assign (|
["cleaned"],
Some (M.get_var (| "value" |))
|)
)) in
M.pure BlockUnit.Tt
)
);
Code.Function.make (
"cleanup_uint256",
["value"],
["cleaned"],
M.scope (
do* ltac:(M.monadic (
M.assign (|
["cleaned"],
Some (M.get_var (| "value" |))
|)
)) in
M.pure BlockUnit.Tt
)
);
```
This version is far longer, but the main difference is that here the variables are represented as names that are strings instead of proper Coq variable names.
A first thing we want to do is to rewrite all of these functions in Coq:
- simplifying the obvious cases, like removing the calls to identity functions,
- using proper Coq variables and functions instead of strings.
:::warning For more
If you have smart contract projects that you want to formally verify, going further than a manual audit to find bugs, contact us at&nbsp;[&#099;&#111;&#110;&#116;&#097;&#099;&#116;&#064;formal&#046;&#108;&#097;&#110;&#100;](mailto:[email protected])! Formal verification has the unique advantage of covering all possible execution cases.
:::
## Conclusion
We have presented our ongoing development of a formal verification tool for Solidity using the Coq proof assistant. We have briefly shown how we translate Solidity code to Coq using the Yul intermediate language and how we define the semantics of Yul in Coq. We have tested our tool on the examples of the Solidity compiler's test suite to check that our formalization is correct.
Our next steps will be to:
1. Complete our definitions of the Ethereum's primitives, to have a 100% success on the Solidity test suite.
2. Formally specify and verify an example of contract, looking at the [erc20.sol](https://github.com/formal-land/solidity/blob/guillaume-claret%40experiments-with-yul/test/libsolidity/semanticTests/various/erc20.sol) example.
Binary file added blog/2024-07-03/erc20-jungle.webp
Binary file not shown.

0 comments on commit 77824e8

Please sign in to comment.