From 56ab15fe691d8fd411b627d38aa7352a662f14f9 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Thu, 5 Oct 2023 10:57:55 +0100 Subject: [PATCH 01/17] chore: add feeReceipient to lidosplit --- src/lido/LidoSplit.sol | 28 +++++++++++++++++++++++++--- src/lido/LidoSplitFactory.sol | 4 ++-- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index 6457e34..6146209 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -17,6 +17,8 @@ interface IwSTETH { contract LidoSplit is Clone { error Invalid_Address(); + error Invalid_FeeShare(uint256 fee); + error Invalid_FeeRecipient(); /// ----------------------------------------------------------------------- /// libraries @@ -25,6 +27,7 @@ contract LidoSplit is Clone { using SafeTransferLib for address; address internal constant ETH_ADDRESS = address(0); + uint256 internal constant PERCENTAGE_SCALE = 1e5; /// ----------------------------------------------------------------------- /// storage - cwia offsets @@ -45,9 +48,20 @@ contract LidoSplit is Clone { /// @notice wstETH token ERC20 public immutable wstETH; - constructor(ERC20 _stETH, ERC20 _wstETH) { + /// @notice fee address + address public immutable feeRecipient; + + /// @notice fee share + uint256 public immutable feeShare; + + constructor(address _feeRecipient, uint256 _feeShare, ERC20 _stETH, ERC20 _wstETH ) { + if(_feeShare >= PERCENTAGE_SCALE) revert Invalid_FeeShare(_feeShare); + if (_feeShare > 0 && _feeRecipient == address(0)) revert Invalid_FeeRecipient(); + + feeRecipient = _feeRecipient; stETH = _stETH; wstETH = _wstETH; + feeShare = _feeShare; } /// Address of split wallet to send funds to to @@ -66,8 +80,16 @@ contract LidoSplit is Clone { stETH.approve(address(wstETH), balance); // wrap into wseth amount = IwSTETH(address(wstETH)).wrap(balance); - // transfer to split wallet - ERC20(wstETH).safeTransfer(splitWallet(), amount); + if (feeShare > 0 ) { + uint256 fee = (amount * feeShare) / PERCENTAGE_SCALE; + // transfer to split wallet + ERC20(wstETH).safeTransfer(splitWallet(), amount - fee); + // transfer to fee address + ERC20(wstETH).safeTransfer(feeRecipient, fee); + } else { + // transfer to split wallet + ERC20(wstETH).safeTransfer(splitWallet(), amount); + } } /// @notice Rescue stuck ETH and tokens diff --git a/src/lido/LidoSplitFactory.sol b/src/lido/LidoSplitFactory.sol index 922827c..e64b3eb 100644 --- a/src/lido/LidoSplitFactory.sol +++ b/src/lido/LidoSplitFactory.sol @@ -36,8 +36,8 @@ contract LidoSplitFactory { /// @dev lido split implementation LidoSplit public immutable lidoSplitImpl; - constructor(ERC20 _stETH, ERC20 _wstETH) { - lidoSplitImpl = new LidoSplit(_stETH, _wstETH); + constructor(address _feeRecipient, uint256 _feeShare, ERC20 _stETH, ERC20 _wstETH) { + lidoSplitImpl = new LidoSplit(_feeRecipient, _feeShare, _stETH, _wstETH); } /// Creates a wrapper for splitWallet that transforms stETH token into From 39f1e30712bc06831ea7e78c36169cd12dcb964e Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 09:49:22 +0200 Subject: [PATCH 02/17] test: fix lido test cases --- src/test/lido/LIdoSplitFactory.t.sol | 19 +++++++++++++++++++ src/test/lido/LidoSplit.t.sol | 8 +++++--- .../integration/LidoSplitIntegrationTest.sol | 8 +++++--- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/test/lido/LIdoSplitFactory.t.sol b/src/test/lido/LIdoSplitFactory.t.sol index 9ffb7cb..8172829 100644 --- a/src/test/lido/LIdoSplitFactory.t.sol +++ b/src/test/lido/LIdoSplitFactory.t.sol @@ -8,6 +8,7 @@ import {LidoSplitTestHelper} from "./LidoSplitTestHelper.sol"; contract LidoSplitFactoryTest is LidoSplitTestHelper, Test { LidoSplitFactory internal lidoSplitFactory; + LidoSplitFactory internal lidoSplitFactoryWithFee; address demoSplit; @@ -18,6 +19,15 @@ contract LidoSplitFactoryTest is LidoSplitTestHelper, Test { vm.createSelectFork(getChain("mainnet").rpcUrl, mainnetBlock); lidoSplitFactory = new LidoSplitFactory( + address(0), + 0, + ERC20(STETH_MAINNET_ADDRESS), + ERC20(WSTETH_MAINNET_ADDRESS) + ); + + lidoSplitFactoryWithFee = new LidoSplitFactory( + address(this), + 1e3, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS) ); @@ -30,10 +40,19 @@ contract LidoSplitFactoryTest is LidoSplitTestHelper, Test { emit CreateLidoSplit(address(0x1)); lidoSplitFactory.createSplit(demoSplit); + + + vm.expectEmit(true, true, true, false, address(lidoSplitFactoryWithFee)); + emit CreateLidoSplit(address(0x1)); + + lidoSplitFactoryWithFee.createSplit(demoSplit); } function testCannot_CreateSplitInvalidAddress() public { vm.expectRevert(LidoSplitFactory.Invalid_Wallet.selector); lidoSplitFactory.createSplit(address(0)); + + vm.expectRevert(LidoSplitFactory.Invalid_Wallet.selector); + lidoSplitFactoryWithFee.createSplit(address(0)); } } diff --git a/src/test/lido/LidoSplit.t.sol b/src/test/lido/LidoSplit.t.sol index 37a5d33..1bd9a5c 100644 --- a/src/test/lido/LidoSplit.t.sol +++ b/src/test/lido/LidoSplit.t.sol @@ -21,9 +21,11 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { vm.createSelectFork(getChain("mainnet").rpcUrl, mainnetBlock); lidoSplitFactory = new LidoSplitFactory( - ERC20(STETH_MAINNET_ADDRESS), - ERC20(WSTETH_MAINNET_ADDRESS) - ); + address(0), + 0, + ERC20(STETH_MAINNET_ADDRESS), + ERC20(WSTETH_MAINNET_ADDRESS) + ); demoSplit = makeAddr("demoSplit"); diff --git a/src/test/lido/integration/LidoSplitIntegrationTest.sol b/src/test/lido/integration/LidoSplitIntegrationTest.sol index e901135..45465a1 100644 --- a/src/test/lido/integration/LidoSplitIntegrationTest.sol +++ b/src/test/lido/integration/LidoSplitIntegrationTest.sol @@ -23,9 +23,11 @@ contract LidoSplitIntegrationTest is LidoSplitTestHelper, Test { vm.createSelectFork(getChain("mainnet").rpcUrl, mainnetBlock); lidoSplitFactory = new LidoSplitFactory( - ERC20(STETH_MAINNET_ADDRESS), - ERC20(WSTETH_MAINNET_ADDRESS) - ); + address(0), + 0, + ERC20(STETH_MAINNET_ADDRESS), + ERC20(WSTETH_MAINNET_ADDRESS) + ); accounts = new address[](2); accounts[0] = makeAddr("accounts0"); From 2947a47dbcdbb92e108973896738befbca948359 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 10:01:01 +0200 Subject: [PATCH 03/17] chore: add wstETH check to rescueFunds; use balanceOf wstETH to calculate balance --- src/lido/LidoSplit.sol | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index 6146209..3b349d9 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -79,7 +79,12 @@ contract LidoSplit is Clone { // approve the wstETH stETH.approve(address(wstETH), balance); // wrap into wseth - amount = IwSTETH(address(wstETH)).wrap(balance); + // we ignore the return value + IwSTETH(address(wstETH)).wrap(balance); + // we use balanceOf here in case some wstETH is stuck in the + // contract we would be able to rescue it + amount = ERC20(wstETH).balanceOf(address(this)); + if (feeShare > 0 ) { uint256 fee = (amount * feeShare) / PERCENTAGE_SCALE; // transfer to split wallet @@ -96,7 +101,9 @@ contract LidoSplit is Clone { /// Uses token == address(0) to represent ETH /// @return balance Amount of ETH or tokens rescued function rescueFunds(address token) external returns (uint256 balance) { - if (token == address(stETH)) revert Invalid_Address(); + // we check wstETH here so rescueFunds can't be used + // to bypass fee + if (token == address(stETH) || token == address(wstETH)) revert Invalid_Address(); if (token == ETH_ADDRESS) { balance = address(this).balance; From 43c14c33d623d5f85ec8d11e73a239eb7a09ec35 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 11:37:19 +0200 Subject: [PATCH 04/17] test: add lido fee test cases --- src/lido/LidoSplit.sol | 6 +++ src/test/lido/LidoSplit.t.sol | 89 ++++++++++++++++++++++++++++++++++- 2 files changed, 93 insertions(+), 2 deletions(-) diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index 3b349d9..ea7422d 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -7,6 +7,7 @@ import {Clone} from "solady/utils/Clone.sol"; interface IwSTETH { function wrap(uint256 amount) external returns (uint256); + function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); } /// @title LidoSplit @@ -54,6 +55,11 @@ contract LidoSplit is Clone { /// @notice fee share uint256 public immutable feeShare; + /// @notice Constructor + /// @param _feeRecipient address to receive fee + /// @param _feeShare fee share scaled by PERCENTAGE_SCALE + /// @param _stETH stETH address + /// @param _wstETH wstETH address constructor(address _feeRecipient, uint256 _feeShare, ERC20 _stETH, ERC20 _wstETH ) { if(_feeShare >= PERCENTAGE_SCALE) revert Invalid_FeeShare(_feeShare); if (_feeShare > 0 && _feeRecipient == address(0)) revert Invalid_FeeRecipient(); diff --git a/src/test/lido/LidoSplit.t.sol b/src/test/lido/LidoSplit.t.sol index 1bd9a5c..5603225 100644 --- a/src/test/lido/LidoSplit.t.sol +++ b/src/test/lido/LidoSplit.t.sol @@ -2,17 +2,26 @@ pragma solidity ^0.8.19; import "forge-std/Test.sol"; -import {LidoSplitFactory, LidoSplit} from "src/lido/LidoSplitFactory.sol"; +import {LidoSplitFactory, LidoSplit, IwSTETH} from "src/lido/LidoSplitFactory.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {LidoSplitTestHelper} from "./LidoSplitTestHelper.sol"; import { MockERC20 } from "src/test/utils/mocks/MockERC20.sol"; contract LidoSplitTest is LidoSplitTestHelper, Test { + + uint256 internal constant PERCENTAGE_SCALE = 1e5; + + LidoSplitFactory internal lidoSplitFactory; + LidoSplitFactory internal lidoSplitFactoryWithFee; + LidoSplit internal lidoSplit; + LidoSplit internal lidoSplitWithFee; address demoSplit; + address feeRecipient; + uint256 feeShare; MockERC20 mERC20; @@ -20,6 +29,9 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { uint256 mainnetBlock = 17_421_005; vm.createSelectFork(getChain("mainnet").rpcUrl, mainnetBlock); + feeRecipient = makeAddr("feeRecipient"); + feeShare = 1e4; + lidoSplitFactory = new LidoSplitFactory( address(0), 0, @@ -27,18 +39,38 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { ERC20(WSTETH_MAINNET_ADDRESS) ); + lidoSplitFactoryWithFee = new LidoSplitFactory( + feeRecipient, + feeShare, + ERC20(STETH_MAINNET_ADDRESS), + ERC20(WSTETH_MAINNET_ADDRESS) + ); + demoSplit = makeAddr("demoSplit"); lidoSplit = LidoSplit(lidoSplitFactory.createSplit(demoSplit)); + lidoSplitWithFee = LidoSplit(lidoSplitFactoryWithFee.createSplit(demoSplit)); mERC20 = new MockERC20("Test Token", "TOK", 18); mERC20.mint(type(uint256).max); } + function test_CannotCreateInvalidFeeRecipient() public { + + } + function test_CloneArgsIsCorrect() public { assertEq(lidoSplit.splitWallet(), demoSplit, "invalid address"); assertEq(address(lidoSplit.stETH()), STETH_MAINNET_ADDRESS, "invalid stETH address"); assertEq(address(lidoSplit.wstETH()), WSTETH_MAINNET_ADDRESS, "invalid wstETH address"); + assertEq(lidoSplit.feeRecipient(), address(0), "invalid fee recipient"); + assertEq(lidoSplit.feeShare(), 0, "invalid fee amount"); + + assertEq(lidoSplitWithFee.splitWallet(), demoSplit, "invalid address"); + assertEq(address(lidoSplitWithFee.stETH()), STETH_MAINNET_ADDRESS, "invalid stETH address"); + assertEq(address(lidoSplitWithFee.wstETH()), WSTETH_MAINNET_ADDRESS, "invalid wstETH address"); + assertEq(lidoSplitWithFee.feeRecipient(), feeRecipient, "invalid fee recipient /2"); + assertEq(lidoSplitWithFee.feeShare(), feeShare, "invalid fee share /2"); } function test_CanRescueFunds() public { @@ -64,9 +96,14 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { LidoSplit.Invalid_Address.selector ); lidoSplit.rescueFunds(address(STETH_MAINNET_ADDRESS)); + + vm.expectRevert( + LidoSplit.Invalid_Address.selector + ); + lidoSplit.rescueFunds(address(WSTETH_MAINNET_ADDRESS)); } - function test_CanDistribute() public { + function test_CanDistributeWithoutFee() public { // we use a random account on Etherscan to credit the lidoSplit address // with 10 ether worth of stETH on mainnet vm.prank(0x2bf3937b8BcccE4B65650F122Bb3f1976B937B2f); @@ -82,4 +119,52 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { assertGe(afterBalance, prevBalance, "after balance greater"); } + + function test_CanDistributeWithFee() public { + // we use a random account on Etherscan to credit the lidoSplit address + // with 10 ether worth of stETH on mainnet + vm.prank(0x2bf3937b8BcccE4B65650F122Bb3f1976B937B2f); + uint256 amountToDistribute = 100 ether; + ERC20(STETH_MAINNET_ADDRESS).transfer(address(lidoSplitWithFee), amountToDistribute); + + uint256 prevBalance = ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(demoSplit); + + uint256 balance = ERC20(STETH_MAINNET_ADDRESS).balanceOf(address(lidoSplitWithFee)); + + uint256 wstETHDistributed = IwSTETH(WSTETH_MAINNET_ADDRESS).getWstETHByStETH(balance); + + uint256 amount = lidoSplitWithFee.distribute(); + + assertTrue(amount > 0, "invalid amount"); + + uint256 afterBalance = ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(demoSplit); + + assertGe(afterBalance, prevBalance, "after balance greater"); + + + uint256 expectedFee = (wstETHDistributed * feeShare) / PERCENTAGE_SCALE; + + assertEq( + ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(feeRecipient), + expectedFee, + "invalid fee transferred" + ); + + assertEq( + ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(demoSplit), + wstETHDistributed - expectedFee, + "invalid amount" + ); + } + + function testFuzz_CanDistributeWithFee( + address feeRecipient, + uint256 feeShare + ) public { + vm.assume(feeShare < PERCENTAGE_SCALE); + vm.assume(feeRecipient != address(0)); + + + + } } From 4d604025bfae8e706e96d67b52844490bf1e3e31 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:21:15 +0200 Subject: [PATCH 05/17] test: add fuzz fee share lidoSplit test case --- src/lido/LidoSplit.sol | 23 ++++---- src/test/lido/LIdoSplitFactory.t.sol | 1 - src/test/lido/LidoSplit.t.sol | 81 +++++++++++++++++----------- 3 files changed, 60 insertions(+), 45 deletions(-) diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index ea7422d..c2a2937 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -16,11 +16,10 @@ interface IwSTETH { /// stETH token to wstETH token because stETH is a rebasing token /// @dev Wraps stETH to wstETH and transfers to defined SplitWallet address contract LidoSplit is Clone { - error Invalid_Address(); error Invalid_FeeShare(uint256 fee); error Invalid_FeeRecipient(); - + /// ----------------------------------------------------------------------- /// libraries /// ----------------------------------------------------------------------- @@ -38,11 +37,10 @@ contract LidoSplit is Clone { // 0; first item uint256 internal constant SPLIT_WALLET_ADDRESS_OFFSET = 0; - /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- - + /// @notice stETH token ERC20 public immutable stETH; @@ -52,7 +50,7 @@ contract LidoSplit is Clone { /// @notice fee address address public immutable feeRecipient; - /// @notice fee share + /// @notice fee share uint256 public immutable feeShare; /// @notice Constructor @@ -60,8 +58,8 @@ contract LidoSplit is Clone { /// @param _feeShare fee share scaled by PERCENTAGE_SCALE /// @param _stETH stETH address /// @param _wstETH wstETH address - constructor(address _feeRecipient, uint256 _feeShare, ERC20 _stETH, ERC20 _wstETH ) { - if(_feeShare >= PERCENTAGE_SCALE) revert Invalid_FeeShare(_feeShare); + constructor(address _feeRecipient, uint256 _feeShare, ERC20 _stETH, ERC20 _wstETH) { + if (_feeShare >= PERCENTAGE_SCALE) revert Invalid_FeeShare(_feeShare); if (_feeShare > 0 && _feeRecipient == address(0)) revert Invalid_FeeRecipient(); feeRecipient = _feeRecipient; @@ -91,15 +89,16 @@ contract LidoSplit is Clone { // contract we would be able to rescue it amount = ERC20(wstETH).balanceOf(address(this)); - if (feeShare > 0 ) { + if (feeShare > 0) { uint256 fee = (amount * feeShare) / PERCENTAGE_SCALE; // transfer to split wallet - ERC20(wstETH).safeTransfer(splitWallet(), amount - fee); + // update amount to reflect fee charged + ERC20(wstETH).safeTransfer(splitWallet(), amount -= fee); // transfer to fee address ERC20(wstETH).safeTransfer(feeRecipient, fee); } else { // transfer to split wallet - ERC20(wstETH).safeTransfer(splitWallet(), amount); + ERC20(wstETH).safeTransfer(splitWallet(), amount); } } @@ -109,8 +108,8 @@ contract LidoSplit is Clone { function rescueFunds(address token) external returns (uint256 balance) { // we check wstETH here so rescueFunds can't be used // to bypass fee - if (token == address(stETH) || token == address(wstETH)) revert Invalid_Address(); - + if (token == address(stETH) || token == address(wstETH)) revert Invalid_Address(); + if (token == ETH_ADDRESS) { balance = address(this).balance; if (balance > 0) splitWallet().safeTransferETH(balance); diff --git a/src/test/lido/LIdoSplitFactory.t.sol b/src/test/lido/LIdoSplitFactory.t.sol index 8172829..98a96f2 100644 --- a/src/test/lido/LIdoSplitFactory.t.sol +++ b/src/test/lido/LIdoSplitFactory.t.sol @@ -41,7 +41,6 @@ contract LidoSplitFactoryTest is LidoSplitTestHelper, Test { lidoSplitFactory.createSplit(demoSplit); - vm.expectEmit(true, true, true, false, address(lidoSplitFactoryWithFee)); emit CreateLidoSplit(address(0x1)); diff --git a/src/test/lido/LidoSplit.t.sol b/src/test/lido/LidoSplit.t.sol index 5603225..bf109b3 100644 --- a/src/test/lido/LidoSplit.t.sol +++ b/src/test/lido/LidoSplit.t.sol @@ -5,14 +5,11 @@ import "forge-std/Test.sol"; import {LidoSplitFactory, LidoSplit, IwSTETH} from "src/lido/LidoSplitFactory.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {LidoSplitTestHelper} from "./LidoSplitTestHelper.sol"; -import { MockERC20 } from "src/test/utils/mocks/MockERC20.sol"; - +import {MockERC20} from "src/test/utils/mocks/MockERC20.sol"; contract LidoSplitTest is LidoSplitTestHelper, Test { - uint256 internal constant PERCENTAGE_SCALE = 1e5; - LidoSplitFactory internal lidoSplitFactory; LidoSplitFactory internal lidoSplitFactoryWithFee; @@ -50,14 +47,12 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { lidoSplit = LidoSplit(lidoSplitFactory.createSplit(demoSplit)); lidoSplitWithFee = LidoSplit(lidoSplitFactoryWithFee.createSplit(demoSplit)); - + mERC20 = new MockERC20("Test Token", "TOK", 18); mERC20.mint(type(uint256).max); } - function test_CannotCreateInvalidFeeRecipient() public { - - } + function test_CannotCreateInvalidFeeRecipient() public {} function test_CloneArgsIsCorrect() public { assertEq(lidoSplit.splitWallet(), demoSplit, "invalid address"); @@ -65,7 +60,7 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { assertEq(address(lidoSplit.wstETH()), WSTETH_MAINNET_ADDRESS, "invalid wstETH address"); assertEq(lidoSplit.feeRecipient(), address(0), "invalid fee recipient"); assertEq(lidoSplit.feeShare(), 0, "invalid fee amount"); - + assertEq(lidoSplitWithFee.splitWallet(), demoSplit, "invalid address"); assertEq(address(lidoSplitWithFee.stETH()), STETH_MAINNET_ADDRESS, "invalid stETH address"); assertEq(address(lidoSplitWithFee.wstETH()), WSTETH_MAINNET_ADDRESS, "invalid wstETH address"); @@ -92,14 +87,10 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { } function testCannot_RescueLidoTokens() public { - vm.expectRevert( - LidoSplit.Invalid_Address.selector - ); + vm.expectRevert(LidoSplit.Invalid_Address.selector); lidoSplit.rescueFunds(address(STETH_MAINNET_ADDRESS)); - vm.expectRevert( - LidoSplit.Invalid_Address.selector - ); + vm.expectRevert(LidoSplit.Invalid_Address.selector); lidoSplit.rescueFunds(address(WSTETH_MAINNET_ADDRESS)); } @@ -141,30 +132,56 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { assertGe(afterBalance, prevBalance, "after balance greater"); - uint256 expectedFee = (wstETHDistributed * feeShare) / PERCENTAGE_SCALE; - - assertEq( - ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(feeRecipient), - expectedFee, - "invalid fee transferred" - ); - assertEq( - ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(demoSplit), - wstETHDistributed - expectedFee, - "invalid amount" - ); + assertEq(ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(feeRecipient), expectedFee, "invalid fee transferred"); + + assertEq(ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(demoSplit), wstETHDistributed - expectedFee, "invalid amount"); } function testFuzz_CanDistributeWithFee( - address feeRecipient, - uint256 feeShare + address anotherSplit, + uint256 amountToDistribute, + address fuzzFeeRecipient, + uint256 fuzzFeeShare ) public { - vm.assume(feeShare < PERCENTAGE_SCALE); - vm.assume(feeRecipient != address(0)); + vm.assume(anotherSplit != address(0)); + vm.assume(fuzzFeeShare > 0 && fuzzFeeShare < PERCENTAGE_SCALE); + vm.assume(fuzzFeeRecipient != address(0)); + vm.assume(amountToDistribute > 1 ether); + vm.assume(amountToDistribute < 10 ether); + + LidoSplitFactory fuzzFactorySplitWithFee = new LidoSplitFactory( + fuzzFeeRecipient, + fuzzFeeShare, + ERC20(STETH_MAINNET_ADDRESS), + ERC20(WSTETH_MAINNET_ADDRESS) + ); + + LidoSplit fuzzSplitWithFee = LidoSplit(fuzzFactorySplitWithFee.createSplit(anotherSplit)); + + vm.prank(0x2bf3937b8BcccE4B65650F122Bb3f1976B937B2f); + + ERC20(STETH_MAINNET_ADDRESS).transfer(address(fuzzSplitWithFee), amountToDistribute); + + uint256 prevBalance = ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(anotherSplit); + + uint256 balance = ERC20(STETH_MAINNET_ADDRESS).balanceOf(address(fuzzSplitWithFee)); + + uint256 wstETHDistributed = IwSTETH(WSTETH_MAINNET_ADDRESS).getWstETHByStETH(balance); + + uint256 amount = fuzzSplitWithFee.distribute(); + + assertTrue(amount > 0, "invalid amount"); + + uint256 afterBalance = ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(anotherSplit); + + assertGe(afterBalance, prevBalance, "after balance greater"); + + uint256 expectedFee = (wstETHDistributed * fuzzFeeShare) / PERCENTAGE_SCALE; - + assertEq(ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(fuzzFeeRecipient), expectedFee, "invalid fee transferred"); + assertEq(ERC20(WSTETH_MAINNET_ADDRESS).balanceOf(anotherSplit), wstETHDistributed - expectedFee, "invalid amount"); } } From 70949880913a71524aa948dc1041933f512b7936 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:24:04 +0200 Subject: [PATCH 06/17] chore: move IwSTETH to a separate file --- src/interfaces/IwsTETH.sol | 7 +++++++ src/lido/LidoSplit.sol | 6 +----- 2 files changed, 8 insertions(+), 5 deletions(-) create mode 100644 src/interfaces/IwsTETH.sol diff --git a/src/interfaces/IwsTETH.sol b/src/interfaces/IwsTETH.sol new file mode 100644 index 0000000..ec087bc --- /dev/null +++ b/src/interfaces/IwsTETH.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +interface IwSTETH { + function wrap(uint256 amount) external returns (uint256); + function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); +} \ No newline at end of file diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index c2a2937..4691198 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -4,11 +4,7 @@ pragma solidity 0.8.19; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; - -interface IwSTETH { - function wrap(uint256 amount) external returns (uint256); - function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); -} +import {IwSTETH} from "../interfaces/IwSTETH.sol"; /// @title LidoSplit /// @author Obol From 4c8e5e225c6bd3061bf964a383617512cf0e5f01 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:31:17 +0200 Subject: [PATCH 07/17] chore: rename IwstETH.sol --- src/interfaces/IwsTETH.sol | 2 +- src/lido/LidoSplit.sol | 4 ++-- src/test/lido/LidoSplit.t.sol | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/interfaces/IwsTETH.sol b/src/interfaces/IwsTETH.sol index ec087bc..7918250 100644 --- a/src/interfaces/IwsTETH.sol +++ b/src/interfaces/IwsTETH.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -interface IwSTETH { +interface IwstETH { function wrap(uint256 amount) external returns (uint256); function getWstETHByStETH(uint256 _stETHAmount) external view returns (uint256); } \ No newline at end of file diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index 4691198..c4f0473 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; -import {IwSTETH} from "../interfaces/IwSTETH.sol"; +import {IwstETH} from "../interfaces/IwstETH.sol"; /// @title LidoSplit /// @author Obol @@ -80,7 +80,7 @@ contract LidoSplit is Clone { stETH.approve(address(wstETH), balance); // wrap into wseth // we ignore the return value - IwSTETH(address(wstETH)).wrap(balance); + IwstETH(address(wstETH)).wrap(balance); // we use balanceOf here in case some wstETH is stuck in the // contract we would be able to rescue it amount = ERC20(wstETH).balanceOf(address(this)); diff --git a/src/test/lido/LidoSplit.t.sol b/src/test/lido/LidoSplit.t.sol index bf109b3..ca9e2bd 100644 --- a/src/test/lido/LidoSplit.t.sol +++ b/src/test/lido/LidoSplit.t.sol @@ -2,7 +2,7 @@ pragma solidity ^0.8.19; import "forge-std/Test.sol"; -import {LidoSplitFactory, LidoSplit, IwSTETH} from "src/lido/LidoSplitFactory.sol"; +import {LidoSplitFactory, LidoSplit, IwstETH} from "src/lido/LidoSplitFactory.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; import {LidoSplitTestHelper} from "./LidoSplitTestHelper.sol"; import {MockERC20} from "src/test/utils/mocks/MockERC20.sol"; @@ -122,7 +122,7 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { uint256 balance = ERC20(STETH_MAINNET_ADDRESS).balanceOf(address(lidoSplitWithFee)); - uint256 wstETHDistributed = IwSTETH(WSTETH_MAINNET_ADDRESS).getWstETHByStETH(balance); + uint256 wstETHDistributed = IwstETH(WSTETH_MAINNET_ADDRESS).getWstETHByStETH(balance); uint256 amount = lidoSplitWithFee.distribute(); @@ -168,7 +168,7 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { uint256 balance = ERC20(STETH_MAINNET_ADDRESS).balanceOf(address(fuzzSplitWithFee)); - uint256 wstETHDistributed = IwSTETH(WSTETH_MAINNET_ADDRESS).getWstETHByStETH(balance); + uint256 wstETHDistributed = IwstETH(WSTETH_MAINNET_ADDRESS).getWstETHByStETH(balance); uint256 amount = fuzzSplitWithFee.distribute(); From 8d2c8dbca92fe2b51c2cdad1a4ff613f6aa8854c Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:35:06 +0200 Subject: [PATCH 08/17] chore: fix IwstETH.sol path --- src/lido/LidoSplit.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index c4f0473..f2c08ea 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; -import {IwstETH} from "../interfaces/IwstETH.sol"; +import {IwstETH} from "src/interfaces/IwstETH.sol"; /// @title LidoSplit /// @author Obol From 37f30023367b3b16e850315c39b948b4ee8c178b Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:48:43 +0200 Subject: [PATCH 09/17] chore: fix IwstETH.sol path --- src/interfaces/{IwsTETH.sol => IwsETH.sol} | 0 src/lido/LidoSplit.sol | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/interfaces/{IwsTETH.sol => IwsETH.sol} (100%) diff --git a/src/interfaces/IwsTETH.sol b/src/interfaces/IwsETH.sol similarity index 100% rename from src/interfaces/IwsTETH.sol rename to src/interfaces/IwsETH.sol diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index f2c08ea..1fb9c77 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; -import {IwstETH} from "src/interfaces/IwstETH.sol"; +import {IwstETH} from "src/interfaces/IwsETH.sol"; /// @title LidoSplit /// @author Obol From f2690f974eac64c21e61ea3128ab5e3e9c71c20e Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:49:19 +0200 Subject: [PATCH 10/17] chore: fix IwstETH.sol path --- src/interfaces/{IwsETH.sol => IwstETH.sol} | 0 src/lido/LidoSplit.sol | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/interfaces/{IwsETH.sol => IwstETH.sol} (100%) diff --git a/src/interfaces/IwsETH.sol b/src/interfaces/IwstETH.sol similarity index 100% rename from src/interfaces/IwsETH.sol rename to src/interfaces/IwstETH.sol diff --git a/src/lido/LidoSplit.sol b/src/lido/LidoSplit.sol index 1fb9c77..f2c08ea 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/LidoSplit.sol @@ -4,7 +4,7 @@ pragma solidity 0.8.19; import {ERC20} from "solmate/tokens/ERC20.sol"; import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; -import {IwstETH} from "src/interfaces/IwsETH.sol"; +import {IwstETH} from "src/interfaces/IwstETH.sol"; /// @title LidoSplit /// @author Obol From fd244a05f964617707b0a40ebb11b523bbd683b8 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 9 Oct 2023 16:57:10 +0200 Subject: [PATCH 11/17] chore: rename lidosplit => obollidosplit --- docs/audit/LidoSplit.md | 6 +-- docs/audit/LidoSplitFactory.md | 8 +-- foundry.toml | 3 +- src/lido/{LidoSplit.sol => ObolLidoSplit.sol} | 4 +- ...itFactory.sol => ObolLidoSplitFactory.sol} | 16 +++--- ...ctory.t.sol => ObolLIdoSplitFactory.t.sol} | 24 ++++----- .../{LidoSplit.t.sol => ObolLidoSplit.t.sol} | 49 +++++++++++++------ ...Helper.sol => ObolLidoSplitTestHelper.sol} | 2 +- .../integration/LidoSplitIntegrationTest.sol | 14 +++--- 9 files changed, 72 insertions(+), 54 deletions(-) rename src/lido/{LidoSplit.sol => ObolLidoSplit.sol} (98%) rename src/lido/{LidoSplitFactory.sol => ObolLidoSplitFactory.sol} (81%) rename src/test/lido/{LIdoSplitFactory.t.sol => ObolLIdoSplitFactory.t.sol} (59%) rename src/test/lido/{LidoSplit.t.sol => ObolLidoSplit.t.sol} (77%) rename src/test/lido/{LidoSplitTestHelper.sol => ObolLidoSplitTestHelper.sol} (91%) diff --git a/docs/audit/LidoSplit.md b/docs/audit/LidoSplit.md index bf0ebe4..97505c1 100644 --- a/docs/audit/LidoSplit.md +++ b/docs/audit/LidoSplit.md @@ -48,7 +48,7 @@ Source Units in Scope: **`1`** (**100%**) | Type | File | Logic Contracts | Interfaces | Lines | nLines | nSLOC | Comment Lines | Complex. Score | Capabilities | | ---- | ------ | --------------- | ---------- | ----- | ------ | ----- | ------------- | -------------- | ------------ | -| ๐Ÿ“๐Ÿ” | src/lido/LidoSplit.sol | 1 | 1 | 72 | 64 | 29 | 31 | 34 | **** | +| ๐Ÿ“๐Ÿ” | src/lido/ObolLidoSplit.sol | 1 | 1 | 72 | 64 | 29 | 31 | 34 | **** | | ๐Ÿ“๐Ÿ” | **Totals** | **1** | **1** | **72** | **64** | **29** | **31** | **34** | **** | @@ -237,7 +237,7 @@ This section lists functions that are explicitly declared public or payable. Ple | File Name | SHA-1 Hash | |-------------|--------------| -| src/lido/LidoSplit.sol | a6d06d355c3e9abd9b6674b54a0b9b9960d3da33 | +| src/lido/ObolLidoSplit.sol | a6d06d355c3e9abd9b6674b54a0b9b9960d3da33 | Contracts Description Table @@ -250,7 +250,7 @@ This section lists functions that are explicitly declared public or payable. Ple | **IwSTETH** | Interface | ||| | โ”” | wrap | External โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | |||||| -| **LidoSplit** | Implementation | Clone ||| +| **ObolLidoSplit** | Implementation | Clone ||| | โ”” | | Public โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | | โ”” | splitWallet | Public โ—๏ธ | |NOโ—๏ธ | | โ”” | stETHAddress | Public โ—๏ธ | |NOโ—๏ธ | diff --git a/docs/audit/LidoSplitFactory.md b/docs/audit/LidoSplitFactory.md index 4749e3a..c518678 100644 --- a/docs/audit/LidoSplitFactory.md +++ b/docs/audit/LidoSplitFactory.md @@ -48,7 +48,7 @@ Source Units in Scope: **`1`** (**100%**) | Type | File | Logic Contracts | Interfaces | Lines | nLines | nSLOC | Comment Lines | Complex. Score | Capabilities | | ---- | ------ | --------------- | ---------- | ----- | ------ | ----- | ------------- | -------------- | ------------ | -| ๐Ÿ“ | src/lido/LidoSplitFactory.sol | 1 | **** | 73 | 73 | 31 | 25 | 24 | **๐ŸŒ€** | +| ๐Ÿ“ | src/lido/ObolLidoSplitFactory.sol | 1 | **** | 73 | 73 | 31 | 25 | 24 | **๐ŸŒ€** | | ๐Ÿ“ | **Totals** | **1** | **** | **73** | **73** | **31** | **25** | **24** | **๐ŸŒ€** | @@ -166,7 +166,7 @@ This section lists functions that are explicitly declared public or payable. Ple | ๐Ÿ“ค Transfers ETH | โšก Low-Level Calls | ๐Ÿ‘ฅ DelegateCall | ๐Ÿงฎ Uses Hash Functions | ๐Ÿ”– ECRecover | ๐ŸŒ€ New/Create/Create2 | | ---------------- | ----------------- | --------------- | ---------------------- | ------------ | --------------------- | -| **** | **** | **** | **** | **** | `yes`
โ†’ `NewContract:LidoSplit` | +| **** | **** | **** | **** | **** | `yes`
โ†’ `NewContract:ObolLidoSplit` | | โ™ป๏ธ TryCatch | ฮฃ Unchecked | | ---------- | ----------- | @@ -236,7 +236,7 @@ This section lists functions that are explicitly declared public or payable. Ple | File Name | SHA-1 Hash | |-------------|--------------| -| src/lido/LidoSplitFactory.sol | fbe7fc44155c90479b3d1c3f46886b2e67f0d5c0 | +| src/lido/ObolLidoSplitFactory.sol | fbe7fc44155c90479b3d1c3f46886b2e67f0d5c0 | Contracts Description Table @@ -246,7 +246,7 @@ This section lists functions that are explicitly declared public or payable. Ple |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | โ”” | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **LidoSplitFactory** | Implementation | ||| +| **ObolLidoSplitFactory** | Implementation | ||| | โ”” | | Public โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | | โ”” | createSplit | External โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | diff --git a/foundry.toml b/foundry.toml index 48cd2d6..47860b3 100644 --- a/foundry.toml +++ b/foundry.toml @@ -9,6 +9,7 @@ remappings = [ 'solady/=lib/solady/src/', ] solc_version = '0.8.19' +gas_reports = ["*"] [rpc_endpoints] @@ -27,4 +28,4 @@ tab_width = 2 wrap_comments = true [fuzz] -runs = 1000 +runs = 10 diff --git a/src/lido/LidoSplit.sol b/src/lido/ObolLidoSplit.sol similarity index 98% rename from src/lido/LidoSplit.sol rename to src/lido/ObolLidoSplit.sol index f2c08ea..c27450b 100644 --- a/src/lido/LidoSplit.sol +++ b/src/lido/ObolLidoSplit.sol @@ -6,12 +6,12 @@ import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol"; import {Clone} from "solady/utils/Clone.sol"; import {IwstETH} from "src/interfaces/IwstETH.sol"; -/// @title LidoSplit +/// @title ObolLidoSplit /// @author Obol /// @notice A wrapper for 0xsplits/split-contracts SplitWallet that transforms /// stETH token to wstETH token because stETH is a rebasing token /// @dev Wraps stETH to wstETH and transfers to defined SplitWallet address -contract LidoSplit is Clone { +contract ObolLidoSplit is Clone { error Invalid_Address(); error Invalid_FeeShare(uint256 fee); error Invalid_FeeRecipient(); diff --git a/src/lido/LidoSplitFactory.sol b/src/lido/ObolLidoSplitFactory.sol similarity index 81% rename from src/lido/LidoSplitFactory.sol rename to src/lido/ObolLidoSplitFactory.sol index e64b3eb..4d0514f 100644 --- a/src/lido/LidoSplitFactory.sol +++ b/src/lido/ObolLidoSplitFactory.sol @@ -3,13 +3,13 @@ pragma solidity 0.8.19; import {LibClone} from "solady/utils/LibClone.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; -import "./LidoSplit.sol"; +import "./ObolLidoSplit.sol"; -/// @title LidoSplitFactory +/// @title ObolLidoSplitFactory /// @author Obol -/// @notice A factory contract for cheaply deploying LidoSplit. +/// @notice A factory contract for cheaply deploying ObolLidoSplit. /// @dev The address returned should be used to as reward address for Lido -contract LidoSplitFactory { +contract ObolLidoSplitFactory { /// ----------------------------------------------------------------------- /// errors /// ----------------------------------------------------------------------- @@ -27,17 +27,17 @@ contract LidoSplitFactory { /// ----------------------------------------------------------------------- /// Emitted after lido split - event CreateLidoSplit(address split); + event CreateObolLidoSplit(address split); /// ----------------------------------------------------------------------- /// storage /// ----------------------------------------------------------------------- /// @dev lido split implementation - LidoSplit public immutable lidoSplitImpl; + ObolLidoSplit public immutable lidoSplitImpl; constructor(address _feeRecipient, uint256 _feeShare, ERC20 _stETH, ERC20 _wstETH) { - lidoSplitImpl = new LidoSplit(_feeRecipient, _feeShare, _stETH, _wstETH); + lidoSplitImpl = new ObolLidoSplit(_feeRecipient, _feeShare, _stETH, _wstETH); } /// Creates a wrapper for splitWallet that transforms stETH token into @@ -49,6 +49,6 @@ contract LidoSplitFactory { lidoSplit = address(lidoSplitImpl).clone(abi.encodePacked(splitWallet)); - emit CreateLidoSplit(lidoSplit); + emit CreateObolLidoSplit(lidoSplit); } } diff --git a/src/test/lido/LIdoSplitFactory.t.sol b/src/test/lido/ObolLIdoSplitFactory.t.sol similarity index 59% rename from src/test/lido/LIdoSplitFactory.t.sol rename to src/test/lido/ObolLIdoSplitFactory.t.sol index 98a96f2..fb86a1c 100644 --- a/src/test/lido/LIdoSplitFactory.t.sol +++ b/src/test/lido/ObolLIdoSplitFactory.t.sol @@ -2,30 +2,30 @@ pragma solidity ^0.8.19; import "forge-std/Test.sol"; -import {LidoSplitFactory} from "src/lido/LidoSplitFactory.sol"; +import {ObolLidoSplitFactory} from "src/lido/ObolLidoSplitFactory.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; -import {LidoSplitTestHelper} from "./LidoSplitTestHelper.sol"; +import {ObolLidoSplitTestHelper} from "./ObolLidoSplitTestHelper.sol"; -contract LidoSplitFactoryTest is LidoSplitTestHelper, Test { - LidoSplitFactory internal lidoSplitFactory; - LidoSplitFactory internal lidoSplitFactoryWithFee; +contract ObolLidoSplitFactoryTest is ObolLidoSplitTestHelper, Test { + ObolLidoSplitFactory internal lidoSplitFactory; + ObolLidoSplitFactory internal lidoSplitFactoryWithFee; address demoSplit; - event CreateLidoSplit(address split); + event CreateObolLidoSplit(address split); function setUp() public { uint256 mainnetBlock = 17_421_005; vm.createSelectFork(getChain("mainnet").rpcUrl, mainnetBlock); - lidoSplitFactory = new LidoSplitFactory( + lidoSplitFactory = new ObolLidoSplitFactory( address(0), 0, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS) ); - lidoSplitFactoryWithFee = new LidoSplitFactory( + lidoSplitFactoryWithFee = new ObolLidoSplitFactory( address(this), 1e3, ERC20(STETH_MAINNET_ADDRESS), @@ -37,21 +37,21 @@ contract LidoSplitFactoryTest is LidoSplitTestHelper, Test { function testCan_CreateSplit() public { vm.expectEmit(true, true, true, false, address(lidoSplitFactory)); - emit CreateLidoSplit(address(0x1)); + emit CreateObolLidoSplit(address(0x1)); lidoSplitFactory.createSplit(demoSplit); vm.expectEmit(true, true, true, false, address(lidoSplitFactoryWithFee)); - emit CreateLidoSplit(address(0x1)); + emit CreateObolLidoSplit(address(0x1)); lidoSplitFactoryWithFee.createSplit(demoSplit); } function testCannot_CreateSplitInvalidAddress() public { - vm.expectRevert(LidoSplitFactory.Invalid_Wallet.selector); + vm.expectRevert(ObolLidoSplitFactory.Invalid_Wallet.selector); lidoSplitFactory.createSplit(address(0)); - vm.expectRevert(LidoSplitFactory.Invalid_Wallet.selector); + vm.expectRevert(ObolLidoSplitFactory.Invalid_Wallet.selector); lidoSplitFactoryWithFee.createSplit(address(0)); } } diff --git a/src/test/lido/LidoSplit.t.sol b/src/test/lido/ObolLidoSplit.t.sol similarity index 77% rename from src/test/lido/LidoSplit.t.sol rename to src/test/lido/ObolLidoSplit.t.sol index ca9e2bd..798a1e3 100644 --- a/src/test/lido/LidoSplit.t.sol +++ b/src/test/lido/ObolLidoSplit.t.sol @@ -2,19 +2,19 @@ pragma solidity ^0.8.19; import "forge-std/Test.sol"; -import {LidoSplitFactory, LidoSplit, IwstETH} from "src/lido/LidoSplitFactory.sol"; +import {ObolLidoSplitFactory, ObolLidoSplit, IwstETH} from "src/lido/ObolLidoSplitFactory.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; -import {LidoSplitTestHelper} from "./LidoSplitTestHelper.sol"; +import {ObolLidoSplitTestHelper} from "./ObolLidoSplitTestHelper.sol"; import {MockERC20} from "src/test/utils/mocks/MockERC20.sol"; -contract LidoSplitTest is LidoSplitTestHelper, Test { +contract ObolLidoSplitTest is ObolLidoSplitTestHelper, Test { uint256 internal constant PERCENTAGE_SCALE = 1e5; - LidoSplitFactory internal lidoSplitFactory; - LidoSplitFactory internal lidoSplitFactoryWithFee; + ObolLidoSplitFactory internal lidoSplitFactory; + ObolLidoSplitFactory internal lidoSplitFactoryWithFee; - LidoSplit internal lidoSplit; - LidoSplit internal lidoSplitWithFee; + ObolLidoSplit internal lidoSplit; + ObolLidoSplit internal lidoSplitWithFee; address demoSplit; address feeRecipient; @@ -29,14 +29,14 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { feeRecipient = makeAddr("feeRecipient"); feeShare = 1e4; - lidoSplitFactory = new LidoSplitFactory( + lidoSplitFactory = new ObolLidoSplitFactory( address(0), 0, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS) ); - lidoSplitFactoryWithFee = new LidoSplitFactory( + lidoSplitFactoryWithFee = new ObolLidoSplitFactory( feeRecipient, feeShare, ERC20(STETH_MAINNET_ADDRESS), @@ -45,14 +45,31 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { demoSplit = makeAddr("demoSplit"); - lidoSplit = LidoSplit(lidoSplitFactory.createSplit(demoSplit)); - lidoSplitWithFee = LidoSplit(lidoSplitFactoryWithFee.createSplit(demoSplit)); + lidoSplit = ObolLidoSplit(lidoSplitFactory.createSplit(demoSplit)); + lidoSplitWithFee = ObolLidoSplit(lidoSplitFactoryWithFee.createSplit(demoSplit)); mERC20 = new MockERC20("Test Token", "TOK", 18); mERC20.mint(type(uint256).max); } - function test_CannotCreateInvalidFeeRecipient() public {} + function test_CannotCreateInvalidFeeRecipient() public { + vm.expectRevert( + ObolLidoSplit.Invalid_FeeRecipient.selector + ); + new ObolLidoSplit(address(0), 10, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS)); + } + + function test_CannotCreateInvalidFeeShare() public { + vm.expectRevert( + abi.encodeWithSelector(ObolLidoSplit.Invalid_FeeShare.selector, PERCENTAGE_SCALE + 1) + ); + new ObolLidoSplit(address(1), PERCENTAGE_SCALE + 1, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS)); + + vm.expectRevert( + abi.encodeWithSelector(ObolLidoSplit.Invalid_FeeShare.selector, PERCENTAGE_SCALE) + ); + new ObolLidoSplit(address(1), PERCENTAGE_SCALE, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS)); + } function test_CloneArgsIsCorrect() public { assertEq(lidoSplit.splitWallet(), demoSplit, "invalid address"); @@ -87,10 +104,10 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { } function testCannot_RescueLidoTokens() public { - vm.expectRevert(LidoSplit.Invalid_Address.selector); + vm.expectRevert(ObolLidoSplit.Invalid_Address.selector); lidoSplit.rescueFunds(address(STETH_MAINNET_ADDRESS)); - vm.expectRevert(LidoSplit.Invalid_Address.selector); + vm.expectRevert(ObolLidoSplit.Invalid_Address.selector); lidoSplit.rescueFunds(address(WSTETH_MAINNET_ADDRESS)); } @@ -151,14 +168,14 @@ contract LidoSplitTest is LidoSplitTestHelper, Test { vm.assume(amountToDistribute > 1 ether); vm.assume(amountToDistribute < 10 ether); - LidoSplitFactory fuzzFactorySplitWithFee = new LidoSplitFactory( + ObolLidoSplitFactory fuzzFactorySplitWithFee = new ObolLidoSplitFactory( fuzzFeeRecipient, fuzzFeeShare, ERC20(STETH_MAINNET_ADDRESS), ERC20(WSTETH_MAINNET_ADDRESS) ); - LidoSplit fuzzSplitWithFee = LidoSplit(fuzzFactorySplitWithFee.createSplit(anotherSplit)); + ObolLidoSplit fuzzSplitWithFee = ObolLidoSplit(fuzzFactorySplitWithFee.createSplit(anotherSplit)); vm.prank(0x2bf3937b8BcccE4B65650F122Bb3f1976B937B2f); diff --git a/src/test/lido/LidoSplitTestHelper.sol b/src/test/lido/ObolLidoSplitTestHelper.sol similarity index 91% rename from src/test/lido/LidoSplitTestHelper.sol rename to src/test/lido/ObolLidoSplitTestHelper.sol index c705688..e75ffeb 100644 --- a/src/test/lido/LidoSplitTestHelper.sol +++ b/src/test/lido/ObolLidoSplitTestHelper.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.19; -contract LidoSplitTestHelper { +contract ObolLidoSplitTestHelper { address internal STETH_MAINNET_ADDRESS = address(0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84); address internal WSTETH_MAINNET_ADDRESS = address(0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0); address internal RANDOM_stETH_ACCOUNT_ADDRESS = address(0x2bf3937b8BcccE4B65650F122Bb3f1976B937B2f); diff --git a/src/test/lido/integration/LidoSplitIntegrationTest.sol b/src/test/lido/integration/LidoSplitIntegrationTest.sol index 45465a1..6c9e7e3 100644 --- a/src/test/lido/integration/LidoSplitIntegrationTest.sol +++ b/src/test/lido/integration/LidoSplitIntegrationTest.sol @@ -2,14 +2,14 @@ pragma solidity ^0.8.19; import "forge-std/Test.sol"; -import {LidoSplitFactory, LidoSplit} from "src/lido/LidoSplitFactory.sol"; +import {ObolLidoSplitFactory, ObolLidoSplit} from "src/lido/ObolLidoSplitFactory.sol"; import {ERC20} from "solmate/tokens/ERC20.sol"; -import {LidoSplitTestHelper} from "../LidoSplitTestHelper.sol"; +import {ObolLidoSplitTestHelper} from "../ObolLidoSplitTestHelper.sol"; import {ISplitMain} from "src/interfaces/ISplitMain.sol"; -contract LidoSplitIntegrationTest is LidoSplitTestHelper, Test { - LidoSplitFactory internal lidoSplitFactory; - LidoSplit internal lidoSplit; +contract ObolLidoSplitIntegrationTest is ObolLidoSplitTestHelper, Test { + ObolLidoSplitFactory internal lidoSplitFactory; + ObolLidoSplit internal lidoSplit; address splitter; @@ -22,7 +22,7 @@ contract LidoSplitIntegrationTest is LidoSplitTestHelper, Test { uint256 mainnetBlock = 17_421_005; vm.createSelectFork(getChain("mainnet").rpcUrl, mainnetBlock); - lidoSplitFactory = new LidoSplitFactory( + lidoSplitFactory = new ObolLidoSplitFactory( address(0), 0, ERC20(STETH_MAINNET_ADDRESS), @@ -39,7 +39,7 @@ contract LidoSplitIntegrationTest is LidoSplitTestHelper, Test { splitter = ISplitMain(SPLIT_MAIN_MAINNET).createSplit(accounts, percentAllocations, 0, address(0)); - lidoSplit = LidoSplit(lidoSplitFactory.createSplit(splitter)); + lidoSplit = ObolLidoSplit(lidoSplitFactory.createSplit(splitter)); } function test_CanDistribute() public { From b1ffd3a051beeeb4423c1bcd9ccf5c33584bfc4b Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:13:02 +0300 Subject: [PATCH 12/17] chore: update obollidosplit audit docs --- docs/audit/{LidoSplit.md => ObolLidoSplit.md} | 25 ++++++++----------- ...plitFactory.md => ObolLidoSplitFactory.md} | 12 ++++----- 2 files changed, 17 insertions(+), 20 deletions(-) rename docs/audit/{LidoSplit.md => ObolLidoSplit.md} (92%) rename docs/audit/{LidoSplitFactory.md => ObolLidoSplitFactory.md} (94%) diff --git a/docs/audit/LidoSplit.md b/docs/audit/ObolLidoSplit.md similarity index 92% rename from docs/audit/LidoSplit.md rename to docs/audit/ObolLidoSplit.md index 97505c1..5eedf98 100644 --- a/docs/audit/LidoSplit.md +++ b/docs/audit/ObolLidoSplit.md @@ -48,8 +48,8 @@ Source Units in Scope: **`1`** (**100%**) | Type | File | Logic Contracts | Interfaces | Lines | nLines | nSLOC | Comment Lines | Complex. Score | Capabilities | | ---- | ------ | --------------- | ---------- | ----- | ------ | ----- | ------------- | -------------- | ------------ | -| ๐Ÿ“๐Ÿ” | src/lido/ObolLidoSplit.sol | 1 | 1 | 72 | 64 | 29 | 31 | 34 | **** | -| ๐Ÿ“๐Ÿ” | **Totals** | **1** | **1** | **72** | **64** | **29** | **31** | **34** | **** | +| ๐Ÿ“ | src/lido/ObolLidoSplit.sol | 1 | **** | 117 | 117 | 53 | 46 | 59 | **** | +| ๐Ÿ“ | **Totals** | **1** | **** | **117** | **117** | **53** | **46** | **59** | **** | Legend: [โž•] @@ -131,14 +131,14 @@ The analysis finished with **`0`** errors and **`0`** duplicate files. #### Inline Documentation -- **Comment-to-Source Ratio:** On average there are`1` code lines per comment (lower=better). +- **Comment-to-Source Ratio:** On average there are`1.15` code lines per comment (lower=better). - **ToDo's:** `0` #### Components | ๐Ÿ“Contracts | ๐Ÿ“šLibraries | ๐Ÿ”Interfaces | ๐ŸŽจAbstract | | ------------- | ----------- | ------------ | ---------- | -| 1 | 0 | 1 | 0 | +| 1 | 0 | 0 | 0 | #### Exposed Functions @@ -146,23 +146,23 @@ This section lists functions that are explicitly declared public or payable. Ple | ๐ŸŒPublic | ๐Ÿ’ฐPayable | | ---------- | --------- | -| 5 | 0 | +| 3 | 0 | | External | Internal | Private | Pure | View | | ---------- | -------- | ------- | ---- | ---- | -| 2 | 3 | 0 | 3 | 0 | +| 2 | 3 | 0 | 1 | 0 | #### StateVariables | Total | ๐ŸŒPublic | | ---------- | --------- | -| 3 | 0 | +| 7 | 4 | #### Capabilities | Solidity Versions observed | ๐Ÿงช Experimental Features | ๐Ÿ’ฐ Can Receive Funds | ๐Ÿ–ฅ Uses Assembly | ๐Ÿ’ฃ Has Destroyable Contracts | | -------------------------- | ------------------------ | -------------------- | ---------------- | ---------------------------- | -| `=0.8.17` | | **** | **** | **** | +| `0.8.19` | | **** | **** | **** | | ๐Ÿ“ค Transfers ETH | โšก Low-Level Calls | ๐Ÿ‘ฅ DelegateCall | ๐Ÿงฎ Uses Hash Functions | ๐Ÿ”– ECRecover | ๐ŸŒ€ New/Create/Create2 | | ---------------- | ----------------- | --------------- | ---------------------- | ------------ | --------------------- | @@ -179,6 +179,7 @@ This section lists functions that are explicitly declared public or payable. Ple | solady/utils/Clone.sol | 1 | | solmate/tokens/ERC20.sol | 1 | | solmate/utils/SafeTransferLib.sol | 1 | +| src/interfaces/IwstETH.sol | 1 | #### Totals @@ -237,7 +238,7 @@ This section lists functions that are explicitly declared public or payable. Ple | File Name | SHA-1 Hash | |-------------|--------------| -| src/lido/ObolLidoSplit.sol | a6d06d355c3e9abd9b6674b54a0b9b9960d3da33 | +| src/lido/ObolLidoSplit.sol | e60ac5c37593dd7b11dc04af62baa7b122e98ed5 | Contracts Description Table @@ -247,15 +248,11 @@ This section lists functions that are explicitly declared public or payable. Ple |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | โ”” | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **IwSTETH** | Interface | ||| -| โ”” | wrap | External โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | -|||||| | **ObolLidoSplit** | Implementation | Clone ||| | โ”” | | Public โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | | โ”” | splitWallet | Public โ—๏ธ | |NOโ—๏ธ | -| โ”” | stETHAddress | Public โ—๏ธ | |NOโ—๏ธ | -| โ”” | wstETHAddress | Public โ—๏ธ | |NOโ—๏ธ | | โ”” | distribute | External โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | +| โ”” | rescueFunds | External โ—๏ธ | ๐Ÿ›‘ |NOโ—๏ธ | Legend diff --git a/docs/audit/LidoSplitFactory.md b/docs/audit/ObolLidoSplitFactory.md similarity index 94% rename from docs/audit/LidoSplitFactory.md rename to docs/audit/ObolLidoSplitFactory.md index c518678..f904fbf 100644 --- a/docs/audit/LidoSplitFactory.md +++ b/docs/audit/ObolLidoSplitFactory.md @@ -48,8 +48,8 @@ Source Units in Scope: **`1`** (**100%**) | Type | File | Logic Contracts | Interfaces | Lines | nLines | nSLOC | Comment Lines | Complex. Score | Capabilities | | ---- | ------ | --------------- | ---------- | ----- | ------ | ----- | ------------- | -------------- | ------------ | -| ๐Ÿ“ | src/lido/ObolLidoSplitFactory.sol | 1 | **** | 73 | 73 | 31 | 25 | 24 | **๐ŸŒ€** | -| ๐Ÿ“ | **Totals** | **1** | **** | **73** | **73** | **31** | **25** | **24** | **๐ŸŒ€** | +| ๐Ÿ“ | src/lido/ObolLidoSplitFactory.sol | 1 | **** | 54 | 54 | 18 | 24 | 22 | **๐ŸŒ€** | +| ๐Ÿ“ | **Totals** | **1** | **** | **54** | **54** | **18** | **24** | **22** | **๐ŸŒ€** | Legend: [โž•] @@ -131,7 +131,7 @@ The analysis finished with **`0`** errors and **`0`** duplicate files. #### Inline Documentation -- **Comment-to-Source Ratio:** On average there are`1.24` code lines per comment (lower=better). +- **Comment-to-Source Ratio:** On average there are`0.75` code lines per comment (lower=better). - **ToDo's:** `0` #### Components @@ -156,13 +156,13 @@ This section lists functions that are explicitly declared public or payable. Ple | Total | ๐ŸŒPublic | | ---------- | --------- | -| 3 | 3 | +| 1 | 1 | #### Capabilities | Solidity Versions observed | ๐Ÿงช Experimental Features | ๐Ÿ’ฐ Can Receive Funds | ๐Ÿ–ฅ Uses Assembly | ๐Ÿ’ฃ Has Destroyable Contracts | | -------------------------- | ------------------------ | -------------------- | ---------------- | ---------------------------- | -| `=0.8.17` | | **** | **** | **** | +| `0.8.19` | | **** | **** | **** | | ๐Ÿ“ค Transfers ETH | โšก Low-Level Calls | ๐Ÿ‘ฅ DelegateCall | ๐Ÿงฎ Uses Hash Functions | ๐Ÿ”– ECRecover | ๐ŸŒ€ New/Create/Create2 | | ---------------- | ----------------- | --------------- | ---------------------- | ------------ | --------------------- | @@ -236,7 +236,7 @@ This section lists functions that are explicitly declared public or payable. Ple | File Name | SHA-1 Hash | |-------------|--------------| -| src/lido/ObolLidoSplitFactory.sol | fbe7fc44155c90479b3d1c3f46886b2e67f0d5c0 | +| src/lido/ObolLidoSplitFactory.sol | 39e631fd6416d7ab96b78b1b26855fda259dff64 | Contracts Description Table From f872529e991b80e338f0869a264cf339bc6dd6f0 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:57:06 +0300 Subject: [PATCH 13/17] chore: change IMSC license --- src/controllers/ImmutableSplitController.sol | 2 +- src/controllers/ImmutableSplitControllerFactory.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/controllers/ImmutableSplitController.sol b/src/controllers/ImmutableSplitController.sol index 543ce37..0c7348a 100644 --- a/src/controllers/ImmutableSplitController.sol +++ b/src/controllers/ImmutableSplitController.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.19; import {ISplitMain} from "../interfaces/ISplitMain.sol"; diff --git a/src/controllers/ImmutableSplitControllerFactory.sol b/src/controllers/ImmutableSplitControllerFactory.sol index 98237af..4999872 100644 --- a/src/controllers/ImmutableSplitControllerFactory.sol +++ b/src/controllers/ImmutableSplitControllerFactory.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity 0.8.19; import {ISplitMain} from "../interfaces/ISplitMain.sol"; From d154d839627e37165792c805da56551a7be81967 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:58:13 +0300 Subject: [PATCH 14/17] chore: change obollido licenses --- src/test/lido/ObolLIdoSplitFactory.t.sol | 2 +- src/test/lido/ObolLidoSplit.t.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/lido/ObolLIdoSplitFactory.t.sol b/src/test/lido/ObolLIdoSplitFactory.t.sol index fb86a1c..fb5d5cc 100644 --- a/src/test/lido/ObolLIdoSplitFactory.t.sol +++ b/src/test/lido/ObolLIdoSplitFactory.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; diff --git a/src/test/lido/ObolLidoSplit.t.sol b/src/test/lido/ObolLidoSplit.t.sol index 798a1e3..4eba66f 100644 --- a/src/test/lido/ObolLidoSplit.t.sol +++ b/src/test/lido/ObolLidoSplit.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; From 0268631909c403183a1c0c361c4b9a277d411df4 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:25:09 +0300 Subject: [PATCH 15/17] chore: add fuzz fee recipient check to testFuzz_CanDistributeWithFee --- src/test/lido/ObolLidoSplit.t.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/lido/ObolLidoSplit.t.sol b/src/test/lido/ObolLidoSplit.t.sol index 4eba66f..c9b98a0 100644 --- a/src/test/lido/ObolLidoSplit.t.sol +++ b/src/test/lido/ObolLidoSplit.t.sol @@ -163,6 +163,7 @@ contract ObolLidoSplitTest is ObolLidoSplitTestHelper, Test { uint256 fuzzFeeShare ) public { vm.assume(anotherSplit != address(0)); + vm.assume(fuzzFeeRecipient != anotherSplit); vm.assume(fuzzFeeShare > 0 && fuzzFeeShare < PERCENTAGE_SCALE); vm.assume(fuzzFeeRecipient != address(0)); vm.assume(amountToDistribute > 1 ether); From d6886ee60346ffdfc584edd18363d0485271404b Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 16 Oct 2023 11:26:21 +0300 Subject: [PATCH 16/17] chore: change fuzz runs to 100 --- foundry.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/foundry.toml b/foundry.toml index 47860b3..03b326f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -28,4 +28,4 @@ tab_width = 2 wrap_comments = true [fuzz] -runs = 10 +runs = 100 From 3c7061ca65601fce014cafaa6258681775761d02 Mon Sep 17 00:00:00 2001 From: samparsky <8148384+samparsky@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:08:30 +0300 Subject: [PATCH 17/17] chore: change test files licenses to gpl --- src/test/controllers/IMSC.t.sol | 2 +- src/test/controllers/IMSCFactory.t.sol | 2 +- src/test/lido/ObolLidoSplitTestHelper.sol | 2 +- src/test/lido/integration/LidoSplitIntegrationTest.sol | 2 +- src/test/owr/OWRTestHelper.t.sol | 2 +- src/test/owr/OptimisticWithdrawalRecipient.t.sol | 2 +- src/test/owr/OptimisticWithdrawalRecipientFactory.t.sol | 2 +- src/test/utils/mocks/MockERC1155.sol | 2 +- src/test/utils/mocks/MockNFT.sol | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/controllers/IMSC.t.sol b/src/test/controllers/IMSC.t.sol index 7d3cc43..b1c9d95 100644 --- a/src/test/controllers/IMSC.t.sol +++ b/src/test/controllers/IMSC.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; diff --git a/src/test/controllers/IMSCFactory.t.sol b/src/test/controllers/IMSCFactory.t.sol index 6a25d45..2079b24 100644 --- a/src/test/controllers/IMSCFactory.t.sol +++ b/src/test/controllers/IMSCFactory.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; diff --git a/src/test/lido/ObolLidoSplitTestHelper.sol b/src/test/lido/ObolLidoSplitTestHelper.sol index e75ffeb..b2c8506 100644 --- a/src/test/lido/ObolLidoSplitTestHelper.sol +++ b/src/test/lido/ObolLidoSplitTestHelper.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; contract ObolLidoSplitTestHelper { diff --git a/src/test/lido/integration/LidoSplitIntegrationTest.sol b/src/test/lido/integration/LidoSplitIntegrationTest.sol index 6c9e7e3..24049a8 100644 --- a/src/test/lido/integration/LidoSplitIntegrationTest.sol +++ b/src/test/lido/integration/LidoSplitIntegrationTest.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; diff --git a/src/test/owr/OWRTestHelper.t.sol b/src/test/owr/OWRTestHelper.t.sol index 1451b2a..925b942 100644 --- a/src/test/owr/OWRTestHelper.t.sol +++ b/src/test/owr/OWRTestHelper.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; contract OWRTestHelper { diff --git a/src/test/owr/OptimisticWithdrawalRecipient.t.sol b/src/test/owr/OptimisticWithdrawalRecipient.t.sol index 8422559..a2ab4e0 100644 --- a/src/test/owr/OptimisticWithdrawalRecipient.t.sol +++ b/src/test/owr/OptimisticWithdrawalRecipient.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; diff --git a/src/test/owr/OptimisticWithdrawalRecipientFactory.t.sol b/src/test/owr/OptimisticWithdrawalRecipientFactory.t.sol index 41f390c..b67b8dd 100644 --- a/src/test/owr/OptimisticWithdrawalRecipientFactory.t.sol +++ b/src/test/owr/OptimisticWithdrawalRecipientFactory.t.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "forge-std/Test.sol"; diff --git a/src/test/utils/mocks/MockERC1155.sol b/src/test/utils/mocks/MockERC1155.sol index 7b9b55c..7176977 100644 --- a/src/test/utils/mocks/MockERC1155.sol +++ b/src/test/utils/mocks/MockERC1155.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC1155} from "solmate/tokens/ERC1155.sol"; diff --git a/src/test/utils/mocks/MockNFT.sol b/src/test/utils/mocks/MockNFT.sol index 4518ac2..53d3c6e 100644 --- a/src/test/utils/mocks/MockNFT.sol +++ b/src/test/utils/mocks/MockNFT.sol @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: MIT +// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.19; import "solmate/tokens/ERC721.sol";