use piecrust::{
ContractData, Error, Session, SessionData, VM, contract_bytecode,
};
use piecrust_uplink::{ARGBUF_LEN, ContractId};
const OWNER: [u8; 32] = [0u8; 32];
const LIMIT: u64 = 1_000_000;
const VALID_RETURN_LEN: i32 = 4;
fn deploy_badreturn() -> Result<(Session, ContractId), Error> {
let vm = VM::ephemeral()?;
let mut session = vm.session(SessionData::builder())?;
let (id, _) = session.deploy::<_, (), _>(
contract_bytecode!("badreturn"),
ContractData::builder().owner(OWNER),
LIMIT,
)?;
Ok((session, id))
}
fn read_counter(session: &mut Session, id: ContractId) -> Result<u32, Error> {
Ok(session.call::<_, u32>(id, "counter", &(), LIMIT)?.data)
}
#[test]
fn top_level_valid_return_len_is_accepted() -> Result<(), Error> {
let (mut session, id) = deploy_badreturn()?;
assert_eq!(read_counter(&mut session, id)?, 72);
let receipt = session.call_raw(
id,
"raw_return_len",
VALID_RETURN_LEN.to_le_bytes(),
LIMIT,
)?;
assert_eq!(receipt.data.len(), VALID_RETURN_LEN as usize);
assert_eq!(read_counter(&mut session, id)?, 73);
Ok(())
}
#[test]
fn top_level_negative_return_len_is_rejected() -> Result<(), Error> {
let (mut session, id) = deploy_badreturn()?;
assert_eq!(read_counter(&mut session, id)?, 72);
let err = session
.call_raw(id, "raw_return_len", (-1i32).to_le_bytes(), LIMIT)
.expect_err("negative return length should be rejected");
let Error::MemoryAccessOutOfBounds { len, .. } = err else {
panic!("unexpected error: {err}");
};
assert_eq!(len, u32::MAX as usize);
assert_eq!(read_counter(&mut session, id)?, 72);
Ok(())
}
#[test]
fn top_level_oversized_return_len_is_rejected() -> Result<(), Error> {
let (mut session, id) = deploy_badreturn()?;
assert_eq!(read_counter(&mut session, id)?, 72);
let oversized =
i32::try_from(ARGBUF_LEN + 1).expect("ARGBUF_LEN fits in i32");
let err = session
.call_raw(id, "raw_return_len", oversized.to_le_bytes(), LIMIT)
.expect_err("oversized return length should be rejected");
let Error::MemoryAccessOutOfBounds { len, .. } = err else {
panic!("unexpected error: {err}");
};
assert_eq!(len, ARGBUF_LEN + 1);
assert_eq!(read_counter(&mut session, id)?, 72);
Ok(())
}