@perfect-abstractions/compose/token/ERC20/Burn/ERC20BurnMod.solHelper function for destroying ERC-20 tokens from any account
burn destroys tokens from any account you name. It performs no allowance check and no role check. Whatever facet calls it is responsible for proving the caller is allowed to do this.
burn(_account, _value) takes the account as a parameter, unlike the facet's caller-only burn(_value).balanceOf and totalSupply, then emits Transfer to address(0).ERC20Storage with no allowance field. See below.Use helper functions from Compose using your own custom facets. See Facets & Modules for more information.
STORAGE_POSITIONbytes32keccak256("erc20"))This module declares only the two fields it uses. The allowance mapping that other ERC-20 contracts declare is absent.
This is a layout-compatible prefix of the full struct, not a different slot. balanceOf and totalSupply occupy the same positions either way, so this module reads and writes exactly the same storage as the rest of ERC-20. It simply does not declare the field it never touches.
ERC20MintMod and the two Bridgeable contracts use the same two-field form. Everything that reads or writes an allowance, including ERC20BurnFacet, declares all three fields.
Returns a pointer to the ERC20Storage struct.
Because this module's struct has no allowance field, the returned pointer cannot reach allowances. If your facet needs to inspect one, import a module that declares the full struct, such as ERC20TransferMod or ERC20ApproveMod.
Returns:
sERC20Storage storagebalanceOf and totalSupply only.Destroys _value tokens held by _account and reduces the total supply by the same amount.
No allowance is consulted and no permission is checked. Gate this behind your own authorization, exactly as you would with a mint. Burning 0 is allowed and still emits Transfer.
Parameters:
_accountaddressaddress(0)._valueuint256_account's balance.Reverts:
ERC20InvalidSendererror_account is address(0).ERC20InsufficientBalanceerror_account holds fewer than _value tokens.Emitted on every successful burn, always with address(0) as the destination. This is how ERC-20 represents a burn.
_fromaddress_account._toaddressaddress(0)._valueuint256Thrown when _account holds less than _value.
_senderaddress_balanceuint256_neededuint256burn in an external function that checks permission first, for example an owner or role guard, or proof that the caller holds the tokens.ERC20BurnFacet instead of writing a wrapper. It already binds the burn to msg.sender.burnFrom, or check the allowance yourself through a module that declares it before calling this helper.STORAGE_POSITION and field order as the other ERC-20 contracts. Do not introduce a second balance mapping.Import the module under a namespace and call it from your facet:
ERC20Storage lives at keccak256("erc20") inside the diamond, the same slot ERC20DataFacet reads, so a burn here is immediately visible through balanceOf() and totalSupply().
The balance and totalSupply subtractions sit inside unchecked, after an explicit balance comparison. That is safe only while no balance exceeds totalSupply. If your facet writes balanceOf directly without adjusting totalSupply, a later burn can underflow totalSupply silently. Keep the two in step.