diff --git a/src/Funnel.sol b/src/Funnel.sol index 803f2cd..694e499 100644 --- a/src/Funnel.sol +++ b/src/Funnel.sol @@ -203,7 +203,9 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable, /// @inheritdoc IERC5827 function allowance(address _owner, address _spender) external view returns (uint256 remaining) { - return _remainingAllowance(_owner, _spender); + uint256 _baseAllowance = _baseToken.allowance(_owner, address(this)); + uint256 _renewableAllowance = _remainingAllowance(_owner, _spender); + return _baseAllowance < _renewableAllowance ? _baseAllowance : _renewableAllowance; } /// @inheritdoc IERC5827Payable @@ -444,11 +446,10 @@ contract Funnel is IFunnel, NativeMetaTransaction, MetaTxContext, Initializable, /// @return remaining allowance left function _remainingAllowance(address _owner, address _spender) private view returns (uint256) { RenewableAllowance memory a = rAllowance[_owner][_spender]; - uint256 baseAllowance = _baseToken.allowance(_owner, address(this)); + uint256 recovered = a.recoveryRate * uint64(block.timestamp - a.lastUpdated); uint256 remainingAllowance = MathUtil.saturatingAdd(a.remaining, recovered); - uint256 currentAllowance = remainingAllowance > a.maxAmount ? a.maxAmount : remainingAllowance; - return currentAllowance > baseAllowance ? baseAllowance : currentAllowance; + return remainingAllowance > a.maxAmount ? a.maxAmount : remainingAllowance; } } diff --git a/test/Funnel.t.sol b/test/Funnel.t.sol index 35c23b8..815fab0 100644 --- a/test/Funnel.t.sol +++ b/test/Funnel.t.sol @@ -90,6 +90,20 @@ contract FunnelTest is ERC5827TestSuite { assertTrue(funnel.transferFromAndCall(user1, address(spender), 10, "")); } + function testInsufficientBaseAllowance() public { + vm.prank(user1); + token.approve(address(funnel), 0); + + vm.prank(user1); + funnel.approveRenewable(user2, 1337, 1); + + assertEq(funnel.allowance(user1, address(spender)), 0); + + vm.prank(user2); + vm.expectRevert("ERC20: insufficient allowance"); + funnel.transferFromAndCall(user1, address(spender), 10, ""); + } + function testOverflow() public { vm.prank(user1); funnel.approveRenewable(address(user2), type(uint256).max - type(uint192).max + 1, type(uint192).max);