@perfect-abstractions/compose/token/ERC20/Transfer/ERC20TransferFacet.solMove tokens between accounts, directly or by spending an allowance
transfer moves the caller's own tokens. transferFrom moves someone else's using an allowance.ERC20Storage at erc8042:erc20.type(uint256).max is treated as unlimited and is never decremented.STORAGE_POSITIONbytes32keccak256("erc20"))Moves _value tokens from the caller to _to.
Transferring 0 is allowed and still emits Transfer. Sending to address(0) is rejected, so use ERC20BurnFacet to destroy tokens.
Parameters:
_toaddressaddress(0)._valueuint256Returns:
-booltrue. Failures revert instead of returning false.Reverts:
ERC20InvalidReceivererror_to is address(0).ERC20InsufficientBalanceerror_value tokens.Moves _value tokens from _from to _to, spending the allowance that _from granted to the caller.
The allowance is checked before the balance. If both are insufficient, the call reverts with ERC20InsufficientAllowance. When the allowance is exactly type(uint256).max it is left untouched, otherwise it is reduced by _value.
Parameters:
_fromaddressaddress(0)._toaddressaddress(0)._valueuint256_from's balance.Returns:
-booltrue. Failures revert instead of returning false.Reverts:
ERC20InvalidSendererror_from is address(0).ERC20InvalidReceivererror_to is address(0).ERC20InsufficientAllowanceerror_from is below _value.ERC20InsufficientBalanceerror_from holds fewer than _value tokens.Emitted by both transfer and transferFrom, including when _value is 0.
_fromaddressmsg.sender for transfer, _from for transferFrom._toaddress_valueuint256Thrown when the account sending tokens holds less than _value.
_senderaddress_balanceuint256_neededuint256Thrown by transferFrom when _from is the zero address.
_senderaddressaddress(0).Thrown by transfer and transferFrom when _to is the zero address.
_receiveraddressaddress(0).Thrown by transferFrom when the caller's allowance over _from is below _value.
_spenderaddressmsg.sender._allowanceuint256_neededuint256ERC20DataFacet alongside this facet so holders can read balances and allowances.transferFrom needs an allowance first, from ERC20ApproveFacet or ERC20PermitFacet.false, but tokens from other implementations might.transfer as proof the recipient noticed it. There is no callback.Balance arithmetic is safe. Every subtraction sits inside unchecked, but only after an explicit comparison has proved the balance or allowance is large enough, so it cannot underflow.
Spending an allowance emits no Approval event. transferFrom lowers the stored allowance and emits only Transfer. Across all of Compose, Approval is emitted solely by the Approve and Permit contracts, so an indexer that tracks allowances from events alone will drift. Read allowance() for the current value.
There are no external calls and no receiver hooks. Neither function calls into _to, so there is no reentrancy surface here, and no ERC-721 style check that the recipient can handle tokens. Tokens sent to a contract that cannot move them are stuck permanently.