From 7824b00e81217a42a2a1a45174974e780e22a82d Mon Sep 17 00:00:00 2001 From: Conner Swenberg Date: Wed, 12 Feb 2025 23:11:15 -0800 Subject: [PATCH] Add EOA-supported SpendPermissionManager --- src/EOASpendPermissionManager.sol | 29 +++++++++++++++++++++++++++++ src/SpendPermissionManager.sol | 2 +- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/EOASpendPermissionManager.sol diff --git a/src/EOASpendPermissionManager.sol b/src/EOASpendPermissionManager.sol new file mode 100644 index 0000000..623439b --- /dev/null +++ b/src/EOASpendPermissionManager.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.28; + +import {PublicERC6492Validator} from "./PublicERC6492Validator.sol"; +import {SpendPermissionManager} from "./SpendPermissionManager.sol"; +import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol"; +import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; + +contract EOASpendPermissionManager is SpendPermissionManager { + using SafeERC20 for IERC20; + + error NativeTokenNotSupported(); + + constructor(PublicERC6492Validator publicERC6492Validator, address magicSpend) + SpendPermissionManager(publicERC6492Validator, magicSpend) + {} + + /// @inheritdoc SpendPermissionManager + /// @dev Because EOAs cannot be called into, native token not supported and assumes existing infinite ERC20 + /// allowance + function _transferFrom(address token, address account, address recipient, uint256 value) internal override { + if (token == NATIVE_TOKEN) { + revert NativeTokenNotSupported(); + } else { + // use allowance to transfer from account to recipient, which will revert if transfer fails + IERC20(token).safeTransferFrom(account, recipient, value); + } + } +} diff --git a/src/SpendPermissionManager.sol b/src/SpendPermissionManager.sol index bbd6d9a..95c3d71 100644 --- a/src/SpendPermissionManager.sol +++ b/src/SpendPermissionManager.sol @@ -727,7 +727,7 @@ contract SpendPermissionManager is EIP712 { /// @param account Address to transfer from. /// @param recipient Address to transfer to. /// @param value Amount to transfer. - function _transferFrom(address token, address account, address recipient, uint256 value) internal { + function _transferFrom(address token, address account, address recipient, uint256 value) internal virtual { if (token == NATIVE_TOKEN) { // set flag to allow contract to receive expected amount of native token _expectedReceiveAmount = value;