Skip to content

Commit

Permalink
Merge pull request #239 from CosmWasm/upgrade-to-storage-plus
Browse files Browse the repository at this point in the history
Converting cw20-* contracts to use storage-plus
  • Loading branch information
ethanfrey authored Mar 9, 2021
2 parents f38e805 + d52a6c8 commit 21ab493
Show file tree
Hide file tree
Showing 25 changed files with 177 additions and 567 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/cw20-atomic-swap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ cw0 = { path = "../../packages/cw0", version = "0.5.0" }
cw2 = { path = "../../packages/cw2", version = "0.5.0" }
cw20 = { path = "../../packages/cw20", version = "0.5.0" }
cosmwasm-std = { version = "0.14.0-alpha2", features = ["iterator"] }
cosmwasm-storage = { version = "0.14.0-alpha2", features = ["iterator"] }
cw-storage-plus = { path = "../../packages/storage-plus", version = "0.5.0", features = ["iterator"] }
schemars = "0.7"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.20" }
Expand Down
19 changes: 10 additions & 9 deletions contracts/cw20-atomic-swap/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use cosmwasm_std::{
};
use sha2::{Digest, Sha256};

use cw0::calc_range_start_string;
use cw2::set_contract_version;
use cw20::{Balance, Cw20Coin, Cw20CoinHuman, Cw20HandleMsg, Cw20ReceiveMsg};

Expand All @@ -13,7 +12,8 @@ use crate::msg::{
is_valid_name, BalanceHuman, CreateMsg, DetailsResponse, HandleMsg, InitMsg, ListResponse,
QueryMsg, ReceiveMsg,
};
use crate::state::{all_swap_ids, atomic_swaps, atomic_swaps_read, AtomicSwap};
use crate::state::{all_swap_ids, AtomicSwap, SWAPS};
use cw_storage_plus::Bound;

// Version info, for migration info
const CONTRACT_NAME: &str = "crates.io:cw20-atomic-swap";
Expand Down Expand Up @@ -102,7 +102,7 @@ pub fn execute_create(
};

// Try to store it, fail if the id already exists (unmodifiable swaps)
atomic_swaps(deps.storage).update(msg.id.as_bytes(), |existing| match existing {
SWAPS.update(deps.storage, &msg.id, |existing| match existing {
None => Ok(swap),
Some(_) => Err(ContractError::AlreadyExists {}),
})?;
Expand All @@ -123,7 +123,7 @@ pub fn execute_release(
id: String,
preimage: String,
) -> Result<Response, ContractError> {
let swap = atomic_swaps_read(deps.storage).load(id.as_bytes())?;
let swap = SWAPS.load(deps.storage, &id)?;
if swap.is_expired(&env.block) {
return Err(ContractError::Expired {});
}
Expand All @@ -136,7 +136,7 @@ pub fn execute_release(
let rcpt = deps.api.human_address(&swap.recipient)?;

// Delete the swap
atomic_swaps(deps.storage).remove(id.as_bytes());
SWAPS.remove(deps.storage, &id);

// Send all tokens out
let msgs = send_tokens(deps.api, &rcpt, swap.balance)?;
Expand All @@ -154,7 +154,7 @@ pub fn execute_release(
}

pub fn execute_refund(deps: DepsMut, env: Env, id: String) -> Result<Response, ContractError> {
let swap = atomic_swaps_read(deps.storage).load(id.as_bytes())?;
let swap = SWAPS.load(deps.storage, &id)?;
// Anyone can try to refund, as long as the contract is expired
if !swap.is_expired(&env.block) {
return Err(ContractError::NotExpired {});
Expand All @@ -163,7 +163,7 @@ pub fn execute_refund(deps: DepsMut, env: Env, id: String) -> Result<Response, C
let rcpt = deps.api.human_address(&swap.source)?;

// We delete the swap
atomic_swaps(deps.storage).remove(id.as_bytes());
SWAPS.remove(deps.storage, &id);

let msgs = send_tokens(deps.api, &rcpt, swap.balance)?;
Ok(Response {
Expand Down Expand Up @@ -223,7 +223,7 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
}

fn query_details(deps: Deps, id: String) -> StdResult<DetailsResponse> {
let swap = atomic_swaps_read(deps.storage).load(id.as_bytes())?;
let swap = SWAPS.load(deps.storage, &id)?;

// Convert balance to human balance
let balance_human = match swap.balance {
Expand Down Expand Up @@ -254,8 +254,9 @@ fn query_list(
start_after: Option<String>,
limit: Option<u32>,
) -> StdResult<ListResponse> {
let start = calc_range_start_string(start_after);
let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize;
let start = start_after.map(|s| Bound::exclusive(s.as_bytes()));

Ok(ListResponse {
swaps: all_swap_ids(deps.storage, start, limit)?,
})
Expand Down
36 changes: 13 additions & 23 deletions contracts/cw20-atomic-swap/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ use schemars::JsonSchema;
use serde::{Deserialize, Serialize};

use cosmwasm_std::{Binary, BlockInfo, CanonicalAddr, Order, StdError, StdResult, Storage};
use cosmwasm_storage::{bucket, bucket_read, prefixed_read, Bucket, ReadonlyBucket};
use cw_storage_plus::{Bound, Map};

use cw20::{Balance, Expiration};

#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
Expand All @@ -22,29 +23,18 @@ impl AtomicSwap {
}
}

pub const PREFIX_SWAP: &[u8] = b"atomic_swap";

/// Returns a bucket with all swaps (query by id)
pub fn atomic_swaps(storage: &mut dyn Storage) -> Bucket<AtomicSwap> {
bucket(storage, PREFIX_SWAP)
}

/// Returns a bucket with all swaps (query by id)
/// (read-only version for queries)
pub fn atomic_swaps_read(storage: &dyn Storage) -> ReadonlyBucket<AtomicSwap> {
bucket_read(storage, PREFIX_SWAP)
}
pub const SWAPS: Map<&str, AtomicSwap> = Map::new("atomic_swap");

/// This returns the list of ids for all active swaps
pub fn all_swap_ids(
storage: &dyn Storage,
start: Option<Vec<u8>>,
start: Option<Bound>,
limit: usize,
) -> StdResult<Vec<String>> {
prefixed_read(storage, PREFIX_SWAP)
.range(start.as_deref(), None, Order::Ascending)
SWAPS
.keys(storage, start, None, Order::Ascending)
.take(limit)
.map(|(k, _)| String::from_utf8(k).map_err(|_| StdError::invalid_utf8("Parsing swap id")))
.map(|k| String::from_utf8(k).map_err(|_| StdError::invalid_utf8("Parsing swap id")))
.collect()
}

Expand Down Expand Up @@ -75,14 +65,14 @@ mod tests {
#[test]
fn test_all_swap_ids() {
let mut storage = MockStorage::new();
atomic_swaps(&mut storage)
.save("lazy".as_bytes(), &dummy_swap())
SWAPS
.save(&mut storage, "lazy".into(), &dummy_swap())
.unwrap();
atomic_swaps(&mut storage)
.save("assign".as_bytes(), &dummy_swap())
SWAPS
.save(&mut storage, "assign".into(), &dummy_swap())
.unwrap();
atomic_swaps(&mut storage)
.save("zen".as_bytes(), &dummy_swap())
SWAPS
.save(&mut storage, "zen".into(), &dummy_swap())
.unwrap();

let ids = all_swap_ids(&storage, None, 10).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion contracts/cw20-base/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ library = []
cw0 = { path = "../../packages/cw0", version = "0.5.0" }
cw2 = { path = "../../packages/cw2", version = "0.5.0" }
cw20 = { path = "../../packages/cw20", version = "0.5.0" }
cw-storage-plus = { path = "../../packages/storage-plus", version = "0.5.0", features = ["iterator"] }
cosmwasm-std = { version = "0.14.0-alpha2", features = ["iterator"] }
cosmwasm-storage = { version = "0.14.0-alpha2", features = ["iterator"] }
schemars = "0.7"
serde = { version = "1.0.103", default-features = false, features = ["derive"] }
thiserror = { version = "1.0.20" }
Expand Down
3 changes: 1 addition & 2 deletions contracts/cw20-base/examples/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use cw20::{
AllAccountsResponse, AllAllowancesResponse, AllowanceResponse, BalanceResponse,
TokenInfoResponse,
};
use cw20_base::msg::{HandleMsg, InitMsg, MigrateMsg, QueryMsg};
use cw20_base::msg::{HandleMsg, InitMsg, QueryMsg};

fn main() {
let mut out_dir = current_dir().unwrap();
Expand All @@ -18,7 +18,6 @@ fn main() {
export_schema(&schema_for!(InitMsg), &out_dir);
export_schema(&schema_for!(HandleMsg), &out_dir);
export_schema(&schema_for!(QueryMsg), &out_dir);
export_schema(&schema_for!(MigrateMsg), &out_dir);
export_schema(&schema_for!(AllowanceResponse), &out_dir);
export_schema(&schema_for!(BalanceResponse), &out_dir);
export_schema(&schema_for!(TokenInfoResponse), &out_dir);
Expand Down
6 changes: 0 additions & 6 deletions contracts/cw20-base/schema/migrate_msg.json

This file was deleted.

56 changes: 27 additions & 29 deletions contracts/cw20-base/src/allowances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cosmwasm_std::{
use cw20::{AllowanceResponse, Cw20ReceiveMsg, Expiration};

use crate::error::ContractError;
use crate::state::{allowances, allowances_read, balances, token_info};
use crate::state::{ALLOWANCES, BALANCES, TOKEN_INFO};

pub fn execute_increase_allowance(
deps: DepsMut,
Expand All @@ -22,8 +22,9 @@ pub fn execute_increase_allowance(
return Err(ContractError::CannotSetOwnAccount {});
}

allowances(deps.storage, owner_raw).update(
spender_raw.as_slice(),
ALLOWANCES.update(
deps.storage,
(&owner_raw, &spender_raw),
|allow| -> StdResult<_> {
let mut val = allow.unwrap_or_default();
if let Some(exp) = expires {
Expand Down Expand Up @@ -56,33 +57,32 @@ pub fn execute_decrease_allowance(
amount: Uint128,
expires: Option<Expiration>,
) -> Result<Response, ContractError> {
let spender_raw = &deps.api.canonical_address(&spender)?;
let owner_raw = &deps.api.canonical_address(&info.sender)?;

if spender_raw == owner_raw {
if spender == info.sender {
return Err(ContractError::CannotSetOwnAccount {});
}

let spender_raw = &deps.api.canonical_address(&spender)?;
let owner_raw = &deps.api.canonical_address(&info.sender)?;

// load value and delete if it hits 0, or update otherwise
let mut bucket = allowances(deps.storage, owner_raw);
let mut allowance = bucket.load(spender_raw.as_slice())?;
let mut allowance = ALLOWANCES.load(deps.storage, (&owner_raw, &spender_raw))?;
if amount < allowance.allowance {
// update the new amount
allowance.allowance = (allowance.allowance - amount)?;
if let Some(exp) = expires {
allowance.expires = exp;
}
bucket.save(spender_raw.as_slice(), &allowance)?;
ALLOWANCES.save(deps.storage, (&owner_raw, &spender_raw), &allowance)?;
} else {
allowances(deps.storage, owner_raw).remove(spender_raw.as_slice());
ALLOWANCES.remove(deps.storage, (&owner_raw, &spender_raw));
}

let res = Response {
submessages: vec![],
messages: vec![],
attributes: vec![
attr("action", "decrease_allowance"),
attr("owner", deps.api.human_address(owner_raw)?),
attr("owner", info.sender),
attr("spender", spender),
attr("amount", amount),
],
Expand All @@ -99,7 +99,7 @@ pub fn deduct_allowance(
block: &BlockInfo,
amount: Uint128,
) -> Result<AllowanceResponse, ContractError> {
allowances(storage, owner).update(spender.as_slice(), |current| {
ALLOWANCES.update(storage, (&owner, &spender), |current| {
match current {
Some(mut a) => {
if a.expires.is_expired(block) {
Expand Down Expand Up @@ -130,12 +130,12 @@ pub fn execute_transfer_from(
// deduct allowance before doing anything else have enough allowance
deduct_allowance(deps.storage, &owner_raw, &spender_raw, &env.block, amount)?;

let mut accounts = balances(deps.storage);
accounts.update(owner_raw.as_slice(), |balance: Option<Uint128>| {
BALANCES.update(deps.storage, &owner_raw, |balance: Option<Uint128>| {
balance.unwrap_or_default() - amount
})?;
accounts.update(
rcpt_raw.as_slice(),
BALANCES.update(
deps.storage,
&rcpt_raw,
|balance: Option<Uint128>| -> StdResult<_> { Ok(balance.unwrap_or_default() + amount) },
)?;

Expand Down Expand Up @@ -169,12 +169,11 @@ pub fn execute_burn_from(
deduct_allowance(deps.storage, &owner_raw, &spender_raw, &env.block, amount)?;

// lower balance
let mut accounts = balances(deps.storage);
accounts.update(owner_raw.as_slice(), |balance: Option<Uint128>| {
BALANCES.update(deps.storage, &owner_raw, |balance: Option<Uint128>| {
balance.unwrap_or_default() - amount
})?;
// reduce total_supply
token_info(deps.storage).update(|mut meta| -> StdResult<_> {
TOKEN_INFO.update(deps.storage, |mut meta| -> StdResult<_> {
meta.total_supply = (meta.total_supply - amount)?;
Ok(meta)
})?;
Expand Down Expand Up @@ -210,27 +209,26 @@ pub fn execute_send_from(
deduct_allowance(deps.storage, &owner_raw, &spender_raw, &env.block, amount)?;

// move the tokens to the contract
let mut accounts = balances(deps.storage);
accounts.update(owner_raw.as_slice(), |balance: Option<Uint128>| {
BALANCES.update(deps.storage, &owner_raw, |balance: Option<Uint128>| {
balance.unwrap_or_default() - amount
})?;
accounts.update(
rcpt_raw.as_slice(),
BALANCES.update(
deps.storage,
&rcpt_raw,
|balance: Option<Uint128>| -> StdResult<_> { Ok(balance.unwrap_or_default() + amount) },
)?;

let spender = deps.api.human_address(&spender_raw)?;
let attrs = vec![
attr("action", "send_from"),
attr("from", &owner),
attr("to", &contract),
attr("by", &spender),
attr("by", &info.sender),
attr("amount", amount),
];

// create a send message
let msg = Cw20ReceiveMsg {
sender: spender,
sender: info.sender,
amount,
msg,
}
Expand All @@ -252,8 +250,8 @@ pub fn query_allowance(
) -> StdResult<AllowanceResponse> {
let owner_raw = deps.api.canonical_address(&owner)?;
let spender_raw = deps.api.canonical_address(&spender)?;
let allowance = allowances_read(deps.storage, &owner_raw)
.may_load(spender_raw.as_slice())?
let allowance = ALLOWANCES
.may_load(deps.storage, (&owner_raw, &spender_raw))?
.unwrap_or_default();
Ok(allowance)
}
Expand Down
Loading

0 comments on commit 21ab493

Please sign in to comment.