Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions script/DeployBETHToETH.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "forge-std/Script.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "src/hooks/cypher-eth/BETHToETH.sol";
import {IWNativeToken} from "src/hooks/cypher-eth/IWNativeToken.sol";

contract DeployBETHToETH is Script {
// mainnet addresses
address constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address constant BETH = 0x5624344235607940d4d4EE76Bf8817d403EB9Cf8;
address constant swapRouter = 0x20C5893f69F635f55b0367C519F3f95e59c0b0Ab;

function run() external {
vm.startBroadcast();

BETHToETH bethToEth = new BETHToETH(IERC20(BETH), IWNativeToken(WETH), ISwapRouter(swapRouter));

console.log("BETHToETH deployed to:", address(bethToEth));
console.log("BETH address:", BETH);
console.log("WETH address:", WETH);

vm.stopBroadcast();
}
}
52 changes: 52 additions & 0 deletions src/hooks/cypher-eth/BETHToETH.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IWNativeToken} from "src/hooks/cypher-eth/IWNativeToken.sol";
import {ISwapRouter} from "src/hooks/cypher-eth/ISwapRouter.sol";

contract BETHToETH {
IERC20 public immutable bethContract;
IWNativeToken public immutable wethContract;
ISwapRouter public immutable swapRouterContract;

constructor(IERC20 _bethContract, IWNativeToken _wethContract, ISwapRouter _swapRouterContract) {
require(address(_bethContract) != address(0), "Invalid BETH address");
require(address(_wethContract) != address(0), "Invalid WETH address");
require(address(_swapRouterContract) != address(0), "Invalid WETH address");
bethContract = _bethContract;
wethContract = _wethContract;
swapRouterContract = _swapRouterContract;
}

function swapBethWithEth(uint256 _swapAmount, address _recipient) public returns (uint256 amountOut) {
require(_swapAmount > 0, "Amount must be greater than 0");
require(_recipient != address(0), "Invalid recipient");

require(
bethContract.transferFrom(msg.sender, address(this), _swapAmount), "error while transferFrom beth to this"
);

bethContract.approve(address(swapRouterContract), _swapAmount);

amountOut = swapRouterContract.exactInputSingle(
ISwapRouter.ExactInputSingleParams({
tokenIn: address(bethContract),
tokenOut: address(wethContract),
deployer: address(0),
recipient: address(this),
deadline: block.timestamp + 15 minutes,
amountIn: _swapAmount,
amountOutMinimum: 0,
limitSqrtPrice: 0
})
);

bethContract.approve(address(swapRouterContract), 0); // extra safety
wethContract.withdraw(amountOut);
(bool success,) = _recipient.call{value: amountOut}("");
require(success, "ETH transfer failed");
}

fallback() external payable {}
}
17 changes: 17 additions & 0 deletions src/hooks/cypher-eth/ISwapRouter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
address deployer;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 limitSqrtPrice;
}

function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
}
13 changes: 13 additions & 0 deletions src/hooks/cypher-eth/IWNativeToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";

/// @title Interface for WNativeToken
interface IWNativeToken is IERC20 {
/// @notice Deposit ether to get wrapped ether
function deposit() external payable;

/// @notice Withdraw wrapped ether to get ether
function withdraw(uint256) external;
}