A collection of lints to catch common mistakes and improve your Cairo code.

Overview

cairo-lint

Check Workflow Status Telegram

Exploration_Team

A collection of lints to catch common mistakes and improve your Cairo code.

Usage

cairo-lint can either be used as a library or as a standalone binary. It can either just detect or fix the detected problems.

To use it with scarb simply install it like so:

cargo install scarb-cairo-lint --git https://github.com/keep-starknet-strange/cairo-lint

and then either run:

# Checks for bad patterns
scarb cairo-lint
# Checks and fixes what it can
scarb cairo-lint --fix

Note: You can also include test files with the --test flag

Contributors

0xLucqs
0xLucqs

💻
Marco Araya Jiménez
Marco Araya Jiménez

💻 ⚠️
Mathieu
Mathieu

💻 ⚠️ 📖
Lau Chaves
Lau Chaves

💻 ⚠️
Renzo Banegas
Renzo Banegas

?? ⚠️
Steven
Steven

💻 ⚠️
Lindsay Morales
Lindsay Morales

💻 ⚠️
Bernal Hidalgo
Bernal Hidalgo

💻 ⚠️
Charlotte
Charlotte

💻 ⚠️
Bruno Ambricca
Bruno Ambricca

💻 ⚠️
guha-rahul
guha-rahul

💻 ⚠️
Yusuf Habib
Yusuf Habib

💻 ⚠️
Tuan Tran
Tuan Tran

💻 ⚠️
BlockyJ
BlockyJ

💻 ⚠️
Luis Jiménez
Luis Jiménez

💻 ⚠️
Mariángela N.
Mariángela N.

💻 ⚠️
Gianfranco99
Gianfranco99

💻 ⚠️

Contributing

Join the telegram group

To run the tests you'll need to provide the path to the cairo corelib (at some point this should be automated but we're not there yet).

CORELIB_PATH="/path/to/corelib/src" cargo test

Cli instructions

To add a new test you can use the dev cli with:

cargo run --bin create_test <lint_name>

Manual instructions

Each lint should have its own tests and should be extensive. To create a new test for a lint you need to create a file in the test_files folder and should be named as your lint. The file should have this format:

//! > Test name

//! > cairo_code
fn main() {
    let a: Option<felt252> = Option::Some(1);
}

Then in the test file declare your lint like so:

test_file!(if_let, "Test name");

The first argument is the lint name (also the file name) and the other ones are the test names. After that you can run

FIX_TESTS=1 cargo test -p cairo-lint-core <name_of_lint>

This will generate the expected values in your test file. Make sure it is correct.

