@perfect-abstractions/compose/token/ERC20/Transfer/ERC20TransferMod.solHelper functions for moving ERC-20 tokens and accessing ERC-20 storage
transfer moves msg.sender's own tokens. It cannot move tokens for any other account.transferFrom spends the allowance that _from granted to msg.sender.msg.sender.Use helper functions from Compose using your own custom facets. See Facets & Modules for more information.
STORAGE_POSITIONbytes32keccak256("erc20"))Returns a pointer to the ERC20Storage struct.
Returns:
sERC20Storage storageMoves _value tokens from the caller to _to.
Inside a diamond, your facet runs through delegatecall, so msg.sender here is the account that called the diamond, not the diamond itself. Transferring 0 is allowed and still emits Transfer.
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 msg.sender.
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).ERC20InsufficientAllowanceerrormsg.sender's allowance over _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 msg.sender's allowance over _from is below _value.
_spenderaddressmsg.sender._allowanceuint256_neededuint256transfer when your facet moves tokens on behalf of whoever called it, for example a wrapper that transfers and then performs a second action in one transaction.msg.sender, these helpers will not do it. Write getStorage().balanceOf directly and emit Transfer yourself, after your own authorization check.STORAGE_POSITION and ERC20Storage layout as the other ERC-20 modules. Do not introduce a second balance mapping._to.Import the module under a namespace and call it from your facet:
ERC20Storage lives at keccak256("erc20") inside the diamond. That is the same slot ERC20DataFacet, ERC20TransferFacet, and the other ERC-20 contracts use, so balances written here are what balanceOf() reports.
Every balance subtraction sits inside unchecked, but only after an explicit comparison has proved the balance or allowance is large enough, so it cannot underflow. Keep that ordering if you adapt the code.