Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

minting cap #88

Merged
merged 24 commits into from
Sep 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
16f321a
Started porting secretcli.py into a rust equivalent
FloppyDisck Sep 5, 2021
ee670dc
Started porting secretcli.py into a rust equivalent
FloppyDisck Sep 5, 2021
8d1fafa
implemented the t_query trait
FloppyDisck Sep 5, 2021
9a98063
new contract tester in rust
FloppyDisck Sep 5, 2021
a202beb
Added handle and init traits for the tester and started implementing …
FloppyDisck Sep 6, 2021
12bdb58
Updated returned output from handle functions
FloppyDisck Sep 7, 2021
5af8534
fixed snip20 compile issue
FloppyDisck Sep 7, 2021
3fd8184
moved band initializer into the shade_protocol package
FloppyDisck Sep 10, 2021
df72276
updated mint overlook
FloppyDisck Sep 10, 2021
dac3a2f
changed initializer query structure to match the standard
FloppyDisck Sep 10, 2021
bcf89bc
added rust tester support
FloppyDisck Sep 10, 2021
c93516b
removed
FloppyDisck Sep 10, 2021
69e8784
removed unnecessary feature
FloppyDisck Sep 10, 2021
e19e399
expanded tester
FloppyDisck Sep 10, 2021
335b7d5
made the tester independent to avoid rand issues
FloppyDisck Sep 10, 2021
be04b50
this initial tester now has all the support tester.py has
FloppyDisck Sep 10, 2021
6f47762
lock files update
FloppyDisck Sep 10, 2021
9b0e95c
Added minting limits
FloppyDisck Sep 11, 2021
a61081f
added account address querying
FloppyDisck Sep 11, 2021
3413c13
updated testers
FloppyDisck Sep 11, 2021
2928880
missing serializable type
FloppyDisck Sep 12, 2021
adecb94
fixed limit bug
FloppyDisck Sep 12, 2021
c773a1c
improved tests
FloppyDisck Sep 12, 2021
0f06164
updated docs
FloppyDisck Sep 12, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
577 changes: 78 additions & 499 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"packages/shade_protocol",
"packages/secretcli",
"contracts/initializer",
"contracts/mint",
"contracts/micro_mint",
Expand Down
6 changes: 3 additions & 3 deletions contracts/initializer/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use cosmwasm_std::{Storage, Api, Querier, Extern, StdResult, to_binary, Binary};
use shade_protocol::initializer::{QueryMsg, ContractsAnswer};
use shade_protocol::initializer::{QueryMsg, QueryAnswer};
use crate::state::config_r;

pub fn query_contracts<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>) -> StdResult<ContractsAnswer> {
Ok(ContractsAnswer { contracts: config_r(&deps.storage).load()?.contracts })
pub fn query_contracts<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
Ok(QueryAnswer::ContractsAnswer { contracts: config_r(&deps.storage).load()?.contracts })
}
72 changes: 45 additions & 27 deletions contracts/micro_mint/README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@

