From d8e7b0640b6c7f0a518831362bbf4684480d56a3 Mon Sep 17 00:00:00 2001 From: kasperpawlowski Date: Thu, 17 Oct 2024 13:26:39 +0200 Subject: [PATCH] feat: add permit2 support in the ESR --- src/Synths/EulerSavingsRate.sol | 16 ++++++++++++---- test/unit/esr/lib/ESRTest.sol | 7 +++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Synths/EulerSavingsRate.sol b/src/Synths/EulerSavingsRate.sol index da03ee51..d93c28da 100644 --- a/src/Synths/EulerSavingsRate.sol +++ b/src/Synths/EulerSavingsRate.sol @@ -3,10 +3,11 @@ pragma solidity ^0.8.0; import {Context} from "openzeppelin-contracts/utils/Context.sol"; import {Math} from "openzeppelin-contracts/utils/math/Math.sol"; -import {IERC20} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; +import {IERC20 as IERC20_OZ} from "openzeppelin-contracts/token/ERC20/IERC20.sol"; import {ERC20} from "openzeppelin-contracts/token/ERC20/ERC20.sol"; import {ERC4626} from "openzeppelin-contracts/token/ERC20/extensions/ERC4626.sol"; import {EVCUtil} from "ethereum-vault-connector/utils/EVCUtil.sol"; +import {SafeERC20Lib, IERC20} from "../EVault/shared/lib/SafeERC20Lib.sol"; /// @title EulerSavingsRate /// @custom:security-contact security@euler.xyz @@ -28,6 +29,8 @@ contract EulerSavingsRate is EVCUtil, ERC4626 { uint256 public constant INTEREST_SMEAR = 2 weeks; + address public immutable PERMIT2; + struct ESRSlot { uint40 lastInterestUpdate; uint40 interestSmearEnd; @@ -40,6 +43,7 @@ contract EulerSavingsRate is EVCUtil, ERC4626 { /// @notice The total assets accounted for in the vault. uint256 internal _totalAssets; + error InvalidAsset(); error Reentrancy(); event Gulped(uint256 gulped, uint256 interestLeft); @@ -53,11 +57,13 @@ contract EulerSavingsRate is EVCUtil, ERC4626 { esrSlot.locked = UNLOCKED; } - constructor(address _evc, address _asset, string memory _name, string memory _symbol) + constructor(address _evc, address _permit2, address _asset, string memory _name, string memory _symbol) EVCUtil(_evc) - ERC4626(IERC20(_asset)) + ERC4626(IERC20_OZ(_asset)) ERC20(_name, _symbol) { + if (_asset.code.length == 0) revert InvalidAsset(); + PERMIT2 = _permit2; esrSlot.locked = UNLOCKED; } @@ -116,7 +122,9 @@ contract EulerSavingsRate is EVCUtil, ERC4626 { } function _deposit(address caller, address receiver, uint256 assets, uint256 shares) internal override { - super._deposit(caller, receiver, assets, shares); + SafeERC20Lib.safeTransferFrom(IERC20(asset()), caller, address(this), assets, PERMIT2); + _mint(receiver, shares); + emit Deposit(caller, receiver, assets, shares); _totalAssets = _totalAssets + assets; } diff --git a/test/unit/esr/lib/ESRTest.sol b/test/unit/esr/lib/ESRTest.sol index 74dd1a29..eb47247a 100644 --- a/test/unit/esr/lib/ESRTest.sol +++ b/test/unit/esr/lib/ESRTest.sol @@ -5,8 +5,10 @@ import "forge-std/Test.sol"; import {EthereumVaultConnector as EVC} from "ethereum-vault-connector/EthereumVaultConnector.sol"; import {EulerSavingsRate} from "../../../../src/Synths/EulerSavingsRate.sol"; import {MockToken} from "./MockToken.sol"; +import {DeployPermit2} from "permit2/test/utils/DeployPermit2.sol"; -contract ESRTest is Test { +contract ESRTest is Test, DeployPermit2 { + address permit2; EVC public evc; EulerSavingsRate public esr; MockToken public asset; @@ -18,9 +20,10 @@ contract ESRTest is Test { string public constant SYMBOL = "ESR"; function setUp() public virtual { + permit2 = deployPermit2(); asset = new MockToken(); evc = new EVC(); - esr = new EulerSavingsRate(address(evc), address(asset), NAME, SYMBOL); + esr = new EulerSavingsRate(address(evc), permit2, address(asset), NAME, SYMBOL); // Set a non zero timestamp vm.warp(420);