Skip to content

Commit

Permalink
Merge pull request #748 from ezekiiel/zeke/minter-removal
Browse files Browse the repository at this point in the history
Add ability to unset minter in UpdateMinter message.
  • Loading branch information
ueco-jb authored Jul 18, 2022
2 parents 5988632 + 803e90a commit 8fd2904
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 12 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

[Full Changelog](https://github.com/CosmWasm/cw-plus/compare/v0.13.4...HEAD)

**Merged pull requests:**

- Add ability to unset minter in UpdateMinter message. [\#748](https://github.com/CosmWasm/cw-plus/pull/748) ([ezekiiel](https://github.com/ezekiiel))

## [v0.13.4](https://github.com/CosmWasm/cw-plus/tree/v0.13.4) (2022-06-02)

[Full Changelog](https://github.com/CosmWasm/cw-plus/compare/v0.13.3...v0.13.4)
Expand Down
66 changes: 56 additions & 10 deletions contracts/cw20-base/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ pub fn execute_update_minter(
deps: DepsMut,
_env: Env,
info: MessageInfo,
new_minter: String,
new_minter: Option<String>,
) -> Result<Response, ContractError> {
let mut config = TOKEN_INFO
.may_load(deps.storage)?
Expand All @@ -404,18 +404,27 @@ pub fn execute_update_minter(
return Err(ContractError::Unauthorized {});
}

let minter = deps.api.addr_validate(&new_minter)?;
let minter_data = MinterData {
minter,
cap: mint.cap,
};
config.mint = Some(minter_data);
let minter_data = new_minter
.map(|new_minter| deps.api.addr_validate(&new_minter))
.transpose()?
.map(|minter| MinterData {
minter,
cap: mint.cap,
});

config.mint = minter_data;

TOKEN_INFO.save(deps.storage, &config)?;

Ok(Response::default()
.add_attribute("action", "update_minter")
.add_attribute("new_minter", new_minter))
.add_attribute(
"new_minter",
config
.mint
.map(|m| m.minter.into_string())
.unwrap_or_else(|| "None".to_string()),
))
}

pub fn execute_update_marketing(
Expand Down Expand Up @@ -927,7 +936,7 @@ mod tests {

let new_minter = "new_minter";
let msg = ExecuteMsg::UpdateMinter {
new_minter: new_minter.to_string(),
new_minter: Some(new_minter.to_string()),
};

let info = mock_info(&minter, &[]);
Expand Down Expand Up @@ -956,7 +965,7 @@ mod tests {
);

let msg = ExecuteMsg::UpdateMinter {
new_minter: String::from("new_minter"),
new_minter: Some("new_minter".to_string()),
};

let info = mock_info("not the minter", &[]);
Expand All @@ -965,6 +974,43 @@ mod tests {
assert_eq!(err, ContractError::Unauthorized {});
}

#[test]
fn unset_minter() {
let mut deps = mock_dependencies();
let minter = String::from("minter");
let cap = None;
do_instantiate_with_minter(
deps.as_mut(),
&String::from("genesis"),
Uint128::new(1234),
&minter,
cap,
);

let msg = ExecuteMsg::UpdateMinter { new_minter: None };

let info = mock_info(&minter, &[]);
let env = mock_env();
let res = execute(deps.as_mut(), env.clone(), info, msg);
assert!(res.is_ok());
let query_minter_msg = QueryMsg::Minter {};
let res = query(deps.as_ref(), env, query_minter_msg);
let mint: Option<MinterResponse> = from_binary(&res.unwrap()).unwrap();

// Check that mint information was removed.
assert_eq!(mint, None);

// Check that old minter can no longer mint.
let msg = ExecuteMsg::Mint {
recipient: String::from("lucky"),
amount: Uint128::new(222),
};
let info = mock_info("minter", &[]);
let env = mock_env();
let err = execute(deps.as_mut(), env, info, msg).unwrap_err();
assert_eq!(err, ContractError::Unauthorized {});
}

#[test]
fn no_one_mints_if_minter_unset() {
let mut deps = mock_dependencies();
Expand Down
5 changes: 5 additions & 0 deletions packages/cw20/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@ minter address and handle updating the ACL there.
this will create `amount` new tokens (updating total supply) and
add them to the balance of `recipient`, as long as it does not exceed the cap.

`UpdateMinter { new_minter: Option<String> }` - Callable only by the
current minter. If `new_minter` is `Some(address)` the minter is set
to the specified address, otherwise the minter is removed and no
future minters may be set.

### Queries

`Minter{}` - Returns who and how much can be minted. Return type is
Expand Down
6 changes: 4 additions & 2 deletions packages/cw20/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ pub enum Cw20ExecuteMsg {
/// Only with the "mintable" extension. If authorized, creates amount new tokens
/// and adds to the recipient balance.
Mint { recipient: String, amount: Uint128 },
/// Only with the "mintable" extension. The current minter may set a new minter.
UpdateMinter { new_minter: String },
/// Only with the "mintable" extension. The current minter may set
/// a new minter. Setting the minter to None will remove the
/// token's minter forever.
UpdateMinter { new_minter: Option<String> },
/// Only with the "marketing" extension. If authorized, updates marketing metadata.
/// Setting None/null for any of these will leave it unchanged.
/// Setting Some("") will clear this field on the contract storage
Expand Down

0 comments on commit 8fd2904

Please sign in to comment.