Giter VIP home page Giter VIP logo

sabre's Introduction

Sabre

Discord

Sabre is a security analysis tool for smart contracts written in Solidity. It uses the MythX symbolic execution & fuzzing service to:

Warning: This is my own MythX client hobby implementation. Please use the official MythX command line client in production environments .

Usage

Installation

$ npm install -g sabre-mythx

Setting up an Account

Sign up for an on the MythX website to generate an API key. Set the MYTHX_API_KEY enviroment variable by adding the following to your .bashrc or .bash_profile):

export MYTHX_API_KEY=eyJhbGciOiJI(...)

Generic bug detection

Run sabre analyze <solidity-file> [contract-name] to submit a smart contract for analysis. The default mode is "quick" analysis which returns results after approximately 2 minutes. You'll also get a dashboard link where you can monitor the progress and view the report later.

Custom property checking

To check specifically for assertion violations and print counter-examples for any violations found, run the following:

$ sabre check <solidity-file> [contract-name]

Example 1: Primality test

You're pretty sure that 973013 is a prime number. It ends with a "3" so why wouldn't it be??

pragma solidity ^0.5.0;

contract Primality {
    
    uint256 public largePrime = 973013;
    
    uint256 x;
    uint256 y;
    
    function setX(uint256 _x) external {
        x = _x;
    }
 
    function setY(uint256 _y) external {
        y = _y;
    }
    
    function verifyPrime() external view {
        require(x > 1 && x < largePrime);
        require(y > 1 && y < largePrime);
        assert(x*y != largePrime);
    }
}

Surely the assertion in verifyPrime() will hold for all possible inputs?

$ sabre check primality.sol
--------------------
ASSERTION VIOLATION!
/Users/bernhardmueller/Desktop/primality.sol: from 21:8 to 21:33

assert(x*y != largePrime)
--------------------
Call sequence:

    1: setY(1021)
    Sender: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [ USER ]
    Value: 0

    2: setX(953)
    Sender: 0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe [ CREATOR ]
    Value: 0

    3: verifyPrimeness()
    Sender: 0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe [ CREATOR ]
    Value: 0

Oh no! 1021 x 953 = 973013, better pick a different number ๐Ÿ™„

Example 2: Integer precision bug

Source: Sigma Prime

Here is a simple contract for buying and selling tokens. What could possibly go wrong?

pragma solidity ^0.5.0;

contract FunWithNumbers {
    uint constant public tokensPerEth = 10;
    uint constant public weiPerEth = 1e18;
    mapping(address => uint) public balances;

    function buyTokens() public payable {
        uint tokens = msg.value/weiPerEth*tokensPerEth; // convert wei to eth, then multiply by token rate
        balances[msg.sender] += tokens;
    }

    function sellTokens(uint tokens) public {
        require(balances[msg.sender] >= tokens);
        uint eth = tokens/tokensPerEth;
        balances[msg.sender] -= tokens;
        msg.sender.transfer(eth*weiPerEth); 
    }
}

Better safe than sorry! Let's check some contract invariants just to be 1,700% sure that everything works as expected.

$ sabre check funwithnumbers.sol 
--------------------
ASSERTION VIOLATION!
/Users/bernhardmueller/Desktop/funwithnumbers.sol: from 47:17 to 47:131

AssertionFailed("Invariant violation: Sender token balance must increase when contract account balance increases")
--------------------
Call sequence:

    1: buyTokens()
    Sender: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa3 [ USER ]
    Value: 6

--------------------
ASSERTION VIOLATION!
/Users/bernhardmueller/Desktop/funwithnumbers.sol: from 56:17 to 56:131

AssertionFailed("Invariant violation: Contract account balance must decrease when sender token balance decreases")
--------------------
Call sequence:

    1: buyTokens()
    Sender: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0 [ USER ]
    Value: 1000000000000000000

    2: sellTokens(6)
    Sender: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa0 [ USER ]
    Value: 0

Um what?? Fractional numbers are rounded down ๐Ÿ˜ฒ

Example 3: Arbitrary storage write

Source: Ethernaut (I made this a bit more complex)

This smart contract has, and will always have, only one owner. There isn't even a transferOwnership function. But... can you be really sure? Don't you at least want to double-check with a high-level, catch-all invariant?

contract VerifyRegistrar is Registrar {
    
    modifier checkInvariants {
        address old_owner = owner;
        _;
        assert(owner == old_owner);
    }
    
    function register(bytes32 _name, address _mappedAddress) checkInvariants public {
        super.register(_name, _mappedAddress);
    }
}

Let's check just to be 15,000% sure.

$ sabre check registrar.sol 
โœ” Loaded solc v0.4.25 from local cache
โœ” Compiled with solc v0.4.25 successfully
โœ” Analysis job submitted: https://dashboard.mythx.io/#/console/analyses/e98a345e-7418-4209-ab99-bffdc2535d9b
--------------------
ASSERTION VIOLATION!
/Users/bernhardmueller/Desktop/registrar.sol: from 40:8 to 40:34

assert(owner == old_owner)
--------------------
Call sequence:

    1: register(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 0x0000000000000000000000000000000000000000)
    Sender: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [ USER ]
    Value: 0

Ooops... better initialize those structs before using them.

Example 4: Pausable token

Source: TrailofBits