Comments
  • Add `manual_unwrap_or_default`

    Add `manual_unwrap_or_default`

    What it does

    Checks if a match or if let expression can be simplified using .unwrap_or_default().

    Why is this bad?

    It can be done in one call with .unwrap_or_default().

    Example

    let x: Option<Array<u32>> = Some(array![]);
    let y: Array<u32> = match x {
        Some(v) => v,
        None => Default::default(),
    };
    
    let x: Option<Array<u32>> = Some(ArrayTrait::new());
    let y: Vec<Array<u32>> = if let Some(v) = x {
        v
    } else {
        Default::default()
    };
    

    Use instead:

    let x: Option<Array<u32>> = Some(array![]);
    let y: Array<u32> = x.unwrap_or_default();
    
    let x: Option<Array<u32>> = Some(ArrayTrait::new());
    let y: Array<u32> = x.unwrap_or_default();
    

    (the examples are for arrays but it can work with any type that implements default

    good first issue lint 
    opened by 0xLucqs 10
  • Feat: add comparison_to_empty

    Feat: add comparison_to_empty

    closes #74 @0xLucqs This is a draft PR

    Implementation

    Checks for comparing to an empty slice such as [], and suggests using .is_empty() where applicable.

    opened by Benjtalkshow 9
  • Add `int_plus_one`

    Add `int_plus_one`

    What it does

    Checks for usage of x >= y + 1 or x - 1 >= y (and <=) in a block

    Why is this bad?

    Readability – better to use > y instead of >= y + 1.

    Example

    if x >= y + 1 {}
    

    Use instead:

    if x > y {}
    
    good first issue lint 
    opened by 0xLucqs 6
  • Add `bitwise_for_parity_check`

    Add `bitwise_for_parity_check`

    What it does

    Checks for an expression like n & 1 which is less efficient than DivRem::div_rem(n, 2)

    Why is this bad

    It's less efficient

    Example

    fn main() {
        let a = 200 & 1;
    }
    

    Use instead:

    fn main() {
        let a = DivRem::div_rem(200, 2);
    }
    
    good first issue lint 
    opened by 0xLucqs 6
  • eq_op base implementation

    eq_op base implementation

    eq_op base implementation

    Is not completed. I still have work to do.

    Changes

    1. I added a new file for the eq_op lint.
    2. I created the comparison directory for the eq_op tests.
    3. I added some tests to see the behaviour of the code that I have.
    4. I added the lint in the plugin.rs file.
    opened by Gerson2102 6
  • feat: add ifs_same_cond

    feat: add ifs_same_cond

    Summary 📌 This PR Resolves: https://github.com/keep-starknet-strange/cairo-lint/issues/87

    What it does: This PR introduces a new lint that detects consecutive if statements with the same condition. When two if or else if blocks check the same condition, this could be an indication of a copy & paste error, and this lint helps prevent such mistakes. All tests pass image

    opened by Gianfranco99 5
  • Automate new test creation

    Automate new test creation

    Write a script to automate the test creation process. The steps are the following:

    To create a new test for a lint you need to create a file in the test_files folder and should be named as your lint. The file should have this format:

    //! > Test name
    
    //! > cairo_code
    fn main() {
        let a: Option<felt252> = Option::Some(1);
    }
    

    Then in the test file declare your lint like so:

    test_file!(if_let, "Test name");
    
    good first issue tooling 
    opened by 0xLucqs 5
  • Add `manual_ok_or`

    Add `manual_ok_or`

    What it does

    Finds patterns that reimplement Option::ok_or.

    Why is this bad?

    Concise code helps focusing on behavior instead of boilerplate.

    Examples

    let foo: Option<i32> = None;
    let foo = match foo {
        Option::Some(v) => Result::Ok(v),
        Option::None => Result::Err('this is an err'),
    }
    

    Use instead:

    let foo: Option<i32> = None;
    foo.ok_or('this is an err');
    
    good first issue lint 
    opened by 0xLucqs 4
  • feat: Add collapsible_if

    feat: Add collapsible_if

    Hi @0xLucqs

    Here my progress about the issue #37

    This PR includes the basic structure with the necessary files to implement the collapsible_if lint. Now, I'll be working on the implementation of the lint and the corresponding tests

    opened by jimenezz22 4
  • feat: autofix single imports unused

    feat: autofix single imports unused

    Partially addresses #18

    Handling all types of imports will require more work. One idea: regrouping all diagnostics, filter them by type (UnusedImport), group them by file, and then for each use statement, re-write it without unused imports.

    opened by enitrat 4
  • Add `erasing_op`

    Add `erasing_op`

    What it does

    Checks for erasing operations, e.g., x * 0.

    Why is this bad?

    The whole expression can be replaced by zero. This is most likely not the intended outcome and should probably be corrected

    Example

    let x = 1;
    0 / x;
    0 * x;
    x & 0;
    

    https://rust-lang.github.io/rust-clippy/master/index.html#/erasing_op

    opened by 0xLucqs 4
  • feat: impossible comparison

    feat: impossible comparison

    Resolves: #119

    Catches 8 cases of impossible comparison :

    • x > 500 && x < 400
    • x > 500 && x <= 400
    • x >= 500 && x < 400
    • x >= 500 && x <= 400
    • x < 400 && x > 500
    • x < 400 && x >= 500
    • x <= 400 && x > 500
    • x <= 400 && x >= 500
    opened by chachaleo 2
  • Refacto: lints

    Refacto: lints

    • Remove the overhead of adding a lint
    • Make sure that the rust compiler will display an error if a new lint is added and it's not added in the allow list
    • Make sure diagnostics are not emitted for compiler generated files
    opened by 0xLucqs 0
  • Refacto: fixer

    Refacto: fixer

    Refactor the fixing part of cairo lint to have:

    • improve the fixinig logic
    • make sure that comments do not disappear when fixing a diagnostic because of the get_text_without_trivia
    • properly format the cairo fixed cairo code
    opened by 0xLucqs 0
  • bug: index out of bounds: the len is 0 but the index is 0

    bug: index out of bounds: the len is 0 but the index is 0

    thread 'main' panicked at crates/cairo-lint-core/src/lints/manual/helpers.rs:170:81: index out of bounds: the len is 0 but the index is 0

    Clone the kakarot repo https://github.com/kkrt-labs/kakarot-ssj/pulls and run scarb-cairo-lint -t --fix

    opened by enitrat 1
  • bug : manual lint panic when match expression is a function

    bug : manual lint panic when match expression is a function

    Manual lint fails when the expression in the ExprMatch is a function

    Example :

    #[derive(Copy, Drop)]
    enum Error {
        Error,
    }
    fn main() {
        let self: u256 = 0; 
        let _self_result: Result<u8, Error> = match self.try_into() {
            Option::Some(value) => Result::Ok(value),
            Option::None => Result::Err(Error::Error)
        };
    }
    

    panics with Expected a variable or path in match expression, because self.try_into() is a function and the lint does not support it currently in the fix function

    opened by chachaleo 0
Owner
Keep Starknet Strange
Trailblazors unit of Starknet.
Keep Starknet Strange
A library to help you sew up your Ethereum project with Rust and just like develop in a common backend

SewUp Secondstate EWasm Utility Program, a library helps you sew up your Ethereum project with Rust and just like development in a common backend. The

Second State 48 Dec 18, 2022
Cleaopatra is a Rust implementation of the Cairo VM

Cleopatra Cairo is a Rust implementation of the Cairo VM. Cairo is a programming language for writing provable programs, where one party can prove to another that a certain computation was executed correctly. Cairo and similar proof systems can be used to provide scalability to blockchains.

Lambdaclass 263 Dec 28, 2022
A minimal template for building smart contracts with Cairo 1.0

Minimal Cairo 1.0 Template Built with auditless/cairo-template A minimal template for building smart contracts with Cairo 1.0 using the Quaireaux proj

Auditless 68 Apr 21, 2023
STARK Cairo prover using lambdaworks

STARK Cairo prover using lambdaworks. Cairo (CPU Algebraic Intermediate Representation) is a programming language for writing provable programs, where one party can prove to another that a certain computation was executed correctly. Cairo and similar proof systems can be used to provide scalability to blockchains.

Lambdaclass 18 Jun 13, 2023
deductive verification of Rust code. (semi) automatically prove your code satisfies your specifications!

Le marteau-pilon, forges et aciéries de Saint-Chamond, Joseph-Fortuné LAYRAUD, 1889 About Creusot is a tool for deductive verification of Rust code. I

Xavier Denis 609 Dec 28, 2022
Parser and test runner for testing compatable common Ethereum full node tests against Polygon Zero's EVM.

EVM Test Parses and runs compatible common Ethereum tests from ethereum/tests against Polygon Zero's EVM. Note: This repo is currently very early in d

Mir Protocol 3 Nov 4, 2022
Common cryptographic library used in software at Mysten Labs.

[fastcrypto] fastcrypto is a common cryptography library used in software at Mysten Labs. It is published as an independent crate to encourage reusabi

Mysten Labs 85 Dec 20, 2022
Common protocol for generating ZK proofs for blocks on different blockchains.

Proof Protocol Decoder A flexible protocol that clients (eg. full nodes) can use to easily generate block proofs for different chains. Specification I

Polygon Zero 3 Oct 5, 2023
Bitcoin Push Notification Service (BPNS) allows you to receive notifications of Bitcoin transactions of your non-custodial wallets on a provider of your choice, all while respecting your privacy

Bitcoin Push Notification Service (BPNS) Description Bitcoin Push Notification Service (BPNS) allows you to receive notifications of Bitcoin transacti

BPNS 1 May 2, 2022
A guide for Mozilla's developers and data scientists to analyze and interpret the data gathered by our data collection systems.

Mozilla Data Documentation This documentation was written to help Mozillians analyze and interpret data collected by our products, such as Firefox and

Mozilla 75 Dec 1, 2022
Taking the best of Substrate Recipes and applying them to a new framework for structuring a collection of how-to guides.

Attention: This repository has been archived and is no longer being maintained. It has been replaced by the Substrate How-to Guides. Please use the Su

Substrate Developer Hub 35 Oct 17, 2022
A general solution for commonly used crypt in rust, collection of cryptography-related traits and algorithms.

Crypto-rs A general solution for commonly used crypt in rust, collection of cryptography-related traits and algorithms. This is a Rust implementation

houseme 4 Nov 28, 2022
CosmWasm-Examples is a collection of example contracts and applications built using the CosmWasm framework

CosmWasm-Examples is a collection of example contracts and applications built using the CosmWasm framework. CosmWasm is a secure and efficient smart contract platform designed specifically for the Cosmos ecosystem.

Vitalii Tsyhulov 20 Jun 9, 2023
Collection of cryptographic hash functions written in pure Rust

RustCrypto: hashes Collection of cryptographic hash functions written in pure Rust. All algorithms reside in the separate crates and implemented using

Rust Crypto 1.2k Jan 8, 2023
Dank - The Internet Computer Decentralized Bank - A collection of Open Internet Services - Including the Cycles Token (XTC)

Dank - The Internet Computer Decentralized Bank Dank is a collection of Open Internet Services for users and developers on the Internet Computer. In t

Psychedelic 56 Nov 12, 2022
The Solana Program Library (SPL) is a collection of on-chain programs targeting the Sealevel parallel runtime.

Solana Program Library The Solana Program Library (SPL) is a collection of on-chain programs targeting the Sealevel parallel runtime. These programs a

null 6 Jun 12, 2022
Collection of stream cipher algorithms

RustCrypto: stream ciphers Collection of stream cipher algorithms written in pure Rust. ⚠️ Security Warning: Hazmat! Crates in this repository do not

Rust Crypto 186 Dec 14, 2022
Collection of block cipher algorithms written in pure Rust

RustCrypto: block ciphers Collection of block ciphers and block modes written in pure Rust. Warnings Currently only the aes crate provides constant-ti

Rust Crypto 506 Jan 3, 2023
A collection of algorithms that can do join between two parties while preserving the privacy of keys on which the join happens

Private-ID Private-ID is a collection of algorithms to match records between two parties, while preserving the privacy of these records. We present tw

Meta Research 169 Dec 5, 2022