From 5fb269c2dea6481c6cef7ced3fe6d2b524121e47 Mon Sep 17 00:00:00 2001 From: kyriediculous Date: Fri, 25 Oct 2024 18:01:48 +0200 Subject: [PATCH] deployment --- script/add_liq.s.sol | 4 +- script/deploy.local.s.sol | 7 ++- script/deploy.local.sh | 2 - script/lpeth.deploy.s.sol | 83 +++++++++++++++++++++++++++++++++++ script/new_adapter.s.sol | 39 ++++++++++++++++ script/prelaunch.deploy.s.sol | 2 +- src/lpETH/LpETH.sol | 19 +++++--- src/periphery/PreLaunch.sol | 16 ++++--- src/periphery/SwapRouter.sol | 47 -------------------- 9 files changed, 151 insertions(+), 68 deletions(-) create mode 100644 script/lpeth.deploy.s.sol create mode 100644 script/new_adapter.s.sol delete mode 100644 src/periphery/SwapRouter.sol diff --git a/script/add_liq.s.sol b/script/add_liq.s.sol index f40afff..2b4dbd4 100644 --- a/script/add_liq.s.sol +++ b/script/add_liq.s.sol @@ -12,9 +12,9 @@ contract AddLiquidity is Script { function run() public { uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); - address swap = 0xa5d6F9108f953AE259Cc2C357547FbbdD693347A; + address swap = 0xF3a75E087A92770b4150fFF14c6d36FB07796252; - LpETH(payable(swap)).deposit{ value: 1000 ether }(0); + LpETH(payable(swap)).deposit{ value: 0.5 ether }(0.5 ether); vm.stopBroadcast(); } } diff --git a/script/deploy.local.s.sol b/script/deploy.local.s.sol index c196db3..153d3ac 100644 --- a/script/deploy.local.s.sol +++ b/script/deploy.local.s.sol @@ -8,7 +8,6 @@ import { LpETH, ConstructorConfig } from "@/lpETH/LpETH.sol"; import { LPToken } from "@/lpETH/LPToken.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import { ERC20 } from "solady/tokens/ERC20.sol"; -import { SwapRouter } from "@/periphery/SwapRouter.sol"; // Adapters import { Adapter } from "@/adapters/Adapter.sol"; @@ -75,9 +74,9 @@ contract DeployLocal is Script { registryProxy.setAdapter(STETH_TOKEN, stETHAdapter); console2.log("StETH Adapter: %s", address(stETHAdapter)); - SwapRouter swapRouter = new SwapRouter(); - console2.log("SwapRouter: %s", address(swapRouter)); - + // TODO: Tranfer ownership to SAFE + address SAFE = 0x5542b58080FEE48dBE6f38ec0135cE9011519d96; + lpETHProxy.transferOwnership(SAFE); vm.stopBroadcast(); } } diff --git a/script/deploy.local.sh b/script/deploy.local.sh index 05aaa35..7149268 100644 --- a/script/deploy.local.sh +++ b/script/deploy.local.sh @@ -8,8 +8,6 @@ forge build curl -H "Content-Type: application/json" -X POST --data '{"jsonrpc":"2.0","id":67,"method":"anvil_setCode","params": ["0x4e59b44847b379578588920ca78fbf26c0b4956c","0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"]}' 127.0.0.1:8545 -export PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 - forge script script/deploy.local.s.sol --legacy --rpc-url http://127.0.0.1:8545 --broadcast --private-key $PRIVATE_KEY -vvvv forge script script/add_liq.s.sol --legacy --rpc-url http://127.0.0.1:8545 --broadcast --private-key $PRIVATE_KEY -vvvv forge script script/prelaunch.local.s.sol --legacy --rpc-url http://127.0.0.1:8545 --broadcast --private-key $PRIVATE_KEY -vvvv diff --git a/script/lpeth.deploy.s.sol b/script/lpeth.deploy.s.sol new file mode 100644 index 0000000..8ff39d9 --- /dev/null +++ b/script/lpeth.deploy.s.sol @@ -0,0 +1,83 @@ +pragma solidity >=0.8.25; + +import { Script, console2 } from "forge-std/Script.sol"; +import { Registry } from "@/Registry.sol"; +import { UnsETH } from "@/unsETH/UnsETH.sol"; +import { Renderer } from "@/unsETH/Renderer.sol"; +import { LpETH, ConstructorConfig } from "@/lpETH/LpETH.sol"; +import { LPToken } from "@/lpETH/LPToken.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import { ERC20 } from "solady/tokens/ERC20.sol"; + +// Adapters +import { Adapter } from "@/adapters/Adapter.sol"; +import { EETHAdapter, EETH_TOKEN } from "@/adapters/eETH/EETHAdapter.sol"; +import { ETHxAdapter, ETHx_TOKEN } from "@/adapters/ETHx/ETHxAdapter.sol"; +import { METHAdapter, METH_TOKEN } from "@/adapters/mETH/METHAdapter.sol"; +import { StETHAdapter, STETH_TOKEN } from "@/adapters/stETH/StETHAdapter.sol"; +import { SwETHAdapter, SWETH_TOKEN } from "@/adapters/swETH/SwETHAdapter.sol"; + +// Token holders, to get some funds +import { EETH_HOLDER } from "@test/adapters/EETHAdapter.t.sol"; +import { ETHx_HOLDER } from "@test/adapters/ETHxAdapter.t.sol"; +import { METH_HOLDER } from "@test/adapters/METHAdapter.t.sol"; +import { STETH_HOLDER } from "@test/adapters/StETHAdapter.t.sol"; +import { SWETH_HOLDER } from "@test/adapters/SwETHAdapter.t.sol"; + +contract DeployLocal is Script { + bytes32 salt = bytes32(0x76302e312e300000000000000000000000000000000000000000000000000000); // "v0.1.0" + + function run() public { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + LPToken lpToken = new LPToken(); + + address registry_impl = address(new Registry{ salt: salt }()); + Registry registryProxy = Registry(address(new ERC1967Proxy{ salt: salt }(address(registry_impl), ""))); + registryProxy.initialize(); + console2.log("Registry Implementation: %s", registry_impl); + console2.log("Registry Proxy: %s", address(registryProxy)); + + address renderer = address(new Renderer()); + address unsETH_impl = address(new UnsETH{ salt: salt }(address(registryProxy), renderer)); + UnsETH unsETHProxy = UnsETH(payable(address(new ERC1967Proxy{ salt: salt }(unsETH_impl, "")))); + unsETHProxy.initialize(); + console2.log("UnsETH Implementation: %s", unsETH_impl); + console2.log("UnsETH Proxy: %s", address(unsETHProxy)); + + ConstructorConfig memory config = + ConstructorConfig({ registry: registryProxy, lpToken: lpToken, unsETH: unsETHProxy, treasury: address(0) }); + + address lpETH_impl = address(new LpETH{ salt: salt }(config)); + LpETH lpETHProxy = LpETH(payable(address(new ERC1967Proxy{ salt: salt }(lpETH_impl, "")))); + lpETHProxy.initialize(); + lpToken.transferOwnership(address(lpETHProxy)); + console2.log("LPETH Implementation: %s", lpETH_impl); + console2.log("LPETH Proxy: %s", address(lpETHProxy)); + console2.log("LP Token: %s", address(lpETHProxy.lpToken())); + + // Register and deploy adapters, send some funds + Adapter eETHAdapter = new EETHAdapter(); + registryProxy.setAdapter(EETH_TOKEN, eETHAdapter); + console2.log("EETH Adapter: %s", address(eETHAdapter)); + + Adapter ethxAdapter = new ETHxAdapter(); + registryProxy.setAdapter(ETHx_TOKEN, ethxAdapter); + console2.log("ETHx Adapter: %s", address(ethxAdapter)); + + Adapter methAdapter = new METHAdapter(); + registryProxy.setAdapter(METH_TOKEN, methAdapter); + console2.log("METH Adapter: %s", address(methAdapter)); + + Adapter stETHAdapter = new StETHAdapter(); + registryProxy.setAdapter(STETH_TOKEN, stETHAdapter); + console2.log("StETH Adapter: %s", address(stETHAdapter)); + + address SAFE = 0x5542b58080FEE48dBE6f38ec0135cE9011519d96; + lpETHProxy.transferOwnership(SAFE); + unsETHProxy.transferOwnership(SAFE); + registryProxy.transferOwnership(SAFE); + vm.stopBroadcast(); + } +} diff --git a/script/new_adapter.s.sol b/script/new_adapter.s.sol new file mode 100644 index 0000000..13caf29 --- /dev/null +++ b/script/new_adapter.s.sol @@ -0,0 +1,39 @@ +pragma solidity >=0.8.25; + +import { Script, console2 } from "forge-std/Script.sol"; +import { Registry } from "@/Registry.sol"; +import { UnsETH } from "@/unsETH/UnsETH.sol"; +import { Renderer } from "@/unsETH/Renderer.sol"; +import { LpETH, ConstructorConfig } from "@/lpETH/LpETH.sol"; +import { LPToken } from "@/lpETH/LPToken.sol"; +import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; +import { ERC20 } from "solady/tokens/ERC20.sol"; + +// Adapters +import { Adapter } from "@/adapters/Adapter.sol"; +import { EETHAdapter, EETH_TOKEN } from "@/adapters/eETH/EETHAdapter.sol"; +import { ETHxAdapter, ETHx_TOKEN } from "@/adapters/ETHx/ETHxAdapter.sol"; +import { METHAdapter, METH_TOKEN } from "@/adapters/mETH/METHAdapter.sol"; +import { StETHAdapter, STETH_TOKEN } from "@/adapters/stETH/StETHAdapter.sol"; +import { SwETHAdapter, SWETH_TOKEN } from "@/adapters/swETH/SwETHAdapter.sol"; + +// Token holders, to get some funds +import { EETH_HOLDER } from "@test/adapters/EETHAdapter.t.sol"; +import { ETHx_HOLDER } from "@test/adapters/ETHxAdapter.t.sol"; +import { METH_HOLDER } from "@test/adapters/METHAdapter.t.sol"; +import { STETH_HOLDER } from "@test/adapters/StETHAdapter.t.sol"; +import { SWETH_HOLDER } from "@test/adapters/SwETHAdapter.t.sol"; + +contract DeployLocal is Script { + bytes32 salt = bytes32(0x76302e312e300000000000000000000000000000000000000000000000000000); // "v0.1.0" + + function run() public { + uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); + vm.startBroadcast(deployerPrivateKey); + + Adapter swETHAdapter = new SwETHAdapter(); + console2.log("SwtETH Adapter: %s", address(swETHAdapter)); + + vm.stopBroadcast(); + } +} diff --git a/script/prelaunch.deploy.s.sol b/script/prelaunch.deploy.s.sol index 63e65d1..ff3010c 100644 --- a/script/prelaunch.deploy.s.sol +++ b/script/prelaunch.deploy.s.sol @@ -13,7 +13,7 @@ contract DeployPrelaunch is Script { function run() public { Config memory cfg = Config({ cap: 80_000 ether, - deadline: block.timestamp + 4 weeks, + deadline: 1_728_746_087, minLockup: 1, maxLockup: 52, epochLength: 604_800, diff --git a/src/lpETH/LpETH.sol b/src/lpETH/LpETH.sol index e09acf6..a0a03a4 100644 --- a/src/lpETH/LpETH.sol +++ b/src/lpETH/LpETH.sol @@ -40,10 +40,10 @@ import { UUPSUpgradeable } from "@openzeppelin/upgradeable/proxy/utils/UUPSUpgra uint256 constant UNSETH_EXPIRATION_TIME = 3 days + 12 hours; UD60x18 constant BASE_FEE = UD60x18.wrap(0.0005e18); -UD60x18 constant K = UD60x18.wrap(4.5e18); +UD60x18 constant K = UD60x18.wrap(3.5e18); UD60x18 constant RELAYER_CUT = UD60x18.wrap(0.025e18); UD60x18 constant TREASURY_CUT = UD60x18.wrap(0.2e18); -UD60x18 constant MIN_LP_CUT = UD60x18.wrap(0.2e18); +UD60x18 constant MIN_LP_CUT = UD60x18.wrap(0.33e18); struct ConstructorConfig { Registry registry; @@ -244,15 +244,24 @@ contract LpETH is emit Withdraw(msg.sender, amount, lpShares, requestId); } - function quote(address asset, uint256 amount) external view returns (uint256 out) { + function quote(address asset, uint256 amount) external view returns (uint256 out, uint256 fee) { Adapter adapter = REGISTRY.adapters(asset); if (address(adapter) == address(0)) revert ErrorInvalidAsset(asset); SwapParams memory p = _getSwapParams(asset, adapter); uint256 ethExpected = adapter.previewWithdraw(amount); out = _quote(asset, ethExpected, p); + fee = ethExpected - out; } - function swap(address asset, uint256 amount, uint256 minOut) external nonreentrant returns (uint256 out) { + function swap( + address asset, + uint256 amount, + uint256 minOut + ) + external + nonreentrant + returns (uint256 out, uint256 fee) + { Data storage $ = _loadStorageSlot(); Adapter adapter = REGISTRY.adapters(asset); if (address(adapter) == address(0)) revert ErrorInvalidAsset(asset); @@ -270,7 +279,7 @@ contract LpETH is (uint256 tokenId, uint256 amountExpected) = UNSETH.requestWithdraw(asset, amount); (out) = _quote(asset, amountExpected, p); - uint256 fee = amountExpected - out; + fee = amountExpected - out; // Revert if slippage threshold is exceeded, i.e. if `out` is less than `minOut` if (out < minOut) revert ErrorSlippage(out, minOut); diff --git a/src/periphery/PreLaunch.sol b/src/periphery/PreLaunch.sol index 8642b46..bf84e16 100644 --- a/src/periphery/PreLaunch.sol +++ b/src/periphery/PreLaunch.sol @@ -52,7 +52,7 @@ contract PreLaunch is Initializable, OwnableUpgradeable, UUPSUpgradeable { uint256 public totalDeposits; // Total deposits address public votingEscrow; // Voting escrow contract address payable lpEth; // LP token for lpETH - uint96 claimableTimestamp; // Timestamp when deposits become claimable + uint96 public claimableTimestamp; // Timestamp when deposits become claimable uint256 lpEthReceived = 0; mapping(address account => Lockup) internal lockups; @@ -80,12 +80,12 @@ contract PreLaunch is Initializable, OwnableUpgradeable, UUPSUpgradeable { return lockups[account]; } - function isActive() public view returns (bool) { - return block.timestamp <= deadline; + function isActive() public pure returns (bool) { + return false; } function isClaimable() public view returns (bool) { - return votingEscrow != address(0) && lpEthReceived > 0; + return lpEthReceived > 0; } function setLpEth(address payable _lpEth) external onlyOwner { @@ -100,7 +100,6 @@ contract PreLaunch is Initializable, OwnableUpgradeable, UUPSUpgradeable { revert(); } votingEscrow = _votingEscrow; - claimableTimestamp = uint96(block.timestamp); } function mintLpEth(uint256 minLpShares) external onlyOwner { @@ -114,6 +113,7 @@ contract PreLaunch is Initializable, OwnableUpgradeable, UUPSUpgradeable { uint256 lpShares = LpETH(lpEth).deposit{ value: address(this).balance }(minLpShares); lpEthReceived += lpShares; + claimableTimestamp = uint96(block.timestamp - 7 days); } function depositETH(uint256 duration) external payable { @@ -214,9 +214,11 @@ contract PreLaunch is Initializable, OwnableUpgradeable, UUPSUpgradeable { // Account for elapsed time since the deposits became claimable in epochs uint256 epochsElapsedSinceClaimable = (block.timestamp - claimableTimestamp) / EPOCH_LENGTH; uint256 lpEthAmount = lockup.amount * lpEthReceived / totalDeposits; - SafeTransferLib.safeApprove(lpEth, votingEscrow, lpEthAmount); if (lockup.duration > epochsElapsedSinceClaimable) { - VotingEscrow(votingEscrow).lockFor(msg.sender, lpEthAmount, lockup.duration - epochsElapsedSinceClaimable); + revert NotClaimable(); + // SafeTransferLib.safeApprove(lpEth, votingEscrow, lpEthAmount); + // VotingEscrow(votingEscrow).lockFor(msg.sender, lpEthAmount, lockup.duration - + // epochsElapsedSinceClaimable); } else { ERC20(LpETH(lpEth).lpToken()).transfer(msg.sender, lpEthAmount); } diff --git a/src/periphery/SwapRouter.sol b/src/periphery/SwapRouter.sol deleted file mode 100644 index 6d78f3e..0000000 --- a/src/periphery/SwapRouter.sol +++ /dev/null @@ -1,47 +0,0 @@ -pragma solidity ^0.8.25; - -import { LpETH } from "@/lpETH/LpETH.sol"; -import { ERC20 } from "@solady/tokens/ERC20.sol"; -import { SafeTransferLib } from "@solady/utils/SafeTransferLib.sol"; -import { STETH_TOKEN } from "@/adapters/stETH/StETHAdapter.sol"; -import { EETH_TOKEN } from "@/adapters/eETH/EETHAdapter.sol"; - -address constant WRAPPED_STETH = 0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0; -address constant WRAPPED_EETH = 0xCd5fE23C85820F7B72D0926FC9b05b43E359b7ee; - -LpETH constant LPETH = LpETH(payable(address(2))); - -interface Unwrap { - function unwrap(uint256 amount) external returns (uint256); -} - -contract SwapRouter { - using SafeTransferLib for address; - - receive() external payable { } - - function swap(address tokenIn, uint256 amount, uint256 minOut) external returns (uint256 out) { - tokenIn.safeTransferFrom(msg.sender, address(this), amount); - if (tokenIn == WRAPPED_STETH || tokenIn == WRAPPED_EETH) { - (tokenIn, amount) = _handleUnwrap(tokenIn, amount); - } - out = LPETH.swap(tokenIn, amount, minOut); - payable(msg.sender).transfer(out); - } - - function _handleUnwrap( - address tokenIn, - uint256 amount - ) - internal - returns (address unwrappedToken, uint256 unwrappedAmount) - { - unwrappedAmount = Unwrap(tokenIn).unwrap(amount); - if (tokenIn == WRAPPED_STETH) { - unwrappedToken = STETH_TOKEN; - } - if (tokenIn == WRAPPED_EETH) { - unwrappedToken = EETH_TOKEN; - } - } -}