neo-devpack-solidity 0.22.0

Production-focused Solidity-to-NeoVM compilation system
Documentation
#[test]
fn neo_hash_helpers_lower_to_cryptolib_native_calls() {
    let source = r#"
    pragma solidity ^0.8.19;

    contract NeoHashHarness {
        function sha(bytes memory data) public view returns (bytes32) {
            return Neo.sha256Hash(data);
        }

        function ripemd(bytes memory data) public view returns (bytes20) {
            return Neo.ripemd160Hash(data);
        }
    }
    "#;

    let metadata = analyse_source(source).expect("analysis failed");
    let module = ir::Module::from_contract(&metadata).expect("IR lowering failed");

    let sha_fn = module
        .functions
        .iter()
        .find(|function| function.name == "sha")
        .expect("expected sha function");
    assert!(
        sha_fn.basic_blocks.iter().any(|block| {
            block.instructions.iter().any(|instr| {
                matches!(
                    instr,
                    ir::Instruction::CallBuiltin {
                        builtin: ir::BuiltinCall::NativeCall { contract, method },
                        arg_count: 1,
                    } if *contract == ir::NativeContract::CryptoLib && method == "sha256"
                )
            })
        }),
        "expected Neo.sha256Hash to lower to CryptoLib.sha256 native call"
    );

    let ripemd_fn = module
        .functions
        .iter()
        .find(|function| function.name == "ripemd")
        .expect("expected ripemd function");
    assert!(
        ripemd_fn.basic_blocks.iter().any(|block| {
            block.instructions.iter().any(|instr| {
                matches!(
                    instr,
                    ir::Instruction::CallBuiltin {
                        builtin: ir::BuiltinCall::NativeCall { contract, method },
                        arg_count: 1,
                    } if *contract == ir::NativeContract::CryptoLib && method == "ripemd160"
                )
            })
        }),
        "expected Neo.ripemd160Hash to lower to CryptoLib.ripemd160 native call"
    );

    assert!(
        module.functions.iter().all(|function| {
            function.basic_blocks.iter().all(|block| {
                block.instructions.iter().all(|instr| {
                    !matches!(
                        instr,
                        ir::Instruction::CallBuiltin {
                            builtin: ir::BuiltinCall::Syscall(name),
                            ..
                        } if name == "System.Crypto.SHA256"
                            || name == "System.Crypto.RIPEMD160"
                    )
                })
            })
        }),
        "Neo hash helpers must not lower to nonexistent System.Crypto hash syscalls"
    );
}