1mod deployed_contracts;
4
5use crate::address::Addressable;
6use crate::gas_report::GasReport;
7use crate::host::deployed_contracts::DeployedContract;
8use crate::{
9 call_result::CallResult, entry_point_callback::EntryPointsCaller, CallDef, ContractCallResult,
10 ContractEnv, EventError, VmError
11};
12#[cfg(not(target_arch = "wasm32"))]
13use crate::{consts, contract::OdraContract, contract_def::HasIdent};
14use crate::{prelude::*, utils};
15use casper_event_standard::EventInstance;
16use casper_types::{
17 bytesrepr::{Bytes, FromBytes, ToBytes},
18 CLTyped, PublicKey, RuntimeArgs, U512
19};
20
21pub trait HostRef {
23 fn new(address: Address, env: HostEnv) -> Self;
25 fn with_tokens(&self, tokens: U512) -> Self;
30 fn contract_address(&self) -> Address;
32 fn env(&self) -> &HostEnv;
34 fn get_event<T>(&self, index: i32) -> Result<T, EventError>
38 where
39 T: FromBytes + EventInstance + 'static;
40 fn last_call(&self) -> ContractCallResult;
42}
43
44impl<T: HostRef> Addressable for T {
45 fn address(&self) -> Address {
46 HostRef::contract_address(self)
47 }
48}
49
50pub trait HostRefLoader<T: HostRef> {
54 fn load(env: &HostEnv, address: Address) -> T;
56}
57
58pub trait EntryPointsCallerProvider {
60 fn entry_points_caller(env: &HostEnv) -> EntryPointsCaller;
62}
63
64#[cfg(not(target_arch = "wasm32"))]
71pub trait Deployer<R: OdraContract>: Sized {
72 fn deploy(env: &HostEnv, init_args: R::InitArgs) -> R::HostRef;
81
82 fn try_deploy(env: &HostEnv, init_args: R::InitArgs) -> OdraResult<R::HostRef>;
86
87 fn deploy_with_cfg(env: &HostEnv, init_args: R::InitArgs, cfg: InstallConfig) -> R::HostRef;
91
92 fn try_deploy_with_cfg(
96 env: &HostEnv,
97 init_args: R::InitArgs,
98 cfg: InstallConfig
99 ) -> OdraResult<R::HostRef>;
100
101 fn try_upgrade(
103 env: &HostEnv,
104 address: Address,
105 init_args: R::UpgradeArgs
106 ) -> OdraResult<R::HostRef>;
107
108 fn try_upgrade_with_cfg(
110 env: &HostEnv,
111 address: Address,
112 upgrade_args: R::UpgradeArgs,
113 cfg: UpgradeConfig
114 ) -> OdraResult<R::HostRef>;
115}
116
117pub trait InitArgs: Into<RuntimeArgs> {}
119pub trait UpgradeArgs: Into<RuntimeArgs> {}
121
122pub struct NoArgs;
128
129impl InitArgs for NoArgs {}
130
131impl UpgradeArgs for NoArgs {}
132
133impl From<NoArgs> for RuntimeArgs {
134 fn from(_: NoArgs) -> Self {
135 RuntimeArgs::new()
136 }
137}
138
139#[cfg(not(target_arch = "wasm32"))]
144pub struct InstallConfig {
145 pub package_named_key: String,
149 pub is_upgradable: bool,
153 pub allow_key_override: bool
155}
156
157#[cfg(not(target_arch = "wasm32"))]
162pub struct UpgradeConfig {
163 pub package_named_key: String,
167 pub force_create_upgrade_group: bool,
170 pub allow_key_override: bool
172}
173
174#[cfg(not(target_arch = "wasm32"))]
175impl InstallConfig {
176 pub fn new<T: HasIdent>(is_upgradable: bool, allow_key_override: bool) -> Self {
178 InstallConfig {
179 package_named_key: T::ident(),
180 is_upgradable,
181 allow_key_override
182 }
183 }
184
185 pub fn upgradable<T: HasIdent>() -> Self {
187 InstallConfig::new::<T>(true, true)
188 }
189}
190
191#[cfg(not(target_arch = "wasm32"))]
192impl UpgradeConfig {
193 pub fn new<T: HasIdent>() -> Self {
196 UpgradeConfig {
197 package_named_key: T::ident(),
198 force_create_upgrade_group: false,
199 allow_key_override: true
200 }
201 }
202}
203
204#[cfg(not(target_arch = "wasm32"))]
205impl<R: OdraContract> Deployer<R> for R {
206 fn deploy(
207 env: &HostEnv,
208 init_args: <R as OdraContract>::InitArgs
209 ) -> <R as OdraContract>::HostRef {
210 let contract_ident = R::HostRef::ident();
211 match Self::try_deploy(env, init_args) {
212 Ok(contract) => contract,
213 Err(OdraError::ExecutionError(ExecutionError::MissingArg)) => {
214 core::panic!("Invalid init args for contract {}.", contract_ident)
215 }
216 Err(e) => core::panic!("Contract init failed {:?}", e)
217 }
218 }
219
220 fn try_deploy(
221 env: &HostEnv,
222 init_args: <R as OdraContract>::InitArgs
223 ) -> OdraResult<<R as OdraContract>::HostRef> {
224 Self::try_deploy_with_cfg(
225 env,
226 init_args,
227 InstallConfig::new::<<R as OdraContract>::HostRef>(false, true)
228 )
229 }
230
231 fn deploy_with_cfg(
232 env: &HostEnv,
233 init_args: <R as OdraContract>::InitArgs,
234 cfg: InstallConfig
235 ) -> <R as OdraContract>::HostRef {
236 let contract_ident = R::HostRef::ident();
237 match Self::try_deploy_with_cfg(env, init_args, cfg) {
238 Ok(contract) => contract,
239 Err(OdraError::ExecutionError(ExecutionError::MissingArg)) => {
240 core::panic!("Invalid init args for contract {}.", contract_ident)
241 }
242 Err(e) => core::panic!("Contract init failed {:?}", e)
243 }
244 }
245
246 fn try_deploy_with_cfg(
247 env: &HostEnv,
248 init_args: <R as OdraContract>::InitArgs,
249 cfg: InstallConfig
250 ) -> OdraResult<<R as OdraContract>::HostRef> {
251 let contract_ident = R::HostRef::ident();
252 let caller = R::HostRef::entry_points_caller(env);
253
254 let mut init_args = init_args.into();
255 init_args.insert(consts::IS_UPGRADABLE_ARG, cfg.is_upgradable)?;
256 init_args.insert(consts::IS_UPGRADE_ARG, false)?;
257 init_args.insert(consts::ALLOW_KEY_OVERRIDE_ARG, cfg.allow_key_override)?;
258 init_args.insert(
259 consts::PACKAGE_HASH_KEY_NAME_ARG,
260 format!("{}_package_hash", cfg.package_named_key)
261 )?;
262
263 let address = env.new_contract(&contract_ident, init_args, caller)?;
264 Ok(R::HostRef::new(address, env.clone()))
265 }
266
267 fn try_upgrade(
268 env: &HostEnv,
269 contract_to_upgrade: Address,
270 upgrade_args: <R as OdraContract>::UpgradeArgs
271 ) -> OdraResult<<R as OdraContract>::HostRef> {
272 Self::try_upgrade_with_cfg(
273 env,
274 contract_to_upgrade,
275 upgrade_args,
276 UpgradeConfig::new::<<R as OdraContract>::HostRef>()
277 )
278 }
279
280 fn try_upgrade_with_cfg(
281 env: &HostEnv,
282 contract_to_upgrade: Address,
283 upgrade_args: <R as OdraContract>::UpgradeArgs,
284 cfg: UpgradeConfig
285 ) -> OdraResult<<R as OdraContract>::HostRef> {
286 let mut upgrade_args = upgrade_args.into();
287 upgrade_args.insert(consts::IS_UPGRADE_ARG, true)?;
288 upgrade_args.insert(
289 consts::PACKAGE_HASH_TO_UPGRADE_ARG,
290 contract_to_upgrade.value()
291 )?;
292 upgrade_args.insert(consts::ALLOW_KEY_OVERRIDE_ARG, cfg.allow_key_override)?;
293 upgrade_args.insert(
294 consts::PACKAGE_HASH_KEY_NAME_ARG,
295 format!("{}_package_hash", cfg.package_named_key)
296 )?;
297 upgrade_args.insert(consts::CREATE_UPGRADE_GROUP, cfg.force_create_upgrade_group)?;
298 let contract_ident = R::HostRef::ident();
299 let entry_points_caller = R::HostRef::entry_points_caller(env);
300
301 let address = env.upgrade_contract(
302 &contract_ident,
303 contract_to_upgrade,
304 upgrade_args,
305 entry_points_caller
306 )?;
307 Ok(HostRef::new(address, env.clone()))
308 }
309}
310
311#[cfg(not(target_arch = "wasm32"))]
312impl<T: OdraContract> HostRefLoader<T::HostRef> for T {
313 fn load(env: &HostEnv, address: Address) -> T::HostRef {
314 let caller = T::HostRef::entry_points_caller(env);
315 let contract_name = T::HostRef::ident();
316 env.register_contract(address, contract_name, caller);
317 T::HostRef::new(address, env.clone())
318 }
319}
320
321#[cfg_attr(test, mockall::automock)]
323pub trait HostContext {
324 fn set_caller(&self, caller: Address);
326
327 fn set_gas(&self, gas: u64);
329
330 fn caller(&self) -> Address;
332
333 fn get_account(&self, index: usize) -> Address;
335
336 fn get_validator(&self, index: usize) -> PublicKey;
338
339 fn remove_validator(&self, index: usize);
341
342 fn balance_of(&self, address: &Address) -> U512;
344
345 fn advance_block_time(&self, time_diff: u64);
347
348 fn advance_with_auctions(&self, time_diff: u64);
350
351 fn auction_delay(&self) -> u64;
353
354 fn unbonding_delay(&self) -> u64;
356
357 fn delegated_amount(&self, delegator: Address, validator: PublicKey) -> U512;
359
360 fn block_time(&self) -> u64;
362
363 fn get_event(&self, contract_address: &Address, index: u32) -> Result<Bytes, EventError>;
365
366 fn get_native_event(&self, contract_address: &Address, index: u32)
368 -> Result<Bytes, EventError>;
369
370 fn get_events_count(&self, contract_address: &Address) -> Result<u32, EventError>;
372
373 fn get_native_events_count(&self, contract_address: &Address) -> Result<u32, EventError>;
375
376 fn call_contract(
378 &self,
379 address: &Address,
380 call_def: CallDef,
381 use_proxy: bool
382 ) -> OdraResult<Bytes>;
383
384 fn new_contract(
386 &self,
387 name: &str,
388 init_args: RuntimeArgs,
389 entry_points_caller: EntryPointsCaller
390 ) -> OdraResult<Address>;
391
392 fn upgrade_contract(
395 &self,
396 name: &str,
397 contract_to_upgrade: Address,
398 upgrade_args: RuntimeArgs,
399 entry_points_caller: EntryPointsCaller
400 ) -> OdraResult<Address>;
401
402 fn register_contract(
404 &self,
405 address: Address,
406 contract_name: String,
407 entry_points_caller: EntryPointsCaller
408 );
409
410 fn contract_env(&self) -> ContractEnv;
412
413 fn gas_report(&self) -> GasReport;
415
416 fn last_call_gas_cost(&self) -> u64;
418
419 fn sign_message(&self, message: &Bytes, address: &Address) -> Bytes;
421
422 fn public_key(&self, address: &Address) -> PublicKey;
424
425 fn transfer(&self, to: Address, amount: U512) -> OdraResult<()>;
427}
428
429#[derive(Clone)]
434pub struct HostEnv {
435 backend: Rc<RefCell<dyn HostContext>>,
436 last_call_result: Rc<RefCell<Option<CallResult>>>,
437 deployed_contracts: Rc<RefCell<BTreeMap<Address, DeployedContract>>>,
438 captures_events: Rc<RefCell<bool>>
439}
440
441impl HostEnv {
442 pub fn new(backend: Rc<RefCell<dyn HostContext>>) -> HostEnv {
444 HostEnv {
445 backend,
446 last_call_result: RefCell::new(None).into(),
447 deployed_contracts: RefCell::new(Default::default()).into(),
448 captures_events: Rc::new(RefCell::new(true))
449 }
450 }
451
452 pub fn set_captures_events(&self, captures: bool) {
454 *self.captures_events.borrow_mut() = captures;
455 if captures {
456 for (contract_address, _) in self.deployed_contracts.borrow().iter() {
458 self.init_events(contract_address);
459 }
460 }
461 }
462
463 pub fn get_account(&self, index: usize) -> Address {
465 let backend = self.backend.borrow();
466 backend.get_account(index)
467 }
468
469 pub fn get_validator(&self, index: usize) -> PublicKey {
471 let backend = self.backend.borrow();
472 backend.get_validator(index)
473 }
474
475 pub fn set_caller(&self, address: Address) {
477 if address.is_contract() {
478 panic!("Caller cannot be a contract: {:?}", address)
479 }
480 let backend = self.backend.borrow();
481 backend.set_caller(address)
482 }
483
484 pub fn advance_block_time(&self, time_diff: u64) {
486 let backend = self.backend.borrow();
487 backend.advance_block_time(time_diff)
488 }
489
490 pub fn advance_with_auctions(&self, time_diff: u64) {
493 let backend = self.backend.borrow();
494 backend.advance_with_auctions(time_diff);
495 }
496
497 pub fn auction_delay(&self) -> u64 {
499 let backend = self.backend.borrow();
500 backend.auction_delay()
501 }
502
503 pub fn unbonding_delay(&self) -> u64 {
505 let backend = self.backend.borrow();
506 backend.unbonding_delay()
507 }
508
509 pub fn delegated_amount(&self, delegator: Address, validator: PublicKey) -> U512 {
511 let backend = self.backend.borrow();
512 backend.delegated_amount(delegator, validator)
513 }
514
515 pub fn remove_validator(&self, index: usize) {
517 let backend = self.backend.borrow();
518 backend.remove_validator(index);
519 }
520
521 pub fn block_time(&self) -> u64 {
523 let backend = self.backend.borrow();
524 backend.block_time()
525 }
526
527 pub fn block_time_millis(&self) -> u64 {
529 let backend = self.backend.borrow();
530 backend.block_time()
531 }
532
533 pub fn block_time_secs(&self) -> u64 {
535 let backend = self.backend.borrow();
536 backend.block_time().checked_div(1000).unwrap()
537 }
538
539 pub fn new_contract(
541 &self,
542 name: &str,
543 init_args: RuntimeArgs,
544 entry_points_caller: EntryPointsCaller
545 ) -> OdraResult<Address> {
546 let mut entry_points_caller = entry_points_caller.clone();
548 entry_points_caller.remove_entry_point("upgrade");
549
550 let backend = self.backend.borrow();
551 let contract_address = backend.new_contract(name, init_args, entry_points_caller)?;
552
553 self.deployed_contracts
554 .borrow_mut()
555 .insert(contract_address, DeployedContract::new(contract_address));
556 Ok(contract_address)
557 }
558
559 pub fn upgrade_contract(
562 &self,
563 name: &str,
564 contract_to_upgrade: Address,
565 upgrade_args: RuntimeArgs,
566 entry_points_caller: EntryPointsCaller
567 ) -> OdraResult<Address> {
568 let mut entry_points_caller = entry_points_caller.clone();
570 entry_points_caller.remove_entry_point("init");
571
572 let backend = self.backend.borrow();
573 let upgraded_contract = backend.upgrade_contract(
574 name,
575 contract_to_upgrade,
576 upgrade_args,
577 entry_points_caller
578 )?;
579 let mut contracts = self.deployed_contracts.borrow_mut();
580 let contract = contracts.get_mut(&upgraded_contract).unwrap();
581 contract.current_version += 1;
582 contract.native_events_count = 0;
584 Ok(upgraded_contract)
585 }
586
587 pub fn register_contract(
590 &self,
591 address: Address,
592 contract_name: String,
593 entry_points_caller: EntryPointsCaller
594 ) {
595 let backend = self.backend.borrow();
596 backend.register_contract(address, contract_name, entry_points_caller);
597 self.deployed_contracts
598 .borrow_mut()
599 .insert(address, DeployedContract::new(address));
600 }
601
602 pub fn call_contract<T: FromBytes + CLTyped>(
604 &self,
605 address: Address,
606 call_def: CallDef
607 ) -> OdraResult<T> {
608 let use_proxy = T::cl_type() != <()>::cl_type() || !call_def.amount().is_zero();
609 let call_result = self.raw_call_contract(address, call_def, use_proxy);
610 call_result.map(|bytes| {
611 T::from_bytes(&bytes)
612 .map(|(obj, _)| obj)
613 .map_err(|_| OdraError::VmError(VmError::Deserialization))
614 })?
615 }
616
617 pub fn raw_call_contract(
620 &self,
621 address: Address,
622 call_def: CallDef,
623 use_proxy: bool
624 ) -> OdraResult<Bytes> {
625 let call_result = {
626 let backend = self.backend.borrow();
627 backend.call_contract(&address, call_def, use_proxy)
628 };
629
630 let mut events_map: BTreeMap<Address, Vec<Bytes>> = BTreeMap::new();
631 let mut native_events_map: BTreeMap<Address, Vec<Bytes>> = BTreeMap::new();
632
633 let captures_events = *self.captures_events.borrow();
634 if captures_events {
635 self.deployed_contracts.borrow_mut().iter_mut().for_each(
637 |(contract_address, contract)| {
638 let events = self.last_events(contract);
639 let native_events = self.last_native_events(contract);
640 events_map.insert(*contract_address, events);
641 native_events_map.insert(*contract_address, native_events);
642 }
643 );
644 }
645
646 let backend = self.backend.borrow();
647 let last_call_gas_cost = backend.last_call_gas_cost();
648
649 self.last_call_result.replace(Some(CallResult::new(
650 address,
651 backend.caller(),
652 last_call_gas_cost,
653 call_result.clone(),
654 events_map,
655 native_events_map
656 )));
657
658 call_result
659 }
660
661 pub fn contract_env(&self) -> ContractEnv {
663 self.backend.borrow().contract_env()
664 }
665
666 pub fn gas_report(&self) -> GasReport {
668 self.backend.borrow().gas_report().clone()
669 }
670
671 pub fn balance_of<T: Addressable>(&self, addr: &T) -> U512 {
673 let backend = self.backend.borrow();
674 backend.balance_of(&addr.address())
675 }
676
677 pub fn get_event<T: FromBytes + EventInstance, R: Addressable>(
684 &self,
685 addr: &R,
686 index: i32
687 ) -> Result<T, EventError> {
688 let contract_address = addr.address();
689 let backend = self.backend.borrow();
690 let events_count = self.events_count(&contract_address);
691 let event_absolute_position = crate::utils::event_absolute_position(events_count, index)
692 .ok_or(EventError::IndexOutOfBounds)?;
693
694 let bytes = backend.get_event(&contract_address, event_absolute_position)?;
695 T::from_bytes(&bytes)
696 .map_err(|_| EventError::Parsing)
697 .map(|r| r.0)
698 }
699
700 pub fn get_native_event<T: FromBytes + EventInstance, R: Addressable>(
707 &self,
708 addr: &R,
709 index: i32
710 ) -> Result<T, EventError> {
711 let contract_address = addr.address();
712 let backend = self.backend.borrow();
713 let events_count = self.native_events_count(&contract_address);
714 let event_absolute_position = crate::utils::event_absolute_position(events_count, index)
715 .ok_or(EventError::IndexOutOfBounds)?;
716
717 let bytes = backend.get_native_event(&contract_address, event_absolute_position)?;
718 T::from_bytes(&bytes)
719 .map_err(|_| EventError::Parsing)
720 .map(|r| r.0)
721 }
722
723 pub fn get_event_bytes<T: Addressable>(
725 &self,
726 addr: &T,
727 index: u32
728 ) -> Result<Bytes, EventError> {
729 let backend = self.backend.borrow();
730 backend.get_event(&addr.address(), index)
731 }
732
733 pub fn get_native_event_bytes<T: Addressable>(
735 &self,
736 addr: &T,
737 index: u32
738 ) -> Result<Bytes, EventError> {
739 let backend = self.backend.borrow();
740 backend.get_native_event(&addr.address(), index)
741 }
742
743 pub fn event_names<T: Addressable>(&self, addr: &T) -> Vec<String> {
745 let events_count = self.events_count(addr);
746
747 let backend = self.backend.borrow();
748 (0..events_count)
749 .map(|event_id| {
750 backend
751 .get_event(&addr.address(), event_id)
752 .and_then(|bytes| utils::extract_event_name(&bytes))
753 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
754 })
755 .collect()
756 }
757
758 pub fn events<T: Addressable>(&self, addr: &T) -> Vec<Bytes> {
760 let backend = self.backend.borrow();
761 let contract_address = addr.address();
762 let events_count = backend
763 .get_events_count(&contract_address)
764 .unwrap_or_default();
765 (0..events_count)
766 .map(|event_id| {
767 backend
768 .get_event(&contract_address, event_id)
769 .unwrap_or_else(|e| {
770 panic!(
771 "Couldn't get event at address {:?} with id {}: {:?}",
772 &contract_address, event_id, e
773 )
774 })
775 })
776 .collect()
777 }
778
779 pub fn events_count<T: Addressable>(&self, addr: &T) -> u32 {
781 let backend = self.backend.borrow();
782 backend
783 .get_events_count(&addr.address())
784 .unwrap_or_default()
785 }
786
787 pub fn native_events_count<T: Addressable>(&self, addr: &T) -> u32 {
789 let backend = self.backend.borrow();
790 backend
791 .get_native_events_count(&addr.address())
792 .unwrap_or_default()
793 }
794
795 pub fn emitted_event<T: ToBytes + EventInstance, R: Addressable>(
797 &self,
798 addr: &R,
799 event: T
800 ) -> bool {
801 let contract_address = addr.address();
802 let events_count = self.events_count(addr);
803
804 let event_bytes = Bytes::from(
805 event
806 .to_bytes()
807 .unwrap_or_else(|_| panic!("Couldn't serialize event"))
808 );
809
810 (0..events_count)
811 .map(|event_id| {
812 self.get_event_bytes(&contract_address, event_id)
813 .unwrap_or_else(|e| {
814 panic!(
815 "Couldn't get event at address {:?} with id {}: {:?}",
816 &contract_address, event_id, e
817 )
818 })
819 })
820 .any(|bytes| bytes == event_bytes)
821 }
822
823 pub fn emitted_native_event<T: ToBytes + EventInstance, R: Addressable>(
825 &self,
826 addr: &R,
827 event: T
828 ) -> bool {
829 let contract_address = addr.address();
830 let events_count = self.native_events_count(addr);
831 if events_count > 0 {
832 let event_bytes = Bytes::from(
833 event
834 .to_bytes()
835 .unwrap_or_else(|_| panic!("Couldn't serialize event"))
836 );
837 (0..events_count)
838 .map(|event_id| {
839 self.get_native_event_bytes(&contract_address, event_id)
840 .unwrap_or_else(|e| {
841 panic!(
842 "Couldn't get event at address {:?} with id {}: {:?}",
843 &contract_address, event_id, e
844 )
845 })
846 })
847 .any(|bytes| bytes == event_bytes)
848 } else {
849 false
850 }
851 }
852
853 pub fn emitted<T: AsRef<str>, R: Addressable>(&self, addr: &R, event_name: T) -> bool {
855 let events_count = self.events_count(addr);
856
857 (0..events_count)
858 .map(|event_id| {
859 self.get_event_bytes(addr, event_id).unwrap_or_else(|e| {
860 panic!(
861 "Couldn't get event at address {:?} with id {}: {:?}",
862 addr.address(),
863 event_id,
864 e
865 )
866 })
867 })
868 .any(|bytes| {
869 utils::extract_event_name(&bytes)
870 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
871 .as_str()
872 == event_name.as_ref()
873 })
874 }
875 pub fn emitted_native<T: AsRef<str>, R: Addressable>(&self, addr: &R, event_name: T) -> bool {
877 let events_count = self.native_events_count(addr);
878
879 (0..events_count)
880 .map(|event_id| {
881 self.get_native_event_bytes(addr, event_id)
882 .unwrap_or_else(|e| {
883 panic!(
884 "Couldn't get event at address {:?} with id {}: {:?}",
885 addr.address(),
886 event_id,
887 e
888 )
889 })
890 })
891 .any(|bytes| {
892 utils::extract_event_name(&bytes)
893 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
894 .as_str()
895 == event_name.as_ref()
896 })
897 }
898
899 pub fn last_call_result(&self, contract_address: Address) -> ContractCallResult {
901 self.last_call_result
902 .borrow()
903 .clone()
904 .unwrap()
905 .contract_last_call(contract_address)
906 }
907
908 pub fn sign_message(&self, message: &Bytes, address: &Address) -> Bytes {
910 let backend = self.backend.borrow();
911 backend.sign_message(message, address)
912 }
913
914 pub fn public_key(&self, address: &Address) -> PublicKey {
916 let backend = self.backend.borrow();
917 backend.public_key(address)
918 }
919
920 pub fn caller(&self) -> Address {
922 let backend = self.backend.borrow();
923 backend.caller()
924 }
925
926 pub fn set_gas(&self, gas: u64) {
928 let backend = self.backend.borrow();
929 backend.set_gas(gas)
930 }
931
932 pub fn transfer(&self, to: Address, amount: U512) -> OdraResult<()> {
934 if to.is_contract() {
935 return Err(OdraError::ExecutionError(
936 ExecutionError::TransferToContract
937 ));
938 }
939 let backend = self.backend.borrow();
940 backend.transfer(to, amount)
941 }
942
943 fn last_events(&self, contract: &mut DeployedContract) -> Vec<Bytes> {
944 let old_count = contract.events_count;
945 let new_count = self.events_count(&contract.address);
946 let mut events = vec![];
947 for count in old_count..new_count {
948 let event = self.get_event_bytes(&contract.address, count).unwrap();
949 events.push(event);
950 }
951
952 contract.events_count = new_count;
953 events
954 }
955
956 fn last_native_events(&self, contract: &mut DeployedContract) -> Vec<Bytes> {
957 let old_count = contract.native_events_count;
958 let new_count = self.native_events_count(&contract.address);
959 let mut events = vec![];
960 for count in old_count..new_count {
961 let event = self
962 .get_native_event_bytes(&contract.address, count)
963 .unwrap();
964 events.push(event);
965 }
966
967 contract.native_events_count = new_count;
968 events
969 }
970
971 fn init_events(&self, contract_address: &Address) {
972 let mut contracts = self.deployed_contracts.borrow_mut();
973 let contract = contracts.get_mut(contract_address).unwrap();
974
975 if !contract.events_initialized {
976 contract.events_count = self.events_count(contract_address);
977 contract.native_events_count = self.native_events_count(contract_address);
978 contract.events_initialized = true;
979 }
980 }
981}
982
983#[cfg(test)]
984mod test {
985 use core::fmt::Debug;
986
987 use super::*;
988 use casper_event_standard::Event;
989 use casper_types::account::AccountHash;
990 use casper_types::contracts::ContractPackageHash;
991 use mockall::{mock, predicate};
992 use std::sync::Mutex;
993
994 static IDENT_MTX: Mutex<()> = Mutex::new(());
995 static EPC_MTX: Mutex<()> = Mutex::new(());
996
997 #[derive(Debug, Event, PartialEq)]
998 struct TestEv {}
999
1000 mock! {
1001 TestRef {}
1002 impl HasIdent for TestRef {
1003 fn ident() -> String;
1004 }
1005 impl EntryPointsCallerProvider for TestRef {
1006 fn entry_points_caller(env: &HostEnv) -> EntryPointsCaller;
1007 }
1008 impl HostRef for TestRef {
1009 fn new(address: Address, env: HostEnv) -> Self;
1010 fn with_tokens(&self, tokens: U512) -> Self;
1011 fn contract_address(&self) -> Address;
1012 fn env(&self) -> &HostEnv;
1013 fn get_event<T>(&self, index: i32) -> Result<T, EventError> where T: FromBytes + EventInstance + 'static;
1014 fn last_call(&self) -> ContractCallResult;
1015 }
1016 }
1017
1018 impl crate::ContractRef for MockTestRef {
1019 fn new(_env: Rc<ContractEnv>, _address: Address) -> Self {
1020 unimplemented!()
1021 }
1022 fn address(&self) -> &Address {
1023 unimplemented!()
1024 }
1025
1026 fn with_tokens(&self, _tokens: U512) -> Self {
1027 unimplemented!()
1028 }
1029 }
1030
1031 impl OdraContract for MockTestRef {
1032 type HostRef = MockTestRef;
1033
1034 type ContractRef = MockTestRef;
1035
1036 type InitArgs = NoArgs;
1037
1038 type UpgradeArgs = NoArgs;
1039 }
1040
1041 mock! {
1042 Ev {}
1043 impl Into<RuntimeArgs> for Ev {
1044 fn into(self) -> RuntimeArgs;
1045 }
1046 }
1047
1048 #[test]
1049 fn test_deploy_with_default_args() {
1050 let _i = IDENT_MTX.lock();
1055 let _e = EPC_MTX.lock();
1056
1057 let indent_ctx = MockTestRef::ident_context();
1059 indent_ctx.expect().returning(|| "TestRef".to_string());
1060
1061 let epc_ctx = MockTestRef::entry_points_caller_context();
1062 epc_ctx
1063 .expect()
1064 .returning(|h| EntryPointsCaller::new(h.clone(), vec![], |_, _| Ok(Bytes::default())));
1065
1066 let instance_ctx = MockTestRef::new_context();
1068 instance_ctx
1069 .expect()
1070 .times(1)
1071 .returning(|_, _| MockTestRef::default());
1072
1073 let mut ctx = MockHostContext::new();
1074 ctx.expect_new_contract()
1075 .returning(|_, _, _| Ok(Address::Account(AccountHash::new([0; 32]))));
1076 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1077 MockTestRef::deploy(&env, NoArgs);
1078 }
1079
1080 #[test]
1081 fn test_load_ref() {
1082 let _e = EPC_MTX.lock();
1087 let _i = IDENT_MTX.lock();
1088
1089 let epc_ctx = MockTestRef::entry_points_caller_context();
1091 epc_ctx
1092 .expect()
1093 .returning(|h| EntryPointsCaller::new(h.clone(), vec![], |_, _| Ok(Bytes::default())));
1094 let indent_ctx = MockTestRef::ident_context();
1095 indent_ctx.expect().returning(|| "TestRef".to_string());
1096
1097 let mut ctx = MockHostContext::new();
1098 ctx.expect_register_contract().returning(|_, _, _| ());
1099 ctx.expect_get_events_count().returning(|_| Ok(0));
1100 ctx.expect_get_native_events_count().returning(|_| Ok(0));
1101
1102 let instance_ctx = MockTestRef::new_context();
1104 instance_ctx
1105 .expect()
1106 .times(1)
1107 .returning(|_, _| MockTestRef::default());
1108
1109 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1110 let address = Address::Account(AccountHash::new([0; 32]));
1111 MockTestRef::load(&env, address);
1112 }
1113
1114 #[test]
1115 fn test_host_env() {
1116 let mut ctx = MockHostContext::new();
1117 ctx.expect_new_contract()
1118 .returning(|_, _, _| Ok(Address::Account(AccountHash::new([0; 32]))));
1119 ctx.expect_caller()
1120 .returning(|| Address::Account(AccountHash::new([2; 32])))
1121 .times(1);
1122 ctx.expect_gas_report().returning(GasReport::new).times(1);
1123 ctx.expect_set_gas().returning(|_| ()).times(1);
1124
1125 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1126
1127 assert_eq!(env.caller(), Address::Account(AccountHash::new([2; 32])));
1128 env.gas_report();
1130 env.set_gas(1_000u64)
1131 }
1132
1133 #[test]
1134 fn test_successful_transfer_to_account() {
1135 let mut ctx = MockHostContext::new();
1137 ctx.expect_transfer().returning(|_, _| Ok(()));
1138 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1139
1140 let addr = Address::Account(AccountHash::new([0; 32]));
1141 let result = env.transfer(addr, 100.into());
1143 assert!(result.is_ok());
1145 }
1146
1147 #[test]
1148 fn test_failing_transfer_to_account() {
1149 let mut ctx = MockHostContext::new();
1151 ctx.expect_transfer()
1152 .returning(|_, _| Err(OdraError::ExecutionError(ExecutionError::UnwrapError)));
1153 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1154
1155 let addr = Address::Account(AccountHash::new([0; 32]));
1156 let result = env.transfer(addr, 100.into());
1158 assert_eq!(
1160 result.err(),
1161 Some(OdraError::ExecutionError(ExecutionError::UnwrapError))
1162 );
1163 }
1164
1165 #[test]
1166 fn test_transfer_to_contract() {
1167 let mut ctx = MockHostContext::new();
1169 ctx.expect_transfer().returning(|_, _| Ok(()));
1170 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1171
1172 let addr = Address::Contract(ContractPackageHash::new([0; 32]));
1173 let result = env.transfer(addr, 100.into());
1175 assert_eq!(
1177 result,
1178 Err(OdraError::ExecutionError(
1179 ExecutionError::TransferToContract
1180 ))
1181 );
1182 }
1183
1184 #[test]
1185 fn test_get_event() {
1186 let addr = Address::Account(AccountHash::new([0; 32]));
1187
1188 let mut ctx = MockHostContext::new();
1189 ctx.expect_get_events_count().returning(|_| Ok(2));
1191 ctx.expect_get_event()
1193 .with(predicate::always(), predicate::eq(0))
1194 .returning(|_, _| Ok(vec![1].into()));
1195 ctx.expect_get_event()
1197 .with(predicate::always(), predicate::eq(1))
1198 .returning(|_, _| Ok(TestEv {}.to_bytes().unwrap().into()));
1199
1200 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1201
1202 assert_eq!(env.get_event(&addr, 1), Ok(TestEv {}));
1203 assert_eq!(env.get_event(&addr, -1), Ok(TestEv {}));
1204 assert_eq!(
1205 env.get_event::<TestEv, _>(&addr, 0),
1206 Err(EventError::Parsing)
1207 );
1208 assert_eq!(
1209 env.get_event::<TestEv, _>(&addr, -2),
1210 Err(EventError::Parsing)
1211 );
1212 assert_eq!(
1213 env.get_event::<TestEv, _>(&addr, 2),
1214 Err(EventError::IndexOutOfBounds)
1215 );
1216 assert_eq!(
1217 env.get_event::<TestEv, _>(&addr, -3),
1218 Err(EventError::IndexOutOfBounds)
1219 );
1220 }
1221
1222 #[test]
1223 fn test_events_works() {
1224 let addr = Address::Account(AccountHash::new([0; 32]));
1225
1226 let mut ctx = MockHostContext::new();
1227 ctx.expect_get_events_count().returning(|_| Ok(2));
1229 ctx.expect_get_event()
1231 .with(predicate::always(), predicate::eq(0))
1232 .returning(|_, _| Ok(vec![1].into()));
1233 ctx.expect_get_event()
1235 .with(predicate::always(), predicate::eq(1))
1236 .returning(|_, _| Ok(vec![1, 0, 1].into()));
1237
1238 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1239
1240 assert_eq!(
1241 env.events(&addr),
1242 vec![vec![1].into(), vec![1, 0, 1].into()]
1243 );
1244 }
1245
1246 #[test]
1247 #[should_panic(
1248 expected = "Couldn't get event at address Account(AccountHash(0000000000000000000000000000000000000000000000000000000000000000)) with id 0: CouldntExtractEventData"
1249 )]
1250 fn test_events_fails() {
1251 let addr = Address::Account(AccountHash::new([0; 32]));
1252
1253 let mut ctx = MockHostContext::new();
1254 ctx.expect_get_events_count().returning(|_| Ok(2));
1256 ctx.expect_get_event()
1258 .with(predicate::always(), predicate::eq(0))
1259 .returning(|_, _| Err(EventError::CouldntExtractEventData));
1260
1261 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1262
1263 env.events(&addr);
1264 }
1265
1266 #[test]
1267 fn test_emitted() {
1268 let addr = Address::Account(AccountHash::new([0; 32]));
1269 let mut ctx = MockHostContext::new();
1270
1271 ctx.expect_get_events_count().returning(|_| Ok(1));
1272 ctx.expect_get_event()
1273 .returning(|_, _| Ok(TestEv {}.to_bytes().unwrap().into()));
1274
1275 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1276 assert!(env.emitted(&addr, "TestEv"));
1277 assert!(!env.emitted(&addr, "AnotherEvent"));
1278 }
1279}