-
Notifications
You must be signed in to change notification settings - Fork 174
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
feature: optional withdrawal address #149
Conversation
… on latest contract.
/// Sets address to send withdrawn fees to. Only owner can call this. | ||
SetWithdrawAddress { address: String }, | ||
/// Removes the withdraw address, so fees are sent to the contract. Only owner can call this. | ||
RemoveWithdrawAddress {}, | ||
/// Withdraw from the contract to the given address. Anyone can call this, | ||
/// which is okay since withdraw address has been set by owner. | ||
WithdrawFunds { amount: Coin }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Execute msgs for new feature here
#[returns(Option<String>)] | ||
GetWithdrawAddress {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Query here
@@ -19,6 +19,7 @@ where | |||
/// Stored as (granter, operator) giving operator full control over granter's account | |||
pub operators: Map<'a, (&'a Addr, &'a Addr), Expiration>, | |||
pub tokens: IndexedMap<'a, &'a str, TokenInfo<T>, TokenIndexes<'a, T>>, | |||
pub withdraw_address: Item<'a, String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
new state here
pub fn set_withdraw_address( | ||
&self, | ||
deps: DepsMut, | ||
sender: &Addr, | ||
address: String, | ||
) -> Result<Response<C>, ContractError> { | ||
cw_ownable::assert_owner(deps.storage, sender)?; | ||
deps.api.addr_validate(&address)?; | ||
self.withdraw_address.save(deps.storage, &address)?; | ||
Ok(Response::new() | ||
.add_attribute("action", "set_withdraw_address") | ||
.add_attribute("address", address)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only owner (aka creator/minter) can set withdraw address
pub fn remove_withdraw_address( | ||
&self, | ||
storage: &mut dyn Storage, | ||
sender: &Addr, | ||
) -> Result<Response<C>, ContractError> { | ||
cw_ownable::assert_owner(storage, sender)?; | ||
let address = self.withdraw_address.may_load(storage)?; | ||
match address { | ||
Some(address) => { | ||
self.withdraw_address.remove(storage); | ||
Ok(Response::new() | ||
.add_attribute("action", "remove_withdraw_address") | ||
.add_attribute("address", address)) | ||
} | ||
None => Err(ContractError::NoWithdrawAddress {}), | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only owner can remove withdraw address
fn test_withdraw_funds() { | ||
let mut deps = mock_dependencies(); | ||
let contract = setup_contract(deps.as_mut()); | ||
|
||
// no withdraw address set | ||
let err = contract | ||
.withdraw_funds(deps.as_mut().storage, &Coin::new(100, "uark")) | ||
.unwrap_err(); | ||
assert_eq!(err, ContractError::NoWithdrawAddress {}); | ||
|
||
// set and withdraw by non-owner | ||
contract | ||
.set_withdraw_address(deps.as_mut(), &Addr::unchecked(MINTER), "foo".to_string()) | ||
.unwrap(); | ||
contract | ||
.withdraw_funds(deps.as_mut().storage, &Coin::new(100, "uark")) | ||
.unwrap(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
test withdraw_funds()
/// Test backward compatibility using instantiate msg from a 0.16 version on latest contract. | ||
/// This ensures existing 3rd party contracts doesnt need to updated as well. | ||
#[test] | ||
fn test_instantiate_016_msg() { | ||
use cw721_base_016 as v16; | ||
let mut app = App::default(); | ||
let admin = || Addr::unchecked("admin"); | ||
|
||
let code_id_latest = app.store_code(cw721_base_latest_contract()); | ||
|
||
let cw721 = app | ||
.instantiate_contract( | ||
code_id_latest, | ||
admin(), | ||
&v16::InstantiateMsg { | ||
name: "collection".to_string(), | ||
symbol: "symbol".to_string(), | ||
minter: admin().into_string(), | ||
}, | ||
&[], | ||
"cw721-base", | ||
Some(admin().into_string()), | ||
) | ||
.unwrap(); | ||
|
||
// assert withdraw address is None | ||
let withdraw_addr: Option<String> = app | ||
.wrap() | ||
.query_wasm_smart(cw721, &crate::QueryMsg::<Empty>::GetWithdrawAddress {}) | ||
.unwrap(); | ||
assert!(withdraw_addr.is_none()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test backward compatibility using instantiate msg from a 0.16 version on latest contract. This ensures existing 3rd party contracts doesnt need to be updated.
Basically NFT contracts behaves like in previous version - this PR just adds an optional feature.
@@ -14,6 +14,7 @@ pub struct InstantiateMsg { | |||
pub cw20_address: Addr, | |||
pub token_uri: String, | |||
pub extension: Extension, | |||
pub withdraw_address: Option<String>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional as well on fix price contract
@@ -93,6 +93,7 @@ mod tests { | |||
name: "".into(), | |||
symbol: "".into(), | |||
minter: "larry".into(), | |||
withdraw_address: None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional as well on metadata onchain contract
@@ -47,6 +47,7 @@ pub mod entry { | |||
name: msg.name, | |||
symbol: msg.symbol, | |||
minter: msg.minter, | |||
withdraw_address: msg.withdraw_address, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
optional as well on non transferrable contract
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm cool with this, but would like to make sure there is broad consensus before we move forward. Otherwise, LGTM.
@shanev could u have a look at this? PR allows now NFT contracts having funds. Owner can set/remove withdraw address - which is used for
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just some minor comments.
cw20 = "1.1.0" | ||
cw721 = { version = "0.18.0", path = "./packages/cw721" } | ||
cw721-base = { version = "0.18.0", path = "./contracts/cw721-base" } | ||
cosmwasm-schema = "^1.2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version numbers should be explicit for smart contracts.
@@ -21,6 +21,7 @@ command = "cargo" | |||
args = ["build", "--release", "--locked", "--target", "wasm32-unknown-unknown"] | |||
|
|||
[tasks.optimize] | |||
# https://hub.docker.com/r/cosmwasm/workspace-optimizer/tags https://hub.docker.com/r/cosmwasm/workspace-optimizer-arm64/tags |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this mean't to be commented out?
@@ -157,6 +167,9 @@ pub enum QueryMsg<Q: JsonSchema> { | |||
/// Extension query | |||
#[returns(())] | |||
Extension { msg: Q }, | |||
|
|||
#[returns(Option<String>)] | |||
GetWithdrawAddress {}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer not having explicit getter in name per Rust convention, so just WithdrawAddress {}
. Developer discretion.
This feature adds an optional withdrawal address. Please note: existing 3rd party doesnt need to update. Like it is still possible using old instantiate msg without defining a withdraw address!
This PR allows current NFT contracts to:
This way launchpads, fee sharing, marketplaces etc. can benefit from this, like:
Added these new messages to cw721-base:
ExecuteMsg:
QueryMsg: