Skip to content

Commit

Permalink
Upgrade to uniswap v3
Browse files Browse the repository at this point in the history
  • Loading branch information
memoriesadrift authored and SebastianJ21 committed Jun 30, 2024
1 parent fa89157 commit f95f542
Show file tree
Hide file tree
Showing 22 changed files with 555 additions and 1,094 deletions.
17 changes: 9 additions & 8 deletions contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
LOCALCHAIN_DEPLOYER_PK=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
WETH_ADDRESS=0x24fe7807089e321395172633aA9c4bBa4Ac4a357
WSTETH_ADDRESS=0xeAc0CE2994032302f72c078b678c09CcA515AD49
UNIV2ROUTER_ADDRESS=0x6682375ebc1df04676c0c5050934272368e6e883
export LOCALCHAIN_DEPLOYER_PK=
export WETH_ADDRESS=0x4200000000000000000000000000000000000006
export WSTETH_ADDRESS=0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452
export UNIROUTER_ADDRESS=
RPC_URL=
DEPLOYER_PRIVATE_KEY=
CONTRACT_OWNER_ADDRESS=
export DEPLOYER_PRIVATE_KEY=
export CONTRACT_OWNER_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
ETHERSCAN_API_KEY=
PROTOCOL_REWARD_BASIS_POINTS=
ARBITERS_REWARD_BASIS_POINTS=
export PROTOCOL_REWARD_BASIS_POINTS=100
export ARBITERS_REWARD_BASIS_POINTS=300

4 changes: 3 additions & 1 deletion contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ libs = ["lib"]
remappings = [
'@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/',
'@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/',
'@uniswap/v2-periphery/contracts/=node_modules/@uniswap/v2-periphery/contracts/'
'@uniswap/v3-periphery/contracts/=node_modules/@uniswap/v3-periphery/contracts/',
'@uniswap/v3-core/contracts/=node_modules/@uniswap/v3-core/contracts/',
'@uniswap/swap-router-contracts/contracts/=node_modules/@uniswap/swap-router-contracts/contracts/'
]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
2 changes: 1 addition & 1 deletion contracts/lib/forge-std
2 changes: 1 addition & 1 deletion contracts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
"devDependencies": {
"@openzeppelin/contracts": "^5.0.1",
"@openzeppelin/contracts-upgradeable": "^5.0.1",
"@uniswap/v2-periphery": "^1.1.0-beta.0"
"@uniswap/swap-router-contracts": "^1.3.1"
}
}
5 changes: 3 additions & 2 deletions contracts/script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ pragma solidity ^0.8.13;
import {Script, console2} from "forge-std/Script.sol";

import {Slaughterhouse} from "../src/Slaughterhouse.sol";
import '@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol';

contract Deploy is Script {
function setUp() public {}

function run() public {
address WETH = vm.envAddress("WETH_ADDRESS");
address WSTETH = vm.envAddress("WSTETH_ADDRESS");
address uniswapV2Router = vm.envAddress("UNIV2ROUTER_ADDRESS");
address uniswapRouter = vm.envAddress("UNIROUTER_ADDRESS");
address initialOwner = vm.envAddress("CONTRACT_OWNER_ADDRESS");
uint256 protocolRewardBasisPoints = vm.envUint("PROTOCOL_REWARD_BASIS_POINTS");
uint256 arbitersRewardBasisPoints = vm.envUint("ARBITERS_REWARD_BASIS_POINTS");
Expand All @@ -20,7 +21,7 @@ contract Deploy is Script {
Slaughterhouse slaughterhouse = new Slaughterhouse(
WETH,
WSTETH,
uniswapV2Router,
uniswapRouter,
initialOwner,
protocolRewardBasisPoints,
arbitersRewardBasisPoints
Expand Down
39 changes: 39 additions & 0 deletions contracts/script/TestCreateBeef.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console2} from "forge-std/Script.sol";

import {Slaughterhouse} from "../src/Slaughterhouse.sol";
import {Beef} from "../src/Beef.sol";

contract Deploy is Script {
function setUp() public {}

function run() public {
address WETH = vm.envAddress("WETH_ADDRESS");
address WSTETH = vm.envAddress("WSTETH_ADDRESS");
address uniswapRouter = vm.envAddress("UNIROUTER_ADDRESS");
address initialOwner = vm.envAddress("CONTRACT_OWNER_ADDRESS");
uint256 protocolRewardBasisPoints = vm.envUint("PROTOCOL_REWARD_BASIS_POINTS");
uint256 arbitersRewardBasisPoints = vm.envUint("ARBITERS_REWARD_BASIS_POINTS");
vm.broadcast();

address[] memory arbitersArray = new address[](3);
arbitersArray[0] = address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8);
arbitersArray[1] = address(0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65);
arbitersArray[2] = address(0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc);
Beef.ConstructorParams memory params = Beef.ConstructorParams({
owner: address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266),
wager: 1 ether,
challenger: address(0x90F79bf6EB2c4f870365E785982E1f101E93b906),
settleStart: block.timestamp + 1 hours,
joinDeadline: block.timestamp + 1 days,
staking: true,
title: "test",
description: "test2",
arbiters: arbitersArray
});
address payable slaughterhouse = payable(0x457cCf29090fe5A24c19c1bc95F492168C0EaFdb);
Slaughterhouse(slaughterhouse).packageBeef{value: 1 ether}(params, 0.1 ether);
}
}
29 changes: 29 additions & 0 deletions contracts/script/TestQuote.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import {Script, console2} from "forge-std/Script.sol";

import '@uniswap/v3-periphery/contracts/interfaces/IQuoterV2.sol';

contract TestQuote is Script {
function setUp() public {}

function run() public {
address WETH = vm.envAddress("WETH_ADDRESS");
address WSTETH = vm.envAddress("WSTETH_ADDRESS");
vm.broadcast();

address qa = address(0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a);
IQuoterV2.QuoteExactInputSingleParams memory params = IQuoterV2.QuoteExactInputSingleParams({
tokenIn: WETH,
tokenOut: WSTETH,
fee: 100,
amountIn: 1 ether,
sqrtPriceLimitX96: 0
});
uint amountOut;
(amountOut,,,) = IQuoterV2(qa).quoteExactInputSingle(params);

console2.log("Quote: ", amountOut);
}
}
75 changes: 54 additions & 21 deletions contracts/src/Beef.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,19 @@ import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";
import '@uniswap/v3-periphery/contracts/libraries/TransferHelper.sol';
import "@uniswap/swap-router-contracts/contracts/interfaces/IV3SwapRouter.sol";
import {Slaughterhouse} from "./Slaughterhouse.sol";

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

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

contract Beef is OwnableUpgradeable {
using Address for address;

Expand Down Expand Up @@ -67,9 +77,9 @@ contract Beef is OwnableUpgradeable {

// @notice Flag indicating if the beef is staking - the underlying ETH had been staked for wstETH and is earning staking yield.
bool public staking;
// @notice Address of the Uniswap V2 Router.
IUniswapV2Router02 public uniswapV2Router;
IERC20 public WETH;
// @notice Address of the Uniswap V3 Router.
IV3SwapRouter public swapRouter;
IWETH9 public WETH9;
IERC20 public WSTETH;

uint128 public resultYes;
Expand Down Expand Up @@ -152,7 +162,7 @@ contract Beef is OwnableUpgradeable {
uint256 amountOutMin,
address _weth,
address _wsteth,
address _uniswapV2Router,
address _swapRouter,
address payable _slaughterhouse,
uint256 _protocolRewardBasisPoints,
uint256 _arbitersRewardBasisPoints
Expand All @@ -171,9 +181,9 @@ contract Beef is OwnableUpgradeable {
arbiters = params.arbiters;
joinDeadline = params.joinDeadline;
staking = params.staking;
WETH = IERC20(_weth);
WETH9 = IWETH9(_weth);
WSTETH = IERC20(_wsteth);
uniswapV2Router = IUniswapV2Router02(_uniswapV2Router);
swapRouter = IV3SwapRouter(_swapRouter);
slaughterhouse = Slaughterhouse(_slaughterhouse);
protocolRewardBasisPoints = _protocolRewardBasisPoints;
arbitersRewardBasisPoints = _arbitersRewardBasisPoints;
Expand Down Expand Up @@ -370,23 +380,46 @@ contract Beef is OwnableUpgradeable {
}

function _stakeBeef(uint256 amountOutMin) internal {
address[] memory path;
path = new address[](2);
path[0] = address(WETH);
path[1] = address(WSTETH);
uniswapV2Router.swapExactETHForTokens{value: address(this).balance}(
amountOutMin, path, address(this), block.timestamp
);
WETH9.deposit{value: address(this).balance}();

uint256 wethBalance = WETH9.balanceOf(address(this));

TransferHelper.safeApprove(address(WETH9), address(swapRouter), wethBalance);

IV3SwapRouter.ExactInputSingleParams memory params =
IV3SwapRouter.ExactInputSingleParams({
tokenIn: address(WETH9),
tokenOut: address(WSTETH),
fee: 100, // 0.01%
recipient: address(this),
amountIn: wethBalance,
amountOutMinimum: amountOutMin,
sqrtPriceLimitX96: 0
});

swapRouter.exactInputSingle(params);
}

function _unstakeBeef(uint256 amountOutMin) internal {
address[] memory path;
path = new address[](2);
path[0] = address(WSTETH);
path[1] = address(WETH);
uint256 amountIn = IERC20(WSTETH).balanceOf(address(this));
WSTETH.approve(address(uniswapV2Router), amountIn);
uniswapV2Router.swapExactTokensForETH(amountIn, amountOutMin, path, address(this), block.timestamp);
uint256 wstethBalance = WSTETH.balanceOf(address(this));

TransferHelper.safeApprove(address(WSTETH), address(swapRouter), wstethBalance);

IV3SwapRouter.ExactInputSingleParams memory params = IV3SwapRouter.ExactInputSingleParams({
tokenIn: address(WSTETH),
tokenOut: address(WETH9),
fee: 100, // 0.01%
recipient: address(this),
amountIn: wstethBalance,
amountOutMinimum: amountOutMin,
sqrtPriceLimitX96: 0
});

swapRouter.exactInputSingle(params);

uint256 wethBalance = WETH9.balanceOf(address(this));

WETH9.withdraw(wethBalance);
}

function _transferEth(address recipient, uint256 amount) internal {
Expand Down
14 changes: 7 additions & 7 deletions contracts/src/Slaughterhouse.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ contract Slaughterhouse is Ownable2Step {
uint256 public arbitersRewardBasisPoints;

// @notice The address of Wrapped ETH
address public WETH;
address public WETH9;
// @notice The address of Wrapped Staked ETH
address public WSTETH;
// @notice The address of Uniswap V2 Router (for swapping WETH/WSTETH)
address public uniswapV2Router;
// @notice The address of Uniswap V3 Router (for swapping WETH9/WSTETH)
address public uniswapV3Router;

error InvalidBasisPoints(uint256 totalBasisPoints, uint256 providedBasisPoints);
error ZeroBalance();
Expand All @@ -42,15 +42,15 @@ contract Slaughterhouse is Ownable2Step {
constructor(
address _weth,
address _wsteth,
address _uniswapV2Router,
address _uniswapV3Router,
address initialOwner,
uint256 _protocolRewardBasisPoints,
uint256 _arbitersRewardBasisPoints
) Ownable(initialOwner) {
beefImplementation = address(new Beef());
WETH = _weth;
WETH9 = _weth;
WSTETH = _wsteth;
uniswapV2Router = _uniswapV2Router;
uniswapV3Router = _uniswapV3Router;
protocolRewardBasisPoints = _protocolRewardBasisPoints;
arbitersRewardBasisPoints = _arbitersRewardBasisPoints;
}
Expand Down Expand Up @@ -94,7 +94,7 @@ contract Slaughterhouse is Ownable2Step {
returns (address payable)
{
address payable beef = payable(Clones.clone(beefImplementation));
Beef(beef).initialize{value: msg.value}(params, amountOutMin, WETH, WSTETH, uniswapV2Router, payable(this), protocolRewardBasisPoints, arbitersRewardBasisPoints);
Beef(beef).initialize{value: msg.value}(params, amountOutMin, WETH9, WSTETH, uniswapV3Router, payable(this), protocolRewardBasisPoints, arbitersRewardBasisPoints);
beefs.push(beef);
emit BeefPackaged(beef, params.owner, params.challenger);
return beef;
Expand Down
1 change: 0 additions & 1 deletion contracts/test/Beef.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";

import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {IUniswapV2Router02} from "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";

import {Beef} from "../src/Beef.sol";
import {Slaughterhouse} from "../src/Slaughterhouse.sol";
Expand Down
4 changes: 2 additions & 2 deletions contracts/test/Slaughterhouse.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ contract SlaughterhouseTest is Test {
assertEq(beef.arbiters(2), params.arbiters[2], "Beef arbiter 2 mismatch");
assertEq(beef.joinDeadline(), params.joinDeadline, "Beef joinDeadline mismatch");
assertEq(beef.staking(), params.staking, "Beef staking mismatch");
assertEq(address(beef.WETH()), WETH, "Beef WETH mismatch");
assertEq(address(beef.WETH9()), WETH, "Beef WETH mismatch");
assertEq(address(beef.WSTETH()), WSTETH, "Beef WSTETH mismatch");
assertEq(address(beef.uniswapV2Router()), uniswapV2Router, "Beef uniswapV2Router mismatch");
assertEq(address(beef.swapRouter()), uniswapV2Router, "Beef uniswapV2Router mismatch");
assertEq(beef.protocolRewardBasisPoints(), slaughterhouse.protocolRewardBasisPoints(), "Beef protocolRewardsBasisPoints mismatch");
assertEq(beef.arbitersRewardBasisPoints(), slaughterhouse.arbitersRewardBasisPoints(), "Beef arbitersRewardsBasisPoints mismatch");
assertEq(beef.totalBasisPoints(), slaughterhouse.totalBasisPoints(), "Beef totalBasisPoints mismatch");
Expand Down
Loading

0 comments on commit f95f542

Please # to comment.