diff --git a/contracts/common/BiconomyTokenPaymasterErrors.sol b/contracts/common/BiconomyTokenPaymasterErrors.sol index 845d87f..274999b 100644 --- a/contracts/common/BiconomyTokenPaymasterErrors.sol +++ b/contracts/common/BiconomyTokenPaymasterErrors.sol @@ -61,11 +61,6 @@ contract BiconomyTokenPaymasterErrors { */ error InvalidTokenAddress(); - /** - * @notice Throws when user tries to pay with an unsupported token - */ - error TokenNotSupported(); - /** * @notice Throws when oracle decimals aren't equal to 8 */ diff --git a/contracts/interfaces/oracles/IOracle.sol b/contracts/interfaces/oracles/IOracle.sol index 65ca924..d939518 100644 --- a/contracts/interfaces/oracles/IOracle.sol +++ b/contracts/interfaces/oracles/IOracle.sol @@ -3,8 +3,11 @@ pragma solidity ^0.8.27; interface IOracle { function decimals() external view returns (uint8); + function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound); + + function latestAnswer() external view returns (int256); } diff --git a/contracts/token/oracles/TwapOracle.sol b/contracts/token/oracles/TwapOracle.sol index 8486711..74cc74d 100644 --- a/contracts/token/oracles/TwapOracle.sol +++ b/contracts/token/oracles/TwapOracle.sol @@ -74,6 +74,10 @@ contract TwapOracle is IOracle { return _buildLatestRoundData(normalizedPrice); } + function latestAnswer() external view override returns (int256) { + return int256(_fetchTwap()); + } + function decimals() external pure override returns (uint8) { return 8; } diff --git a/contracts/token/swaps/Uniswapper.sol b/contracts/token/swaps/Uniswapper.sol index b00aa67..136e98b 100644 --- a/contracts/token/swaps/Uniswapper.sol +++ b/contracts/token/swaps/Uniswapper.sol @@ -29,6 +29,7 @@ abstract contract Uniswapper { // Errors error UniswapReverted(address tokenIn, address tokenOut, uint256 amountIn); error TokensAndPoolsLengthMismatch(); + error TokenNotSupported(); constructor( IV3SwapRouter uniswapRouterArg, @@ -56,6 +57,7 @@ abstract contract Uniswapper { } function _swapTokenToWeth(address tokenIn, uint256 amountIn, uint256 minAmountOut) internal returns (uint256 amountOut) { + require(tokenToPools[tokenIn] != 0, TokenNotSupported()); IV3SwapRouter.ExactInputSingleParams memory params = IV3SwapRouter.ExactInputSingleParams({ tokenIn: tokenIn, tokenOut: wrappedNative, diff --git a/test/mocks/MockOracle.sol b/test/mocks/MockOracle.sol index a23b110..1e49273 100644 --- a/test/mocks/MockOracle.sol +++ b/test/mocks/MockOracle.sol @@ -74,4 +74,8 @@ contract MockOracle is IOracle { 73_786_976_294_838_215_802 // Mock round ID for answeredInRound ); } + + function latestAnswer() external view override returns (int256) { + return price; + } } diff --git a/test/unit/concrete/TestTokenPaymaster.Base.t.sol b/test/unit/concrete/TestTokenPaymaster.Base.t.sol index 17133a1..54a8c4f 100644 --- a/test/unit/concrete/TestTokenPaymaster.Base.t.sol +++ b/test/unit/concrete/TestTokenPaymaster.Base.t.sol @@ -132,10 +132,7 @@ contract TestTokenPaymasterBase is TestBase { initialPaymasterEpBalance, initialUserTokenBalance, initialPaymasterTokenBalance, - // IF THIS CASE FAILS ON 2% TOLERANCE => PUT THE FRESH PRICE FROM ORACLE HERE - // https://basescan.org/address/0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70#readContract#F8 - // and remove two last digits from the price - 3358580000, + uint256(nativeOracle.latestAnswer()) / 100, _PRICE_MARKUP_DENOMINATOR, this.getMaxPenalty(ops[0]), this.getRealPenalty(ops[0], gasValue, customGasPrice));