# Mint Contract
* [Introduction](#Introduction)
* [Sections](#Sections)
* [Init](#Init)
* [Admin](#Admin)
* Messages
* [Migrate](#Migrate)
* [UpdateConfig](#UpdateConfig)
* [UpdateMintLimit](#UpdateMintLimit)
* [RegisterAsset](#RegisterAsset)
* Queries
* [GetNativeAsset](#GetNativeAsset)
* [GetConfig](#GetConfig)
* [SupportedAssets](#SupportedAssets)
* [GetAsset](#getAsset)
* [MintLimit](#GetMintLimit)
* [SupportedAssets](#GetSupportedAssets)
* [GetAsset](#GetAsset)
* [User](#User)
* Messages
* [Receive](#Receive)
Expand All @@ -22,25 +24,26 @@ Contract responsible to mint a paired snip20 asset

## Init
##### Request
|Name |Type |Description | optional |
|-------------|----------|-------------------------------------------------------------------------------------------------------------------|----------|
|admin | string | New contract owner; SHOULD be a valid bech32 address, but contracts may use a different naming scheme as well | yes |
|native_asset | Contract | Asset to mint | no |
|peg | String | Symbol to peg to when querying oracle (defaults to native_asset symbol) | yes |
|treasury | Contract | Treasury contract | yes |
|oracle | Contract | Oracle contract | no |

|Name |Type |Description | optional |
|-----------------|----------|-------------------------------------------------------------------------------------------------------------------|----------|
|admin | string | New contract owner; SHOULD be a valid bech32 address, but contracts may use a different naming scheme as well | yes |
|native_asset | Contract | Asset to mint | no |
|peg | String | Symbol to peg to when querying oracle (defaults to native_asset symbol) | yes |
|treasury | Contract | Treasury contract | yes |
|oracle | Contract | Oracle contract | no |
|epoch_frequency | String | The frequency in which the mint limit resets, if 0 then no limit is enforced | yes |
|epoch_mint_limit | String | The limit of uTokens to mint per epoch | yes |
## Admin

### Messages
### Migrate
Migrates all the contracts state and data into a new contract
#### Request
| Name | Type | Description | optional |
|----------| -------|---------------------|----------|
|label | String | Contract label name | no |
|code_id | u64 | Contract ID | no |
|code_hash | String | Contract code hash | no |
#### UpdateConfig
Updates the given values
##### Request
|Name |Type |Description | optional |
|----------|----------|-------------------------------------------------------------------------------------------------------------------|----------|
|owner | string | New contract owner; SHOULD be a valid bech32 address, but contracts may use a different naming scheme as well | yes |
|treasury | Contract | Treasury contract | yes |
|oracle | Contract | Oracle contract | yes |
##### Response
```json
{
Expand All @@ -50,18 +53,17 @@ Migrates all the contracts state and data into a new contract
}
```

#### UpdateConfig
#### UpdateMintLimit
Updates the given values
##### Request
|Name |Type |Description | optional |
|----------|----------|-------------------------------------------------------------------------------------------------------------------|----------|
|owner | string | New contract owner; SHOULD be a valid bech32 address, but contracts may use a different naming scheme as well | yes |
|treasury | Contract | Treasury contract | yes |
|oracle | Contract | Oracle contract | yes |
|Name |Type |Description | optional |
|----------|----------|---------------------------------------------------------------------------------------|----------|
|epoch_frequency | String | The frequency in which the mint limit resets, if 0 then no limit is enforced | yes |
|epoch_mint_limit | String | The limit of uTokens to mint per epoch | yes |
##### Response
```json
{
"update_config": {
"update_mint_limit": {
"status": "success"
}
}
Expand Down Expand Up @@ -120,7 +122,23 @@ Gets the contract's configuration variables
}
```

#### SupportedAssets
#### GetMintLimit
Gets the contract's configuration variables
##### Response
```json
{
"limit": {
"mint_limit": {
"frequency": "Frequency per epoch reset",
"mint_capacity": "Mint capacity per epoch",
"total_minted": "Total minted in current epoch",
"next_epoch": "Timestamp for the next epoch"
}
}
}
```

#### GetSupportedAssets
Get all the contract's supported assets.
##### Response
```json
Expand Down
31 changes: 26 additions & 5 deletions contracts/micro_mint/src/contract.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use cosmwasm_std::{
debug_print, to_binary, Api, Binary,
Env, Extern, HandleResponse, InitResponse,
Querier, StdResult, Storage,
};
use cosmwasm_std::{debug_print, to_binary, Api, Binary, Env, Extern, HandleResponse, InitResponse, Querier, StdResult, Storage, Uint128};
use secret_toolkit::snip20::token_info_query;

use shade_protocol::{
Expand All @@ -25,6 +21,8 @@ use crate::{
},
handle, query,
};
use shade_protocol::micro_mint::MintLimit;
use crate::state::limit_w;

pub fn init<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>,
Expand All @@ -42,6 +40,24 @@ pub fn init<S: Storage, A: Api, Q: Querier>(
activated: true,
};

// Set the minting limit
let limit = MintLimit {
frequency: match msg.epoch_frequency {
None => 0,
Some(frequency) => frequency.u128() as u64,
},
mint_capacity: match msg.epoch_mint_limit {
None => Uint128(0),
Some(capacity) => capacity
},
total_minted: Uint128(0),
next_epoch: match msg.epoch_frequency {
None => 0,
Some(frequency) => env.block.time + frequency.u128() as u64,
FloppyDisck marked this conversation as resolved.
Show resolved Hide resolved
},
};
limit_w(&mut deps.storage).save(&limit)?;

config_w(&mut deps.storage).save(&state)?;
let token_info = token_info_query(
&deps.querier, 1,
Expand Down Expand Up @@ -86,6 +102,10 @@ pub fn handle<S: Storage, A: Api, Q: Querier>(
oracle,
treasury,
} => handle::try_update_config(deps, env, owner, oracle, treasury),
HandleMsg::UpdateMintLimit {
epoch_frequency,
epoch_limit,
} => handle::try_update_limit(deps, env, epoch_frequency, epoch_limit),
HandleMsg::RegisterAsset {
contract,
commission,
Expand All @@ -108,5 +128,6 @@ pub fn query<S: Storage, A: Api, Q: Querier>(
QueryMsg::GetSupportedAssets {} => to_binary(&query::supported_assets(deps)?),
QueryMsg::GetAsset { contract } => to_binary(&query::asset(deps, contract)?),
QueryMsg::GetConfig {} => to_binary(&query::config(deps)?),
QueryMsg::GetMintLimit {} => to_binary(&query::limit(deps)?),
}
}
83 changes: 72 additions & 11 deletions contracts/micro_mint/src/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use shade_protocol::{
Config,
SupportedAsset,
},
mint::SnipMsgHook,
mint::MintMsgHook,
snip20::{Snip20Asset, token_config_query, TokenConfig},
oracle::{
QueryMsg::GetPrice,
Expand All @@ -24,14 +24,7 @@ use shade_protocol::{
generic_response::ResponseStatus,
};

use crate::state::{
config_w, config_r,
native_asset_r,
asset_peg_r,
assets_w, assets_r,
asset_list_w,
total_burned_w,
};
use crate::state::{config_w, config_r, native_asset_r, asset_peg_r, assets_w, assets_r, asset_list_w, total_burned_w, limit_w, limit_r};

pub fn try_burn<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>,
Expand Down Expand Up @@ -70,7 +63,7 @@ pub fn try_burn<S: Storage, A: Api, Q: Querier>(

// Setup msgs
let mut messages = vec![];
let msgs: SnipMsgHook = match msg {
let msgs: MintMsgHook = match msg {
Some(x) => from_binary(&x)?,
None => return Err(StdError::generic_err("data cannot be empty")),
};
Expand Down Expand Up @@ -124,13 +117,36 @@ pub fn try_burn<S: Storage, A: Api, Q: Querier>(
let mint_asset = native_asset_r(&deps.storage).load()?;

// This will calculate the total mint value
// Amount minted does not consider commission
let amount_to_mint: Uint128 = mint_amount(&deps, amount, &burn_asset, &mint_asset)?;

// Check against slippage amount
if amount_to_mint < msgs.minimum_expected_amount {
return Err(StdError::generic_err("Mint amount is less than the minimum expected."))
}

// Check against mint cap
let mut limit_storage = limit_w(&mut deps.storage);
let mut limit = limit_storage.load()?;

// When frequency is 0 it means that mint limits are disabled
if limit.frequency != 0 {
FloppyDisck marked this conversation as resolved.
Show resolved Hide resolved
// Reset total and next epoch
if limit.next_epoch <= env.block.time {
limit.next_epoch = env.block.time + limit.frequency;
limit.total_minted = Uint128(0);
}

let new_total = limit.total_minted + amount_to_mint;

if new_total > limit.mint_capacity {
return Err(StdError::generic_err("Amount to be minted exceeds mint capacity"))
}

limit.total_minted = new_total;

limit_storage.save(&limit);
}

debug_print!("Minting: {} {}", amount_to_mint, &mint_asset.token_info.symbol);

messages.push(mint_msg(from,
Expand Down Expand Up @@ -191,6 +207,51 @@ pub fn try_update_config<S: Storage, A: Api, Q: Querier>(
})
}

pub fn try_update_limit<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>,
env: Env,
epoch_frequency: Option<Uint128>,
epoch_limit: Option<Uint128>,
) -> StdResult<HandleResponse> {
let config = config_r(&deps.storage).load()?;
// Check if admin
if env.message.sender != config.owner {
return Err(StdError::Unauthorized { backtrace: None });
}
// Check if contract enabled
if !config.activated {
return Err(StdError::Unauthorized { backtrace: None });
}

// Reset limit and set new limits
let mut limit = limit_w(&mut deps.storage);
limit.update(|mut state| {
if let Some(frequency) = epoch_frequency {
state.frequency = frequency.u128() as u64;
}
if let Some(limit) = epoch_limit {
state.mint_capacity = limit
}
// Reset total minted
state.total_minted = Uint128(0);

// Reset next epoch
if state.frequency == 0 {
state.next_epoch = 0;
} else {
state.next_epoch = env.block.time + state.frequency;
}
Ok(state)
})?;

Ok(HandleResponse {
messages: vec![],
log: vec![],
data: Some( to_binary( &HandleAnswer::UpdateMintLimit {
status: ResponseStatus::Success } )? )
})
}

pub fn try_register_asset<S: Storage, A: Api, Q: Querier>(
deps: &mut Extern<S, A, Q>,
env: &Env,
Expand Down
27 changes: 15 additions & 12 deletions contracts/micro_mint/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
use cosmwasm_std::{
Api, Extern, Querier, StdError, StdResult, Storage,
};
use crate::state::{
config_r,
native_asset_r,
asset_peg_r,
assets_r,
asset_list_r,
total_burned_r,
};
use crate::state::{config_r, native_asset_r, asset_peg_r, assets_r, asset_list_r,
total_burned_r, limit_r};
use shade_protocol::{
micro_mint::{
QueryAnswer
},
};

pub fn native_asset<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
pub fn native_asset<S: Storage, A: Api, Q: Querier>
(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
Ok(QueryAnswer::NativeAsset { asset: native_asset_r(&deps.storage).load()?,
peg: asset_peg_r(&deps.storage).load()? })
}

pub fn supported_assets<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
pub fn supported_assets<S: Storage, A: Api, Q: Querier>
(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
Ok(QueryAnswer::SupportedAssets { assets: asset_list_r(&deps.storage).load()? })
}

pub fn asset<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>, contract: String) -> StdResult<QueryAnswer> {
pub fn asset<S: Storage, A: Api, Q: Querier>
(deps: &Extern<S, A, Q>, contract: String) -> StdResult<QueryAnswer> {
let assets = assets_r(&deps.storage);

return match assets.may_load(contract.as_bytes())? {
Expand All @@ -38,6 +35,12 @@ pub fn asset<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>, contract: S
};
}

pub fn config<S: Storage, A: Api, Q: Querier>(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
pub fn config<S: Storage, A: Api, Q: Querier>
(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
Ok(QueryAnswer::Config { config: config_r(&deps.storage).load()? })
}

pub fn limit<S: Storage, A: Api, Q: Querier>
(deps: &Extern<S, A, Q>) -> StdResult<QueryAnswer> {
Ok(QueryAnswer::MintLimit { limit: limit_r(&deps.storage).load()? })
}
Loading