How the MUSHROOM ERC-20 example splits transfer fees—and what its tests check

A source article published November 12, 2026, at 16:07 UTC+8 presents a MUSHROOM (SHROOM) example contract built with Solidity 0.8.28 and OpenZeppelin v5. It uses the name of a token discussed in the article, but the supplied material does not establish that this example is the token’s deployed contract. The useful developer question is narrower: what does the example do when tokens move?

Follow a transfer through _update

At deployment, the constructor mints 1 billion tokens to the deployer, sets the supplied treasury address, and exempts both addresses from fees. The default fee rates are 1% for burning and 1% for the treasury, expressed against a denominator of 10,000.

For a transfer between two non-exempt addresses, the override of OpenZeppelin’s _update calculates both fees, burns the first portion through super._update(from, address(0), burnAmount), sends the second to treasuryWallet, and transfers the remainder to the recipient. In the article’s 1,000-token test case, that means 10 tokens burned, 10 sent to the treasury, and 980 received. Burning reduces totalSupply; the code does not send those tokens to a burn wallet. It also does not implement an automatic buyback—the treasury receives tokens, but any later use of them is outside this example.

Minting and burning bypass the fee calculation. So does a transfer if either its sender or recipient is marked isFeeExempt. That makes the exemption list important to the effective fee policy, not merely an implementation detail.

Check the owner controls

Only the owner can change the two rates, change the treasury address, or set an address’s exemption status. setFees rejects a combined rate above 10%. This limits the configured fee, but it does not by itself establish that a token is safe or that trading will work as intended.

One detail to review before reusing the example: updateTreasuryWallet changes the destination for treasury fees, but does not update the exemption list. The old treasury remains exempt, while the new one is not automatically exempt.

What the supplied tests cover

The article provides a Hardhat/Viem test script using Node.js’s node:test and node:assert. Its assertions check the initial supply, treasury and default rates; the 1,000-token fee split and supply reduction; a transfer from an exempt address; rejection of non-owner fee and treasury changes; and rejection of an 11% combined fee while accepting 6%. The initialization test’s description mentions the exemption list, but that test does not assert the initial exemption flags.

These are supplied test cases, not evidence here that the script was run or that the contract was audited or verified on a production chain. For this example, the observable outcomes to inspect are recipient and treasury balances, totalSupply, exemption flags, and whether restricted calls revert.

Further reading