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