-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Zapper for LidoARM #31
Changes from 3 commits
d547c17
d1b287e
164f6bb
75fbb57
734d0d4
5224257
b006fb3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
// Contracts | ||
import {Ownable} from "./Ownable.sol"; | ||
|
||
// Interfaces | ||
import {IWETH} from "./Interfaces.sol"; | ||
import {IERC20} from "./Interfaces.sol"; | ||
import {ILidoARM} from "./Interfaces.sol"; | ||
|
||
contract ZapperLidoARM is Ownable { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need the Zapper to be If we do want the Zapper to be Ownerable, we need to decide who the owner should be. Options are:
@DanielVF what do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I completely agree, it was just in case someone mistakenly send token to it (like people sending wETH to wETH contract). However if we want to keep it, I think Strategist or Relayer is enough. |
||
IWETH public immutable weth; | ||
ILidoARM public immutable lidoArm; | ||
|
||
event Zap(address indexed sender, uint256 shares); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should also include the amount of ETH (assets) deposited There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've pushed the change to add the amount of assets (WETH) deposited |
||
|
||
constructor(address _weth, address _lidoArm) { | ||
weth = IWETH(_weth); | ||
lidoArm = ILidoARM(_lidoArm); | ||
|
||
weth.approve(_lidoArm, type(uint256).max); | ||
} | ||
|
||
/// @notice Deposit ETH to LidoARM and receive shares | ||
receive() external payable { | ||
deposit(); | ||
} | ||
|
||
/// @notice Deposit ETH to LidoARM and receive shares | ||
function deposit() public payable returns (uint256 shares) { | ||
// Wrap all ETH to WETH | ||
uint256 balance = address(this).balance; | ||
weth.deposit{value: balance}(); | ||
|
||
// Deposit all WETH to LidoARM | ||
shares = lidoArm.deposit(balance); | ||
|
||
// Transfer received shares to msg.sender | ||
lidoArm.transfer(msg.sender, shares); | ||
|
||
// Emit event | ||
emit Zap(msg.sender, shares); | ||
} | ||
|
||
/// @notice Rescue ERC20 tokens | ||
/// @param token The address of the ERC20 token | ||
function rescueERC20(address token, uint256 amount) external onlyOwner { | ||
IERC20(token).transfer(msg.sender, amount); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
// Test imports | ||
import {Fork_Shared_Test_} from "test/fork/shared/Shared.sol"; | ||
|
||
// Contracts | ||
import {ZapperLidoARM} from "contracts/ZapperLidoARM.sol"; | ||
|
||
contract Fork_Concrete_ZapperLidoARM_Deposit_Test_ is Fork_Shared_Test_ { | ||
function setUp() public override { | ||
super.setUp(); | ||
|
||
vm.deal(address(this), DEFAULT_AMOUNT); | ||
} | ||
|
||
function test_Deposit_ViaFunction() public setLiquidityProviderCap(address(zapperLidoARM), DEFAULT_AMOUNT) { | ||
assertEq(lidoARM.balanceOf(address(this)), 0); | ||
uint256 expectedShares = lidoARM.previewDeposit(DEFAULT_AMOUNT); | ||
|
||
vm.expectEmit({emitter: address(zapperLidoARM)}); | ||
emit ZapperLidoARM.Zap(address(this), expectedShares); | ||
// Deposit | ||
zapperLidoARM.deposit{value: DEFAULT_AMOUNT}(); | ||
|
||
// Check balance | ||
assertEq(lidoARM.balanceOf(address(this)), DEFAULT_AMOUNT); | ||
} | ||
|
||
function test_Deposit_ViaCall() public setLiquidityProviderCap(address(zapperLidoARM), DEFAULT_AMOUNT) { | ||
assertEq(lidoARM.balanceOf(address(this)), 0); | ||
uint256 expectedShares = lidoARM.previewDeposit(DEFAULT_AMOUNT); | ||
|
||
vm.expectEmit({emitter: address(zapperLidoARM)}); | ||
emit ZapperLidoARM.Zap(address(this), expectedShares); | ||
// Deposit | ||
(bool success,) = address(zapperLidoARM).call{value: DEFAULT_AMOUNT}(""); | ||
assertTrue(success); | ||
|
||
// Check balance | ||
assertEq(lidoARM.balanceOf(address(this)), DEFAULT_AMOUNT); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.23; | ||
|
||
// Test imports | ||
import {Fork_Shared_Test_} from "test/fork/shared/Shared.sol"; | ||
|
||
// Contracts | ||
import {ZapperLidoARM} from "contracts/ZapperLidoARM.sol"; | ||
|
||
contract Fork_Concrete_ZapperLidoARM_RescueToken_Test_ is Fork_Shared_Test_ { | ||
function test_RevertWhen_RescueToken_CalledByNonOwner() public asRandomAddress { | ||
vm.expectRevert("ARM: Only owner can call this function."); | ||
zapperLidoARM.rescueERC20(address(badToken), DEFAULT_AMOUNT); | ||
} | ||
|
||
function test_RescueToken() public { | ||
deal(address(weth), address(zapperLidoARM), DEFAULT_AMOUNT); | ||
assertEq(weth.balanceOf(address(zapperLidoARM)), DEFAULT_AMOUNT); | ||
assertEq(weth.balanceOf(address(this)), 0); | ||
|
||
// Rescue the tokens | ||
vm.prank(zapperLidoARM.owner()); | ||
zapperLidoARM.rescueERC20(address(weth), DEFAULT_AMOUNT); | ||
|
||
// Check balance | ||
assertEq(weth.balanceOf(address(zapperLidoARM)), 0); | ||
assertEq(weth.balanceOf(address(this)), DEFAULT_AMOUNT); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a ILiquidityProviderARM interface that already has deposit. We can extend IERC20 so we also get transfer.