Skip to content

Commit

Permalink
feat: add Wrapped Staked Eth hook
Browse files Browse the repository at this point in the history
  • Loading branch information
marktoda committed Feb 19, 2025
1 parent fdb5d3e commit 69dda63
Show file tree
Hide file tree
Showing 4 changed files with 488 additions and 0 deletions.
73 changes: 73 additions & 0 deletions src/hooks/WstETHHook.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {Currency, CurrencyLibrary} from "@uniswap/v4-core/src/types/Currency.sol";
import {BaseTokenWrapperHook} from "../base/hooks/BaseTokenWrapperHook.sol";
import {IWstETH} from "../interfaces/external/IWstETH.sol";

/// @title Wrapped Staked ETH (wstETH) Hook
/// @notice Hook for wrapping/unwrapping stETH to wstETH in Uniswap V4 pools
/// @dev Implements dynamic exchange rate wrapping/unwrapping between stETH and wstETH
/// @dev wstETH represents stETH with accrued staking rewards, maintaining a dynamic exchange rate
contract WstETHHook is BaseTokenWrapperHook {
/// @notice Thrown when unwrapping wstETH to stETH fails
error WithdrawFailed();

/// @notice The wstETH contract used for wrapping/unwrapping operations
IWstETH public immutable wstETH;

/// @notice Creates a new wstETH wrapper hook
/// @param _manager The Uniswap V4 pool manager
/// @param _wsteth The wstETH contract address
/// @dev Initializes with wstETH as wrapper token and stETH as underlying token
constructor(IPoolManager _manager, IWstETH _wsteth)
BaseTokenWrapperHook(
_manager,
Currency.wrap(address(_wsteth)), // wrapper token is wsteth
Currency.wrap(_wsteth.stETH()) // underlying token is stETH
)
{
wstETH = _wsteth;
ERC20(Currency.unwrap(underlyingCurrency)).approve(address(wstETH), type(uint256).max);
}

/// @inheritdoc BaseTokenWrapperHook
/// @notice Wraps stETH to wstETH
/// @param underlyingAmount Amount of stETH to wrap
/// @return Amount of wstETH received
function _deposit(uint256 underlyingAmount) internal override returns (uint256) {
return wstETH.wrap(underlyingAmount);
}

/// @inheritdoc BaseTokenWrapperHook
/// @notice Unwraps wstETH to stETH
/// @param wrapperAmount Amount of wstETH to unwrap
/// @return Amount of stETH received
function _withdraw(uint256 wrapperAmount) internal override returns (uint256) {
return wstETH.unwrap(wrapperAmount);
}

/// @inheritdoc BaseTokenWrapperHook
/// @notice Calculates how much stETH is needed to receive a specific amount of wstETH
/// @param wrappedAmount Desired amount of wstETH
/// @return Amount of stETH required
/// @dev Uses current stETH/wstETH exchange rate for calculation
function _getWrapInputRequired(uint256 wrappedAmount) internal view override returns (uint256) {
return wstETH.getStETHByWstETH(wrappedAmount);
}

/// @inheritdoc BaseTokenWrapperHook
/// @notice Calculates how much wstETH is needed to receive a specific amount of stETH
/// @param underlyingAmount Desired amount of stETH
/// @return Amount of wstETH required
/// @dev Uses current stETH/wstETH exchange rate for calculation
function _getUnwrapInputRequired(uint256 underlyingAmount) internal view override returns (uint256) {
return wstETH.getWstETHByStETH(underlyingAmount);
}

/// @notice Required to receive ETH from unwrapping operations
/// @dev Needed for protocol integrations that might send ETH to this contract
receive() external payable {}
}
15 changes: 15 additions & 0 deletions src/interfaces/external/IWstETH.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: 2021 Lido <info@lido.fi>
// https://github.com/lidofinance/core/blob/master/contracts/0.6.12/WstETH.sol

// SPDX-License-Identifier: GPL-3.0

/* See contracts/COMPILERS.md */
pragma solidity ^0.8.0;

interface IWstETH {
function wrap(uint256 _stETHAmount) external returns (uint256);
function unwrap(uint256 _wstETHAmount) external returns (uint256);
function getStETHByWstETH(uint256 _wstETHAmount) external view returns (uint256);
function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256);
function stETH() external view returns (address);
}
Loading

0 comments on commit 69dda63

Please sign in to comment.