use crate::prelude::*;
use crate::types::LogLevel;
pub(crate) mod env {
extern "C" {
pub(crate) fn fvm_storage_read(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32,
val: *mut u8, vlen: u32, offset: u32) -> u32;
pub(crate) fn fvm_call_contract(addr: *const u8, input_ptr: *const u8, input_len: u32) -> u32;
pub(crate) fn fvm_cns_call_contract(cns: *const u8, cns_len: u32, input_ptr: *const u8, input_len: u32) -> u32;
pub(crate) fn fvm_storage_write(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32, val: *const u8, vlen: u32);
pub(crate) fn fvm_storage_delete(key_ptr: *const u8, key_len: u32, prefix_ptr: *const u8, prefix_len: u32);
pub(crate) fn fvm_block_height() -> u64;
pub(crate) fn fvm_input_length() -> u32;
pub(crate) fn fvm_block_time() -> u64;
pub(crate) fn fvm_fetch_input(dst: *mut u8);
pub(crate) fn fvm_tx_hash(tx_hash: *const u8);
pub(crate) fn fvm_self_address(dest: *mut u8);
pub(crate) fn fvm_caller_address(dest: *mut u8);
pub(crate) fn fvm_origin_address(dest: *mut u8);
pub(crate) fn fvm_return(ptr: *const u8, len: u32);
pub(crate) fn fvm_revert(ptr: *const u8, len: u32) -> !;
pub(crate) fn fvm_log(ptr: *const u8, len: u32);
pub(crate) fn fvm_debug(class_prt: *const u8, class_len: u32, ptr: *const u8, len: u32, level: u32);
pub(crate) fn fvm_call_return(dst: *mut u8);
pub(crate) fn fvm_sha256(data_ptr: *const u8, len: u32, val: *mut u8);
pub(crate) fn fvm_add_list_key(list_name_ptr: *const u8, list_name_len: u32, index: u32) -> i64;
pub(crate) fn fvm_get_list_key(list_name_ptr: *const u8, list_name_len: u32, index: u32) -> i64;
pub(crate) fn fvm_remove_list_key(list_name_ptr: *const u8, list_name_len: u32, index: u32) -> i64;
pub(crate) fn fvm_write_list_keys(old_list_name_ptr: *const u8, old_list_name_len: u32, new_list_name_ptr: *const u8, new_list_name_len: u32, size: u32);
}
}
pub(crate) fn call_contract(addr: &Address, input: &[u8]) -> Vec<u8> {
let addr: &[u8] = addr.as_ref();
let size =
unsafe { env::fvm_call_contract(addr.as_ptr(), input.as_ptr(), input.len() as u32) };
let mut output = vec![0u8; size as usize];
if size != 0 {
let value = &mut output[..];
unsafe {
env::fvm_call_return(value.as_mut_ptr());
}
}
output
}
pub(crate) fn cns_call_contract(cns: &[u8], input: &[u8]) -> Vec<u8> {
let size =
unsafe { env::fvm_cns_call_contract(cns.as_ptr(), cns.len() as u32, input.as_ptr(), input.len() as u32) };
let mut output = vec![0u8; size as usize];
if size != 0 {
let value = &mut output[..];
unsafe {
env::fvm_call_return(value.as_mut_ptr());
}
}
output
}
pub(crate) fn storage_write(key: &[u8], prefix: &[u8], val: &[u8]) {
unsafe {
env::fvm_storage_write(key.as_ptr(), key.len() as u32,
prefix.as_ptr(), prefix.len() as u32,
val.as_ptr(), val.len() as u32);
}
}
pub(crate) fn storage_read(key: &[u8], prefix: &[u8]) -> Option<Vec<u8>> {
const INITIAL: usize = 32;
let mut val = vec![0; INITIAL];
let size = unsafe {
env::fvm_storage_read(
key.as_ptr(), key.len() as u32,
prefix.as_ptr(), prefix.len() as u32,
val.as_mut_ptr(),
val.len() as u32,
0,
)
};
if size == 0 {
return None;
}
let size = size as usize;
val.resize(size, 0);
if size > INITIAL {
let value = &mut val[INITIAL..];
debug_assert!(value.len() == size - INITIAL);
unsafe {
env::fvm_storage_read(
key.as_ptr(), key.len() as u32,
prefix.as_ptr(), prefix.len() as u32,
value.as_mut_ptr(),
value.len() as u32,
INITIAL as u32,
)
};
}
Some(val)
}
pub(crate) fn storage_delete(key: &[u8], prefix: &[u8]) {
unsafe {
env::fvm_storage_delete(key.as_ptr(), key.len() as u32,
prefix.as_ptr(), prefix.len() as u32);
}
}
pub(crate) fn block_time() -> u64 {
unsafe { env::fvm_block_time() }
}
pub(crate) fn block_height() -> u64 {
unsafe { env::fvm_block_height() }
}
pub(crate) fn self_address() -> Address {
let mut addr: Address = Address::zero();
unsafe {
env::fvm_self_address(addr.as_mut().as_mut_ptr());
}
addr
}
pub(crate) fn caller_address() -> Address {
let mut addr: Address = Address::zero();
unsafe {
env::fvm_caller_address(addr.as_mut().as_mut_ptr());
}
addr
}
pub(crate) fn origin_address() -> Address {
let mut addr: Address = Address::zero();
unsafe {
env::fvm_origin_address(addr.as_mut().as_mut_ptr());
}
addr
}
pub(crate) fn tx_hash() -> H256 {
let tx_hash = H256::zero();
unsafe {
env::fvm_tx_hash(tx_hash.as_ptr());
}
tx_hash
}
pub(crate) fn sha256(data: impl AsRef<[u8]>) -> H256 {
let data = data.as_ref();
let mut hash = H256::zero();
unsafe {
env::fvm_sha256(data.as_ptr(), data.len() as u32, hash.as_mut_ptr());
}
hash
}
pub(crate) fn input() -> Vec<u8> {
let len = unsafe { env::fvm_input_length() };
if len == 0 {
Vec::new()
} else {
let mut data = vec![0; len as usize];
unsafe {
env::fvm_fetch_input(data.as_mut_ptr());
}
data
}
}
pub(crate) fn ret(data: &[u8]) {
unsafe {
env::fvm_return(data.as_ptr(), data.len() as u32);
}
}
pub(crate) fn event(data: &[u8]) {
unsafe {
env::fvm_log(data.as_ptr(), data.len() as u32);
}
}
pub(crate) fn log(class_name: &[u8], data: &[u8], level: LogLevel) {
let level_type: u32 = match level {
LogLevel::CRITICAL => 0,
LogLevel::ERROR => 1,
LogLevel::WARNING => 2,
LogLevel::NOTICE => 3,
LogLevel::INFO => 4,
LogLevel::DEBUG => 5,
};
unsafe {
env::fvm_debug(class_name.as_ptr(), class_name.len() as u32, data.as_ptr(), data.len() as u32, level_type);
}
}
pub(crate) fn revert(msg: &str) -> ! {
unsafe {
env::fvm_revert(msg.as_ptr(), msg.len() as u32);
}
}
pub(crate) fn add_list_key(list_name: &[u8], index: u32) -> Option<i64> {
let key =
unsafe { env::fvm_add_list_key(list_name.as_ptr(), list_name.len() as u32, index) };
if key < 0 {
None
} else {
Some(key)
}
}
pub(crate) fn get_list_key(list_name: &[u8], index: u32) -> Option<i64> {
let key =
unsafe { env::fvm_get_list_key(list_name.as_ptr(), list_name.len() as u32, index) };
if key < 0 {
None
} else {
Some(key)
}
}
pub(crate) fn remove_list_key(list_name: &[u8], index: u32) -> Option<i64> {
let key =
unsafe { env::fvm_remove_list_key(list_name.as_ptr(), list_name.len() as u32, index) };
if key < 0 {
None
} else {
Some(key)
}
}
pub(crate) fn write_list_keys_back(old_list_name: &[u8], list_name: &[u8], size: u32) {
unsafe { env::fvm_write_list_keys(old_list_name.as_ptr(), old_list_name.len() as u32, list_name.as_ptr(), list_name.len() as u32, size) };
}