1use crate::address::Addressable;
4use crate::gas_report::GasReport;
5use crate::{
6 call_result::CallResult, entry_point_callback::EntryPointsCaller, CallDef, ContractCallResult,
7 ContractEnv, EventError, VmError
8};
9#[cfg(not(target_arch = "wasm32"))]
10use crate::{consts, contract::OdraContract, contract_def::HasIdent};
11use crate::{prelude::*, utils};
12use casper_event_standard::EventInstance;
13use casper_types::{
14 bytesrepr::{Bytes, FromBytes, ToBytes},
15 CLTyped, PublicKey, RuntimeArgs, U512
16};
17
18pub trait HostRef {
20 fn new(address: Address, env: HostEnv) -> Self;
22 fn with_tokens(&self, tokens: U512) -> Self;
27 fn contract_address(&self) -> Address;
29 fn env(&self) -> &HostEnv;
31 fn get_event<T>(&self, index: i32) -> Result<T, EventError>
35 where
36 T: FromBytes + EventInstance + 'static;
37 fn last_call(&self) -> ContractCallResult;
39}
40
41impl<T: HostRef> Addressable for T {
42 fn address(&self) -> Address {
43 HostRef::contract_address(self)
44 }
45}
46
47pub trait HostRefLoader<T: HostRef> {
51 fn load(env: &HostEnv, address: Address) -> T;
53}
54
55pub trait EntryPointsCallerProvider {
57 fn entry_points_caller(env: &HostEnv) -> EntryPointsCaller;
59}
60
61#[cfg(not(target_arch = "wasm32"))]
68pub trait Deployer<R: OdraContract>: Sized {
69 fn deploy(env: &HostEnv, init_args: R::InitArgs) -> R::HostRef;
78
79 fn try_deploy(env: &HostEnv, init_args: R::InitArgs) -> OdraResult<R::HostRef>;
83
84 fn deploy_with_cfg<T: OdraConfig>(env: &HostEnv, init_args: R::InitArgs, cfg: T) -> R::HostRef;
88
89 fn try_deploy_with_cfg<T: OdraConfig>(
93 env: &HostEnv,
94 init_args: R::InitArgs,
95 cfg: T
96 ) -> OdraResult<R::HostRef>;
97}
98
99pub trait InitArgs: Into<RuntimeArgs> {}
101
102pub struct NoArgs;
108
109impl InitArgs for NoArgs {}
110
111impl From<NoArgs> for RuntimeArgs {
112 fn from(_: NoArgs) -> Self {
113 RuntimeArgs::new()
114 }
115}
116
117pub trait OdraConfig {
122 fn package_hash(&self) -> String;
126 fn is_upgradable(&self) -> bool;
130 fn allow_key_override(&self) -> bool;
132}
133
134#[cfg(not(target_arch = "wasm32"))]
135struct DefaultOdraConfig {
137 name: String
138}
139
140#[cfg(not(target_arch = "wasm32"))]
141impl OdraConfig for DefaultOdraConfig {
142 fn package_hash(&self) -> String {
143 self.name.clone()
144 }
145
146 fn is_upgradable(&self) -> bool {
147 false
148 }
149
150 fn allow_key_override(&self) -> bool {
151 true
152 }
153}
154
155#[cfg(not(target_arch = "wasm32"))]
156impl<R: OdraContract> Deployer<R> for R {
157 fn deploy(
158 env: &HostEnv,
159 init_args: <R as OdraContract>::InitArgs
160 ) -> <R as OdraContract>::HostRef {
161 let contract_ident = R::HostRef::ident();
162 match Self::try_deploy(env, init_args) {
163 Ok(contract) => contract,
164 Err(OdraError::ExecutionError(ExecutionError::MissingArg)) => {
165 core::panic!("Invalid init args for contract {}.", contract_ident)
166 }
167 Err(e) => core::panic!("Contract init failed {:?}", e)
168 }
169 }
170
171 fn try_deploy(
172 env: &HostEnv,
173 init_args: <R as OdraContract>::InitArgs
174 ) -> OdraResult<<R as OdraContract>::HostRef> {
175 Self::try_deploy_with_cfg(
176 env,
177 init_args,
178 DefaultOdraConfig {
179 name: R::HostRef::ident()
180 }
181 )
182 }
183
184 fn deploy_with_cfg<T: OdraConfig>(
185 env: &HostEnv,
186 init_args: <R as OdraContract>::InitArgs,
187 cfg: T
188 ) -> <R as OdraContract>::HostRef {
189 let contract_ident = R::HostRef::ident();
190 match Self::try_deploy_with_cfg(env, init_args, cfg) {
191 Ok(contract) => contract,
192 Err(OdraError::ExecutionError(ExecutionError::MissingArg)) => {
193 core::panic!("Invalid init args for contract {}.", contract_ident)
194 }
195 Err(e) => core::panic!("Contract init failed {:?}", e)
196 }
197 }
198
199 fn try_deploy_with_cfg<T: OdraConfig>(
200 env: &HostEnv,
201 init_args: <R as OdraContract>::InitArgs,
202 cfg: T
203 ) -> OdraResult<<R as OdraContract>::HostRef> {
204 let contract_ident = R::HostRef::ident();
205 let caller = R::HostRef::entry_points_caller(env);
206
207 let mut init_args = init_args.into();
208 init_args.insert(consts::IS_UPGRADABLE_ARG, cfg.is_upgradable())?;
209 init_args.insert(consts::ALLOW_KEY_OVERRIDE_ARG, cfg.allow_key_override())?;
210 init_args.insert(
211 consts::PACKAGE_HASH_KEY_NAME_ARG,
212 format!("{}_package_hash", cfg.package_hash())
213 )?;
214
215 let address = env.new_contract(&contract_ident, init_args, caller)?;
216 Ok(R::HostRef::new(address, env.clone()))
217 }
218}
219
220#[cfg(not(target_arch = "wasm32"))]
221impl<T: OdraContract> HostRefLoader<T::HostRef> for T {
222 fn load(env: &HostEnv, address: Address) -> T::HostRef {
223 let caller = T::HostRef::entry_points_caller(env);
224 let contract_name = T::HostRef::ident();
225 env.register_contract(address, contract_name, caller);
226 T::HostRef::new(address, env.clone())
227 }
228}
229
230#[cfg_attr(test, mockall::automock)]
232pub trait HostContext {
233 fn set_caller(&self, caller: Address);
235
236 fn set_gas(&self, gas: u64);
238
239 fn caller(&self) -> Address;
241
242 fn get_account(&self, index: usize) -> Address;
244
245 fn get_validator(&self, index: usize) -> PublicKey;
247
248 fn remove_validator(&self, index: usize);
250
251 fn balance_of(&self, address: &Address) -> U512;
253
254 fn advance_block_time(&self, time_diff: u64);
256
257 fn advance_with_auctions(&self, time_diff: u64);
259
260 fn auction_delay(&self) -> u64;
262
263 fn unbonding_delay(&self) -> u64;
265
266 fn delegated_amount(&self, delegator: Address, validator: PublicKey) -> U512;
268
269 fn block_time(&self) -> u64;
271
272 fn get_event(&self, contract_address: &Address, index: u32) -> Result<Bytes, EventError>;
274
275 fn get_native_event(&self, contract_address: &Address, index: u32)
277 -> Result<Bytes, EventError>;
278
279 fn get_events_count(&self, contract_address: &Address) -> Result<u32, EventError>;
281
282 fn get_native_events_count(&self, contract_address: &Address) -> Result<u32, EventError>;
284
285 fn call_contract(
287 &self,
288 address: &Address,
289 call_def: CallDef,
290 use_proxy: bool
291 ) -> OdraResult<Bytes>;
292
293 fn new_contract(
295 &self,
296 name: &str,
297 init_args: RuntimeArgs,
298 entry_points_caller: EntryPointsCaller
299 ) -> OdraResult<Address>;
300
301 fn register_contract(
303 &self,
304 address: Address,
305 contract_name: String,
306 entry_points_caller: EntryPointsCaller
307 );
308
309 fn contract_env(&self) -> ContractEnv;
311
312 fn gas_report(&self) -> GasReport;
314
315 fn last_call_gas_cost(&self) -> u64;
317
318 fn sign_message(&self, message: &Bytes, address: &Address) -> Bytes;
320
321 fn public_key(&self, address: &Address) -> PublicKey;
323
324 fn transfer(&self, to: Address, amount: U512) -> OdraResult<()>;
326}
327
328#[derive(Clone)]
333pub struct HostEnv {
334 backend: Rc<RefCell<dyn HostContext>>,
335 last_call_result: Rc<RefCell<Option<CallResult>>>,
336 deployed_contracts: Rc<RefCell<Vec<Address>>>,
337 events_count: Rc<RefCell<BTreeMap<Address, u32>>>, native_events_count: Rc<RefCell<BTreeMap<Address, u32>>>, events_initialized: Rc<RefCell<BTreeMap<Address, bool>>>,
340 captures_events: Rc<RefCell<bool>>
341}
342
343impl HostEnv {
344 pub fn new(backend: Rc<RefCell<dyn HostContext>>) -> HostEnv {
346 HostEnv {
347 backend,
348 last_call_result: RefCell::new(None).into(),
349 deployed_contracts: RefCell::new(vec![]).into(),
350 events_count: Rc::new(RefCell::new(Default::default())),
351 native_events_count: Rc::new(RefCell::new(Default::default())),
352 events_initialized: Rc::new(RefCell::new(Default::default())),
353 captures_events: Rc::new(RefCell::new(true))
354 }
355 }
356
357 pub fn set_captures_events(&self, captures: bool) {
359 *self.captures_events.borrow_mut() = captures;
360 if captures {
361 for contract in self.deployed_contracts.borrow().iter() {
363 self.init_events(contract);
364 }
365 }
366 }
367
368 pub fn get_account(&self, index: usize) -> Address {
370 let backend = self.backend.borrow();
371 backend.get_account(index)
372 }
373
374 pub fn get_validator(&self, index: usize) -> PublicKey {
376 let backend = self.backend.borrow();
377 backend.get_validator(index)
378 }
379
380 pub fn set_caller(&self, address: Address) {
382 if address.is_contract() {
383 panic!("Caller cannot be a contract: {:?}", address)
384 }
385 let backend = self.backend.borrow();
386 backend.set_caller(address)
387 }
388
389 pub fn advance_block_time(&self, time_diff: u64) {
391 let backend = self.backend.borrow();
392 backend.advance_block_time(time_diff)
393 }
394
395 pub fn advance_with_auctions(&self, time_diff: u64) {
397 let backend = self.backend.borrow();
398 backend.advance_with_auctions(time_diff);
399 }
400
401 pub fn auction_delay(&self) -> u64 {
403 let backend = self.backend.borrow();
404 backend.auction_delay()
405 }
406
407 pub fn unbonding_delay(&self) -> u64 {
409 let backend = self.backend.borrow();
410 backend.unbonding_delay()
411 }
412
413 pub fn delegated_amount(&self, delegator: Address, validator: PublicKey) -> U512 {
415 let backend = self.backend.borrow();
416 backend.delegated_amount(delegator, validator)
417 }
418
419 pub fn remove_validator(&self, index: usize) {
421 let backend = self.backend.borrow();
422 backend.remove_validator(index);
423 }
424
425 pub fn block_time(&self) -> u64 {
427 let backend = self.backend.borrow();
428 backend.block_time()
429 }
430
431 pub fn block_time_millis(&self) -> u64 {
433 let backend = self.backend.borrow();
434 backend.block_time()
435 }
436
437 pub fn block_time_secs(&self) -> u64 {
439 let backend = self.backend.borrow();
440 backend.block_time().checked_div(1000).unwrap()
441 }
442
443 pub fn new_contract(
445 &self,
446 name: &str,
447 init_args: RuntimeArgs,
448 entry_points_caller: EntryPointsCaller
449 ) -> OdraResult<Address> {
450 let backend = self.backend.borrow();
451 let deployed_contract = backend.new_contract(name, init_args, entry_points_caller)?;
452
453 self.deployed_contracts.borrow_mut().push(deployed_contract);
454 self.events_count.borrow_mut().insert(deployed_contract, 0);
455 self.native_events_count
456 .borrow_mut()
457 .insert(deployed_contract, 0);
458 self.events_initialized
459 .borrow_mut()
460 .insert(deployed_contract, true);
461 Ok(deployed_contract)
462 }
463
464 pub fn register_contract(
467 &self,
468 address: Address,
469 contract_name: String,
470 entry_points_caller: EntryPointsCaller
471 ) {
472 let backend = self.backend.borrow();
473 backend.register_contract(address, contract_name, entry_points_caller);
474 self.deployed_contracts.borrow_mut().push(address);
475 }
476
477 pub fn call_contract<T: FromBytes + CLTyped>(
479 &self,
480 address: Address,
481 call_def: CallDef
482 ) -> OdraResult<T> {
483 let use_proxy = T::cl_type() != <()>::cl_type() || !call_def.amount().is_zero();
484 let call_result = self.raw_call_contract(address, call_def, use_proxy);
485 call_result.map(|bytes| {
486 T::from_bytes(&bytes)
487 .map(|(obj, _)| obj)
488 .map_err(|_| OdraError::VmError(VmError::Deserialization))
489 })?
490 }
491
492 pub fn raw_call_contract(
495 &self,
496 address: Address,
497 call_def: CallDef,
498 use_proxy: bool
499 ) -> OdraResult<Bytes> {
500 let backend = self.backend.borrow();
501 let call_result = backend.call_contract(&address, call_def, use_proxy);
502
503 let mut events_map: BTreeMap<Address, Vec<Bytes>> = BTreeMap::new();
504 let mut native_events_map: BTreeMap<Address, Vec<Bytes>> = BTreeMap::new();
505
506 let captures_events = *self.captures_events.borrow();
507 if captures_events {
508 self.deployed_contracts
510 .borrow()
511 .iter()
512 .for_each(|contract_address| {
513 let events = self.last_events(contract_address);
514 let native_events = self.last_native_events(contract_address);
515 events_map.insert(*contract_address, events);
516 native_events_map.insert(*contract_address, native_events);
517 });
518 }
519
520 let last_call_gas_cost = backend.last_call_gas_cost();
521
522 self.last_call_result.replace(Some(CallResult::new(
523 address,
524 backend.caller(),
525 last_call_gas_cost,
526 call_result.clone(),
527 events_map,
528 native_events_map
529 )));
530
531 call_result
532 }
533
534 pub fn contract_env(&self) -> ContractEnv {
536 self.backend.borrow().contract_env()
537 }
538
539 pub fn gas_report(&self) -> GasReport {
541 self.backend.borrow().gas_report().clone()
542 }
543
544 pub fn balance_of<T: Addressable>(&self, addr: &T) -> U512 {
546 let backend = self.backend.borrow();
547 backend.balance_of(&addr.address())
548 }
549
550 pub fn get_event<T: FromBytes + EventInstance, R: Addressable>(
557 &self,
558 addr: &R,
559 index: i32
560 ) -> Result<T, EventError> {
561 let contract_address = addr.address();
562 let backend = self.backend.borrow();
563 let events_count = self.events_count(&contract_address);
564 let event_absolute_position = crate::utils::event_absolute_position(events_count, index)
565 .ok_or(EventError::IndexOutOfBounds)?;
566
567 let bytes = backend.get_event(&contract_address, event_absolute_position)?;
568 T::from_bytes(&bytes)
569 .map_err(|_| EventError::Parsing)
570 .map(|r| r.0)
571 }
572
573 pub fn get_native_event<T: FromBytes + EventInstance, R: Addressable>(
580 &self,
581 addr: &R,
582 index: i32
583 ) -> Result<T, EventError> {
584 let contract_address = addr.address();
585 let backend = self.backend.borrow();
586 let events_count = self.native_events_count(&contract_address);
587 let event_absolute_position = crate::utils::event_absolute_position(events_count, index)
588 .ok_or(EventError::IndexOutOfBounds)?;
589
590 let bytes = backend.get_native_event(&contract_address, event_absolute_position)?;
591 T::from_bytes(&bytes)
592 .map_err(|_| EventError::Parsing)
593 .map(|r| r.0)
594 }
595
596 pub fn get_event_bytes<T: Addressable>(
598 &self,
599 addr: &T,
600 index: u32
601 ) -> Result<Bytes, EventError> {
602 let backend = self.backend.borrow();
603 backend.get_event(&addr.address(), index)
604 }
605
606 pub fn get_native_event_bytes<T: Addressable>(
608 &self,
609 addr: &T,
610 index: u32
611 ) -> Result<Bytes, EventError> {
612 let backend = self.backend.borrow();
613 backend.get_native_event(&addr.address(), index)
614 }
615
616 pub fn event_names<T: Addressable>(&self, addr: &T) -> Vec<String> {
618 let events_count = self.events_count(addr);
619
620 let backend = self.backend.borrow();
621 (0..events_count)
622 .map(|event_id| {
623 backend
624 .get_event(&addr.address(), event_id)
625 .and_then(|bytes| utils::extract_event_name(&bytes))
626 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
627 })
628 .collect()
629 }
630
631 pub fn events<T: Addressable>(&self, addr: &T) -> Vec<Bytes> {
633 let backend = self.backend.borrow();
634 let contract_address = addr.address();
635 let events_count = backend
636 .get_events_count(&contract_address)
637 .unwrap_or_default();
638 (0..events_count)
639 .map(|event_id| {
640 backend
641 .get_event(&contract_address, event_id)
642 .unwrap_or_else(|e| {
643 panic!(
644 "Couldn't get event at address {:?} with id {}: {:?}",
645 &contract_address, event_id, e
646 )
647 })
648 })
649 .collect()
650 }
651
652 pub fn events_count<T: Addressable>(&self, addr: &T) -> u32 {
654 let backend = self.backend.borrow();
655 backend
656 .get_events_count(&addr.address())
657 .unwrap_or_default()
658 }
659
660 pub fn native_events_count<T: Addressable>(&self, addr: &T) -> u32 {
662 let backend = self.backend.borrow();
663 backend
664 .get_native_events_count(&addr.address())
665 .unwrap_or_default()
666 }
667
668 pub fn emitted_event<T: ToBytes + EventInstance, R: Addressable>(
670 &self,
671 addr: &R,
672 event: T
673 ) -> bool {
674 let contract_address = addr.address();
675 let events_count = self.events_count(addr);
676
677 let event_bytes = Bytes::from(
678 event
679 .to_bytes()
680 .unwrap_or_else(|_| panic!("Couldn't serialize event"))
681 );
682
683 (0..events_count)
684 .map(|event_id| {
685 self.get_event_bytes(&contract_address, event_id)
686 .unwrap_or_else(|e| {
687 panic!(
688 "Couldn't get event at address {:?} with id {}: {:?}",
689 &contract_address, event_id, e
690 )
691 })
692 })
693 .any(|bytes| bytes == event_bytes)
694 }
695
696 pub fn emitted_native_event<T: ToBytes + EventInstance, R: Addressable>(
698 &self,
699 addr: &R,
700 event: T
701 ) -> bool {
702 let contract_address = addr.address();
703 let events_count = self.native_events_count(addr);
704 if events_count > 0 {
705 let event_bytes = Bytes::from(
706 event
707 .to_bytes()
708 .unwrap_or_else(|_| panic!("Couldn't serialize event"))
709 );
710 (0..events_count)
711 .map(|event_id| {
712 self.get_native_event_bytes(&contract_address, event_id)
713 .unwrap_or_else(|e| {
714 panic!(
715 "Couldn't get event at address {:?} with id {}: {:?}",
716 &contract_address, event_id, e
717 )
718 })
719 })
720 .any(|bytes| bytes == event_bytes)
721 } else {
722 false
723 }
724 }
725
726 pub fn emitted<T: AsRef<str>, R: Addressable>(&self, addr: &R, event_name: T) -> bool {
728 let events_count = self.events_count(addr);
729
730 (0..events_count)
731 .map(|event_id| {
732 self.get_event_bytes(addr, event_id).unwrap_or_else(|e| {
733 panic!(
734 "Couldn't get event at address {:?} with id {}: {:?}",
735 addr.address(),
736 event_id,
737 e
738 )
739 })
740 })
741 .any(|bytes| {
742 utils::extract_event_name(&bytes)
743 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
744 .as_str()
745 == event_name.as_ref()
746 })
747 }
748 pub fn emitted_native<T: AsRef<str>, R: Addressable>(&self, addr: &R, event_name: T) -> bool {
750 let events_count = self.native_events_count(addr);
751
752 (0..events_count)
753 .map(|event_id| {
754 self.get_native_event_bytes(addr, event_id)
755 .unwrap_or_else(|e| {
756 panic!(
757 "Couldn't get event at address {:?} with id {}: {:?}",
758 addr.address(),
759 event_id,
760 e
761 )
762 })
763 })
764 .any(|bytes| {
765 utils::extract_event_name(&bytes)
766 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
767 .as_str()
768 == event_name.as_ref()
769 })
770 }
771
772 pub fn last_call_result(&self, contract_address: Address) -> ContractCallResult {
774 self.last_call_result
775 .borrow()
776 .clone()
777 .unwrap()
778 .contract_last_call(contract_address)
779 }
780
781 pub fn sign_message(&self, message: &Bytes, address: &Address) -> Bytes {
783 let backend = self.backend.borrow();
784 backend.sign_message(message, address)
785 }
786
787 pub fn public_key(&self, address: &Address) -> PublicKey {
789 let backend = self.backend.borrow();
790 backend.public_key(address)
791 }
792
793 pub fn caller(&self) -> Address {
795 let backend = self.backend.borrow();
796 backend.caller()
797 }
798
799 pub fn set_gas(&self, gas: u64) {
801 let backend = self.backend.borrow();
802 backend.set_gas(gas)
803 }
804
805 pub fn transfer(&self, to: Address, amount: U512) -> OdraResult<()> {
807 if to.is_contract() {
808 return Err(OdraError::ExecutionError(
809 ExecutionError::TransferToContract
810 ));
811 }
812 let backend = self.backend.borrow();
813 backend.transfer(to, amount)
814 }
815
816 fn last_events(&self, contract_address: &Address) -> Vec<Bytes> {
817 let mut old_count_binding = self.events_count.borrow_mut();
818 let old_count = *old_count_binding
819 .get(contract_address)
820 .expect("Contract address not found in events count");
821 let new_count = self.events_count(contract_address);
822 let mut events = vec![];
823 for count in old_count..new_count {
824 let event = self.get_event_bytes(contract_address, count).unwrap();
825 events.push(event);
826 }
827
828 old_count_binding.insert(*contract_address, new_count);
829 events
830 }
831
832 fn last_native_events(&self, contract_address: &Address) -> Vec<Bytes> {
833 let mut old_count_binding = self.native_events_count.borrow_mut();
834 let old_count = *old_count_binding.get(contract_address).unwrap();
835 let new_count = self.native_events_count(contract_address);
836 let mut events = vec![];
837 for count in old_count..new_count {
838 let event = self
839 .get_native_event_bytes(contract_address, count)
840 .unwrap();
841 events.push(event);
842 }
843
844 old_count_binding.insert(*contract_address, new_count);
845 events
846 }
847
848 fn init_events(&self, contract_address: &Address) {
849 let events_initialized = self
850 .events_initialized
851 .borrow()
852 .get(contract_address)
853 .copied()
854 .unwrap_or(false);
855 if !events_initialized {
856 self.events_count
857 .borrow_mut()
858 .insert(*contract_address, self.events_count(contract_address));
859 self.native_events_count.borrow_mut().insert(
860 *contract_address,
861 self.native_events_count(contract_address)
862 );
863 self.events_initialized
864 .borrow_mut()
865 .insert(*contract_address, true);
866 }
867 }
868}
869
870#[cfg(test)]
871mod test {
872 use core::fmt::Debug;
873
874 use super::*;
875 use casper_event_standard::Event;
876 use casper_types::account::AccountHash;
877 use casper_types::contracts::ContractPackageHash;
878 use mockall::{mock, predicate};
879 use std::sync::Mutex;
880
881 static IDENT_MTX: Mutex<()> = Mutex::new(());
882 static EPC_MTX: Mutex<()> = Mutex::new(());
883
884 #[derive(Debug, Event, PartialEq)]
885 struct TestEv {}
886
887 mock! {
888 TestRef {}
889 impl HasIdent for TestRef {
890 fn ident() -> String;
891 }
892 impl EntryPointsCallerProvider for TestRef {
893 fn entry_points_caller(env: &HostEnv) -> EntryPointsCaller;
894 }
895 impl HostRef for TestRef {
896 fn new(address: Address, env: HostEnv) -> Self;
897 fn with_tokens(&self, tokens: U512) -> Self;
898 fn contract_address(&self) -> Address;
899 fn env(&self) -> &HostEnv;
900 fn get_event<T>(&self, index: i32) -> Result<T, EventError> where T: FromBytes + EventInstance + 'static;
901 fn last_call(&self) -> ContractCallResult;
902 }
903 }
904
905 impl crate::ContractRef for MockTestRef {
906 fn new(_env: Rc<ContractEnv>, _address: Address) -> Self {
907 unimplemented!()
908 }
909 fn address(&self) -> &Address {
910 unimplemented!()
911 }
912
913 fn with_tokens(&self, _tokens: U512) -> Self {
914 unimplemented!()
915 }
916 }
917
918 impl OdraContract for MockTestRef {
919 type HostRef = MockTestRef;
920
921 type ContractRef = MockTestRef;
922
923 type InitArgs = NoArgs;
924 }
925
926 mock! {
927 Ev {}
928 impl Into<RuntimeArgs> for Ev {
929 fn into(self) -> RuntimeArgs;
930 }
931 }
932
933 #[test]
934 fn test_deploy_with_default_args() {
935 let _i = IDENT_MTX.lock();
940 let _e = EPC_MTX.lock();
941
942 let indent_ctx = MockTestRef::ident_context();
944 indent_ctx.expect().returning(|| "TestRef".to_string());
945
946 let epc_ctx = MockTestRef::entry_points_caller_context();
947 epc_ctx
948 .expect()
949 .returning(|h| EntryPointsCaller::new(h.clone(), vec![], |_, _| Ok(Bytes::default())));
950
951 let instance_ctx = MockTestRef::new_context();
953 instance_ctx
954 .expect()
955 .times(1)
956 .returning(|_, _| MockTestRef::default());
957
958 let mut ctx = MockHostContext::new();
959 ctx.expect_new_contract()
960 .returning(|_, _, _| Ok(Address::Account(AccountHash::new([0; 32]))));
961 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
962 MockTestRef::deploy(&env, NoArgs);
963 }
964
965 #[test]
966 fn test_load_ref() {
967 let _e = EPC_MTX.lock();
972 let _i = IDENT_MTX.lock();
973
974 let epc_ctx = MockTestRef::entry_points_caller_context();
976 epc_ctx
977 .expect()
978 .returning(|h| EntryPointsCaller::new(h.clone(), vec![], |_, _| Ok(Bytes::default())));
979 let indent_ctx = MockTestRef::ident_context();
980 indent_ctx.expect().returning(|| "TestRef".to_string());
981
982 let mut ctx = MockHostContext::new();
983 ctx.expect_register_contract().returning(|_, _, _| ());
984 ctx.expect_get_events_count().returning(|_| Ok(0));
985 ctx.expect_get_native_events_count().returning(|_| Ok(0));
986
987 let instance_ctx = MockTestRef::new_context();
989 instance_ctx
990 .expect()
991 .times(1)
992 .returning(|_, _| MockTestRef::default());
993
994 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
995 let address = Address::Account(AccountHash::new([0; 32]));
996 MockTestRef::load(&env, address);
997 }
998
999 #[test]
1000 fn test_host_env() {
1001 let mut ctx = MockHostContext::new();
1002 ctx.expect_new_contract()
1003 .returning(|_, _, _| Ok(Address::Account(AccountHash::new([0; 32]))));
1004 ctx.expect_caller()
1005 .returning(|| Address::Account(AccountHash::new([2; 32])))
1006 .times(1);
1007 ctx.expect_gas_report().returning(GasReport::new).times(1);
1008 ctx.expect_set_gas().returning(|_| ()).times(1);
1009
1010 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1011
1012 assert_eq!(env.caller(), Address::Account(AccountHash::new([2; 32])));
1013 env.gas_report();
1015 env.set_gas(1_000u64)
1016 }
1017
1018 #[test]
1019 fn test_successful_transfer_to_account() {
1020 let mut ctx = MockHostContext::new();
1022 ctx.expect_transfer().returning(|_, _| Ok(()));
1023 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1024
1025 let addr = Address::Account(AccountHash::new([0; 32]));
1026 let result = env.transfer(addr, 100.into());
1028 assert!(result.is_ok());
1030 }
1031
1032 #[test]
1033 fn test_failing_transfer_to_account() {
1034 let mut ctx = MockHostContext::new();
1036 ctx.expect_transfer()
1037 .returning(|_, _| Err(OdraError::ExecutionError(ExecutionError::UnwrapError)));
1038 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1039
1040 let addr = Address::Account(AccountHash::new([0; 32]));
1041 let result = env.transfer(addr, 100.into());
1043 assert_eq!(
1045 result.err(),
1046 Some(OdraError::ExecutionError(ExecutionError::UnwrapError))
1047 );
1048 }
1049
1050 #[test]
1051 fn test_transfer_to_contract() {
1052 let mut ctx = MockHostContext::new();
1054 ctx.expect_transfer().returning(|_, _| Ok(()));
1055 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1056
1057 let addr = Address::Contract(ContractPackageHash::new([0; 32]));
1058 let result = env.transfer(addr, 100.into());
1060 assert_eq!(
1062 result,
1063 Err(OdraError::ExecutionError(
1064 ExecutionError::TransferToContract
1065 ))
1066 );
1067 }
1068
1069 #[test]
1070 fn test_get_event() {
1071 let addr = Address::Account(AccountHash::new([0; 32]));
1072
1073 let mut ctx = MockHostContext::new();
1074 ctx.expect_get_events_count().returning(|_| Ok(2));
1076 ctx.expect_get_event()
1078 .with(predicate::always(), predicate::eq(0))
1079 .returning(|_, _| Ok(vec![1].into()));
1080 ctx.expect_get_event()
1082 .with(predicate::always(), predicate::eq(1))
1083 .returning(|_, _| Ok(TestEv {}.to_bytes().unwrap().into()));
1084
1085 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1086
1087 assert_eq!(env.get_event(&addr, 1), Ok(TestEv {}));
1088 assert_eq!(env.get_event(&addr, -1), Ok(TestEv {}));
1089 assert_eq!(
1090 env.get_event::<TestEv, _>(&addr, 0),
1091 Err(EventError::Parsing)
1092 );
1093 assert_eq!(
1094 env.get_event::<TestEv, _>(&addr, -2),
1095 Err(EventError::Parsing)
1096 );
1097 assert_eq!(
1098 env.get_event::<TestEv, _>(&addr, 2),
1099 Err(EventError::IndexOutOfBounds)
1100 );
1101 assert_eq!(
1102 env.get_event::<TestEv, _>(&addr, -3),
1103 Err(EventError::IndexOutOfBounds)
1104 );
1105 }
1106
1107 #[test]
1108 fn test_events_works() {
1109 let addr = Address::Account(AccountHash::new([0; 32]));
1110
1111 let mut ctx = MockHostContext::new();
1112 ctx.expect_get_events_count().returning(|_| Ok(2));
1114 ctx.expect_get_event()
1116 .with(predicate::always(), predicate::eq(0))
1117 .returning(|_, _| Ok(vec![1].into()));
1118 ctx.expect_get_event()
1120 .with(predicate::always(), predicate::eq(1))
1121 .returning(|_, _| Ok(vec![1, 0, 1].into()));
1122
1123 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1124
1125 assert_eq!(
1126 env.events(&addr),
1127 vec![vec![1].into(), vec![1, 0, 1].into()]
1128 );
1129 }
1130
1131 #[test]
1132 #[should_panic(
1133 expected = "Couldn't get event at address Account(AccountHash(0000000000000000000000000000000000000000000000000000000000000000)) with id 0: CouldntExtractEventData"
1134 )]
1135 fn test_events_fails() {
1136 let addr = Address::Account(AccountHash::new([0; 32]));
1137
1138 let mut ctx = MockHostContext::new();
1139 ctx.expect_get_events_count().returning(|_| Ok(2));
1141 ctx.expect_get_event()
1143 .with(predicate::always(), predicate::eq(0))
1144 .returning(|_, _| Err(EventError::CouldntExtractEventData));
1145
1146 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1147
1148 env.events(&addr);
1149 }
1150
1151 #[test]
1152 fn test_emitted() {
1153 let addr = Address::Account(AccountHash::new([0; 32]));
1154 let mut ctx = MockHostContext::new();
1155
1156 ctx.expect_get_events_count().returning(|_| Ok(1));
1157 ctx.expect_get_event()
1158 .returning(|_, _| Ok(TestEv {}.to_bytes().unwrap().into()));
1159
1160 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1161 assert!(env.emitted(&addr, "TestEv"));
1162 assert!(!env.emitted(&addr, "AnotherEvent"));
1163 }
1164}