Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add more heuristics for compiler version detection #307

Open
github-actions bot opened this issue Jan 26, 2024 · 2 comments
Open

add more heuristics for compiler version detection #307

github-actions bot opened this issue Jan 26, 2024 · 2 comments
Assignees
Labels
T-todo Type: todo todo

Comments

@github-actions
Copy link
Contributor

New Codebase TODO

add more heuristics for compiler version detection

Location

// TODO: add more heuristics for compiler version detection

use std::fmt::Display;

use crate::{debug_max, utils::iter::ByteSliceExt};

#[derive(Debug, PartialEq, Clone)]
pub enum Compiler {
    Solc,
    Vyper,
    Proxy,
    Unknown,
}

impl Display for Compiler {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Compiler::Solc => write!(f, "solc"),
            Compiler::Vyper => write!(f, "vyper"),
            Compiler::Proxy => write!(f, "proxy"),
            Compiler::Unknown => write!(f, "unknown"),
        }
    }
}

// returns the compiler version used to compile the contract.
// for example: (solc, 0.8.10) or (vyper, 0.2.16)
pub fn detect_compiler(bytecode: &[u8]) -> (Compiler, String) {
    let mut compiler = Compiler::Unknown;
    let mut version = "unknown".to_string();

    // perfom prefix check for rough version matching
    if bytecode.starts_with(&[0x36, 0x3d, 0x3d, 0x37, 0x3d, 0x3d, 0x3d, 0x36, 0x3d, 0x73]) ||
        bytecode.starts_with(&[0x5f, 0x5f, 0x36, 0x5f, 0x5f, 0x37])
    {
        compiler = Compiler::Proxy;
        version = "minimal".to_string();
    } else if bytecode.starts_with(&[
        0x36, 0x60, 0x00, 0x60, 0x00, 0x37, 0x61, 0x10, 0x00, 0x60, 0x00, 0x36, 0x60, 0x00, 0x73,
    ]) {
        compiler = Compiler::Proxy;
        version = "vyper".to_string();
    } else if bytecode.starts_with(&[0x60, 0x04, 0x36, 0x10, 0x15]) {
        compiler = Compiler::Vyper;
        version = "0.2.0-0.2.4,0.2.11-0.3.3".to_string();
    } else if bytecode.starts_with(&[0x34, 0x15, 0x61, 0x00, 0x0a]) {
        compiler = Compiler::Vyper;
        version = "0.2.5-0.2.8".to_string();
    } else if bytecode.starts_with(&[0x73, 0x1b, 0xf7, 0x97]) {
        compiler = Compiler::Solc;
        version = "0.4.10-0.4.24".to_string();
    } else if bytecode.starts_with(&[0x60, 0x80, 0x60, 0x40, 0x52]) {
        compiler = Compiler::Solc;
        version = "0.4.22+".to_string();
    } else if bytecode.starts_with(&[0x60, 0x60, 0x60, 0x40, 0x52]) {
        compiler = Compiler::Solc;
        version = "0.4.11-0.4.21".to_string();
    } else if bytecode.contains_slice(&[0x76, 0x79, 0x70, 0x65, 0x72]) {
        compiler = Compiler::Vyper;
    } else if bytecode.contains_slice(&[0x73, 0x6f, 0x6c, 0x63]) {
        compiler = Compiler::Solc;
    }

    // TODO: add more heuristics for compiler version detection

    // check for cbor encoded compiler metadata
    // https://cbor.io
    if compiler == Compiler::Solc {
        let compiler_version = bytecode.split_by_slice(&[0x73, 0x6f, 0x6c, 0x63, 0x43]);

        if compiler_version.len() > 1 {
            if let Some(encoded_version) = compiler_version.get(1).and_then(|last| last.get(0..3)) {
                version = encoded_version
                    .into_iter()
                    .map(|v| v.to_string())
                    .collect::<Vec<String>>()
                    .join(".");
            }
@iankressin
Copy link
Contributor

Is this up for grabs?

@Jon-Becker
Copy link
Owner

yessir!!

@Jon-Becker Jon-Becker assigned iankressin and unassigned Jon-Becker May 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-todo Type: todo todo
Projects
None yet
Development

No branches or pull requests

2 participants