Smart contracts get hacked all the time so it's always great to have a pause button, even if it's just a simple token . This is even an off-switch if we pause the token and throw away the admin account? Or is it?

Why not create an instance of the contract that's infinitely paused and check if there's any way to unpause it.

contract VerifyToken is Token {

    event AssertionFailed(string message);

    constructor() public {
        paused();
        owner = address(0x0); // lose ownership
    }
     
     function transfer(address to, uint value) public {
        uint256 old_balance = balances[msg.sender];

        super.transfer(to, value);

        if (balances[msg.sender] != old_balance) {
            emit AssertionFailed("Tokens transferred even though this contract instance was infinitely paused!!");
        }
     }
}

Given that this contract is forever paused, it should never be possible to transfer any tokens right?

$ sabre check token.sol 
โœ” Loaded solc v0.5.16 from local cache
โœ” Compiled with solc v0.5.16 successfully
โœ” Analysis job submitted: https://dashboard.mythx.io/#/console/analyses/8d4b0eb0-69d3-4d82-b6c6-bc90332a292c
--------------------
ASSERTION VIOLATION!
/Users/bernhardmueller/Desktop/token.sol: from 64:17 to 64:113

AssertionFailed("Tokens transferred even though this contract instance was infinitely paused!!")
--------------------
Call sequence:

    1: Owner()
    Sender: 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef [ ATTACKER ]
    Value: 0

    2: resume()
    Sender: 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef [ ATTACKER ]
    Value: 0

    3: transfer(0x0008000002400240000200104000104080001000, 614153205830163099331592192)
    Sender: 0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe [ CREATOR ]
    Value: 0

Oh no ๐Ÿ˜ต Looks like somebody slipped up there when naming the constructor.

Analysis mode

--mode <quick/standard/deep>

MythX integrates various analysis methods including static analysis, input fuzzing and symbolic execution. In the backend, each incoming analysis job is distributed to a number of workers that perform various tasks in parallel. There are two analysis modes, "quick", "standard" and "deep", that differ in the amount of resources dedicated to the analysis.

Report format

--format <text/stylish/compact/table/html/json>

Select the report format. By default, Sabre outputs a verbose text report. Other options stylish, compact, table, html and json. Note that you can also view reports for past analyses on the dashboard.

Other commands

Besides analyze the following commands are available.

- list              Get a list of submitted analyses.
- status <UUID>     Get the status of an already submitted analysis
- version           Print Sabre Version
- apiVersion        Print MythX API version

Debugging

--debug

Dump the API request and reponse when submitting an analysis.

How it works

Some articles and papers explaining the tech behind that runs in MythX:

sabre's People

Contributors

blitz-1306 avatar eswarasai avatar iamonuwa avatar maurelian avatar muellerberndt avatar skyge avatar tagomaru avatar thec00n avatar yacare555 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

sabre's Issues

Add a batch analysis mode

Description

Add a batch analysis mode that scans multiple Solidity files and produces a combined report.

Implementation

I'm not 100% sure about how to best explore this feature to users. Some options are:

  1. Accept multiple filename/contract, i.e.
$ sabre <file1.sol>[:contractName1] <file2.sol>[:contractName2]

This would allow the user to do bash stuff like find ./ -name "*.sol" | xargs sabre or save the a Sabre command line as a shell script to repeatedly analysis a whole repo.

  1. Accept an input directory, traverse the directory recursively to find and analyze all .sol files.

This would be convenient but would cost the user some control. One question is how we would handle .sol files containing multiple contract classes. We'd probably also need a feature to exclude specific contracts etc.

TypeError: Profiler.resolveAllSources is not a function

Description

Sabre analysis exits with a typeError:

$ $SABRE analyze contracts/TokenSale.sol 
โœ” Downloaded solc v0.7.0 and saved to local cache
โœ– Resolving imports
TypeError: Profiler.resolveAllSources is not a function

Expected behaviour

The analysis should complete successfully.

Imports can't always be resolved

Sabre isn't always able to resolve imports. Apparently, imports can be either relative to the path of the importing file or the current working directory. Also, solc has an "allow-paths" argument which further complicates things.

For example, in this project, there is no way of getting imports working:

$ sabre agreements/ActiveAgreement.sol 
โœ” Compiled with solc v0.4.25 successfully
ActiveAgreement.sol:3:1: ParserError: Source "commons-collections/DataStorage.sol" not found: File import callback not supported
import "commons-collections/DataStorage.sol";
^-------------------------------------------^

ActiveAgreement.sol:4:1: ParserError: Source "commons-collections/AddressScopes.sol" not found: File import callback not supported
import "commons-collections/AddressScopes.sol";
^---------------------------------------------^

ActiveAgreement.sol:5:1: ParserError: Source "commons-events/EventEmitter.sol" not found: File import callback not supported
import "commons-events/EventEmitter.sol";
^---------------------------------------^

ActiveAgreement.sol:6:1: ParserError: Source "documents-commons/Signable.sol" not found: File import callback not supported
import "documents-commons/Signable.sol";
^--------------------------------------^

ActiveAgreement.sol:7:1: ParserError: Source "commons-management/VersionedArtifact.sol" not found: File import callback not supported
import "commons-management/VersionedArtifact.sol";
^------------------------------------------------^

