diff --git a/src/contracts/AbstractARM.sol b/src/contracts/AbstractARM.sol index 245613a..dbdaf48 100644 --- a/src/contracts/AbstractARM.sol +++ b/src/contracts/AbstractARM.sol @@ -104,7 +104,9 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable { address public capManager; - uint256[43] private _gap; + address public zap; + + uint256[41] private _gap; //////////////////////////////////////////////////// /// Events @@ -121,6 +123,7 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable { event FeeUpdated(uint256 fee); event FeeCollectorUpdated(address indexed newFeeCollector); event CapManagerUpdated(address indexed capManager); + event ZapUpdated(address indexed zap); constructor(address _token0, address _token1, address _liquidityAsset, uint256 _claimDelay) { require(IERC20(_token0).decimals() == 18); @@ -424,6 +427,22 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable { /// @param assets The amount of liquidity assets to deposit /// @return shares The amount of shares that were minted function deposit(uint256 assets) external returns (uint256 shares) { + shares = _deposit(assets, msg.sender); + } + + /// @notice deposit liquidity assets in exchange for liquidity provider (LP) shares. + /// This function is restricted to the Zap contract. + /// @param assets The amount of liquidity assets to deposit + /// @param liquidityProvider The address of the liquidity provider + /// @return shares The amount of shares that were minted + function deposit(uint256 assets, address liquidityProvider) external returns (uint256 shares) { + require(msg.sender == zap, "Only Zap"); + + shares = _deposit(assets, liquidityProvider); + } + + /// @dev Internal logic for depositing liquidity assets in exchange for liquidity provider (LP) shares. + function _deposit(uint256 assets, address liquidityProvider) internal returns (uint256 shares) { // Calculate the amount of shares to mint after the performance fees have been accrued // which reduces the available assets, and before new assets are deposited. shares = convertToShares(assets); @@ -432,17 +451,17 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable { IERC20(liquidityAsset).transferFrom(msg.sender, address(this), assets); // mint shares - _mint(msg.sender, shares); + _mint(liquidityProvider, shares); // Add the deposited assets to the last available assets lastAvailableAssets += SafeCast.toInt128(SafeCast.toInt256(assets)); // Check the liquidity provider caps after the new assets have been deposited if (capManager != address(0)) { - ICapManager(capManager).postDepositHook(msg.sender, assets); + ICapManager(capManager).postDepositHook(liquidityProvider, assets); } - emit Deposit(msg.sender, assets, shares); + emit Deposit(liquidityProvider, assets, shares); } /// @notice Preview the amount of assets that would be received for burning a given amount of shares @@ -599,6 +618,13 @@ abstract contract AbstractARM is OwnableOperable, ERC20Upgradeable { emit CapManagerUpdated(_capManager); } + /// @notice Set the Zap contract address. + function setZap(address _zap) external onlyOwner { + zap = _zap; + + emit ZapUpdated(_zap); + } + //////////////////////////////////////////////////// /// Performance Fee Functions //////////////////////////////////////////////////// diff --git a/src/contracts/Interfaces.sol b/src/contracts/Interfaces.sol index e453356..408f0f6 100644 --- a/src/contracts/Interfaces.sol +++ b/src/contracts/Interfaces.sol @@ -110,6 +110,7 @@ interface IOethARM { interface ILiquidityProviderARM is IERC20 { function previewDeposit(uint256 assets) external returns (uint256 shares); function deposit(uint256 assets) external returns (uint256 shares); + function deposit(uint256 assets, address liquidityProvider) external returns (uint256 shares); function previewRedeem(uint256 shares) external returns (uint256 assets); function requestRedeem(uint256 shares) external returns (uint256 requestId, uint256 assets); diff --git a/src/contracts/ZapperLidoARM.sol b/src/contracts/ZapperLidoARM.sol index d127740..945f46f 100644 --- a/src/contracts/ZapperLidoARM.sol +++ b/src/contracts/ZapperLidoARM.sol @@ -41,10 +41,7 @@ contract ZapperLidoARM is Ownable { weth.deposit{value: ethBalance}(); // Deposit all WETH to LidoARM - shares = lidoArm.deposit(ethBalance); - - // Transfer received ARM LP shares to msg.sender - lidoArm.transfer(msg.sender, shares); + shares = lidoArm.deposit(ethBalance, msg.sender); // Emit event emit Zap(msg.sender, ethBalance, shares); diff --git a/test/fork/Zapper/Deposit.t.sol b/test/fork/Zapper/Deposit.t.sol index 7d8449e..eb54f1c 100644 --- a/test/fork/Zapper/Deposit.t.sol +++ b/test/fork/Zapper/Deposit.t.sol @@ -5,6 +5,7 @@ pragma solidity ^0.8.23; import {Fork_Shared_Test_} from "test/fork/shared/Shared.sol"; // Contracts +import {CapManager} from "src/contracts/CapManager.sol"; import {ZapperLidoARM} from "contracts/ZapperLidoARM.sol"; contract Fork_Concrete_ZapperLidoARM_Deposit_Test_ is Fork_Shared_Test_ { @@ -14,10 +15,13 @@ contract Fork_Concrete_ZapperLidoARM_Deposit_Test_ is Fork_Shared_Test_ { vm.deal(address(this), DEFAULT_AMOUNT); } - function test_Deposit_ViaFunction() public setLiquidityProviderCap(address(zapperLidoARM), DEFAULT_AMOUNT) { + function test_Deposit_ViaFunction() public { assertEq(lidoARM.balanceOf(address(this)), 0); uint256 expectedShares = lidoARM.previewDeposit(DEFAULT_AMOUNT); + uint256 capBefore = capManager.liquidityProviderCaps(address(this)); + vm.expectEmit({emitter: address(capManager)}); + emit CapManager.LiquidityProviderCap(address(this), capBefore - DEFAULT_AMOUNT); vm.expectEmit({emitter: address(zapperLidoARM)}); emit ZapperLidoARM.Zap(address(this), DEFAULT_AMOUNT, expectedShares); // Deposit @@ -25,12 +29,16 @@ contract Fork_Concrete_ZapperLidoARM_Deposit_Test_ is Fork_Shared_Test_ { // Check balance assertEq(lidoARM.balanceOf(address(this)), DEFAULT_AMOUNT); + assertEq(capManager.liquidityProviderCaps(address(this)), capBefore - DEFAULT_AMOUNT); } - function test_Deposit_ViaCall() public setLiquidityProviderCap(address(zapperLidoARM), DEFAULT_AMOUNT) { + function test_Deposit_ViaCall() public { assertEq(lidoARM.balanceOf(address(this)), 0); uint256 expectedShares = lidoARM.previewDeposit(DEFAULT_AMOUNT); + uint256 capBefore = capManager.liquidityProviderCaps(address(this)); + vm.expectEmit({emitter: address(capManager)}); + emit CapManager.LiquidityProviderCap(address(this), capBefore - DEFAULT_AMOUNT); vm.expectEmit({emitter: address(zapperLidoARM)}); emit ZapperLidoARM.Zap(address(this), DEFAULT_AMOUNT, expectedShares); // Deposit @@ -39,5 +47,6 @@ contract Fork_Concrete_ZapperLidoARM_Deposit_Test_ is Fork_Shared_Test_ { // Check balance assertEq(lidoARM.balanceOf(address(this)), DEFAULT_AMOUNT); + assertEq(capManager.liquidityProviderCaps(address(this)), capBefore - DEFAULT_AMOUNT); } } diff --git a/test/fork/shared/Shared.sol b/test/fork/shared/Shared.sol index bb6073d..915c9bd 100644 --- a/test/fork/shared/Shared.sol +++ b/test/fork/shared/Shared.sol @@ -169,6 +169,9 @@ abstract contract Fork_Shared_Test_ is Modifiers { // --- Deploy ZapperLidoARM --- zapperLidoARM = new ZapperLidoARM(address(weth), address(lidoProxy)); + + // Set zap address in LidoARM. + lidoARM.setZap(address(zapperLidoARM)); } function _label() internal {