From a0d59324e7f900f5fe58b3165f43bfc947ea69a8 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 12 Jul 2021 18:43:39 +0200 Subject: [PATCH 1/2] Add has to Path and Map --- packages/storage-plus/src/map.rs | 33 +++++++++++++++++++++++++++++++ packages/storage-plus/src/path.rs | 6 ++++++ 2 files changed, 39 insertions(+) diff --git a/packages/storage-plus/src/map.rs b/packages/storage-plus/src/map.rs index e07648e7f..fa5f4fd7c 100644 --- a/packages/storage-plus/src/map.rs +++ b/packages/storage-plus/src/map.rs @@ -66,6 +66,12 @@ where self.key(k).may_load(store) } + /// has returns true or false if any data is at this key, without parsing or interpreting the + /// contents. + pub fn has(&self, store: &dyn Storage, k: K) -> bool { + self.key(k).has(store) + } + /// Loads the data, perform the specified action, and store the result /// in the database. This is shorthand for some common sequences, which may be useful. /// @@ -199,6 +205,33 @@ mod test { assert_eq!(None, john.may_load(&store).unwrap()); } + #[test] + fn existence() { + let mut store = MockStorage::new(); + + // set data in proper format + let data = Data { + name: "John".to_string(), + age: 32, + }; + PEOPLE.save(&mut store, b"john", &data).unwrap(); + + // set and remove it + PEOPLE.save(&mut store, b"removed", &data).unwrap(); + PEOPLE.remove(&mut store, b"removed"); + + // invalid, but non-empty data + store.set(&PEOPLE.key(b"random"), b"random-data"); + + // any data, including invalid or empty is returned as "has" + assert!(PEOPLE.has(&store, b"john")); + assert!(PEOPLE.has(&store, b"random")); + + // if nothing was written, it is false + assert!(!PEOPLE.has(&store, b"never-writen")); + assert!(!PEOPLE.has(&store, b"removed")); + } + #[test] fn composite_keys() { let mut store = MockStorage::new(); diff --git a/packages/storage-plus/src/path.rs b/packages/storage-plus/src/path.rs index dd6b76b54..ca1db9d38 100644 --- a/packages/storage-plus/src/path.rs +++ b/packages/storage-plus/src/path.rs @@ -65,6 +65,12 @@ where may_deserialize(&value) } + /// has returns true or false if any data is at this key, without parsing or interpreting the + /// contents. It will returns true for an length-0 byte array (Some(b"")), if you somehow manage to set that. + pub fn has(&self, store: &dyn Storage) -> bool { + store.get(&self.storage_key).is_some() + } + /// Loads the data, perform the specified action, and store the result /// in the database. This is shorthand for some common sequences, which may be useful. /// From 9908541f7877185de00254c98ce6a54de0af5934 Mon Sep 17 00:00:00 2001 From: Ethan Frey Date: Mon, 12 Jul 2021 18:48:03 +0200 Subject: [PATCH 2/2] Use existence check in cw1155-base --- contracts/cw1155-base/src/contract.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/contracts/cw1155-base/src/contract.rs b/contracts/cw1155-base/src/contract.rs index 6f03ccf9b..4bcb9aa47 100644 --- a/contracts/cw1155-base/src/contract.rs +++ b/contracts/cw1155-base/src/contract.rs @@ -233,9 +233,9 @@ pub fn execute_mint( } // insert if not exist - let key = TOKENS.key(&token_id); - if deps.storage.get(&key).is_none() { - key.save(deps.storage, &"".to_owned())?; + if !TOKENS.has(deps.storage, &token_id) { + // we must save some valid data here + TOKENS.save(deps.storage, &token_id, &String::new())?; } Ok(rsp) @@ -329,10 +329,9 @@ pub fn execute_batch_mint( event.add_attributes(&mut rsp); // insert if not exist - let key = TOKENS.key(&token_id); - if deps.storage.get(&key).is_none() { - // insert an empty entry so token enumeration can find it - key.save(deps.storage, &"".to_owned())?; + if !TOKENS.has(deps.storage, &token_id) { + // we must save some valid data here + TOKENS.save(deps.storage, &token_id, &String::new())?; } }