Project that allows to search for vulnerabilities in Smart Contracts
=================
The project was developed to provide an API to search for vulnerabilities in smart contracts. It was developed with Node.js and Express, using Husky, lint-staged, eslint, prettier and commitlint with conventional commits.
Currently only two vulnerabilities are supported:
- Unchecked Call Return Value (SWC-104)
- Unprotected SELFDESTRUCT Instruction (SWC-106)
Before starting, you need Node.js, Yarn and Git installed and configured.
# Clone this repository
$ git clone https://github.com/rafaelfl/web3-security-contract-detector
# Enter in the project folder in terminal/cmd
$ cd detector-contract
It's important to have Slither and Mythril tools installed in your system! Please, follow the installation instructions from both sites and make sure the tools are available in the shell's PATH.
After installing the tools and the source code, you can install the dependencies and run the project.
# Install dependencies
$ yarn install
The main (public) configurations are available in the .env
file. Using that file one can customize the default port number and the debug mode (i.e., it should print debugging messages or not).
DEBUG=true
PORT=3000
To use the suggestion API, another (private) configuration file, you should create a .env.local
with the environment variable OPENAI_API_KEY
, containing the api key obtained from OpenAI API web interface. The .env.local
file is included in the .gitignore
, so it won't be stored in the repository.
OPENAI_API_KEY="YOUR API KEY"
After configuring the environment variables and the dependencies, you can run the service.
# Run the project using the following syntax
$ yarn start
The application will be available on http://localhost:3000
.
Some other interesting commands:
yarn clean
- clean the build filesyarn dev
- run the service in watch mode (withnodemon
)yarn build
- build the page for deployingyarn lint
- run the linter to identify some problems in codeyarn lint:fix
- run the linter to identify and fix problems in codeyarn prettier
- run the prettier formatter
Furthermore, the Husky is configured to verify commit messages incompatible with the "Conventional Commits" standard, as well as to run the linter and prettier in the code.
To run the code directly on a Docker container (avoiding to install Slither and Mythril in your local system), you can build and run the current image using the docker-compose
command.
# Build and run the current Docker image
$ docker-compose up -d
Running this command in the project directory begins the installation of all dependencies, builds the image and runs the container.
After having the service running, you can access it through the following endpoints (Swagger documentation page can be accessed through this link: http://localhost:3000/api-docs):
Endpoints:
-
POST
http://localhost:3000/api/v1/scan
- Body:
{ sourceCode: "smart contract source code" }
- Body:
-
POST
http://localhost:3000/api/v1/suggestion
- Body:
{ sourceCode: "smart contract source code" }
- Body:
Some examples of API calls can be imported to Postman and are available here.
Examples using curl
:
- Scan
killbilly.sol
:
curl --location 'http://localhost:3000/api/v1/scan' \
--header 'Content-Type: application/json' \
--data '{
"sourceCode": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.18;\n\ncontract KillBilly {\n\tbool public is_killable;\n\tmapping (address => bool) public approved_killers;\n\n\tconstructor() public {\n\t\tis_killable = false;\n\t}\n\n\tfunction killerize(address addr) public {\n\t\tapproved_killers[addr] = true;\n\t}\n\n\tfunction activatekillability() public {\n\t\trequire(approved_killers[msg.sender] == true);\n\t\tis_killable = true;\n\t}\n\n\tfunction commencekilling() public {\n\t require(is_killable);\n\n // cast address to payable\n address payable addr = payable(msg.sender);\n\n\t \tselfdestruct(addr);\n\t}\n}"
}'
- Scan
returnvalue.sol
:
curl --location 'http://localhost:3000/api/v1/scan' \
--header 'Content-Type: application/json' \
--data '{
"sourceCode": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.18;\n\ncontract ReturnValue {\n address public callee = 0xE0f7e56E62b4267062172495D7506087205A4229;\n\n function callnotchecked() public {\n callee.call(\"\");\n }\n\n function callchecked() public {\n (bool success, bytes memory data) = callee.call(\"\");\n require(success);\n }\n}\n"
}'
- Suggestions
killbilly.sol
:
curl --location 'http://localhost:3000/api/v1/suggestion' \
--header 'Content-Type: application/json' \
--data '{
"sourceCode": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.18;\n\ncontract KillBilly {\n\tbool public is_killable;\n\tmapping (address => bool) public approved_killers;\n\n\tconstructor() public {\n\t\tis_killable = false;\n\t}\n\n\tfunction killerize(address addr) public {\n\t\tapproved_killers[addr] = true;\n\t}\n\n\tfunction activatekillability() public {\n\t\trequire(approved_killers[msg.sender] == true);\n\t\tis_killable = true;\n\t}\n\n\tfunction commencekilling() public {\n\t require(is_killable);\n\n // cast address to payable\n address payable addr = payable(msg.sender);\n\n\t \tselfdestruct(addr);\n\t}\n}"
}'
- Suggestions
returnvalue.sol
:
curl --location 'http://localhost:3000/api/v1/suggestion' \
--header 'Content-Type: application/json' \
--data '{
"sourceCode": "// SPDX-License-Identifier: MIT\npragma solidity >=0.8.18;\n\ncontract ReturnValue {\n address public callee = 0xE0f7e56E62b4267062172495D7506087205A4229;\n\n function callnotchecked() public {\n callee.call(\"\");\n }\n\n function callchecked() public {\n (bool success, bytes memory data) = callee.call(\"\");\n require(success);\n }\n}\n"
}'
- Document the API with Swagger
- Create a docker container for running the service with zero setup
- Unit tests
- Customize plugins source code to allow in-memory operations, avoiding the service to save the files before processing it
Rafael Fernandes Lopes
Developed with 💜 by Rafael Fernandes Lopes