Skip to content

SRI-CSL/smart-contract-explorer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Smart Contract Explorer

Exploring behaviors of Solidity smart contracts.

Requirements

While solc-verify must currently be built from source, the remainder are available from various package managers, e.g., from Homebrew:

$ brew install node opam
$ opam init

Setup

$ git clone git@github.com:SRI-CSL/smart-contract-explorer.git
$ git submodule init
$ git submodule update
$ npm link

and optionally:

$ npm run test

Usage

$ sc-simulation --help
usage: sc-simulation --source <filename> --target <filename>

Options:
  --version     Show version number                                    [boolean]
  --verbose     output verbosity                      [boolean] [default: false]
  --output      output directory     [string] [default: ".sc-simulation.ignore"]
  --source      source smart contract                        [string] [required]
  --target      target smart contract                        [string] [required]
  --states      number of states to explore                [number] [default: 5]
  --relation    append to the simulation relation                       [string]
  --examples    generate examples for synthesis        [boolean] [default: true]
  --synthesize  synthesize the simulation relation     [boolean] [default: true]
  --verify      verify the simulation contract         [boolean] [default: true]
  --help        Show help                                              [boolean]

Generating examples for synthesis

$ sc-simulation --source resources/contracts/Token/ERC20-molochventures/ERC20.impl.sol  --target resources/contracts/Token/ERC20-openzeppelin/ERC20.spec.sol --no-synthesize --no-verify && cat .sc-simulation.ignore/SimulationExamples.sol
sc-simulation version 0.0.1

---
Generating examples
---
Warning: did not generate accessor for mapping: _allowed
Warning: did not generate accessor for mapping: allowances
pragma solidity ^0.5.0;

import "/Users/mje/Code/smart-contract-explorer/.sc-simulation.ignore/ERC20.impl.exemplified.sol";
import "/Users/mje/Code/smart-contract-explorer/.sc-simulation.ignore/ERC20.spec.exemplified.sol";

