use piecrust::{ContractData, Error, SessionData, VM, contract_bytecode};
use piecrust_uplink::ContractError;
const OWNER: [u8; 32] = [0u8; 32];
const LIMIT: u64 = 1_000_000;
#[test]
fn inter_contract_call_validates_return_bytes() -> Result<(), Error> {
let vm = VM::ephemeral()?;
let mut session = vm.session(SessionData::builder())?;
let (badreturn_id, _) = session.deploy::<_, (), _>(
contract_bytecode!("badreturn"),
ContractData::builder().owner(OWNER),
LIMIT,
)?;
let (center_id, _) = session.deploy::<_, (), _>(
contract_bytecode!("callcenter"),
ContractData::builder().owner(OWNER),
LIMIT,
)?;
let garbage_result: Result<bool, ContractError> = session
.call(
center_id,
"try_query_bool",
&(badreturn_id, String::from("garbage_value")),
LIMIT,
)?
.data;
let panic_msg = match &garbage_result {
Err(ContractError::Panic(msg)) => msg,
_ => panic!(
"Garbage return bytes should produce Err(Panic), got: \
{garbage_result:?}"
),
};
assert!(
panic_msg.starts_with("Callee return value failed validation:"),
"Unexpected panic error message for invalid callee bytes: {panic_msg}"
);
let valid_result: Result<bool, ContractError> = session
.call(
center_id,
"try_query_bool",
&(badreturn_id, String::from("valid_bool")),
LIMIT,
)?
.data;
assert_eq!(
valid_result,
Ok(true),
"Valid return bytes should deserialize correctly"
);
Ok(())
}
#[test]
fn host_call_rejects_garbage_return() -> Result<(), Error> {
let vm = VM::ephemeral()?;
let mut session = vm.session(SessionData::builder())?;
let (badreturn_id, _) = session.deploy::<_, (), _>(
contract_bytecode!("badreturn"),
ContractData::builder().owner(OWNER),
LIMIT,
)?;
let result =
session.call::<_, bool>(badreturn_id, "garbage_value", &(), LIMIT);
let err = result
.expect_err("Host call to a contract returning garbage should fail");
assert!(
matches!(err, Error::ValidationError),
"Host call to a contract returning garbage should produce a ValidationError, got: {err:?}"
);
assert_eq!(
err.to_string(),
"ValidationError",
"Unexpected error message for host-side validation failure"
);
Ok(())
}