hashgraph / hashgraph/guardian
retirementDocumentBlock does not correctly wipe NFTs when using a Wipe Contract
- Dominant language
- TypeScript
- Stars
- 146
- Forks
- 186
- Avg merge
- 2d 20h
- Merged PRs (30d)
- 126
Description
### Problem description
When using the retirementDocumentBlock to perform NFT wipes the transaction fails. This happens when the token to be wiped is configured to use a Wipe Contract.
When inspecting the failed [tx](https://hashscan.io/testnet/transactionsById/0.0.7461274-1766151366-742341941) ([error](https://hashscan.io/testnet/transaction/1766151374.162639001/result)) in the explorer, it looks like the wipe is being executed as if the token were fungible rather than non fungible.
Use the following policy to reproduce the issue:
[Wipe Issue_1766419878241.policy.zip](https://github.com/user-attachments/files/24295655/Wipe.Issue_1766419878241.policy.zip)
### Step to reproduce
Preconditions:
* Have an Standard Registry available
* Have a Default user available (OPERATOR)
* Have a Wipe Contract available in Guardian (in the Standard Registry user)
Steps to reproduce the behavior:
Importing the policy
1. Login with the Standard Registry user
2. Import the Policy
3. Open Tokens
4. Configure the Token to use the available Wipe Contract
5. Deploy the Policy
Assign operator user to policy
1. Login with the Standard Registry user
2. From the side panel select Administration>User management
3. Search for the operator user and press the pencil (edit)
4. Select Assigned policies tab
5. Assign the user to the policy deployed
Assign OPERATOR role to operator user
1. Login with the operator user
2. From the side panel select Policies>List of Policies
3. Search the policy and click the Register button in the corresponding row.
4. Select OPERATOR role and confirm
Give SR wiping capabilities on the Wipe Contract for the Token
1. Login with the Standard Registry user
2. From the side panel Manage contracts
3. Search for the Token Wiping Contract
4. Press operation button (...) and select Add wiper
5. Fill with the corresponding accounts (Standard Registry and Token) and press Ok.
Token Association
1. Login with the operator user
2. Search the policy and click the Register button in the corresponding row.
3. Press the Associate button
4. Fill with any text (blabla) and press Validate&Create
(Wait until the token associate operation was successfully completed)
Token Mint
1. Login with the Standard Registry user
2. From the side panel select Policies>List of Policies
3. Search the policy and click the Open button in the corresponding row.
4. Press the button Mint
5. Fill with quantity to mint (10), Hedera account to receive tokens (use the operator account), and press Validate&Create
(Wait until tokens have been minted and transfered to the operator successfully)
Token Retirement
1. Login with the Standard Registry user
2. From the side panel select Policies>List of Policies
3. Search the policy and click the Open button in the corresponding row.
4. Press the button Retire
5. Fill with startSerial (1), endSerial (5), and the operator user hedera account that is holding the tokens, and press Validate&Create
This operation fails with the popup saying that retirementDocumentBlock failed.
If we look at the standard registry account in hashscan we will se something similar to this:
The contract call to the Wipe Contract and the Token Wipe.
If we open the TOKEN WIPE operation and look at [results](https://hashscan.io/testnet/account/0.0.7461274/operations?p1=1&k1=1766420170.542516000) tab we will see that the function invoked is:
function wipeTokenAccount(address token, address account, int64 amount) returns (int64 responseCode)
which is for fungible tokens not for non fungible tokens.
### Expected behavior
Retirement to be done successfully through the Wipe Contract.
### Other comments
We decided not to use the Retirement Contract or the Guardian Retirement API, as they introduce additional complexity that we don’t need.
What do we want instead?
We want to be able to perform token wipes inside the policy using the retirementDocumentBlock, while also keeping the flexibility to execute wipes outside of Guardian, directly against the WipeContract.
After reviewing the Guardian codebase, this should be fairly straightforward. Rather than invoking wipe, we would simply call wipeNFT when the token type is NFT. This at minting [service > wipe function](https://github.com/hashgraph/guardian/blob/v3.4.0-rc/policy-service/src/policy-engine/mint/mint-service.ts)
Contributor guide
Assessment
This issue has not been assessed yet.