Description
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 forsoroban_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.