ActiveAgreement.sol:9:1: ParserError: Source "agreements/Agreements.sol" not found: File import callback not supported
import "agreements/Agreements.sol";
^---------------------------------^

This can only be addressed comprehensively by researching the exact imports resolution logic used by solc and setting up a number of test scenarios to verify that all cases are accounted for.

Trial Mode usage return error "TypeError: Cannot read property 'replace' of undefined"

I tried to use Sabre without exporting MYTHX_ETH_ADDRESS and MYTHX_PASSWORD
Before it was working by showing maximum 3 found issues and Mythx Api tral mode message to be one of them. Now any contract analysis failing with
"TypeError: Cannot read property 'replace' of undefined"
if I didn't put MYTHX_ETH_ADDRESS and MYTHX_PASSWORD environment variables.
Would be good to fix it

Passing ASTs to the API

It seems like currently ASTs are not passed to the API as part of the request. Maru will soon require this and it would be great if Sabre supported this (see corresponding changes in Mythos at cleanunicorn/mythos#34).

Add support for --mode argument

Currently Sabre ignores the --mode command line flag and still runs a quick analysis even if full is selected. Add code to select "quick" or "full" mode on the command line.

Definition of Done

Launching an analysis with:

$ sabre --mode full <solidity-file>

Kicks of an analysis in full mode.

TypeError: Cannot read property 'source' of undefined

Description

When passing the absolute path of an input file to Sabre, the analysis fails with the "TypeError: Cannot read property 'source' of undefined".

For example with MythX Playground:

$ sabre /Users/bernhardmueller/Projects/mythx-playground/exercise5/token-with-backdoor.sol 
TypeError: Cannot read property 'source' of undefined

The same works when running analysis from the same directory:

$ cd exercise5
$  sabre token-with-backdoor.sol 
[=== ] Analyzing Token
$ sabre token-with-backdoor.sol 
token-with-backdoor.sol
  15:8  warning  integer overflow  https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-101
   1:0  warning  No pragma is set  https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-103

โœ– 2 problems (0 errors, 2 warnings)

Expected behavior

Should work in both situations.

Incorrect documentation links in output

I run these 2 simple contracts with Sabre on Ubuntu 16.04:

sabre contracts/MetaCoin.sol 

contracts/MetaCoin.sol
  -1:0  warning  MythX API trial mode  ๏ฟฝ]8;;https://smartcontractsecurity.github.io/SWC-registry/docs/๏ฟฝ]8;;

โœ– 1 problem (0 errors, 1 warning)

sap1ens@sap1ens:~/MetaCoin$ sabre contracts/
ConvertLib.sol                Migrations.sol                storage.sol                   typo_safe_math.sol            visibility_not_set.sol        
MetaCoin.sol                  .placeholder                  typo_one_command.sol          visibility_not_set_fixed.sol  .vscode/                      
sap1ens@sap1ens:~/MetaCoin$ sabre contracts/ConvertLib.sol 

contracts/ConvertLib.sol
   1:0  warning  A floating pragma is set  ๏ฟฝ]8;;https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-103SWC-103๏ฟฝ]8;;
  -1:0  warning  MythX API trial mode      ๏ฟฝ]8;;https://smartcontractsecurity.github.io/SWC-registry/docs/๏ฟฝ]8;;

โœ– 2 problems (0 errors, 2 warnings)

So there are 3 issues:

  1. All links have these weird ๏ฟฝ]8;; prefix and postfix on links
  2. Mythx API trial mode link https://smartcontractsecurity.github.io/SWC-registry/docs/ is not exist
  3. Link to issue about pragma also has incorrect link of https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-103SWC-103

Failing test: 'eslint format issues for contract token.sol'

ESlint Issues Format Tests fails with the error 'eslint format issues for contract token.sol'.

How to reproduce

$ npm test

> [email protected] test /Users/bernhardmueller/Projects/sabre
> nyc mocha



  Contracts Compilation Test
    โœ“ compiling contract ConvertLib.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract ERC721.sol
    โœ“ compiling contract MetaCoin.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract Migrations.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract OwnedToken.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract TokenSale.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract empty.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract external-lib.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract import.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract no-pragma.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract token.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract use-external-lib.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }
    โœ“ compiling contract vulnerable.sol
{ AssertionError: expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:51:32)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected 'expected false to be true' to equal 'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.'",
  showDiff: true,
  actual: 'expected false to be true',
  expected:
   'โœ– Compiling the Solidity code did not return any bytecode. Note that abstract contracts cannot be analyzed.' }

  ESlint Issues Format Test
    โœ“ eslint format issues for contract token.sol
{ AssertionError: expected { Object (mythxIssue, mythxTextLocations, ...) } to have property 'line' of 13, but got -1
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:85:24)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected { Object (mythxIssue, mythxTextLocations, ...) } to have property 'line' of 13, but got -1",
  showDiff: true,
  actual: -1,
  expected: 13 }
{ AssertionError: expected { Object (mythxIssue, mythxTextLocations, ...) } to have property 'line' of 13, but got -1
    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:85:24)
    at processTicksAndRejections (internal/process/task_queues.js:86:5)
  message:
   "expected { Object (mythxIssue, mythxTextLocations, ...) } to have property 'line' of 13, but got -1",
  showDiff: true,
  actual: -1,
  expected: 13 }
    1) eslint format issues for contract token.sol

  14 passing (2s)
  1 failing

  1) ESlint Issues Format Test
       eslint format issues for contract token.sol:
     Uncaught Error: the string "abort({\"name\":\"AssertionError\",\"message\":\"expected { Object (mythxIssue, mythxTextLocations, ...) } to have property 'line' of 13, but got -1\",\"showDiff\":true,\"actual\":-1,\"expected\":13,\"stack\":\"AssertionError: expected { Object (mythxIssue, mythxTextLocations, ...) } to have property 'line' of 13, but got -1\\n    at Profiler.resolveAllSources.then.resolved (/Users/bernhardmueller/Projects/sabre/test/sabre.test.js:85:24)\\n    at processTicksAndRejections (internal/process/task_queues.js:86:5)\"}). Build with -s ASSERTIONS=1 for more info." was thrown, throw an Error :)
      at processEmit [as emit] (node_modules/signal-exit/index.js:155:32)
      at process._fatalException (internal/process/execution.js:123:25)

Expected behaviour

Tests should be fixed or modified to match new response format.

Downloading solc failed (error parsing compiler version)

Downloading solc fails with the following input contract:

pragma solidity >=0.4.24;

contract Test {
    
}

Output:

$ sabre test.sol 
โœ– Downloading solc v>=0.4.24 failed
Error: Error retrieving binary: Not Found

Expected behavior

Use the latest compiler version when >= is used in the pragma.

Add support for multiple contracts

Description

Figure out how solc-js and sabre handle different cases like below:

  • Multiple separate contracts in a single file
  • Base contract and inherited contract in the same file
  • Base contract in an imported file

Allow user to select contract to analyze

Add an extra optional argument that allows the user to specify a contract name for analysis. I.e.:

$ sabre [options] <solidity_file> [contract_name]

Expected behavior:

  1. If the user omits the contract name, behave as usual: Analyze the contract with the largest bytecode, or the only contract if only one is returned.
  2. If a contract name is specified, attempt to submit the bytecode of that contract for analysis. Exit with an error message if no contract of that name exists.

Add support for MYTHX_ACCESS_TOKEN and recommend it as default mode of authentication

Currently Sabre only supports MYTHX_ETH_ADDRESS + MYTHX_PASSWORD for authentication. Add support for MYTHX_ACCESS_TOKEN and update the documentation to make usage of MYTHX_ACCESS_TOKEN the default option.

Background

We now recommend using the lower-privileged MYTHX_ACCESS_TOKEN with external tools instead of exposing username and password. The tokens are generated on the MythX dashboard and allow access to analysis functionality only.

Definition of Done

  • Sabre is capable of reading MYTHX_ACCESS_TOKEN from the environment or from the --access-token command line argument and authenticate using the token.
  • README is updated with the recommendation of setting the MYTHX_ACCESS_TOKEN environment variable instead of MYTHX_ETH_ADDRESS + MYTHX_PASSWORD.

The behaviour should be identical to MythX-CLI:

https://mythx-cli.readthedocs.io/en/latest/usage.html#authentication

Incorrect issue titles in text output

Description

In text output format, every issue is titled as "Exception State". E.g.

$ sabre WalletLibDemo.sol 
[    ] Downloading solc v0.4.25(node:48147) V8: :3 Invalid asm.js: Invalid member of stdlib
โœ” Compiled with solc v0.4.25 successfully
==== Exception State ====
Severity: High
File: /Users/bernhardmueller/Library/Mobile Documents/com~apple~CloudDocs/MythX-Testing/WalletLibDemo.sol
Link: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-101
-------------------------
The binary addition can overflow.
The operands of the addition operation are not sufficiently constrained. The addition could therefore result in an integer overflow. Prevent the overflow by checking inputs or ensure sure that the overflow is caught by an assertion.
-------------------------
Location: from 135:2 to 145:3

function initMultiowned(address[] _owners, uint _required) only_uninitialized {
    m_numOwners = _owners.length + 1;
    m_owners[1] = uint(msg.sender);
    m_ownerIndex[uint(msg.sender)] = 1;
    for (uint i = 0; i < _owners.length; ++i)
    {
      m_owners[2 + i] = uint(_owners[i]);
      m_ownerIndex[uint(_owners[i])] = 2 + i;
    }  
        m_required = _required;
  }

==== Exception State ====
Severity: High
File: /Users/bernhardmueller/Library/Mobile Documents/com~apple~CloudDocs/MythX-Testing/WalletLibDemo.sol
Link: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-106
-------------------------
The contract can be killed by anyone.
Anyone can kill this contract and withdraw its balance to an arbitrary address.
-------------------------
Location: from 162:4 to 162:16

suicide(_to)

==== Exception State ====
Severity: Medium
File: /Users/bernhardmueller/Library/Mobile Documents/com~apple~CloudDocs/MythX-Testing/WalletLibDemo.sol
Link: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-111
-------------------------
Use of disallowed function "suicide()"
"suicide()" is disallowed as of Solidity version 0.5.0, use "selfdestruct()" instead.
-------------------------
Location: from 162:4 to 162:16

suicide(_to)

==== Exception State ====
Severity: Low
File: /Users/bernhardmueller/Library/Mobile Documents/com~apple~CloudDocs/MythX-Testing/WalletLibDemo.sol
Link: https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-103
-------------------------
A floating pragma is set.
It is recommended to make a conscious choice on what version of Solidity is used for compilation. Currently multiple versions "^0.4.25" are allowed.
-------------------------
Location: from 12:0 to 12:24

