Skip to content

contractimport! emits compiler errors for contract types containing RawVal. #939

Closed
@brson

Description

@brson

What version are you using?

0.8.0

What did you do?

I created a contract with a #[contracttype] containing RawVal and compiled it to wasm.
Then I tried to load it in a host environment with the contractimport! macro.

The contract looks like

#![no_std]

use soroban_sdk::{contractimpl, contracttype, log, Env, RawVal};

#[contracttype]
#[derive(Clone, Debug)]
pub enum FuzzInstruction {
    LogValue(RawVal),
}

pub struct FuzzContract;

#[contractimpl]
impl FuzzContract {
    pub fn run(env: Env, fuzz_instruction: FuzzInstruction) {
        match fuzz_instruction {
            FuzzInstruction::LogValue(rawval) => log!(&env, "log value: {}", rawval)
        }

    }
}

and the host code looks like (some of this fuzzing code is not valid on the master branch)

#![no_main]

use libfuzzer_sys::fuzz_target;
use soroban_sdk::{Env, FromVal};
use fuzzcontract::FuzzInstruction;
use soroban_sdk::arbitrary::SorobanArbitrary;

mod fuzzcontract {
    soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/contract_for_fuzz.wasm");
}

fuzz_target!(|input: <FuzzInstruction as SorobanArbitrary>::Prototype| {
    let env = Env::default();
    
    let contract_id = env.register_contract_wasm(None, fuzzcontract::WASM);
    
    let client = fuzzcontract::Client::new(&env, &contract_id);

    let fuzz_instruction = FuzzInstruction::from_val(&env, &input);

    client.run(&fuzz_instruction)
});

What did you expect to see?

When compiling the host crate, I expected the compilation to succeed.

What did you see instead?

The host crate fails to compile with

error[E0277]: the trait bound `RawVal: Eq` is not satisfied
 --> fuzz_targets/fuzz_target_1.rs:9:5
  |
9 |     soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/contract_for_fuzz.wasm");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq` is not implemented for `RawVal`
  |
note: required by a bound in `AssertParamIsEq`
 --> /rustc/c4190f2d3a46a59f435f7b42f58bc22b2f4d6917/library/core/src/cmp.rs:313:1
  = note: this error originates in the derive macro `Eq` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0369]: binary operation `==` cannot be applied to type `RawVal`
 --> fuzz_targets/fuzz_target_1.rs:9:5
  |
9 |     soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/contract_for_fuzz.wasm");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `RawVal: Ord` is not satisfied
 --> fuzz_targets/fuzz_target_1.rs:9:5
  |
9 |     soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/contract_for_fuzz.wasm");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Ord` is not implemented for `RawVal`
  |
  = note: this error originates in the derive macro `Ord` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: can't compare `RawVal` with `_`
 --> fuzz_targets/fuzz_target_1.rs:9:5
  |
9 |     soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/contract_for_fuzz.wasm");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `RawVal < _` and `RawVal > _`
  |
  = help: the trait `PartialOrd<_>` is not implemented for `RawVal`
  = note: this error originates in the derive macro `PartialOrd` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `soroban_sdk::xdr::ScVec: TryFrom<(&str, &RawVal)>` is not satisfied
 --> fuzz_targets/fuzz_target_1.rs:9:5
  |
9 |     soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/contract_for_fuzz.wasm");
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `TryFrom<(&str, &RawVal)>` is not implemented for `soroban_sdk::xdr::ScVec`
  |
  = help: the following other types implement trait `TryFrom<T>`:
            <soroban_sdk::xdr::ScVec as TryFrom<&FuzzInstruction>>
            <soroban_sdk::xdr::ScVec as TryFrom<&soroban_sdk::Vec<T>>>
            <soroban_sdk::xdr::ScVec as TryFrom<&std::vec::Vec<soroban_sdk::xdr::ScVal>>>
            <soroban_sdk::xdr::ScVec as TryFrom<(T0, T1)>>
            <soroban_sdk::xdr::ScVec as TryFrom<(T0, T1, T2)>>
            <soroban_sdk::xdr::ScVec as TryFrom<(T0, T1, T2, T3)>>
            <soroban_sdk::xdr::ScVec as TryFrom<(T0, T1, T2, T3, T4)>>
            <soroban_sdk::xdr::ScVec as TryFrom<(T0, T1, T2, T3, T4, T5)>>
          and 11 others
  = note: required for `(&str, &RawVal)` to implement `TryInto<soroban_sdk::xdr::ScVec>`
  = note: this error originates in the attribute macro `soroban_sdk::contracttype` (in Nightly builds, run with -Z macro-backtrace for more info)

This indicates three errors

  • RawVal does not implement Eq and Ord
  • TryFrom<(&str, &RawVal)> is not implemented for soroban_sdk::xdr::ScVec

The former are easy to understand as RawVal doesn't implement Eq and Ord, and contractimport emits #[derive(Eq, Ord)] for all contracttypes it imports:

pub fn generate_enum(spec: &ScSpecUdtEnumV0) -> TokenStream {
    let ident = format_ident!("{}", spec.name.to_string().unwrap());
    if spec.lib.len() > 0 {
        let lib_ident = format_ident!("{}", spec.lib.to_string_lossy());
        quote! {
            pub type #ident = ::#lib_ident::#ident;
        }
    } else {
        let variants = spec.cases.iter().map(|c| {
            let v_ident = format_ident!("{}", c.name.to_string().unwrap());
            let v_value = Literal::u32_unsuffixed(c.value);
            quote! { #v_ident = #v_value }
        });
        quote! {
            #[soroban_sdk::contracttype(export = false)]
            #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
            pub enum #ident { #(#variants,)* }
        }
    }
}

The missing ScVec conversion I don't understand yet.


My use case is that I am attempting to load a contract into the VM that accepts RawVals as inputs for the purposes of fuzzing the host/guest interface.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions