@perfect-abstractions/compose/token/ERC20/Approve/ERC20ApproveMod.solHelper functions for setting ERC-20 allowances and accessing ERC-20 storage
approve always sets the allowance of msg.sender. It cannot approve on behalf of another owner.Approval on every successful call.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 storageSets how many of the caller's tokens _spender may move. The stored allowance becomes exactly _value, overwriting any previous allowance for that spender.
Inside a diamond, your facet runs through delegatecall, so msg.sender here is the account that called the diamond, not the diamond itself.
Parameters:
_spenderaddressaddress(0)._valueuint2560 revokes it. type(uint256).max grants an unlimited allowance that is never decremented.Returns:
-booltrue. Failures revert instead of returning false.Reverts:
ERC20InvalidSpendererror_spender is address(0).Emitted on every successful approve, including when _value is 0 or unchanged.
_owneraddressmsg.sender._spenderaddress_valueuint256Thrown by approve when _spender is the zero address.
_spenderaddressaddress(0).approve when your facet sets an allowance on behalf of whoever is calling it, for example a wrapper that approves and then performs a second action in one transaction.STORAGE_POSITION and ERC20Storage layout as the other ERC-20 modules. Do not introduce a second allowance mapping.0 first. Compose has no increaseAllowance or decreaseAllowance, so an N to M change can be front-run by a spender who uses N first.Import the module under a namespace and call it from your facet:
approve cannot set an allowance for any owner other than msg.sender. If your facet authorizes an owner some other way, such as a signature, write getStorage().allowance[_owner][_spender] directly and emit Approval yourself. ERC20PermitFacet does exactly this.
ERC20Storage lives at keccak256("erc20") inside the diamond. That is the same slot ERC20DataFacet, ERC20TransferFacet, and the other ERC-20 contracts use, so an allowance set here is what allowance() returns and what transferFrom spends.