pragma solidity ^0.4.25;

Expected Behavior

The contents of the swcTitle response field should be used as title.

Affected version

  • Sabre v0.7.1

SyntaxError: Unexpected end of input

I'm getting a compiler error for several test contracts. E.g.:

pragma solidity 0.4.25;

contract SimpleDAO {
  mapping (address => uint) public credit;
    
  function donate(address to) payable public{
    credit[to] += msg.value;
  }
    
  function withdraw(uint amount) public{
    if (credit[msg.sender]>= amount) {
      require(msg.sender.call.value(amount)());
      credit[msg.sender]-=amount;
    }
  }  

  function queryCredit(address to) view public returns(uint){
    return credit[to];
  }
}
$ sabre TokenSaleChallenge.sol 
โœ” Compiled with solc v0.4.25 successfully
โœ– Compilation with solc v0.4.25 failed
SyntaxError: Unexpected end of input

Change output to ESLint format

Currently, sabre simply dumps the API response to stdout. Change this to standard linter output format as used in Truffle Security, which is based on the ESLint format.

For example, here is the output for the EtherBank smart contract:

$ truffle run verify --no-progress

/Etherbank.sol
   1:0   warning  A floating pragma is set                       SWC-103
  17:42  warning  A call to a user-supplied address is executed  SWC-107
  30:4   error    The binary addition can overflow               SWC-101

โœ– 3 problems (1 error, 2 warnings)

Note that this needs requires the src field of each issue to be converted to a line and column number. src conforms to the solc source mapping format. Truffle security uses remix-lib to do the conversion which might be a shortcut.

Clean up the code, add tests and CI

Sabre was written as a proof-of-concept. Improve the code to fulfill professional standard, including:

  • Fix linter errors
  • Re-architect code if necessary (move stuff into libraries, etc.)
  • Add tests for all functionality (100% coverage if possible)
  • Set up integration tests with CircleCI
  • Set up automatic publishing of new releases to npm
  • Handle user errors and provide informative error messages
  • Document all available command line arguments in the README

Add Mythril-style transaction traces to text output

Description

Mythril outputs a transaction trace for each vulnerability discovered. For example consider this input contract:

Mythril output:

$ myth analyze simple_suicide.sol 
==== Unprotected Selfdestruct ====
SWC ID: 106
Severity: High
Contract: SimpleSuicide
Function name: sudicideAnyone()
PC address: 77
Estimated Gas Usage: 121 - 216
The contract can be killed by anyone.
Anyone can kill this contract and withdraw its balance to an arbitrary address.
--------------------
In file: simple_suicide.sol:4

selfdestruct(msg.sender)

--------------------
Initial State:

Account: [CREATOR], balance: 0x1, nonce:0, storage:{}
Account: [ATTACKER], balance: 0x1, nonce:0, storage:{}
Account: [SOMEGUY], balance: 0x0, nonce:0, storage:{}

Transaction Sequence:

Caller: [CREATOR], data: [CONTRACT CREATION], value: 0x0
Caller: [ATTACKER], function: sudicideAnyone(), txdata: 0xa56a3b5a, value: 0x0

Replicate this behaviour in Sabre using the steps returned by MythX in the "extra" field:

$ sabre --debug simple_suicide.sol
(...)
            extra:
             { testCases:
                [ { initialState:
                     { accounts:
                        { '0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe': { nonce: 0, balance: '0x0', code: '', storage: {} },
                          '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef': { nonce: 0, balance: '0x0', code: '', storage: {} } } },
                    steps:
                     [ { address: '',
                         gasLimit: '0x7d000',
                         gasPrice: '0x773594000',
                         input:
                          '0x6080604052348015600f57600080fd5b50606480601d6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063a56a3b5a14602d575b600080fd5b60336035565b005b33fffea165627a7a7230582079629b9b52f5964a07d1503c072e929663e6e4cc5db41256f159c865605ce7450029',
                         origin: '0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe',
                         value: '0x0',
                         blockCoinbase: '0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb',
                         blockDifficulty: '0xa7d7343662e26',
                         blockGasLimit: '0x7d0000',
                         blockNumber: '0x66e393',
                         blockTime: '0x5bfa4639' },
                       { address: '0x901d12ebe1b195e5aa8748e62bd7734ae19b51f',
                         gasLimit: '0x7d000',
                         gasPrice: '0x773594000',
                         input: '0xa56a3b5a',
                         origin: '0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef',
                         value: '0x0',
                         blockCoinbase: '0xcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcbcb',
                         blockDifficulty: '0xa7d7343662e26',
                         blockGasLimit: '0x7d0000',
                         blockNumber: '0x66e393',
                         blockTime: '0x5bfa4639' } ] } ] },
            decodedLocations: null },

^^ In the output above there are three steps. The input field of each step contains the transaction data to be displayed.

Expected behaviour

