Skip to content

Commit

Permalink
Last call result
Browse files Browse the repository at this point in the history
  • Loading branch information
kubaplas committed Nov 15, 2023
2 parents 0f37a70 + 27250ba commit f884ca1
Show file tree
Hide file tree
Showing 18 changed files with 245 additions and 57 deletions.
1 change: 0 additions & 1 deletion examples2/bin/build_contract.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![no_std]
#![no_main]

#![allow(unused_imports)]
use examples2;
119 changes: 94 additions & 25 deletions examples2/src/erc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Erc20 {
self.env.emit_event(Approval {
owner: self.env.caller(),
spender: to,
value: amount,
value: amount
});
}

Expand Down Expand Up @@ -368,12 +368,12 @@ mod __erc20_wasm_parts {
// #[cfg(not(target_arch = "wasm32"))]
mod __erc20_test_parts {
use crate::erc20::Erc20;
use odra2::casper_event_standard::EventInstance;
use odra2::event::EventError;
use odra2::prelude::*;
use odra2::types::casper_types::EntryPoints;
use odra2::types::{runtime_args, Address, Bytes, RuntimeArgs, ToBytes, U256, U512, FromBytes};
use odra2::types::{runtime_args, Address, Bytes, FromBytes, RuntimeArgs, ToBytes, U256, U512};
use odra2::{CallDef, ContractEnv, EntryPointsCaller, HostEnv};
use odra2::casper_event_standard::EventInstance;
use odra2::event::EventError;

pub struct Erc20ContractRef {
pub address: Address,
Expand Down Expand Up @@ -578,8 +578,11 @@ use odra2::types::RuntimeArgs;
#[cfg(test)]
mod tests {
pub use super::*;
use odra2::types::ToBytes;
use odra2::types::casper_types::system::mint::Error::InsufficientFunds;
use odra2::types::OdraError::ExecutionError;
use odra2::types::U512;
use odra2::types::{Bytes, OdraError, ToBytes};
use odra2::CallResult;

#[test]
fn erc20_works() {
Expand Down Expand Up @@ -638,6 +641,58 @@ mod tests {
env.print_gas_report()
}

#[test]
fn erc20_call_result() {
let env = odra2::test_env();
let alice = env.get_account(0);
let bob = env.get_account(1);
let charlie = env.get_account(2);

// Deploy the contract as Alice.
let erc20 = Erc20Deployer::init(&env, Some(100.into()));

// Make a call or two

assert_eq!(env.get_events_count(&erc20.address), 0);
erc20.transfer(bob, 10.into());
assert_eq!(env.get_events_count(&erc20.address), 1);
erc20.transfer(bob, 30.into());
// // Test call result
let call_result = env.last_call_result();
assert_eq!(call_result.error, None);
assert_eq!(call_result.contract_address, erc20.address);
assert_eq!(call_result.caller, alice);
assert_eq!(
call_result.result.unwrap(),
Bytes::from(().to_bytes().unwrap())
);
assert_eq!(env.get_events_count(&erc20.address), 2);
assert_eq!(
call_result.events,
vec![(
erc20.address,
Bytes::from(
Transfer {
from: Some(alice),
to: Some(bob),
amount: 30.into()
}
.to_bytes()
.unwrap()
)
)]
);

// Test error last call when errors are implementedus
// erc20.transfer(bob, 100_000_000.into());
// let call_result = env.last_call_result();
// assert!(call_result.error.is_some());
// assert_eq!(call_result.contract_address, erc20.address);
// assert_eq!(call_result.caller, alice);
// assert_eq!(call_result.result, None);
// assert_eq!(call_result.events, vec![]);
}

#[test]
fn erc20_events_work() {
let env = odra2::test_env();
Expand All @@ -655,35 +710,49 @@ mod tests {

// Test events
let event: Transfer = erc20.get_event(0).unwrap();
assert_eq!(event, Transfer {
from: Some(alice),
to: Some(bob),
amount: 10.into()
});
assert_eq!(
event,
Transfer {
from: Some(alice),
to: Some(bob),
amount: 10.into()
}
);

let event: Approval = erc20.get_event(1).unwrap();
assert_eq!(event, Approval {
owner: alice,
spender: bob,
value: 10.into()
});
assert_eq!(
event,
Approval {
owner: alice,
spender: bob,
value: 10.into()
}
);

let event: Transfer = erc20.get_event(2).unwrap();
assert_eq!(event, Transfer {
from: Some(alice),
to: Some(charlie),
amount: 20.into()
});
assert_eq!(
event,
Transfer {
from: Some(alice),
to: Some(charlie),
amount: 20.into()
}
);

// Test negative indices
let event: Transfer = erc20.get_event(-1).unwrap();
assert_eq!(event, Transfer {
from: Some(alice),
to: Some(charlie),
amount: 20.into()
});
assert_eq!(
event,
Transfer {
from: Some(alice),
to: Some(charlie),
amount: 20.into()
}
);

// Test out of bounds
assert!(erc20.get_event::<Transfer>(3).is_err());

// Test event
}
}
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ build-erc20:
mv examples2/target/wasm32-unknown-unknown/release/contract.wasm examples2/wasm/erc20.wasm

test-erc20: build-erc20
cd examples2 && ODRA_BACKEND=casper cargo test --lib erc20_works -- --nocapture
cd examples2 && ODRA_BACKEND=casper cargo test --lib erc20 -- --nocapture

build-counter-pack:
cd examples2 && ODRA_MODULE=CounterPack cargo build --release --target wasm32-unknown-unknown --bin counter_pack
Expand Down
12 changes: 12 additions & 0 deletions odra-casper/test-vm/src/casper_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ impl HostContext for CasperHost {
self.vm.borrow_mut().set_caller(caller)
}

fn caller(&self) -> Address {
self.vm.borrow().get_caller()
}

fn get_account(&self, index: usize) -> Address {
self.vm.borrow().get_account(index)
}
Expand All @@ -50,6 +54,10 @@ impl HostContext for CasperHost {
self.vm.borrow().get_event(contract_address, index)
}

fn get_events_count(&self, contract_address: &Address) -> u32 {
self.vm.borrow().get_events_count(contract_address)
}

fn call_contract(&self, address: &Address, call_def: CallDef, use_proxy: bool) -> Bytes {
self.vm
.borrow_mut()
Expand All @@ -74,6 +82,10 @@ impl HostContext for CasperHost {
fn print_gas_report(&self) {
self.vm.borrow().print_gas_report()
}

fn last_call_gas_cost(&self) -> u64 {
self.vm.borrow().last_call_gas_cost()
}
}

impl CasperHost {
Expand Down
46 changes: 33 additions & 13 deletions odra-casper/test-vm/src/vm/casper_vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ impl CasperVm {
self.active_account = caller;
}

pub fn get_caller(&self) -> Address {
self.active_account
}

pub fn get_account(&self, index: usize) -> Address {
self.accounts[index]
}
Expand All @@ -164,19 +168,7 @@ impl CasperVm {
.as_uref()
.unwrap();

let events_length: u32 = self
.context
.query(
None,
Key::Hash(contract_hash.value()),
&[String::from(consts::EVENTS_LENGTH)]
)
.unwrap()
.as_cl_value()
.unwrap()
.clone()
.into_t()
.unwrap();
let events_length = self.events_length(&contract_hash);

let event_position = odra_utils::event_absolute_position(events_length as usize, index)
.ok_or(EventError::IndexOutOfBounds)?;
Expand All @@ -199,6 +191,13 @@ impl CasperVm {
}
}

pub fn get_events_count(&self, contract_address: &Address) -> u32 {
let contract_package_hash = contract_address.as_contract_package_hash().unwrap();
let contract_hash: ContractHash = self.get_contract_package_hash(contract_package_hash);

self.events_length(&contract_hash)
}

pub fn attach_value(&mut self, amount: U512) {
self.attached_value = amount;
}
Expand Down Expand Up @@ -423,4 +422,25 @@ impl CasperVm {
println!("{}: {}", name, cost);
}
}

pub fn last_call_gas_cost(&self) -> u64 {
self.last_call_contract_gas_cost().as_u64()
}
}

impl CasperVm {
fn events_length(&self, contract_hash: &ContractHash) -> u32 {
self.context
.query(
None,
Key::Hash(contract_hash.value()),
&[String::from(consts::EVENTS_LENGTH)]
)
.unwrap()
.as_cl_value()
.unwrap()
.clone()
.into_t()
.unwrap()
}
}
2 changes: 1 addition & 1 deletion odra-casper/wasm-env/src/host_functions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ fn read_host_buffer_into(dest: &mut [u8]) -> Result<usize, ApiError> {
}

pub fn emit_event(event: &Bytes) {
casper_event_standard::emit(event)
casper_event_standard::emit_bytes(event.clone())
}

pub fn set_value(key: &[u8], value: &[u8]) {
Expand Down
3 changes: 2 additions & 1 deletion odra-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ edition = "2021"

[dependencies]
odra-types = { path = "../types" }
casper-event-standard = "0.4.0"
casper-event-standard = "0.4.0"
bytes = "1.5.0"
12 changes: 12 additions & 0 deletions odra-core/src/call_result.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use alloc::vec::Vec;
use odra_types::{Address, Bytes, OdraError};

#[derive(Debug, Clone)]
pub struct CallResult {
pub contract_address: Address,
pub caller: Address,
pub gas_used: u64,
pub error: Option<OdraError>,
pub result: Option<Bytes>,
pub events: Vec<(Address, Bytes)>
}
2 changes: 1 addition & 1 deletion odra-core/src/contract_context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use odra_types::call_def::CallDef;
use odra_types::{Address, Bytes, ToBytes, U512};
use odra_types::{Address, Bytes, U512};

pub trait ContractContext {
fn get_value(&self, key: &[u8]) -> Option<Bytes>;
Expand Down
3 changes: 3 additions & 0 deletions odra-core/src/host_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ use odra_types::{Address, U512};

pub trait HostContext {
fn set_caller(&self, caller: Address);
fn caller(&self) -> Address;
fn get_account(&self, index: usize) -> Address;
fn balance_of(&self, address: &Address) -> U512;
fn advance_block_time(&self, time_diff: u64);
/// Returns event bytes by contract address and index.
fn get_event(&self, contract_address: &Address, index: i32) -> Result<Bytes, EventError>;
fn get_events_count(&self, contract_address: &Address) -> u32;
fn call_contract(&self, address: &Address, call_def: CallDef, use_proxy: bool) -> Bytes;
fn new_contract(
&self,
Expand All @@ -21,4 +23,5 @@ pub trait HostContext {
) -> Address;
fn contract_env(&self) -> ContractEnv;
fn print_gas_report(&self);
fn last_call_gas_cost(&self) -> u64;
}
Loading

0 comments on commit f884ca1

Please sign in to comment.