use crate::{str, vec, Vec, U256};
use borsh::{BorshDeserialize, BorshSerialize};
pub mod address;
pub mod balance;
pub mod fee;
pub mod gas;
pub mod wei;
pub use address::{make_address, Address};
pub use balance::*;
pub use fee::*;
pub use gas::*;
pub use wei::*;
pub type RawU256 = [u8; 32];
pub type RawH256 = [u8; 32];
pub type StorageUsage = u64;
pub const ERC20_MINT_SELECTOR: &[u8] = &[64, 193, 15, 25];
pub const ERC20_SET_METADATA_SELECTOR: &[u8] = &[55, 210, 194, 244];
pub const ERC20_NAME_SELECTOR: &[u8] = &[6, 253, 222, 3];
pub const ERC20_SYMBOL_SELECTOR: &[u8] = &[149, 216, 155, 65];
pub const ERC20_DECIMALS_SELECTOR: &[u8] = &[49, 60, 229, 103];
#[derive(Debug)]
pub enum AddressValidationError {
FailedDecodeHex,
IncorrectLength,
}
impl AsRef<[u8]> for AddressValidationError {
fn as_ref(&self) -> &[u8] {
match self {
Self::FailedDecodeHex => b"FAILED_DECODE_ETH_ADDRESS",
Self::IncorrectLength => b"ETH_WRONG_ADDRESS_LENGTH",
}
}
}
pub const STORAGE_PRICE_PER_BYTE: u128 = 10_000_000_000_000_000_000;
pub const ERR_FAILED_PARSE: &str = "ERR_FAILED_PARSE";
pub const ERR_INVALID_ETH_ADDRESS: &str = "ERR_INVALID_ETH_ADDRESS";
#[derive(Debug)]
pub struct InternalMetaCallArgs {
pub sender: Address,
pub nonce: U256,
pub fee_amount: Wei,
pub fee_address: Address,
pub contract_address: Address,
pub value: Wei,
pub input: Vec<u8>,
}
pub struct StorageBalanceBounds {
pub min: Yocto,
pub max: Option<Yocto>,
}
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub enum PromiseResult {
NotReady,
Successful(Vec<u8>),
Failed,
}
impl PromiseResult {
#[must_use]
pub fn size(&self) -> usize {
match self {
Self::Failed | Self::NotReady => 1,
Self::Successful(bytes) => bytes.len(),
}
}
}
pub struct FtResolveTransferResult {
pub amount: Balance,
pub refund_amount: Balance,
}
#[derive(Default)]
pub struct Stack<T> {
stack: Vec<T>,
boundaries: Vec<usize>,
}
impl<T> Stack<T> {
#[must_use]
pub fn new() -> Self {
Self {
stack: Vec::new(),
boundaries: vec![0],
}
}
pub fn enter(&mut self) {
self.boundaries.push(self.stack.len());
}
pub fn commit(&mut self) {
self.boundaries.pop().unwrap();
}
pub fn discard(&mut self) {
let boundary = self.boundaries.pop().unwrap();
self.stack.truncate(boundary);
}
pub fn push(&mut self, value: T) {
self.stack.push(value);
}
#[must_use]
#[allow(clippy::missing_const_for_fn)]
pub fn into_vec(self) -> Vec<T> {
self.stack
}
}
#[must_use]
pub fn str_from_slice(inp: &[u8]) -> &str {
str::from_utf8(inp).unwrap()
}
#[cfg(test)]
mod tests {
use super::*;
fn view_stack(stack: &Stack<i32>) -> Vec<Option<i32>> {
let mut res = vec![];
let mut pnt = 0;
for pos in &stack.boundaries {
while pnt < *pos {
res.push(Some(stack.stack[pnt]));
pnt += 1;
}
res.push(None);
}
while pnt < stack.stack.len() {
res.push(Some(stack.stack[pnt]));
pnt += 1;
}
res
}
fn check_stack(stack: &Stack<i32>, expected: &[Option<i32>]) {
if let Some(&last) = stack.boundaries.last() {
assert!(last <= stack.stack.len());
}
assert_eq!(view_stack(stack), expected);
}
#[test]
fn test_stack() {
let mut stack = Stack::new(); check_stack(&stack, &[None]);
stack.push(1); check_stack(&stack, &[None, Some(1)]);
stack.push(2); check_stack(&stack, &[None, Some(1), Some(2)]);
stack.enter(); check_stack(&stack, &[None, Some(1), Some(2), None]);
stack.push(3); check_stack(&stack, &[None, Some(1), Some(2), None, Some(3)]);
stack.discard(); check_stack(&stack, &[None, Some(1), Some(2)]);
stack.enter();
check_stack(&stack, &[None, Some(1), Some(2), None]);
stack.push(4); check_stack(&stack, &[None, Some(1), Some(2), None, Some(4)]);
stack.enter(); check_stack(&stack, &[None, Some(1), Some(2), None, Some(4), None]);
stack.push(5); check_stack(
&stack,
&[None, Some(1), Some(2), None, Some(4), None, Some(5)],
);
stack.commit(); check_stack(&stack, &[None, Some(1), Some(2), None, Some(4), Some(5)]);
stack.discard(); check_stack(&stack, &[None, Some(1), Some(2)]);
stack.push(6); check_stack(&stack, &[None, Some(1), Some(2), Some(6)]);
stack.enter(); check_stack(&stack, &[None, Some(1), Some(2), Some(6), None]);
stack.enter(); check_stack(&stack, &[None, Some(1), Some(2), Some(6), None, None]);
stack.enter(); check_stack(&stack, &[None, Some(1), Some(2), Some(6), None, None, None]);
stack.commit(); check_stack(&stack, &[None, Some(1), Some(2), Some(6), None, None]);
stack.discard(); check_stack(&stack, &[None, Some(1), Some(2), Some(6), None]);
stack.push(7);
assert_eq!(stack.into_vec(), vec![1, 2, 6, 7]);
}
}