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 let deployed_contracts = self.deployed_contracts.borrow().clone();
458 for (contract_address, _) in deployed_contracts.iter() {
459 self.init_events(contract_address);
460 }
461 }
462 }
463
464 pub fn get_account(&self, index: usize) -> Address {
466 let backend = self.backend.borrow();
467 backend.get_account(index)
468 }
469
470 pub fn get_validator(&self, index: usize) -> PublicKey {
472 let backend = self.backend.borrow();
473 backend.get_validator(index)
474 }
475
476 pub fn set_caller(&self, address: Address) {
478 if address.is_contract() {
479 panic!("Caller cannot be a contract: {:?}", address)
480 }
481 let backend = self.backend.borrow();
482 backend.set_caller(address)
483 }
484
485 pub fn advance_block_time(&self, time_diff: u64) {
487 let backend = self.backend.borrow();
488 backend.advance_block_time(time_diff)
489 }
490
491 pub fn advance_with_auctions(&self, time_diff: u64) {
494 let backend = self.backend.borrow();
495 backend.advance_with_auctions(time_diff);
496 }
497
498 pub fn auction_delay(&self) -> u64 {
500 let backend = self.backend.borrow();
501 backend.auction_delay()
502 }
503
504 pub fn unbonding_delay(&self) -> u64 {
506 let backend = self.backend.borrow();
507 backend.unbonding_delay()
508 }
509
510 pub fn delegated_amount(&self, delegator: Address, validator: PublicKey) -> U512 {
512 let backend = self.backend.borrow();
513 backend.delegated_amount(delegator, validator)
514 }
515
516 pub fn remove_validator(&self, index: usize) {
518 let backend = self.backend.borrow();
519 backend.remove_validator(index);
520 }
521
522 pub fn block_time(&self) -> u64 {
524 let backend = self.backend.borrow();
525 backend.block_time()
526 }
527
528 pub fn block_time_millis(&self) -> u64 {
530 let backend = self.backend.borrow();
531 backend.block_time()
532 }
533
534 pub fn block_time_secs(&self) -> u64 {
536 let backend = self.backend.borrow();
537 backend.block_time().checked_div(1000).unwrap()
538 }
539
540 pub fn new_contract(
542 &self,
543 name: &str,
544 init_args: RuntimeArgs,
545 entry_points_caller: EntryPointsCaller
546 ) -> OdraResult<Address> {
547 let mut entry_points_caller = entry_points_caller.clone();
549 entry_points_caller.remove_entry_point("upgrade");
550
551 let backend = self.backend.borrow();
552 let contract_address = backend.new_contract(name, init_args, entry_points_caller)?;
553
554 self.deployed_contracts
555 .borrow_mut()
556 .insert(contract_address, DeployedContract::new(contract_address));
557 Ok(contract_address)
558 }
559
560 pub fn upgrade_contract(
563 &self,
564 name: &str,
565 contract_to_upgrade: Address,
566 upgrade_args: RuntimeArgs,
567 entry_points_caller: EntryPointsCaller
568 ) -> OdraResult<Address> {
569 let mut entry_points_caller = entry_points_caller.clone();
571 entry_points_caller.remove_entry_point("init");
572
573 let backend = self.backend.borrow();
574 let upgraded_contract = backend.upgrade_contract(
575 name,
576 contract_to_upgrade,
577 upgrade_args,
578 entry_points_caller
579 )?;
580 let mut contracts = self.deployed_contracts.borrow_mut();
581 let contract = contracts.get_mut(&upgraded_contract).unwrap();
582 contract.current_version += 1;
583 contract.native_events_count = 0;
585 Ok(upgraded_contract)
586 }
587
588 pub fn register_contract(
591 &self,
592 address: Address,
593 contract_name: String,
594 entry_points_caller: EntryPointsCaller
595 ) {
596 let backend = self.backend.borrow();
597 backend.register_contract(address, contract_name, entry_points_caller);
598 self.deployed_contracts
599 .borrow_mut()
600 .insert(address, DeployedContract::new(address));
601 }
602
603 pub fn call_contract<T: FromBytes + CLTyped>(
605 &self,
606 address: Address,
607 call_def: CallDef
608 ) -> OdraResult<T> {
609 let use_proxy = T::cl_type() != <()>::cl_type() || !call_def.amount().is_zero();
610 let call_result = self.raw_call_contract(address, call_def, use_proxy);
611 call_result.map(|bytes| {
612 T::from_bytes(&bytes)
613 .map(|(obj, _)| obj)
614 .map_err(|_| OdraError::VmError(VmError::Deserialization))
615 })?
616 }
617
618 pub fn raw_call_contract(
621 &self,
622 address: Address,
623 call_def: CallDef,
624 use_proxy: bool
625 ) -> OdraResult<Bytes> {
626 let call_result = {
627 let backend = self.backend.borrow();
628 backend.call_contract(&address, call_def, use_proxy)
629 };
630
631 let mut events_map: BTreeMap<Address, Vec<Bytes>> = BTreeMap::new();
632 let mut native_events_map: BTreeMap<Address, Vec<Bytes>> = BTreeMap::new();
633
634 let captures_events = *self.captures_events.borrow();
635 if captures_events {
636 self.deployed_contracts.borrow_mut().iter_mut().for_each(
638 |(contract_address, contract)| {
639 let events = self.last_events(contract);
640 let native_events = self.last_native_events(contract);
641 events_map.insert(*contract_address, events);
642 native_events_map.insert(*contract_address, native_events);
643 }
644 );
645 }
646
647 let backend = self.backend.borrow();
648 let last_call_gas_cost = backend.last_call_gas_cost();
649
650 self.last_call_result.replace(Some(CallResult::new(
651 address,
652 backend.caller(),
653 last_call_gas_cost,
654 call_result.clone(),
655 events_map,
656 native_events_map
657 )));
658
659 call_result
660 }
661
662 pub fn contract_env(&self) -> ContractEnv {
664 self.backend.borrow().contract_env()
665 }
666
667 pub fn gas_report(&self) -> GasReport {
669 self.backend.borrow().gas_report().clone()
670 }
671
672 pub fn balance_of<T: Addressable>(&self, addr: &T) -> U512 {
674 let backend = self.backend.borrow();
675 backend.balance_of(&addr.address())
676 }
677
678 pub fn get_event<T: FromBytes + EventInstance, R: Addressable>(
685 &self,
686 addr: &R,
687 index: i32
688 ) -> Result<T, EventError> {
689 let contract_address = addr.address();
690 let backend = self.backend.borrow();
691 let events_count = self.events_count(&contract_address);
692 let event_absolute_position = crate::utils::event_absolute_position(events_count, index)
693 .ok_or(EventError::IndexOutOfBounds)?;
694
695 let bytes = backend.get_event(&contract_address, event_absolute_position)?;
696 T::from_bytes(&bytes)
697 .map_err(|_| EventError::Parsing)
698 .map(|r| r.0)
699 }
700
701 pub fn get_native_event<T: FromBytes + EventInstance, R: Addressable>(
708 &self,
709 addr: &R,
710 index: i32
711 ) -> Result<T, EventError> {
712 let contract_address = addr.address();
713 let backend = self.backend.borrow();
714 let events_count = self.native_events_count(&contract_address);
715 let event_absolute_position = crate::utils::event_absolute_position(events_count, index)
716 .ok_or(EventError::IndexOutOfBounds)?;
717
718 let bytes = backend.get_native_event(&contract_address, event_absolute_position)?;
719 T::from_bytes(&bytes)
720 .map_err(|_| EventError::Parsing)
721 .map(|r| r.0)
722 }
723
724 pub fn get_event_bytes<T: Addressable>(
726 &self,
727 addr: &T,
728 index: u32
729 ) -> Result<Bytes, EventError> {
730 let backend = self.backend.borrow();
731 backend.get_event(&addr.address(), index)
732 }
733
734 pub fn get_native_event_bytes<T: Addressable>(
736 &self,
737 addr: &T,
738 index: u32
739 ) -> Result<Bytes, EventError> {
740 let backend = self.backend.borrow();
741 backend.get_native_event(&addr.address(), index)
742 }
743
744 pub fn event_names<T: Addressable>(&self, addr: &T) -> Vec<String> {
746 let events_count = self.events_count(addr);
747
748 let backend = self.backend.borrow();
749 (0..events_count)
750 .map(|event_id| {
751 backend
752 .get_event(&addr.address(), event_id)
753 .and_then(|bytes| utils::extract_event_name(&bytes))
754 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
755 })
756 .collect()
757 }
758
759 pub fn events<T: Addressable>(&self, addr: &T) -> Vec<Bytes> {
761 let backend = self.backend.borrow();
762 let contract_address = addr.address();
763 let events_count = backend
764 .get_events_count(&contract_address)
765 .unwrap_or_default();
766 (0..events_count)
767 .map(|event_id| {
768 backend
769 .get_event(&contract_address, event_id)
770 .unwrap_or_else(|e| {
771 panic!(
772 "Couldn't get event at address {:?} with id {}: {:?}",
773 &contract_address, event_id, e
774 )
775 })
776 })
777 .collect()
778 }
779
780 pub fn events_count<T: Addressable>(&self, addr: &T) -> u32 {
782 let backend = self.backend.borrow();
783 backend
784 .get_events_count(&addr.address())
785 .unwrap_or_default()
786 }
787
788 pub fn native_events_count<T: Addressable>(&self, addr: &T) -> u32 {
790 let backend = self.backend.borrow();
791 backend
792 .get_native_events_count(&addr.address())
793 .unwrap_or_default()
794 }
795
796 pub fn emitted_event<T: ToBytes + EventInstance, R: Addressable>(
798 &self,
799 addr: &R,
800 event: T
801 ) -> bool {
802 let contract_address = addr.address();
803 let events_count = self.events_count(addr);
804
805 let event_bytes = Bytes::from(
806 event
807 .to_bytes()
808 .unwrap_or_else(|_| panic!("Couldn't serialize event"))
809 );
810
811 (0..events_count)
812 .map(|event_id| {
813 self.get_event_bytes(&contract_address, event_id)
814 .unwrap_or_else(|e| {
815 panic!(
816 "Couldn't get event at address {:?} with id {}: {:?}",
817 &contract_address, event_id, e
818 )
819 })
820 })
821 .any(|bytes| bytes == event_bytes)
822 }
823
824 pub fn emitted_native_event<T: ToBytes + EventInstance, R: Addressable>(
826 &self,
827 addr: &R,
828 event: T
829 ) -> bool {
830 let contract_address = addr.address();
831 let events_count = self.native_events_count(addr);
832 if events_count > 0 {
833 let event_bytes = Bytes::from(
834 event
835 .to_bytes()
836 .unwrap_or_else(|_| panic!("Couldn't serialize event"))
837 );
838 (0..events_count)
839 .map(|event_id| {
840 self.get_native_event_bytes(&contract_address, event_id)
841 .unwrap_or_else(|e| {
842 panic!(
843 "Couldn't get event at address {:?} with id {}: {:?}",
844 &contract_address, event_id, e
845 )
846 })
847 })
848 .any(|bytes| bytes == event_bytes)
849 } else {
850 false
851 }
852 }
853
854 pub fn emitted<T: AsRef<str>, R: Addressable>(&self, addr: &R, event_name: T) -> bool {
856 let events_count = self.events_count(addr);
857
858 (0..events_count)
859 .map(|event_id| {
860 self.get_event_bytes(addr, event_id).unwrap_or_else(|e| {
861 panic!(
862 "Couldn't get event at address {:?} with id {}: {:?}",
863 addr.address(),
864 event_id,
865 e
866 )
867 })
868 })
869 .any(|bytes| {
870 utils::extract_event_name(&bytes)
871 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
872 .as_str()
873 == event_name.as_ref()
874 })
875 }
876 pub fn emitted_native<T: AsRef<str>, R: Addressable>(&self, addr: &R, event_name: T) -> bool {
878 let events_count = self.native_events_count(addr);
879
880 (0..events_count)
881 .map(|event_id| {
882 self.get_native_event_bytes(addr, event_id)
883 .unwrap_or_else(|e| {
884 panic!(
885 "Couldn't get event at address {:?} with id {}: {:?}",
886 addr.address(),
887 event_id,
888 e
889 )
890 })
891 })
892 .any(|bytes| {
893 utils::extract_event_name(&bytes)
894 .unwrap_or_else(|e| panic!("Couldn't extract event name: {:?}", e))
895 .as_str()
896 == event_name.as_ref()
897 })
898 }
899
900 pub fn last_call_result(&self, contract_address: Address) -> ContractCallResult {
902 self.last_call_result
903 .borrow()
904 .clone()
905 .unwrap()
906 .contract_last_call(contract_address)
907 }
908
909 pub fn sign_message(&self, message: &Bytes, address: &Address) -> Bytes {
911 let backend = self.backend.borrow();
912 backend.sign_message(message, address)
913 }
914
915 pub fn public_key(&self, address: &Address) -> PublicKey {
917 let backend = self.backend.borrow();
918 backend.public_key(address)
919 }
920
921 pub fn caller(&self) -> Address {
923 let backend = self.backend.borrow();
924 backend.caller()
925 }
926
927 pub fn set_gas(&self, gas: u64) {
929 let backend = self.backend.borrow();
930 backend.set_gas(gas)
931 }
932
933 pub fn transfer(&self, to: Address, amount: U512) -> OdraResult<()> {
935 if to.is_contract() {
936 return Err(OdraError::ExecutionError(
937 ExecutionError::TransferToContract
938 ));
939 }
940 let backend = self.backend.borrow();
941 backend.transfer(to, amount)
942 }
943
944 fn last_events(&self, contract: &mut DeployedContract) -> Vec<Bytes> {
945 let old_count = contract.events_count;
946 let new_count = self.events_count(&contract.address);
947 let mut events = vec![];
948 for count in old_count..new_count {
949 let event = self.get_event_bytes(&contract.address, count).unwrap();
950 events.push(event);
951 }
952
953 contract.events_count = new_count;
954 events
955 }
956
957 fn last_native_events(&self, contract: &mut DeployedContract) -> Vec<Bytes> {
958 let old_count = contract.native_events_count;
959 let new_count = self.native_events_count(&contract.address);
960 let mut events = vec![];
961 for count in old_count..new_count {
962 let event = self
963 .get_native_event_bytes(&contract.address, count)
964 .unwrap();
965 events.push(event);
966 }
967
968 contract.native_events_count = new_count;
969 events
970 }
971
972 fn init_events(&self, contract_address: &Address) {
973 let mut contracts = self.deployed_contracts.borrow_mut();
974 let contract = contracts.get_mut(contract_address).unwrap();
975
976 if !contract.events_initialized {
977 contract.events_count = self.events_count(contract_address);
978 contract.native_events_count = self.native_events_count(contract_address);
979 contract.events_initialized = true;
980 }
981 }
982}
983
984#[cfg(test)]
985mod test {
986 use core::fmt::Debug;
987
988 use super::*;
989 use casper_event_standard::Event;
990 use casper_types::account::AccountHash;
991 use casper_types::contracts::ContractPackageHash;
992 use mockall::{mock, predicate};
993 use std::sync::Mutex;
994
995 static IDENT_MTX: Mutex<()> = Mutex::new(());
996 static EPC_MTX: Mutex<()> = Mutex::new(());
997
998 #[derive(Debug, Event, PartialEq)]
999 struct TestEv {}
1000
1001 mock! {
1002 TestRef {}
1003 impl HasIdent for TestRef {
1004 fn ident() -> String;
1005 }
1006 impl EntryPointsCallerProvider for TestRef {
1007 fn entry_points_caller(env: &HostEnv) -> EntryPointsCaller;
1008 }
1009 impl HostRef for TestRef {
1010 fn new(address: Address, env: HostEnv) -> Self;
1011 fn with_tokens(&self, tokens: U512) -> Self;
1012 fn contract_address(&self) -> Address;
1013 fn env(&self) -> &HostEnv;
1014 fn get_event<T>(&self, index: i32) -> Result<T, EventError> where T: FromBytes + EventInstance + 'static;
1015 fn last_call(&self) -> ContractCallResult;
1016 }
1017 }
1018
1019 impl crate::ContractRef for MockTestRef {
1020 fn new(_env: Rc<ContractEnv>, _address: Address) -> Self {
1021 unimplemented!()
1022 }
1023 fn address(&self) -> &Address {
1024 unimplemented!()
1025 }
1026
1027 fn with_tokens(&self, _tokens: U512) -> Self {
1028 unimplemented!()
1029 }
1030 }
1031
1032 impl OdraContract for MockTestRef {
1033 type HostRef = MockTestRef;
1034
1035 type ContractRef = MockTestRef;
1036
1037 type InitArgs = NoArgs;
1038
1039 type UpgradeArgs = NoArgs;
1040 }
1041
1042 mock! {
1043 Ev {}
1044 impl Into<RuntimeArgs> for Ev {
1045 fn into(self) -> RuntimeArgs;
1046 }
1047 }
1048
1049 #[test]
1050 fn test_deploy_with_default_args() {
1051 let _i = IDENT_MTX.lock();
1056 let _e = EPC_MTX.lock();
1057
1058 let indent_ctx = MockTestRef::ident_context();
1060 indent_ctx.expect().returning(|| "TestRef".to_string());
1061
1062 let epc_ctx = MockTestRef::entry_points_caller_context();
1063 epc_ctx
1064 .expect()
1065 .returning(|h| EntryPointsCaller::new(h.clone(), vec![], |_, _| Ok(Bytes::default())));
1066
1067 let instance_ctx = MockTestRef::new_context();
1069 instance_ctx
1070 .expect()
1071 .times(1)
1072 .returning(|_, _| MockTestRef::default());
1073
1074 let mut ctx = MockHostContext::new();
1075 ctx.expect_new_contract()
1076 .returning(|_, _, _| Ok(Address::Account(AccountHash::new([0; 32]))));
1077 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1078 MockTestRef::deploy(&env, NoArgs);
1079 }
1080
1081 #[test]
1082 fn test_load_ref() {
1083 let _e = EPC_MTX.lock();
1088 let _i = IDENT_MTX.lock();
1089
1090 let epc_ctx = MockTestRef::entry_points_caller_context();
1092 epc_ctx
1093 .expect()
1094 .returning(|h| EntryPointsCaller::new(h.clone(), vec![], |_, _| Ok(Bytes::default())));
1095 let indent_ctx = MockTestRef::ident_context();
1096 indent_ctx.expect().returning(|| "TestRef".to_string());
1097
1098 let mut ctx = MockHostContext::new();
1099 ctx.expect_register_contract().returning(|_, _, _| ());
1100 ctx.expect_get_events_count().returning(|_| Ok(0));
1101 ctx.expect_get_native_events_count().returning(|_| Ok(0));
1102
1103 let instance_ctx = MockTestRef::new_context();
1105 instance_ctx
1106 .expect()
1107 .times(1)
1108 .returning(|_, _| MockTestRef::default());
1109
1110 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1111 let address = Address::Account(AccountHash::new([0; 32]));
1112 MockTestRef::load(&env, address);
1113 }
1114
1115 #[test]
1116 fn test_host_env() {
1117 let mut ctx = MockHostContext::new();
1118 ctx.expect_new_contract()
1119 .returning(|_, _, _| Ok(Address::Account(AccountHash::new([0; 32]))));
1120 ctx.expect_caller()
1121 .returning(|| Address::Account(AccountHash::new([2; 32])))
1122 .times(1);
1123 ctx.expect_gas_report().returning(GasReport::new).times(1);
1124 ctx.expect_set_gas().returning(|_| ()).times(1);
1125
1126 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1127
1128 assert_eq!(env.caller(), Address::Account(AccountHash::new([2; 32])));
1129 env.gas_report();
1131 env.set_gas(1_000u64)
1132 }
1133
1134 #[test]
1135 fn test_successful_transfer_to_account() {
1136 let mut ctx = MockHostContext::new();
1138 ctx.expect_transfer().returning(|_, _| Ok(()));
1139 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1140
1141 let addr = Address::Account(AccountHash::new([0; 32]));
1142 let result = env.transfer(addr, 100.into());
1144 assert!(result.is_ok());
1146 }
1147
1148 #[test]
1149 fn test_failing_transfer_to_account() {
1150 let mut ctx = MockHostContext::new();
1152 ctx.expect_transfer()
1153 .returning(|_, _| Err(OdraError::ExecutionError(ExecutionError::UnwrapError)));
1154 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1155
1156 let addr = Address::Account(AccountHash::new([0; 32]));
1157 let result = env.transfer(addr, 100.into());
1159 assert_eq!(
1161 result.err(),
1162 Some(OdraError::ExecutionError(ExecutionError::UnwrapError))
1163 );
1164 }
1165
1166 #[test]
1167 fn test_transfer_to_contract() {
1168 let mut ctx = MockHostContext::new();
1170 ctx.expect_transfer().returning(|_, _| Ok(()));
1171 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1172
1173 let addr = Address::Contract(ContractPackageHash::new([0; 32]));
1174 let result = env.transfer(addr, 100.into());
1176 assert_eq!(
1178 result,
1179 Err(OdraError::ExecutionError(
1180 ExecutionError::TransferToContract
1181 ))
1182 );
1183 }
1184
1185 #[test]
1186 fn test_get_event() {
1187 let addr = Address::Account(AccountHash::new([0; 32]));
1188
1189 let mut ctx = MockHostContext::new();
1190 ctx.expect_get_events_count().returning(|_| Ok(2));
1192 ctx.expect_get_event()
1194 .with(predicate::always(), predicate::eq(0))
1195 .returning(|_, _| Ok(vec![1].into()));
1196 ctx.expect_get_event()
1198 .with(predicate::always(), predicate::eq(1))
1199 .returning(|_, _| Ok(TestEv {}.to_bytes().unwrap().into()));
1200
1201 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1202
1203 assert_eq!(env.get_event(&addr, 1), Ok(TestEv {}));
1204 assert_eq!(env.get_event(&addr, -1), Ok(TestEv {}));
1205 assert_eq!(
1206 env.get_event::<TestEv, _>(&addr, 0),
1207 Err(EventError::Parsing)
1208 );
1209 assert_eq!(
1210 env.get_event::<TestEv, _>(&addr, -2),
1211 Err(EventError::Parsing)
1212 );
1213 assert_eq!(
1214 env.get_event::<TestEv, _>(&addr, 2),
1215 Err(EventError::IndexOutOfBounds)
1216 );
1217 assert_eq!(
1218 env.get_event::<TestEv, _>(&addr, -3),
1219 Err(EventError::IndexOutOfBounds)
1220 );
1221 }
1222
1223 #[test]
1224 fn test_events_works() {
1225 let addr = Address::Account(AccountHash::new([0; 32]));
1226
1227 let mut ctx = MockHostContext::new();
1228 ctx.expect_get_events_count().returning(|_| Ok(2));
1230 ctx.expect_get_event()
1232 .with(predicate::always(), predicate::eq(0))
1233 .returning(|_, _| Ok(vec![1].into()));
1234 ctx.expect_get_event()
1236 .with(predicate::always(), predicate::eq(1))
1237 .returning(|_, _| Ok(vec![1, 0, 1].into()));
1238
1239 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1240
1241 assert_eq!(
1242 env.events(&addr),
1243 vec![vec![1].into(), vec![1, 0, 1].into()]
1244 );
1245 }
1246
1247 #[test]
1248 #[should_panic(
1249 expected = "Couldn't get event at address Account(AccountHash(0000000000000000000000000000000000000000000000000000000000000000)) with id 0: CouldntExtractEventData"
1250 )]
1251 fn test_events_fails() {
1252 let addr = Address::Account(AccountHash::new([0; 32]));
1253
1254 let mut ctx = MockHostContext::new();
1255 ctx.expect_get_events_count().returning(|_| Ok(2));
1257 ctx.expect_get_event()
1259 .with(predicate::always(), predicate::eq(0))
1260 .returning(|_, _| Err(EventError::CouldntExtractEventData));
1261
1262 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1263
1264 env.events(&addr);
1265 }
1266
1267 #[test]
1268 fn test_emitted() {
1269 let addr = Address::Account(AccountHash::new([0; 32]));
1270 let mut ctx = MockHostContext::new();
1271
1272 ctx.expect_get_events_count().returning(|_| Ok(1));
1273 ctx.expect_get_event()
1274 .returning(|_, _| Ok(TestEv {}.to_bytes().unwrap().into()));
1275
1276 let env = HostEnv::new(Rc::new(RefCell::new(ctx)));
1277 assert!(env.emitted(&addr, "TestEv"));
1278 assert!(!env.emitted(&addr, "AnotherEvent"));
1279 }
1280}