Skip to content

Commit 9628c36

Browse files
authored
feat: add Wrapped Staked Eth hook (#451)
* feat: add Wrapped Staked Eth hook * fix: respond to comments * feat: add staked eth pool
1 parent a6e9621 commit 9628c36

File tree

6 files changed

+481
-2
lines changed

6 files changed

+481
-2
lines changed

src/base/hooks/BaseTokenWrapperHook.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// SPDX-License-Identifier: MIT
12
pragma solidity ^0.8.0;
23

34
import {

src/hooks/WETHHook.sol

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@ contract WETHHook is BaseTokenWrapperHook {
1313
/// @notice The WETH9 contract
1414
WETH public immutable weth;
1515

16-
error WithdrawFailed();
17-
1816
/// @notice Creates a new WETH wrapper hook
1917
/// @param _manager The Uniswap V4 pool manager
2018
/// @param _weth The WETH9 contract address

src/hooks/WstETHHook.sol

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-License-Identifier: MIT
2+
pragma solidity ^0.8.0;
3+
4+
import {ERC20} from "solmate/src/tokens/ERC20.sol";
5+
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
6+
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
7+
import {BaseTokenWrapperHook} from "../base/hooks/BaseTokenWrapperHook.sol";
8+
import {IWstETH} from "../interfaces/external/IWstETH.sol";
9+
10+
/// @title Wrapped Staked ETH (wstETH) Hook
11+
/// @notice Hook for wrapping/unwrapping stETH/wstETH in Uniswap V4 pools
12+
/// @dev Implements dynamic exchange rate wrapping/unwrapping between stETH and wstETH
13+
/// @dev wstETH represents stETH with accrued staking rewards, maintaining a dynamic exchange rate
14+
contract WstETHHook is BaseTokenWrapperHook {
15+
/// @notice The wstETH contract used for wrapping/unwrapping operations
16+
IWstETH public immutable wstETH;
17+
18+
/// @notice Creates a new wstETH wrapper hook
19+
/// @param _manager The Uniswap V4 pool manager
20+
/// @param _wsteth The wstETH contract address
21+
/// @dev Initializes with wstETH as wrapper token and stETH as underlying token
22+
constructor(IPoolManager _manager, IWstETH _wsteth)
23+
BaseTokenWrapperHook(
24+
_manager,
25+
Currency.wrap(address(_wsteth)), // wrapper token is wsteth
26+
Currency.wrap(_wsteth.stETH()) // underlying token is stETH
27+
)
28+
{
29+
wstETH = _wsteth;
30+
ERC20(Currency.unwrap(underlyingCurrency)).approve(address(wstETH), type(uint256).max);
31+
}
32+
33+
/// @inheritdoc BaseTokenWrapperHook
34+
/// @notice Wraps stETH to wstETH
35+
/// @param underlyingAmount Amount of stETH to wrap
36+
/// @return Amount of wstETH received
37+
function _deposit(uint256 underlyingAmount) internal override returns (uint256) {
38+
return wstETH.wrap(underlyingAmount);
39+
}
40+
41+
/// @inheritdoc BaseTokenWrapperHook
42+
/// @notice Unwraps wstETH to stETH
43+
/// @param wrapperAmount Amount of wstETH to unwrap
44+
/// @return Amount of stETH received
45+
function _withdraw(uint256 wrapperAmount) internal override returns (uint256) {
46+
return wstETH.unwrap(wrapperAmount);
47+
}
48+
49+
/// @inheritdoc BaseTokenWrapperHook
50+
/// @notice Calculates how much stETH is needed to receive a specific amount of wstETH
51+
/// @param wrappedAmount Desired amount of wstETH
52+
/// @return Amount of stETH required
53+
/// @dev Uses current stETH/wstETH exchange rate for calculation
54+
function _getWrapInputRequired(uint256 wrappedAmount) internal view override returns (uint256) {
55+
return wstETH.getStETHByWstETH(wrappedAmount);
56+
}
57+
58+
/// @inheritdoc BaseTokenWrapperHook
59+
/// @notice Calculates how much wstETH is needed to receive a specific amount of stETH
60+
/// @param underlyingAmount Desired amount of stETH
61+
/// @return Amount of wstETH required
62+
/// @dev Uses current stETH/wstETH exchange rate for calculation
63+
function _getUnwrapInputRequired(uint256 underlyingAmount) internal view override returns (uint256) {
64+
return wstETH.getWstETHByStETH(underlyingAmount);
65+
}
66+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-FileCopyrightText: 2021 Lido <[email protected]>
2+
// https://github.com/lidofinance/core/blob/master/contracts/0.6.12/WstETH.sol
3+
4+
// SPDX-License-Identifier: GPL-3.0
5+
6+
/* See contracts/COMPILERS.md */
7+
pragma solidity ^0.8.0;
8+
9+
interface IWstETH {
10+
function wrap(uint256 _stETHAmount) external returns (uint256);
11+
function unwrap(uint256 _wstETHAmount) external returns (uint256);
12+
function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);
13+
function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);
14+
function stETH() external view returns (address);
15+
}

0 commit comments

Comments
 (0)