The implementation of HIP-573 in mainnet release v0.31 (November 10th, 2022) enables token creators whose tokenomics require custom fees and different collection accounts to exempt fee collectors from paying custom fees when exchanging token units.
This example guides you through the following steps:
Creating a Helper Function and defining three new accounts (Account 1, 2, 3)
Initializing Fractional Fees for each new account and creating a Fungible Token
Transferring 10.000 units from the Treasury Account to Account 2 and then from Account 2 to Account 1
To simplify creating accounts, you need to create a helper function. In this example, the function is called accountCreator, and the parameters you need to specify are an initial balance and a private key. Note that the token association is automatic to further simplify the tutorial, as you can see below.
Let’s define three fractional fees for the fungible token we are about to create. During a token transfer, the first account will receive 1% of the amount, the second 2%, and the third 3%.
Note that the critical factor of this tutorial is using the setAllCollectorsAreExempt() extension method on fractional fee creation, as you can see below.
const fee1 = new CustomFractionalFee()
.setFeeCollectorAccountId(accountId1)
.setNumerator(1)
.setDenominator(100)
.setAllCollectorsAreExempt(true);
const fee2 = new CustomFractionalFee()
.setFeeCollectorAccountId(accountId2)
.setNumerator(2)
.setDenominator(100)
.setAllCollectorsAreExempt(true);
const fee3 = new CustomFractionalFee()
.setFeeCollectorAccountId(accountId3)
.setNumerator(3)
.setDenominator(100)
.setAllCollectorsAreExempt(true);
Now, you can create the fungible token and specify the fees you just defined. Remember to sign the TokenCreateTransaction() using all the accounts (fee collectors included).
Before transferring a token from one collection account to another, you first need to transfer some tokens from the treasury account (in this example, the operator) to one of the collection accounts.
// STEP 3: Send token from treasury to one account and from one account to another
const transferFromTreasuryTx = await new TransferTransaction()
.addTokenTransfer(tokenId, operatorId, -10000)
.addTokenTransfer(tokenId, accountId2, 10000)
.freezeWith(client)
.execute(client);
const transferFromTreasuryRx = await transferFromTreasuryTx.getReceipt(client);
const transferFromTreasuryStatus = transferFromTreasuryRx.status.toString();
console.log(`STEP 3 \nToken transfer from treasury to account 2: ${transferFromTreasuryStatus}`);
Now that Account 2 has 10.000 fungible tokens, you can try to transfer the tokens from Account 2 to Account 1.
Done! Now you need to check each account balance to verify if they are actually exempt from token fees.
// Check collectors account balance (methods will be deprecated soon, use axios and mirror node api)
const checkBalance1 = await new AccountBalanceQuery()
.setAccountId(accountId1)
.execute(client);
const balance1 = checkBalance1.tokens._map.get(tokenId.toString());
const checkBalance2 = await new AccountBalanceQuery()
.setAccountId(accountId2)
.execute(client);
const balance2 = checkBalance2.tokens._map.get(tokenId.toString());
const checkBalance3 = await new AccountBalanceQuery()
.setAccountId(accountId3)
.execute(client);
const balance3 = checkBalance3.tokens._map.get(tokenId.toString());
console.log(`Accounts Balance: \nAccount 1: ${balance1} \nAccount 2: ${balance2} \nAccount 3: ${balance3} \n`);
Console Output:
v0.30
v0.31
As you can see in v0.30, the third collector receives 3% of the 10.000 transferred from the second to the first collector. While in v0.31, fee collectors are exempt from fees.
For further questions, don't hesitate to get in touch with us on the Hedera Discord Server.