Skip to content

Commit

Permalink
fixed other contract bugs
Browse files Browse the repository at this point in the history
finished to fix integration tests
  • Loading branch information
leobragaz committed Nov 18, 2020
1 parent f9f0460 commit 058d01c
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 143 deletions.
101 changes: 16 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,90 +1,21 @@
# CosmWasm Starter Pack
# Bonsai contract

This is a contract that I made for study purposes of the cosmWASM framework.
The idea behind it is a bonsai 🌳 shop platform, nothing serious, probably it contains some bugs too (🐜).

CosmWASM allows you to create, compile and build smart contracts on a
cosmosSDK based blockchain.

This is a template to build smart contracts in Rust to run inside a
[Cosmos SDK](https://github.com/cosmos/cosmos-sdk) module on all chains that enable it.
To understand the framework better, please read the overview in the
[cosmwasm repo](https://github.com/CosmWasm/cosmwasm/blob/master/README.md),
and dig into the [cosmwasm docs](https://www.cosmwasm.com).
This assumes you understand the theory and just want to get coding.

## Creating a new repo from template

Assuming you have a recent version of rust and cargo installed (via [rustup](https://rustup.rs/)),
then the following should get you a new repo to start a contract:

First, install
[cargo-generate](https://github.com/ashleygwilliams/cargo-generate).
Unless you did that before, run this line now:

```sh
cargo install cargo-generate --features vendored-openssl
```

Now, use it to create your new contract.
Go to the folder in which you want to place it and run:

**0.10 (latest)**

```sh
cargo generate --git https://github.com/CosmWasm/cosmwasm-template.git --name PROJECT_NAME
```

**0.9**

```sh
cargo generate --git https://github.com/CosmWasm/cosmwasm-template.git --branch 0.9 --name PROJECT_NAME
```

**0.8**

```sh
cargo generate --git https://github.com/CosmWasm/cosmwasm-template.git --branch 0.8 --name PROJECT_NAME
```

You will now have a new folder called `PROJECT_NAME` (I hope you changed that to something else)
containing a simple working contract and build system that you can customize.

## Create a Repo

After generating, you have a initialized local git repo, but no commits, and no remote.
Go to a server (eg. github) and create a new upstream repo (called `YOUR-GIT-URL` below).
Then run the following:

```sh
# this is needed to create a valid Cargo.lock file (see below)
cargo check
git checkout -b master # in case you generate from non-master
git add .
git commit -m 'Initial Commit'
git remote add origin YOUR-GIT-URL
git push -u origin master
```

## CI Support

We have template configurations for both [GitHub Actions](.github/workflows/Basic.yml)
and [Circle CI](.circleci/config.yml) in the generated project, so you can
get up and running with CI right away.

One note is that the CI runs all `cargo` commands
with `--locked` to ensure it uses the exact same versions as you have locally. This also means
you must have an up-to-date `Cargo.lock` file, which is not auto-generated.
The first time you set up the project (or after adding any dep), you should ensure the
`Cargo.lock` file is updated, so the CI will test properly. This can be done simply by
running `cargo check` or `cargo unit-test`.

## Using your project

Once you have your custom repo, you should check out [Developing](./Developing.md) to explain
more on how to run tests and develop code. Or go through the
[online tutorial](https://www.cosmwasm.com/docs/getting-started/intro) to get a better feel
of how to develop.

[Publishing](./Publishing.md) contains useful information on how to publish your contract
to the world, once you are ready to deploy it on a running blockchain. And
[Importing](./Importing.md) contains information about pulling in other contracts or crates
that have been published.

Please replace this README file with information about your specific project. You can keep
the `Developing.md` and `Publishing.md` files as useful referenced, but please set some
proper description in the README.
# How to try it
1. [Install the requested components and set up the environment](https://docs.cosmwasm.com/getting-started/installation.html).
2. Clone the project: from your CLI `git clone https://github.com/bragaz/wasm-test-contract.git`
3. Move inside the project folder: `cd ../wasm-test-contract`
4. Run the docker command to compile the contract: `docker run --rm -v "$(pwd)":/code \
--mount type=volume,source="$(basename "$(pwd)")_cache",target=/code/target \
--mount type=volume,source=registry_cache,target=/usr/local/cargo/registry \
cosmwasm/rust-optimizer:0.10.4`
5. Inside the contract `helper.ts` file there is an example of how to try out the contract
19 changes: 11 additions & 8 deletions src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn init<S: Storage, A: Api, Q: Querier>(
msg: InitMsg,
) -> Result<InitResponse, MyCustomError> {
// set_contract_version(&mut deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
let bonsai_list = BonsaiList::grow_bonsais(msg.number, env.block.height, msg.price.clone());
let bonsai_list = BonsaiList::grow_bonsais(msg.number, env.block.height, msg.price);
bonsai_store(&mut deps.storage).save(&bonsai_list)?;
let mut res = InitResponse::default();
res.attributes = vec![attr("action", "grown_bonsais")];
Expand Down Expand Up @@ -105,12 +105,16 @@ pub fn handle_buy_bonsai<S: Storage, A: Api, Q: Querier>(
};

// check if the gardener has enough funds to buy the bonsai
let denom = deps.querier.query_bonded_denom()?;
let balance = deps.querier.query_balance(&info.sender, &denom.as_str())?;
deps.api.debug(info.sender.clone().as_str());
if balance.amount < bonsai.price.amount {
deps.api.debug(balance.amount.clone().to_string().as_str());
deps.api.debug(bonsai.price.amount.clone().to_string().as_str());
let sent_funds = info.sent_funds.first().ok_or_else(|| {
MyCustomError::Std(StdError::generic_err("No funds to complete the purchase"))
})?;
if sent_funds.denom == bonsai.price.denom {
if sent_funds.amount < bonsai.price.amount {
return Err(MyCustomError::Std(StdError::generic_err(
"Insufficient funds to buy the bonsai",
)));
}
} else {
return Err(MyCustomError::Std(StdError::generic_err(
"Insufficient funds to buy the bonsai",
)));
Expand All @@ -124,7 +128,6 @@ pub fn handle_buy_bonsai<S: Storage, A: Api, Q: Querier>(

let canonical_addr = &deps.api.canonical_address(&info.sender)?;
// todo check if it's possible to use may_update
gardeners_store(&mut deps.storage).load(canonical_addr.as_slice())?;
gardeners_store(&mut deps.storage).update::<_, StdError>(
canonical_addr.as_slice(),
|gardener| {
Expand Down
65 changes: 34 additions & 31 deletions src/contract_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@ use crate::state::{bonsai_store_readonly, gardeners_store, Bonsai, Gardener};
use assert::equal;
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info, MockQuerier};
use cosmwasm_std::{
attr, coin, Api, BankMsg, Coin, Decimal, Env, Extern, HandleResponse, HumanAddr, Querier,
Storage, Validator,
attr, coin, coins, Api, BankMsg, Coin, Decimal, Env, Extern, HandleResponse, HumanAddr,
MessageInfo, Querier, Storage, Validator,
};
use rand::seq::SliceRandom;

const DEFAULT_VALIDATOR: &str = "default-validator";
const BOND_DENOM: &str = "bonsai";

// Mock validator constructor
fn sample_validator<U: Into<HumanAddr>>(addr: U) -> Validator {
Expand Down Expand Up @@ -42,15 +43,15 @@ fn set_balance(querier: &mut MockQuerier, addr: HumanAddr, balance: Vec<Coin>) {
fn setup_test<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>,
env: &Env,
info: MessageInfo,
bonsai_price: Coin,
bonsai_number: u64,
) {
let init_msg = InitMsg {
price: bonsai_price,
number: bonsai_number,
};
let sender_addr = HumanAddr::from("addr0001");
init(deps, env.clone(), mock_info(&sender_addr, &[]), init_msg).unwrap();
init(deps, env.clone(), info, init_msg).unwrap();
}

// return a random bonsai id
Expand Down Expand Up @@ -89,11 +90,11 @@ fn test_become_gardener_works() {
let mut deps = mock_dependencies(&[]);

let sender_addr = HumanAddr::from("addr0001");
let bond_denom = "bonsai";
let bonsai_price = coin(10, bond_denom);
let bonsai_price = coin(10, BOND_DENOM);
let bonsai_height = 100;
let env = mock_env_height(bonsai_height);
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);

let mut exp_res = HandleResponse::default();
exp_res.attributes = vec![
Expand All @@ -104,7 +105,7 @@ fn test_become_gardener_works() {
let msg = HandleMsg::BecomeGardener {
name: String::from("leo"),
};
let res = handle(&mut deps, env.clone(), mock_info(&sender_addr, &[]), msg);
let res = handle(&mut deps, env.clone(), info.clone(), msg);

// verify it not fails
assert!(res.is_ok());
Expand All @@ -117,19 +118,18 @@ fn test_buy_bonsai_works() {
let mut deps = mock_dependencies(&[]);

let sender_addr = HumanAddr::from("addr0001");
let bond_denom = "bonsai";
let bonsai_price = coin(10, bond_denom);
let bonsai_price = coin(10, BOND_DENOM);
let bonsai_height = 100;
let env = mock_env_height(bonsai_height);
let info = mock_info(sender_addr, &[]);
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));

// setup test environment
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
set_validator(&mut deps.querier, bond_denom);
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);
set_validator(&mut deps.querier, BOND_DENOM);
set_balance(
&mut deps.querier,
info.sender.clone(),
vec![coin(1000, bond_denom)],
vec![coin(1000, BOND_DENOM)],
);

let canonical_addr = &deps.api.canonical_address(&info.sender.clone()).unwrap();
Expand All @@ -155,7 +155,7 @@ fn test_buy_bonsai_works() {

let msg = HandleMsg::BuyBonsai { b_id: bonsai_id };

let res = handle(&mut deps, env.clone(), mock_info(&info.sender, &[]), msg);
let res = handle(&mut deps, env.clone(), info, msg);

assert!(res.is_ok());
assert_eq!(exp_res, res.unwrap())
Expand All @@ -167,19 +167,18 @@ fn test_sell_bonsai_works() {

let sender_addr = HumanAddr::from("addr0001");
let buyer_addr = HumanAddr::from("addr0002");
let bond_denom = "bonsai";
let bonsai_price = coin(10, bond_denom);
let bonsai_price = coin(10, BOND_DENOM);
let bonsai_height = 100;
let env = mock_env_height(bonsai_height);
let info = mock_info(sender_addr, &[]);
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));

// setup test environment
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
set_validator(&mut deps.querier, bond_denom);
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);
set_validator(&mut deps.querier, BOND_DENOM);
set_balance(
&mut deps.querier,
buyer_addr.clone(),
vec![coin(1000, bond_denom)],
vec![coin(1000, BOND_DENOM)],
);

let bonsai = query_bonsais(&deps)
Expand Down Expand Up @@ -228,17 +227,16 @@ fn test_cut_bonsai_works() {
let mut deps = mock_dependencies(&[]);

let sender_addr = HumanAddr::from("addr0001");
let bond_denom = "bonsai";
let bonsai_price = coin(10, bond_denom);
let bonsai_price = coin(10, BOND_DENOM);
let bonsai_height = 100;
let env = mock_env_height(bonsai_height);
let info = mock_info(sender_addr, &[]);
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));

// setup test environment
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);

let canonical_addr = &deps.api.canonical_address(&info.sender.clone()).unwrap();
let bonsai = Bonsai::new(10,bonsai_height, bonsai_price);
let bonsai = Bonsai::new(10, bonsai_height, bonsai_price);
let gardener = Gardener::new(
"leo".to_string(),
canonical_addr.clone(),
Expand Down Expand Up @@ -272,8 +270,11 @@ fn query_bonsais_works() {
let mut deps = mock_dependencies(&[]);
let bonsai_price = coin(10, "bonsai");
let bonsai_height = 100;
let sender_addr = HumanAddr::from("addr0001");

let env = mock_env_height(bonsai_height);
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);

let bonsais = query_bonsais(&deps).unwrap();

Expand All @@ -286,11 +287,12 @@ fn query_gardener_works() {
let sender_addr = HumanAddr::from("addr0001");
let bonsai_price = coin(10, "bonsai");
let bonsai_height = 100;
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));

let env = mock_env_height(bonsai_height);
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);

let bonsai = Bonsai::new(10,bonsai_height, bonsai_price);
let bonsai = Bonsai::new(10, bonsai_height, bonsai_price);
let canonical_addr = &deps.api.canonical_address(&sender_addr).unwrap();

let gardener = Gardener::new("leo".to_string(), canonical_addr.clone(), vec![bonsai]);
Expand All @@ -310,9 +312,10 @@ fn query_all_gardeners_works() {
let bonsai_height = 100;

let env = mock_env_height(bonsai_height);
setup_test(&mut deps, &env, bonsai_price.clone(), 10);
let info = mock_info(sender_addr.clone(), &coins(25, BOND_DENOM));
setup_test(&mut deps, &env, info.clone(), bonsai_price.clone(), 10);

let bonsai = Bonsai::new(10,bonsai_height, bonsai_price);
let bonsai = Bonsai::new(10, bonsai_height, bonsai_price);
let canonical_addr = &deps.api.canonical_address(&sender_addr).unwrap();
let other_addr = HumanAddr::from("addr0002");
let other_addr = &deps.api.canonical_address(&other_addr).unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl BonsaiList {
bonsais.push(Bonsai::new(i, birth_date, price.clone()));
i += 1;
}
BonsaiList{ bonsais }
BonsaiList { bonsais }
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/state_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ fn new_bonsai() {
price: coin(145, "testCoin"),
};

let cur_bonsai = Bonsai::new(1,100, exp_bonsai.price.clone());
let cur_bonsai = Bonsai::new(1, 100, exp_bonsai.price.clone());

exp_bonsai.id = cur_bonsai.id.clone();

Expand Down
Loading

0 comments on commit 058d01c

Please sign in to comment.