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

check_can_send(): expose for query and helper #148

Open
taitruong opened this issue Dec 22, 2023 · 3 comments
Open

check_can_send(): expose for query and helper #148

taitruong opened this issue Dec 22, 2023 · 3 comments

Comments

@taitruong
Copy link
Collaborator

check_can_send() can rn only be used internally. But externals, 3rd party contract, might benefit from this as well. Use case:

  • contract (e.g. staking, markeptplace) gets approval by NFT owner
  • use calls contract like staking or listing NFT
    • sub call: contract calls cw721-base e.g. transferring NFT to contract or another owner

Even contract is approved to do so, it needs to check whether sender is owner and eligible to do so on contract.

This is boilerplate and covered by check_can_send():

pub fn check_can_send(
&self,
deps: Deps,
env: &Env,
info: &MessageInfo,
token: &TokenInfo<T>,
) -> Result<(), ContractError> {
// owner can send
if token.owner == info.sender {
return Ok(());
}
// any non-expired token approval can send
if token
.approvals
.iter()
.any(|apr| apr.spender == info.sender && !apr.is_expired(&env.block))
{
return Ok(());
}

we just need to change input param from info: &MessageInfo to sender: String and return a bool, then we can expose this function.

@taitruong
Copy link
Collaborator Author

query should be expose in helpers.rs here: https://github.com/CosmWasm/cw-nfts/blob/main/contracts/cw721-base/src/helpers.rs

@taitruong
Copy link
Collaborator Author

Actually for 3rd party contracts it is quite tedious, since it needs to check and query, sender being:

  • owner,
  • spender (approval), or
  • operator

if token.owner == info.sender {
return Ok(());
}
// any non-expired token approval can send
if token
.approvals
.iter()
.any(|apr| apr.spender == info.sender && !apr.is_expired(&env.block))
{
return Ok(());
}
// operator can send
let op = self
.operators
.may_load(deps.storage, (&token.owner, &info.sender))?;
match op {
Some(ex) => {
if ex.is_expired(&env.block) {
Err(ContractError::Ownership(OwnershipError::NotOwner))
} else {
Ok(())
}
}
None => Err(ContractError::Ownership(OwnershipError::NotOwner)),
}

@hoanm
Copy link

hoanm commented Dec 22, 2023

I found this issue when trying to send nfts between chains. Right after owner of nft allows some operators (contracts) to transfer/send his token, other person can send a message with their information to contract and steal the token.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants