Skip to content

Commit

Permalink
Wip
Browse files Browse the repository at this point in the history
  • Loading branch information
kubaplas committed Nov 15, 2023
2 parents 0f37a70 + 27250ba commit c801f67
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 47 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;
97 changes: 72 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 @@ -577,8 +577,9 @@ use odra2::types::RuntimeArgs;

#[cfg(test)]
mod tests {
use odra2::CallResult;
pub use super::*;
use odra2::types::ToBytes;
use odra2::types::{Bytes, ToBytes};
use odra2::types::U512;

#[test]
Expand Down Expand Up @@ -638,6 +639,38 @@ 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
erc20.transfer(bob, 10.into());
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!(call_result.events, vec![
(
erc20.address,
Bytes::from(Transfer {
from: Some(alice),
to: Some(bob),
amount: 30.into()
}.to_bytes().unwrap())
)
])
}

#[test]
fn erc20_events_work() {
let env = odra2::test_env();
Expand All @@ -655,35 +688,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
}
}
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()
}
}
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;
}
40 changes: 37 additions & 3 deletions odra-core/src/host_env.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::call_result::CallResult;
use crate::entry_point_callback::EntryPointsCaller;
use crate::event::EventError;
use crate::host_context::HostContext;
Expand All @@ -10,12 +11,18 @@ use odra_types::{CLTyped, FromBytes};

#[derive(Clone)]
pub struct HostEnv {
backend: Rc<RefCell<dyn HostContext>>
backend: Rc<RefCell<dyn HostContext>>,
last_call_result: Rc<RefCell<Option<CallResult>>>,
deployed_contracts: Rc<RefCell<Vec<Address>>>
}

impl HostEnv {
pub fn new(backend: Rc<RefCell<dyn HostContext>>) -> HostEnv {
HostEnv { backend }
HostEnv {
backend,
last_call_result: RefCell::new(None).into(),
deployed_contracts: RefCell::new(vec![]).into()
}
}

pub fn get_account(&self, index: usize) -> Address {
Expand All @@ -40,13 +47,34 @@ impl HostEnv {
entry_points_caller: Option<EntryPointsCaller>
) -> Address {
let backend = self.backend.borrow();
backend.new_contract(name, init_args, entry_points_caller)
let deployed_contract = backend.new_contract(name, init_args, entry_points_caller);
self.deployed_contracts
.borrow_mut()
.push(deployed_contract.clone());
deployed_contract
}

pub fn call_contract<T: FromBytes + CLTyped>(&self, address: &Address, call_def: CallDef) -> T {
let backend = self.backend.borrow();

self.last_call_result.replace(Some(CallResult {
contract_address: address.clone(),
caller: backend.caller(),
gas_used: 0,
error: None,
result: None,
events: vec![]
}));

let use_proxy = T::cl_type() != <()>::cl_type() || !call_def.attached_value().is_zero();
let result = backend.call_contract(address, call_def, use_proxy);

self.last_call_result.borrow_mut().as_mut().unwrap().result = Some(result.clone());
self.last_call_result
.borrow_mut()
.as_mut()
.unwrap()
.gas_used = backend.last_call_gas_cost();
T::from_bytes(&result).unwrap().0
}

Expand Down Expand Up @@ -84,6 +112,12 @@ impl HostEnv {
}
}

pub fn last_call_result(&self) -> CallResult {
self.last_call_result.borrow().clone().unwrap().clone()
}
}

impl HostEnv {
/// Returns the name of the passed event
fn extract_event_name(bytes: &[u8]) -> Result<String, EventError> {
let name = FromBytes::from_bytes(bytes).map_err(|_| EventError::CouldntExtractName)?;
Expand Down
1 change: 1 addition & 0 deletions odra-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

extern crate alloc;

pub mod call_result;
mod contract_context;
mod contract_env;
pub mod entry_point_callback;
Expand Down
Loading

0 comments on commit c801f67

Please sign in to comment.