Skip to content

Commit

Permalink
Add steak-token contract
Browse files Browse the repository at this point in the history
  • Loading branch information
larry0x committed Apr 8, 2022
1 parent e85dfa5 commit 7cb13d1
Show file tree
Hide file tree
Showing 6 changed files with 196 additions and 5 deletions.
9 changes: 9 additions & 0 deletions Cargo.lock

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

29 changes: 25 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,31 @@ Steak is audited by [SCV Security](https://twitter.com/TerraSCV) ([link](https:/

## Contracts

| Contract | Description |
| ------------------------------------------ | ------------------------------------------------------ |
| [`steak-hub`](./contracts/steak-hub) | Manages minting/burning of Steak token and bonded Luna |
| [`steak-zapper`](./contracts/steak-zapper) | Allows zapping into Steak from various assets |
| Contract | Description |
| ------------------------------------ | ------------------------------------------------------ |
| [`steak-hub`](./contracts/hub) | Manages minting/burning of Steak token and bonded Luna |
| [`steak-token`](./contracts/token) | Modified CW20 token contract |
| [`steak-zapper`](./contracts/zapper) | Allows zapping into Steak from various assets |

## Deployment

### Mainnet

| Contract | Address |
| -------------------- | ------- |
| Steak Hub | TBD |
| Steak Token | TBD |
| Steak Zapper | TBD |
| Steak Admin Multisig | TBD |

### Testnet

| Contract | Address |
| -------------------- | ------- |
| Steak Hub | TBD |
| Steak Token | TBD |
| Steak Zapper | TBD |
| Steak Admin Multisig | TBD |

## License

Expand Down
18 changes: 18 additions & 0 deletions contracts/token/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "steak-token"
version = "0.1.0"
authors = ["larry <[email protected]>"]
edition = "2018"
license = "GPL-3.0-or-later"
repository = "https://github.com/st4k3h0us3/steak-contracts"

[lib]
crate-type = ["cdylib", "rlib"]

[features]
backtraces = ["cosmwasm-std/backtraces"]

[dependencies]
cosmwasm-std = { version = "0.16", features = ["staking"] }
cw20 = "0.9"
cw20-base = { version = "0.9", features = ["library"] }
6 changes: 6 additions & 0 deletions contracts/token/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Steak Token

Steak Token is based the [vanilla CW20 contract](https://github.com/CosmWasm/cw-plus/tree/v0.9.1/contracts/cw20-base) with two changes to prevent manipulations of token prices:

- `ExecuteMsg::Burn` can only be executed by the minter, i.e. Steak Hub contract;
- `ExecuteMsg::BurnFrom` is disabled.
137 changes: 137 additions & 0 deletions contracts/token/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use cosmwasm_std::{
entry_point, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult,
Storage,
};
use cw20_base::contract::{
execute as cw20_execute, instantiate as cw20_instantiate, query as cw20_query,
};
use cw20_base::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use cw20_base::state::{MinterData, TOKEN_INFO};
use cw20_base::ContractError;

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: InstantiateMsg,
) -> Result<Response, ContractError> {
cw20_instantiate(deps, env, info, msg)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
// For `burn`, we assert that the caller is the minter
// For `burn_from`, we disable it since there should never be a case where it is needed
match msg {
ExecuteMsg::Burn { .. } => assert_minter(deps.storage, &info.sender)?,
ExecuteMsg::BurnFrom { .. } => return Err(StdError::generic_err("`burn_from` command is disabled").into()),
_ => (),
}

cw20_execute(deps, env, info, msg)
}

fn assert_minter(storage: &dyn Storage, sender: &Addr) -> Result<(), ContractError> {
let token_info = TOKEN_INFO.load(storage)?;

if let Some(MinterData { minter, .. }) = &token_info.mint {
if sender != minter {
return Err(StdError::generic_err("only minter can execute token burn").into());
}
}

Ok(())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
cw20_query(deps, env, msg)
}

#[cfg(test)]
mod tests {
use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info, MockApi, MockQuerier, MockStorage};
use cosmwasm_std::{OwnedDeps, Uint128};
use cw20_base::state::{BALANCES, TokenInfo};

use super::*;

fn setup_test() -> OwnedDeps<MockStorage, MockApi, MockQuerier> {
let mut deps = mock_dependencies(&[]);

TOKEN_INFO
.save(
deps.as_mut().storage,
&TokenInfo {
name: "Steak Token".to_string(),
symbol: "STEAK".to_string(),
decimals: 6,
total_supply: Uint128::new(200),
mint: Some(MinterData {
minter: Addr::unchecked("steak_hub"),
cap: None,
}),
},
)
.unwrap();

BALANCES
.save(
deps.as_mut().storage,
&Addr::unchecked("steak_hub"),
&Uint128::new(100)
)
.unwrap();

BALANCES
.save(
deps.as_mut().storage,
&Addr::unchecked("alice"),
&Uint128::new(100)
)
.unwrap();

deps
}

#[test]
fn asserting_minter() {
let mut deps = setup_test();

// Alice is not allowed to burn her balance
let res = execute(
deps.as_mut(),
mock_env(),
mock_info("alice", &[]),
ExecuteMsg::Burn {
amount: Uint128::new(100),
},
);
assert_eq!(res, Err(StdError::generic_err("only minter can execute token burn").into()));

// Steak Hub can burn
let res = execute(
deps.as_mut(),
mock_env(),
mock_info("steak_hub", &[]),
ExecuteMsg::Burn {
amount: Uint128::new(100),
},
);
assert!(res.is_ok());

// Steak Hub's token balance should have been reduced
let balance = BALANCES.load(deps.as_ref().storage, &Addr::unchecked("steak_hub")).unwrap();
assert_eq!(balance, Uint128::zero());

// Total supply should have been reduced
let token_info = TOKEN_INFO.load(deps.as_ref().storage).unwrap();
assert_eq!(token_info.total_supply, Uint128::new(100));
}
}
2 changes: 1 addition & 1 deletion scripts/2_upload_cw20.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const argv = yargs(process.argv)
binary: {
type: "string",
demandOption: false,
default: "../../cw-plus/artifacts/cw20_base.wasm",
default: "../artifacts/steak_token.wasm",
},
})
.parseSync();
Expand Down

0 comments on commit 7cb13d1

Please sign in to comment.