diff --git a/crates/engine/src/ext.rs b/crates/engine/src/ext.rs index ecfcc59be73..d784d12094b 100644 --- a/crates/engine/src/ext.rs +++ b/crates/engine/src/ext.rs @@ -257,6 +257,17 @@ impl Engine { } } + /// Returns the size of the value stored in the contract storage at the key if any. + pub fn contains_storage(&mut self, key: &[u8; 32]) -> Option { + let callee = self.get_callee(); + let account_id = AccountId::from_bytes(&callee[..]); + + self.debug_info.inc_reads(account_id); + self.database + .get_from_contract_storage(&callee, key) + .map(|val| val.len() as u32) + } + /// Removes the storage entries at the given key. pub fn clear_storage(&mut self, key: &[u8; 32]) { let callee = self.get_callee(); diff --git a/crates/env/src/engine/off_chain/impls.rs b/crates/env/src/engine/off_chain/impls.rs index 63e312b9f58..26e1e3b4f1a 100644 --- a/crates/env/src/engine/off_chain/impls.rs +++ b/crates/env/src/engine/off_chain/impls.rs @@ -206,10 +206,8 @@ impl EnvBackend for EnvInstance { Ok(Some(decoded)) } - fn contract_storage_contains(&mut self, _key: &Key) -> Option { - unimplemented!( - "the off-chain env does not implement `seal_contains_storage`, yet" - ) + fn contract_storage_contains(&mut self, key: &Key) -> Option { + self.engine.contains_storage(key.as_ref()) } fn clear_contract_storage(&mut self, key: &Key) { diff --git a/crates/storage/src/lazy/mapping.rs b/crates/storage/src/lazy/mapping.rs index 0f1a80631e7..a704217f0ca 100644 --- a/crates/storage/src/lazy/mapping.rs +++ b/crates/storage/src/lazy/mapping.rs @@ -161,13 +161,24 @@ where /// /// Returns `None` if no `value` exists at the given `key`. #[inline] - pub fn contains(&self, key: Q) -> Option + pub fn size(&self, key: Q) -> Option where Q: scale::EncodeLike, { ink_env::contract_storage_contains(&self.storage_key(&key)) } + /// Checks if a value is stored at the given `key` in the contract storage. + /// + /// Returns `None` if no `value` exists at the given `key`. + #[inline] + pub fn contains(&self, key: Q) -> bool + where + Q: scale::EncodeLike, + { + ink_env::contract_storage_contains(&self.storage_key(&key)).is_some() + } + /// Clears the value at `key` from storage. pub fn remove(&self, key: Q) where diff --git a/examples/dns/lib.rs b/examples/dns/lib.rs index 6a54f4a2213..7a389da1c0f 100644 --- a/examples/dns/lib.rs +++ b/examples/dns/lib.rs @@ -96,7 +96,7 @@ mod dns { #[ink(message)] pub fn register(&mut self, name: Hash) -> Result<()> { let caller = self.env().caller(); - if self.name_to_owner.get(&name).is_some() { + if self.name_to_owner.contains(&name) { return Err(Error::NameAlreadyExists) } diff --git a/examples/erc1155/lib.rs b/examples/erc1155/lib.rs index 0c9a3f432a2..12d68f78d55 100644 --- a/examples/erc1155/lib.rs +++ b/examples/erc1155/lib.rs @@ -539,7 +539,7 @@ mod erc1155 { #[ink(message)] fn is_approved_for_all(&self, owner: AccountId, operator: AccountId) -> bool { - self.approvals.get((&owner, &operator)).is_some() + self.approvals.contains((&owner, &operator)) } } diff --git a/examples/erc721/lib.rs b/examples/erc721/lib.rs index 4d528e73ac6..0bc88fad932 100644 --- a/examples/erc721/lib.rs +++ b/examples/erc721/lib.rs @@ -283,7 +283,7 @@ mod erc721 { .. } = self; - if token_owner.get(&id).is_none() { + if !token_owner.contains(&id) { return Err(Error::TokenNotFound) } @@ -305,7 +305,7 @@ mod erc721 { .. } = self; - if token_owner.get(&id).is_some() { + if token_owner.contains(&id) { return Err(Error::TokenExists) } @@ -360,7 +360,7 @@ mod erc721 { return Err(Error::NotAllowed) }; - if self.token_approvals.get(&id).is_some() { + if self.token_approvals.contains(&id) { return Err(Error::CannotInsert) } else { self.token_approvals.insert(&id, to); @@ -387,7 +387,7 @@ mod erc721 { /// Gets an operator on other Account's behalf. fn approved_for_all(&self, owner: AccountId, operator: AccountId) -> bool { - self.operator_approvals.get((&owner, &operator)).is_some() + self.operator_approvals.contains((&owner, &operator)) } /// Returns true if the `AccountId` `from` is the owner of token `id` @@ -405,7 +405,7 @@ mod erc721 { /// Returns true if token `id` exists or false if it does not. fn exists(&self, id: TokenId) -> bool { - self.token_owner.get(&id).is_some() + self.token_owner.contains(&id) } } diff --git a/examples/multisig/lib.rs b/examples/multisig/lib.rs index 0e3ca6a9bce..afb8a2a3deb 100755 --- a/examples/multisig/lib.rs +++ b/examples/multisig/lib.rs @@ -504,7 +504,7 @@ mod multisig { pub fn revoke_confirmation(&mut self, trans_id: TransactionId) { self.ensure_caller_is_owner(); let caller = self.env().caller(); - if self.confirmations.get(&(trans_id, caller)).is_some() { + if self.confirmations.contains(&(trans_id, caller)) { self.confirmations.remove(&(trans_id, caller)); let mut confirmation_count = self .confirmation_count @@ -601,7 +601,7 @@ mod multisig { ) -> ConfirmationStatus { let mut count = self.confirmation_count.get(&transaction).unwrap_or(0); let key = (transaction, confirmer); - let new_confirmation = self.confirmations.get(&key).is_none(); + let new_confirmation = !self.confirmations.contains(&key); if new_confirmation { count += 1; self.confirmations.insert(&key, &()); @@ -659,7 +659,7 @@ mod multisig { fn clean_owner_confirmations(&mut self, owner: &AccountId) { for trans_id in &self.transaction_list.transactions { let key = (*trans_id, *owner); - if self.confirmations.get(&key).is_some() { + if self.confirmations.contains(&key) { self.confirmations.remove(&key); let mut count = self.confirmation_count.get(&trans_id).unwrap_or(0); count -= 1; @@ -696,12 +696,12 @@ mod multisig { /// Panic if `owner` is not an owner, fn ensure_owner(&self, owner: &AccountId) { - assert!(self.is_owner.get(owner).is_some()); + assert!(self.is_owner.contains(owner)); } /// Panic if `owner` is an owner. fn ensure_no_owner(&self, owner: &AccountId) { - assert!(self.is_owner.get(owner).is_none()); + assert!(!self.is_owner.contains(owner)); } } @@ -794,12 +794,12 @@ mod multisig { assert_eq!(contract.owners.len(), 3); assert_eq!(contract.requirement, 2); assert!(contract.owners.iter().eq(owners.iter())); - assert!(contract.is_owner.get(&accounts.alice).is_some()); - assert!(contract.is_owner.get(&accounts.bob).is_some()); - assert!(contract.is_owner.get(&accounts.eve).is_some()); - assert!(contract.is_owner.get(&accounts.charlie).is_none()); - assert!(contract.is_owner.get(&accounts.django).is_none()); - assert!(contract.is_owner.get(&accounts.frank).is_none()); + assert!(contract.is_owner.contains(&accounts.alice)); + assert!(contract.is_owner.contains(&accounts.bob)); + assert!(contract.is_owner.contains(&accounts.eve)); + assert!(!contract.is_owner.contains(&accounts.charlie)); + assert!(!contract.is_owner.contains(&accounts.django)); + assert!(!contract.is_owner.contains(&accounts.frank)); assert_eq!(contract.transaction_list.transactions.len(), 0); } @@ -831,7 +831,7 @@ mod multisig { let owners = contract.owners.len(); contract.add_owner(accounts.frank); assert_eq!(contract.owners.len(), owners + 1); - assert!(contract.is_owner.get(&accounts.frank).is_some()); + assert!(contract.is_owner.contains(&accounts.frank)); assert_eq!(test::recorded_events().count(), 1); } @@ -861,7 +861,7 @@ mod multisig { let owners = contract.owners.len(); contract.remove_owner(accounts.alice); assert_eq!(contract.owners.len(), owners - 1); - assert!(contract.is_owner.get(&accounts.alice).is_none()); + assert!(!contract.is_owner.contains(&accounts.alice)); assert_eq!(test::recorded_events().count(), 1); } @@ -891,8 +891,8 @@ mod multisig { let owners = contract.owners.len(); contract.replace_owner(accounts.alice, accounts.django); assert_eq!(contract.owners.len(), owners); - assert!(contract.is_owner.get(&accounts.alice).is_none()); - assert!(contract.is_owner.get(&accounts.django).is_some()); + assert!(!contract.is_owner.contains(&accounts.alice)); + assert!(contract.is_owner.contains(&accounts.django)); assert_eq!(test::recorded_events().count(), 2); } @@ -1053,7 +1053,7 @@ mod multisig { set_caller(accounts.alice); contract.revoke_confirmation(0); assert_eq!(test::recorded_events().count(), 3); - assert!(contract.confirmations.get(&(0, accounts.alice)).is_none()); + assert!(!contract.confirmations.contains(&(0, accounts.alice))); assert_eq!(contract.confirmation_count.get(&0).unwrap(), 0); } @@ -1064,7 +1064,7 @@ mod multisig { set_caller(accounts.bob); contract.revoke_confirmation(0); assert_eq!(test::recorded_events().count(), 2); - assert!(contract.confirmations.get(&(0, accounts.alice)).is_some()); + assert!(contract.confirmations.contains(&(0, accounts.alice))); assert_eq!(contract.confirmation_count.get(&0).unwrap(), 1); }