neo-decompiler 0.6.2

Minimal tooling for inspecting Neo N3 NEF bytecode
Documentation
use std::fmt::Write;

use crate::manifest::ContractManifest;
use crate::nef::NefFile;
use crate::util;

use super::super::super::helpers::format_permission_entry;
use super::super::helpers::escape_csharp_string;

pub(super) fn write_preamble(output: &mut String) {
    writeln!(output, "using System;").unwrap();
    writeln!(output, "using System.Numerics;").unwrap();
    writeln!(output, "using Neo.SmartContract.Framework;").unwrap();
    writeln!(output, "using Neo.SmartContract.Framework.Attributes;").unwrap();
    writeln!(output, "using Neo.SmartContract.Framework.Services;").unwrap();
    writeln!(output).unwrap();
}

pub(super) fn write_contract_open(
    output: &mut String,
    contract_name: &str,
    nef: &NefFile,
    manifest: Option<&ContractManifest>,
) {
    writeln!(output, "namespace NeoDecompiler.Generated {{").unwrap();
    if let Some(manifest) = manifest {
        // Emit all ManifestExtra fields from the extra object.
        if let Some(serde_json::Value::Object(map)) = manifest.extra.as_ref() {
            for (key, value) in map {
                if let Some(s) = value.as_str() {
                    writeln!(
                        output,
                        "    [ManifestExtra(\"{}\", \"{}\")]",
                        escape_csharp_string(key),
                        escape_csharp_string(s)
                    )
                    .unwrap();
                }
            }
        }
        // Emit SupportedStandards as a proper attribute.
        if !manifest.supported_standards.is_empty() {
            let standards = manifest
                .supported_standards
                .iter()
                .map(|s| format!("\"{}\"", escape_csharp_string(s)))
                .collect::<Vec<_>>()
                .join(", ");
            writeln!(output, "    [SupportedStandards({standards})]").unwrap();
        }
    }
    writeln!(output, "    public class {contract_name} : SmartContract").unwrap();
    writeln!(output, "    {{").unwrap();

    let script_hash = nef.script_hash();
    writeln!(
        output,
        "        // script hash (little-endian): {}",
        util::format_hash(&script_hash)
    )
    .unwrap();
    writeln!(
        output,
        "        // script hash (big-endian): {}",
        util::format_hash_be(&script_hash)
    )
    .unwrap();

    if let Some(manifest) = manifest {
        if manifest.features.storage || manifest.features.payable {
            writeln!(output, "        // features:").unwrap();
            if manifest.features.storage {
                writeln!(output, "        //   storage = true").unwrap();
            }
            if manifest.features.payable {
                writeln!(output, "        //   payable = true").unwrap();
            }
        }
        if !manifest.permissions.is_empty() {
            writeln!(output, "        // permissions:").unwrap();
            for permission in &manifest.permissions {
                writeln!(
                    output,
                    "        //   {}",
                    format_permission_entry(permission)
                )
                .unwrap();
            }
        }
        if let Some(trusts) = manifest.trusts.as_ref() {
            writeln!(output, "        // trusts = {}", trusts.describe()).unwrap();
        }
    } else {
        writeln!(output, "        // manifest not provided").unwrap();
    }

    writeln!(output).unwrap();
}

pub(super) fn write_contract_close(output: &mut String) {
    writeln!(output, "    }}").unwrap();
    writeln!(output, "}}").unwrap();
}