If the 'testCases' field is present in the API response, display a each step in a similar format to Mythril:

  • Function Name (can be determined from the initial 4 bytes
  • Sender (see below)
  • Calldata
  • Call value

Address conventions

  • Creator address: 0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe
  • Other users: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[0-9a-fA-F]
  • Attacker (optional, only if the tool is sure): 0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef

Notes:

  • Do not display the contract creation transaction;
  • Note that Maru does no not return transaction data.

Compiler warnings printed to stderr

Sabre prints compiler warnings in some cases. BecToken for example:

$ sabre BECToken/BECToken.sol 
(node:14221) V8: soljson-v0.4.16+commit.d7661dd9.js:3 Invalid asm.js: Invalid member of stdlib

Note that the analysis still completes successfully.

Expected Behaivour

Hide those warnings from the user as they aren't relevant for the outcome of the analysis.

Dependency issue: Cannot find module '@truffle/provisioner'

A fresh installation of Sabre 0.10.2 throws an error when running the 'analyze' command.

$ sabre analyze contracts/MetaCoin.sol 
Error: Cannot find module '@truffle/provisioner'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:668:15)
    at Function.Module._load (internal/modules/cjs/loader.js:591:27)
    at Module.require (internal/modules/cjs/loader.js:723:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/Users/bernhardmueller/.nvm/versions/node/v11.15.0/lib/node_modules/sabre-mythx/node_modules/@truffle/resolver/lib/resolver.ts:3:19)
    at Module._compile (internal/modules/cjs/loader.js:816:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)
    at Function.Module._load (internal/modules/cjs/loader.js:620:12)
    at Module.require (internal/modules/cjs/loader.js:723:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/Users/bernhardmueller/.nvm/versions/node/v11.15.0/lib/node_modules/sabre-mythx/node_modules/@truffle/resolver/lib/index.ts:3:1)
    at Module._compile (internal/modules/cjs/loader.js:816:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)
    at Function.Module._load (internal/modules/cjs/loader.js:620:12)
    at Module.require (internal/modules/cjs/loader.js:723:19)
    at require (internal/modules/cjs/helpers.js:14:16)
    at Object.<anonymous> (/Users/bernhardmueller/.nvm/versions/node/v11.15.0/lib/node_modules/sabre-mythx/lib/controllers/analyze.js:7:18)
    at Module._compile (internal/modules/cjs/loader.js:816:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:827:10)
    at Module.load (internal/modules/cjs/loader.js:685:32)

** Expected behaviour

Should run normally.

Imports with relative path break in AragonOS project

Running Sabre on the AragonOS smart contracts throws an error:

$ pwd
/MythX-Testing/aragonOS/contracts
$ sabre apps/AppStorage.sol 
โœ” Downloaded solc v0.4.24 successfully
kernel/IKernel.sol:7:1: ParserError: Source "acl/IACL.sol" not found: Import acl/IACL.sol not found
import "../acl/IACL.sol";
^-----------------------^

kernel/IKernel.sol:8:1: ParserError: Source "common/IVaultRecoverable.sol" not found: Import common/IVaultRecoverable.sol not found
import "../common/IVaultRecoverable.sol";
^---------------------------------------^

Expected behavior

The imports should be processed correctly.

Support relative paths in imports

Currently the following scenario is not supported:

imported.sol
files/
   import.sol

In import.sol:

  import "../imported.sol";

Returns the following error:

**$ sabre files/imports.sol 
โœ” Downloaded solc v0.5.0 successfully
inputfile:5:1: ParserError: Source "import3.sol" not found: ENOENT: no such file or directory, stat 'files/import3.sol'
import "../import3.sol";
^----------------------^
**

Expected behavior

Files in relative paths outside the base directory should be imported correctly.
It might be necessary to flatten the code explicitly if solcjs doesn't support this (see e.g. here).

TypeError: Cannot read property 'replace' of undefined error on simple contract analysis

I tried to analyze following demo contract https://github.com/ConsenSys/truffle-webpack-demo/blob/master/contracts/ConvertLib.sol with MYTHX_ETH_ADDRESS and MYTHX_PASSWORD env variables set properly.
Result is

sabre contracts/ConvertLib.sol 
โœ” Compiled with solc v0.4.25 successfully
TypeError: Cannot read property 'replace' of undefined

this is pretty simple contract which failed without any reason.
Please fix it

Optimize download compiler version.

At the current version, I notice that, in the package.json, we use solc dependency to compile the contract,

"dependencies": {
    "solc": "^0.5.7",
  },

so if we specify version at here, we should always update it manually when the solc version becomes 0.5.8, 0.5.9 and so on. So I think we should download the required version automatically.

Error loading formatter when running Sabre command line tool

Description

The Sabre CLI fails with an error message when installed via npm:

$ sabre simple_suicide.sol 
โœ” Compiled with solc v0.5.7 successfully
โœ– Analysis failed
Error: There was a problem loading formatter: /Users/bernhardmueller/Library/Mobile Documents/com~apple~CloudDocs/MythX-Testing/lib/formatters/text
Error: Cannot find module '/Users/bernhardmueller/Library/Mobile Documents/com~apple~CloudDocs/MythX-Testing/lib/formatters/text'

The command line tool should work from any directory.

Sabre picks incorrect compiler version

When pragma is set to a fixed version, Sabre attempts to compile with a later release which fails. E.g.:

suicide.sol:

pragma solidity 0.4.24;

contract Suicide {

  function kill(address addr) public {
    if (addr == address(0x0)) {
      selfdestruct(addr);
    }
  }

}

Output:

