Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
Amxx committed Jun 10, 2024
1 parent 281510a commit a65c473
Showing 1 changed file with 25 additions and 14 deletions.
39 changes: 25 additions & 14 deletions contracts/token/ERC20/extensions/draft-ERC20TemporaryApproval.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ abstract contract ERC20TemporaryApproval is ERC20, IERC7674 {
* @dev Internal getter for the current temporary allowance that `spender` has over `owner` tokens.
*/
function _temporaryAllowance(address owner, address spender) internal view virtual returns (uint256) {
return ERC20TemporaryApprovalStorageLocation.deriveMapping(owner).deriveMapping(spender).asUint256().tload();
return _temporaryAllowanceSlot(owner, spender).tload();
}

/**
Expand Down Expand Up @@ -77,30 +77,41 @@ abstract contract ERC20TemporaryApproval is ERC20, IERC7674 {
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
ERC20TemporaryApprovalStorageLocation.deriveMapping(owner).deriveMapping(spender).asUint256().tstore(value);
_temporaryAllowanceSlot(owner, spender).tstore(value);
}

/**
* @dev {_spendAllowance} override that consumes the temporary allowance (if any) before eventually falling back
* to consumming the persistent allowance.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual override {
unchecked {
// load transient allowance
uint256 currentTemporaryAllowance = _temporaryAllowance(owner, spender);
// if there is temporary allowance
if (currentTemporaryAllowance > 0) {
// if infinite, do nothing
if (currentTemporaryAllowance == type(uint256).max) return;
// check how much of the value is covered by the transient allowance
uint256 spendTemporaryAllowance = Math.min(currentTemporaryAllowance, value);
// load transient allowance
uint256 currentTemporaryAllowance = _temporaryAllowance(owner, spender);

// Check and update (if needed) the temporary allowance + set remaining value
uint256 remainingValue;
if (currentTemporaryAllowance == type(uint256).max) {
remainingValue = 0;
} else if (currentTemporaryAllowance > 0) {
// check how much of the value is covered by the transient allowance
uint256 spendTemporaryAllowance = Math.min(currentTemporaryAllowance, value);
unchecked {
// decrease transient allowance accordingly
_temporaryApprove(owner, spender, currentTemporaryAllowance - spendTemporaryAllowance);
// update value necessary
value -= spendTemporaryAllowance;
remainingValue = value - spendTemporaryAllowance;
}
// reduce any remaining value from the persistent allowance
super._spendAllowance(owner, spender, value);
} else {
remainingValue = value;
}
// reduce any remaining value from the persistent allowance
super._spendAllowance(owner, spender, remainingValue);
}

function _temporaryAllowanceSlot(
address owner,
address spender
) private pure returns (StorageSlot.Uint256SlotType) {
return ERC20TemporaryApprovalStorageLocation.deriveMapping(owner).deriveMapping(spender).asUint256();
}
}

0 comments on commit a65c473

Please sign in to comment.