use anyhow::Result;
pub(crate) struct Instance(pub(crate) wasmer::Instance);
impl Instance {
pub(crate) unsafe fn call_method(&self) -> Result<u64, (u64, MethodCallError)> {
let remaining_gas = match wasmer_middlewares::metering::get_remaining_points(&self.0) {
wasmer_middlewares::metering::MeteringPoints::Exhausted => 0,
wasmer_middlewares::metering::MeteringPoints::Remaining(gas_left_after_execution) => {
gas_left_after_execution
}
};
let method = match self
.0
.exports
.get_native_function::<(), ()>(CONTRACT_METHOD)
{
Ok(m) => m,
Err(e) => return Err((remaining_gas, MethodCallError::NoExportedMethod(e))), };
let execution_result = method.call();
let remaining_gas = match wasmer_middlewares::metering::get_remaining_points(&self.0) {
wasmer_middlewares::metering::MeteringPoints::Exhausted => 0,
wasmer_middlewares::metering::MeteringPoints::Remaining(gas_left_after_execution) => {
gas_left_after_execution
}
};
match execution_result{
Ok(_) => Ok(remaining_gas),
Err(_) if remaining_gas == 0 => Err((remaining_gas, MethodCallError::GasExhaustion)),
Err(e) => Err((remaining_gas, MethodCallError::Runtime(e)))
}
}
pub(crate) fn remaining_points(&self) -> wasmer::Global {
self.0
.exports
.get_global("wasmer_metering_remaining_points")
.unwrap()
.clone()
}
}
#[derive(Debug)]
pub enum MethodCallError {
Runtime(wasmer::RuntimeError),
GasExhaustion,
NoExportedMethod(wasmer::ExportError),
}
#[derive(Debug)]
pub enum ContractValidateError {
MethodNotFound,
InstantiateError,
}
pub const CONTRACT_METHOD: &str = "entrypoint";