$ sabre solidity_examples/suicide.sol 
โœ” Compiled with solc v0.4.25 successfully
inputfile:1:1: SyntaxError: Source file requires different compiler version (current compiler is 0.4.25+commit.59dbf8f1.Emscripten.clang - note that nightly builds are considered to be strictly less than the released version
pragma solidity 0.4.24;
^---------------------^

Refactor the command line interface to be identical to MythX-CLI

Sabre currently only supports a single use-case: Launch an analysis and retrieve the report. The Python MythX CLI command interface allows more comprehensive access to the functionality of MythX. Refactor Sabre to largely implement the same commands as MythX CLI.

Definition of Done:

Change Sabre command line syntax from:

  • sabre <Solidity file> [contract_name]

To:

  • analyze <Solidity file> [contract_name] : Analyse the smart contract, same behaviour as calling Sabre without any command.
  • list: Get a list of submitted analyses.
  • report <UUID> Fetch the report for a single or multiple job UUIDs.
  • status <UUID> Get the status of an already submitted analysis.
  • version Display API version information.

See also:

https://mythx-cli.readthedocs.io/en/latest/usage.html#the-analysis-functionality
https://docs.mythx.io/en/latest/building-security-tools/index.html
https://api.mythx.io/v1/openapi

Source map does not resolve correctly for imported vulnerable contracts

We have a 2 contract setup, in which the main contract inherits a vulnerable contract:

vulnerableImport.sol

pragma solidity 0.5.0;

import "./imported.sol";

contract C is Imported {}

imported.sol

pragma solidity 0.5.0;

contract Imported {
    function f() public {
        selfdestruct(msg.sender);
    }
}

Scanning finds the correct selfdestruct problem:

$ sabre ./vulnerableImport.sol
โœ” Compiled with solc v0.5.0 successfully
[    ] Analyzing C(node:30670) V8: :3 Invalid asm.js: Invalid member of stdlib

./vulnerableImport.sol
  6:2  error  The contract can be killed by anyone  https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-106

โœ– 1 problem (1 error, 0 warnings)

However the source mapping does not point to the correct line number. Reported location is 6:2 but line 6 does not exist in the vulnerableImport.sol file.

Observation
Doing a few more tests I found an interesting behavior. Adding an extra empty line in the vulnerable contract (before the vulnerable code) will increase 6:2 to 6:3.

Make reports more verbose

Output a verbose text report by default that also includes the full description of the issue as well the vulnerable code snippet.

Definition of done

A new report format called text has been added that outputs the following for each issue.

  • Head
  • Description
  • Affected file and line in file
  • Code snippet
  • SWC Link

Example (but can be formatted better):

==== Exception State ====
Severity: Low
File: Simplest
A reachable exception has been detected.
It is possible to trigger an exception (opcode 0xfe). Exceptions can be caused by type errors, division by zero, out-of-bounds array access, or assert violations. Note that explicit `assert()` should only be used to check invariants. Use `require()` for regular input checking.
--------------------
In file: lol.sol:6

assert(keccak256(abi.encodePacked(keccak256(abi.encodePacked(keccak256(abi.encodePacked('abc')))))) ==
keccak256(abi.encodePacked(x)))

--------------------

Add support for npm-style imports

Description

Currently, sabre cannot handle imports such as the ones used in the 0x project. For instance this fails:

$ sabre contracts/coordinator/contracts/src/Coordinator.sol 
โœ– Resolving imports failed
Could not find @0x/contracts-utils/contracts/src/LibBytes.sol from any sources; imported from /Users/bernhardmueller/0x-monorepo/contracts/coordinator/contracts/src/MixinSignatureValidator.sol

Due to the line:

import "tso/contracts-utils/contracts/src/LibBytes.sol";

Expected Behaviour

The import should be successfully resolved.

Merge solfuzz functionality into Sabre

Recently MythX introduced a new property checking mode that searches more efficientl for assertion violations. I made a tool specifically for that mode, however it would be better to merge this functionality into Sabre.

This would introduce a new "check" command:

$ sabre check <solidity-file> [contract-name]

With the following differences:

  1. Set propertyChecking to true when submitting the request
  2. Only report issue of type SWC-110.

The text report should also look different, e.g.:

$ solfuzz check primality.sol
--------------------
ASSERTION VIOLATION!
/Users/bernhardmueller/Desktop/primality.sol: from 21:8 to 21:33

assert(x*y != largePrime)
--------------------
Call sequence:

    1: setY(1021)
    Sender: 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa [ USER ]
    Value: 0

    2: setX(953)
    Sender: 0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe [ CREATOR ]
    Value: 0

    3: verifyPrimeness()
    Sender: 0xaffeaffeaffeaffeaffeaffeaffeaffeaffeaffe [ CREATOR ]
    Value: 0

See the solfuzz README for more examples.

** Requirements for completion**

  • New check command added and works as described above;
  • Test for check command added.

Sample contract failing to be match for required pattern

Standard truffle contracts unboxed with https://truffleframework.com/docs/truffle/getting-started/creating-a-project return error with Sabre:

sabre contracts/MetaCoin.sol 
Bad data in analysis-request JSON:
In contract MetaCoin:
* field "bytecode" with value "608060405234801561001057600080fd5b50326000908152602081905260409020612710905561024b806100346000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a111461007e578063f8b2cb4f146100be575b600080fd5b61006c6004803603602081101561005c57600080fd5b50356001600160a01b03166100e4565b60408051918252519081900360200190f35b6100aa6004803603604081101561009457600080fd5b506001600160a01b038135169060200135610178565b604080519115158252519081900360200190f35b61006c600480360360208110156100d457600080fd5b50356001600160a01b0316610204565b600073__$c1e9661f796f9214b5c8076e394fd5a419$__6396e4ee3d61010984610204565b60026040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561014657600080fd5b505af415801561015a573d6000803e3d6000fd5b505050506040513d602081101561017057600080fd5b505192915050565b33600090815260208190526040812054821115610197575060006101fe565b33600081815260208181526040808320805487900390556001600160a01b03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35060015b92915050565b6001600160a01b03166000908152602081905260409020549056fea165627a7a723058204870795535bc4f787f5cf8ad43aa2639bfc2dc28f1700ad9c97f8cd5853dd3220029" fails to match the required pattern: /^(0x)?([0-9a-fA-F]{2})+$/
* field "deployedBytecode" with value "608060405234801561001057600080fd5b50600436106100415760003560e01c80637bd703e81461004657806390b98a111461007e578063f8b2cb4f146100be575b600080fd5b61006c6004803603602081101561005c57600080fd5b50356001600160a01b03166100e4565b60408051918252519081900360200190f35b6100aa6004803603604081101561009457600080fd5b506001600160a01b038135169060200135610178565b604080519115158252519081900360200190f35b61006c600480360360208110156100d457600080fd5b50356001600160a01b0316610204565b600073__$c1e9661f796f9214b5c8076e394fd5a419$__6396e4ee3d61010984610204565b60026040518363ffffffff1660e01b8152600401808381526020018281526020019250505060206040518083038186803b15801561014657600080fd5b505af415801561015a573d6000803e3d6000fd5b505050506040513d602081101561017057600080fd5b505192915050565b33600090815260208190526040812054821115610197575060006101fe565b33600081815260208181526040808320805487900390556001600160a01b03871680845292819020805487019055805186815290519293927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef929181900390910190a35060015b92915050565b6001600160a01b03166000908152602081905260409020549056fea165627a7a723058204870795535bc4f787f5cf8ad43aa2639bfc2dc28f1700ad9c97f8cd5853dd3220029" fails to match the required pattern: /^(0x)?([0-9a-fA-F]{2})+$/

Please check and fix. I'm getting this in Ubuntu and MacOs environments

Display job UUID as soon as job has been submitted

Display the UUID of the job once it has been submitted / queued. This allows the user to obtain the result later if the job fails for any reason (or the user aborts it with CTRL+C, etc.).

This could look like:

$ sabre contracts/token.sol 
โœ” Compiled with solc v0.5.10 successfully
โœ” Submitted MythX with job id 5f74034b-7c1c-4079-8240-0a5a522d31b5
[  ==] Analyzing Token

Incorrect source maps

Incorrect source mappings are sometimes reported. This issue was first reported by @glesaint in the MythX plugin for Truffle.

E.g. ERC 20 TokenTimelock.sol:

$ sabre TokenTimelock.sol

utils/Address.sol
27:263  warning  Multiple sends are executed in one transaction  https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-113
math/SafeMath.sol
66:1307  warning  The contract executes an external message call  https://smartcontractsecurity.github.io/SWC-registry/docs/SWC-107

This issue was fixed in MythX-Truffle with PR 185.

Error in regular expression

When I try to scan my contracts I get the following error:

SyntaxError: Invalid regular expression: /(?<line>\d+):(?<col>\d+):(?<source>\d+)/: Invalid group

It raises in lib/helpers.js, line 131

So, I had to change this line into

const sourceMapRegex = /(\d+):(\d+):(\d+)/g;

My node version is v8.10.0

Moreover, there is one more problem:
The numbers of lines are incorrect in my scan. I suppose it is because of multi-line comments and NatSpec comments (ones starting with /** ).

Issues reported for compiler gen'd code

If the mythx api returns an issue with a sourcemap like "x:x:-1" then this indicates an issue in compiler generated code.

Currently it seems like this case isn't treated in sabre

Cache solc versions

Currently, sabre re-downloads the required compiler version with every run. Instead, each version should be downloaded at most once. Either:

  • Find a way of caching compiler versions so that already downloaded versions can be re-used
  • Add the latest minor releases to dependencies and always use 0.4.25 for 0.4.x / 0.5.7 for 0.5.x. This is easier but less precise and requires updating whenever a new solc version is released.

Bad data in analysis-request JSON

I tried Sabre with open source contract
https://github.com/cryptocopycats/awesome-cryptokitties/blob/master/contracts/ERC721.sol
which failed like:

sabre contracts/ERC721.sol 
Bad data in analysis-request JSON:
In contract ERC721:
* field "bytecode" is not allowed to be empty
* field "bytecode" with value "" fails to match the required pattern: /^(0x)?([0-9a-fA-F]{2})+$/
* field "deployedBytecode" is not allowed to be empty
* field "deployedBytecode" with value "" fails to match the required pattern: /^(0x)?([0-9a-fA-F]{2})+$/
* field "sourceMap" is not allowed to be empty
* field "deployedSourceMap" is not allowed to be empty

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.