contract SimulationExamples {
    Token impl;
    ERC20 spec;

    function positiveExample0() public {
        impl = (new Token)();
        spec = (new ERC20)();
    }

    function positiveExample1() public {
        impl = (new Token)();
        impl.transfer(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0);
        spec = (new ERC20)();
        spec.transfer(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0);
    }

    function positiveExample2() public {
        impl = (new Token)();
        impl.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 0);
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 0);
    }

    function negativeExample0() public {
        impl = (new Token)();
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
    }

    function negativeExample1() public {
        impl = (new Token)();
        impl.transfer(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0);
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
    }

    function negativeExample2() public {
        impl = (new Token)();
        impl.transfer(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 1);
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
    }

    function negativeExample3() public {
        impl = (new Token)();
        impl.transfer(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 2);
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
    }

    function negativeExample4() public {
        impl = (new Token)();
        impl.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 0);
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
    }

    function negativeExample5() public {
        impl = (new Token)();
        impl.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
        spec = (new ERC20)();
        spec.transfer(0x6999c8a988a86C52297D9351235644e5768c28e6, 1);
    }

    function impl$_balances() public view returns (bytes32) {
        return keccak256(abi.encode(
            impl._balances(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            impl._balances(0x6999c8a988a86C52297D9351235644e5768c28e6)
        ));
    }

    function impl$_allowed() public view returns (bytes32) {
        return keccak256(abi.encode(
            impl._allowed(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            impl._allowed(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0x6999c8a988a86C52297D9351235644e5768c28e6),
            impl._allowed(0x6999c8a988a86C52297D9351235644e5768c28e6, 0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            impl._allowed(0x6999c8a988a86C52297D9351235644e5768c28e6, 0x6999c8a988a86C52297D9351235644e5768c28e6)
        ));
    }

    function impl$_totalSupply() public view returns (uint) {
        impl._totalSupply();
    }

    function spec$balances() public view returns (bytes32) {
        return keccak256(abi.encode(
            spec.balances(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            spec.balances(0x6999c8a988a86C52297D9351235644e5768c28e6)
        ));
    }

    function spec$allowances() public view returns (bytes32) {
        return keccak256(abi.encode(
            spec.allowances(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            spec.allowances(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09, 0x6999c8a988a86C52297D9351235644e5768c28e6),
            spec.allowances(0x6999c8a988a86C52297D9351235644e5768c28e6, 0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            spec.allowances(0x6999c8a988a86C52297D9351235644e5768c28e6, 0x6999c8a988a86C52297D9351235644e5768c28e6)
        ));
    }

    function spec$minters() public view returns (bytes32) {
        return keccak256(abi.encode(
            spec.minters(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            spec.minters(0x6999c8a988a86C52297D9351235644e5768c28e6)
        ));
    }

    function spec$burners() public view returns (bytes32) {
        return keccak256(abi.encode(
            spec.burners(0xab7A7Cb3E460a4ec0B73e07dA54F4173d9bB0c09),
            spec.burners(0x6999c8a988a86C52297D9351235644e5768c28e6)
        ));
    }
}

Synthesizing simulation relations

$ sc-simulation --source resources/contracts/Token/BasicToken-impl/BasicToken.impl.sol  --target resources/contracts/Token/BasicToken-spec/BasicToken.spec.sol --no-verify
sc-simulation version 0.0.1

---
Generating examples
---
Warning: did not generate accessor for mapping: allowances
Warning: did not generate accessor for mapping: allowances

---
Synthesizing simulation relation
---

---
Computed simulation relation:

   spec$balances == impl$balances

---

Verifying simulation relations

$ DEBUG=*:evaluate sc-simulation --source resources/contracts/Token/ERC20-molochventures/ERC20.impl.sol  --target resources/contracts/Token/ERC20-openzeppelin/ERC20.spec.sol --no-synthesize && cat .sc-simulation.ignore/SimulationCheck.sol
Keccak bindings are not compiled. Pure JS implementation will be used.

sc-simulation version 0.0.1

---
Generating examples
---
Warning: did not generate accessor for mapping: _allowed
Warning: did not generate accessor for mapping: allowances

---
Checking simulation relation
---

---
Verified simulation relation
---
pragma solidity ^0.5.0;

import "/Users/mje/Code/smart-contract-explorer/.sc-simulation.ignore/ERC20.impl.internalized.sol";
import "/Users/mje/Code/smart-contract-explorer/.sc-simulation.ignore/ERC20.spec.internalized.sol";

/**
 * @notice invariant __verifier_eq(Token._balances, ERC20.balances)
 * @notice invariant __verifier_eq(Token._allowed, ERC20.allowances)
 */
contract SimulationCheck is Token, ERC20 {

    /**
     * @notice postcondition impl_ret_0 == spec_ret_0
     */
    function check$balance(address account) public view returns (uint256 impl_ret_0, uint256 spec_ret_0) {
        impl_ret_0 = Token.balance(account);
        spec_ret_0 = ERC20.balance(account);
        return (impl_ret_0, spec_ret_0);
    }

    /**
     * @notice postcondition impl_ret_0 == spec_ret_0
     */
    function check$allowance(address owner, address beneficiary) public view returns (uint256 impl_ret_0, uint256 spec_ret_0) {
        impl_ret_0 = Token.allowance(owner, beneficiary);
        spec_ret_0 = ERC20.allowance(owner, beneficiary);
        return (impl_ret_0, spec_ret_0);
    }

    /**
     * @notice modifies Token._balances[msg.sender]
     * @notice modifies Token._balances[to]
     * @notice modifies ERC20.balances[msg.sender]
     * @notice modifies ERC20.balances[to]
     * @notice precondition to != address(0)
     * @notice precondition to != msg.sender
     * @notice precondition ERC20.balances[to] + val >= ERC20.balances[to]
     * @notice precondition ERC20.balances[msg.sender] - val >= 0
     */
    function check$transfer(address to, uint256 val) public {
        Token.transfer(to, val);
        ERC20.transfer(to, val);
    }

    /**
     * @notice modifies Token._allowed[msg.sender]
     * @notice modifies ERC20.allowances[msg.sender]
     * @notice precondition to != address(0)
     */
    function check$approve(address to, uint256 val) public {
        Token.approve(to, val);
        ERC20.approve(to, val);
    }

    /**
     * @notice modifies Token._balances[to]
     * @notice modifies Token._balances[from]
     * @notice modifies Token._allowed[from]
     * @notice modifies ERC20.balances[to]
     * @notice modifies ERC20.balances[from]
     * @notice modifies ERC20.allowances[from]
     * @notice precondition to != address(0)
     * @notice precondition to != from
     * @notice precondition ERC20.allowances[from][msg.sender] - val >= 0
     * @notice precondition ERC20.balances[to] + val >= ERC20.balances[to]
     * @notice precondition ERC20.balances[from] - val >= 0
     */
    function check$transferFrom(address from, address to, uint256 val) public {
        Token.transferFrom(from, to, val);
        ERC20.transferFrom(from, to, val);
    }

    /**
     * @notice modifies Token._allowed[msg.sender]
     * @notice modifies ERC20.allowances[msg.sender]
     * @notice precondition spender != address(0)
     * @notice precondition ERC20.allowances[msg.sender][spender] + val >= ERC20.allowances[msg.sender][spender]
     */
    function check$increaseAllowance(address spender, uint256 val) public {
        Token.increaseAllowance(spender, val);
        ERC20.increaseAllowance(spender, val);
    }

    /**
     * @notice modifies Token._allowed[msg.sender]
     * @notice modifies ERC20.allowances[msg.sender]
     * @notice precondition spender != address(0)
     * @notice precondition ERC20.allowances[msg.sender][spender] - val >= 0
     */
    function check$decreaseAllowance(address spender, uint256 val) public {
        Token.decreaseAllowance(spender, val);
        ERC20.decreaseAllowance(spender, val);
    }

    /**
     * @notice modifies Token._balances[to]
     * @notice modifies Token._totalSupply
     * @notice modifies ERC20.balances[to]
     * @notice precondition to != address(0)
     * @notice precondition ERC20.minters[msg.sender]
     * @notice precondition ERC20.balances[to] + val >= ERC20.balances[to]
     */
    function check$mint(address to, uint256 val) public {
        Token.mint(to, val);
        ERC20.mint(to, val);
    }

    /**
     * @notice modifies Token._balances[from]
     * @notice modifies Token._totalSupply
     * @notice modifies ERC20.balances[from]
     * @notice precondition from != address(0)
     * @notice precondition ERC20.burners[msg.sender]
     * @notice precondition ERC20.balances[from] - val >= 0
     */
    function check$burn(address from, uint256 val) public {
        Token.burn(from, val);
        ERC20.burn(from, val);
    }
}

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published