From a8fbced1abc6df83376efa7789ab6abc3cf5aab9 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Fri, 19 Jan 2024 20:10:16 -0700 Subject: [PATCH 1/5] build: pre and post hooks --- .../HealthCheck/BaseHealthCheck.sol | 0 .../HealthCheck/IBaseHealthCheck.sol | 0 src/Bases/Hooks/BaseHooks.sol | 196 +++++++++++++++++ src/test/BaseHook.t.sol | 197 ++++++++++++++++++ src/test/mocks/MockHealthCheck.sol | 9 +- src/test/mocks/MockHooks.sol | 104 +++++++++ 6 files changed, 499 insertions(+), 7 deletions(-) rename src/{ => Bases}/HealthCheck/BaseHealthCheck.sol (100%) rename src/{ => Bases}/HealthCheck/IBaseHealthCheck.sol (100%) create mode 100644 src/Bases/Hooks/BaseHooks.sol create mode 100644 src/test/BaseHook.t.sol create mode 100644 src/test/mocks/MockHooks.sol diff --git a/src/HealthCheck/BaseHealthCheck.sol b/src/Bases/HealthCheck/BaseHealthCheck.sol similarity index 100% rename from src/HealthCheck/BaseHealthCheck.sol rename to src/Bases/HealthCheck/BaseHealthCheck.sol diff --git a/src/HealthCheck/IBaseHealthCheck.sol b/src/Bases/HealthCheck/IBaseHealthCheck.sol similarity index 100% rename from src/HealthCheck/IBaseHealthCheck.sol rename to src/Bases/HealthCheck/IBaseHealthCheck.sol diff --git a/src/Bases/Hooks/BaseHooks.sol b/src/Bases/Hooks/BaseHooks.sol new file mode 100644 index 0000000..9125b3f --- /dev/null +++ b/src/Bases/Hooks/BaseHooks.sol @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.18; + +import {BaseHealthCheck, ERC20} from "../HealthCheck/BaseHealthCheck.sol"; + +abstract contract DepositHooks { + function _preDepositHook( + uint256 assets, + uint256 shares, + address receiver + ) internal virtual {} + + function _postDepositHook( + uint256 assets, + uint256 shares, + address receiver + ) internal virtual {} +} + +abstract contract WithdrawHooks { + function _preWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) internal virtual {} + + function _postWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) internal virtual {} +} + +abstract contract TransferHooks { + function _preTransferHook( + address from, + address to, + uint256 amount + ) internal virtual {} + + function _postTransferHook( + address from, + address to, + uint256 amount, + bool success + ) internal virtual {} +} + +abstract contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {} + +/** + * @title Base Hooks + * @author Yearn.finance + * @notice This contract can be inherited by any Yearn + * strategy wishing to implement pre or post deposit, withdraw + * or transfer hooks in their strategy. + */ +abstract contract BaseHooks is BaseHealthCheck, Hooks { + constructor( + address _asset, + string memory _name + ) BaseHealthCheck(_asset, _name) {} + + // Deposit + function deposit( + uint256 assets, + address receiver + ) external virtual returns (uint256 shares) { + _preDepositHook(assets, shares, receiver); + shares = abi.decode( + _delegateCall( + abi.encodeCall(TokenizedStrategy.deposit, (assets, receiver)) + ), + (uint256) + ); + _postDepositHook(assets, shares, receiver); + } + + // Mint + function mint( + uint256 shares, + address receiver + ) external virtual returns (uint256 assets) { + _preDepositHook(assets, shares, receiver); + assets = abi.decode( + _delegateCall( + abi.encodeCall(TokenizedStrategy.mint, (shares, receiver)) + ), + (uint256) + ); + _postDepositHook(assets, shares, receiver); + } + + // Withdraw + function withdraw( + uint256 assets, + address receiver, + address owner + ) external virtual returns (uint256 shares) { + return withdraw(assets, receiver, owner, 0); + } + + function withdraw( + uint256 assets, + address receiver, + address owner, + uint256 maxLoss + ) public virtual returns (uint256 shares) { + _preWithdrawHook(assets, shares, receiver, owner, maxLoss); + shares = abi.decode( + _delegateCall( + // Have to use encodeWithSignature due to overloading parameters. + abi.encodeWithSignature( + "withdraw(uint256,address,address,uint256)", + assets, + receiver, + owner, + maxLoss + ) + ), + (uint256) + ); + _postWithdrawHook(assets, shares, receiver, owner, maxLoss); + } + + // Redeem + function redeem( + uint256 shares, + address receiver, + address owner + ) external virtual returns (uint256) { + // We default to not limiting a potential loss. + return redeem(shares, receiver, owner, MAX_BPS); + } + + function redeem( + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) public returns (uint256 assets) { + _preWithdrawHook(assets, shares, receiver, owner, maxLoss); + assets = abi.decode( + _delegateCall( + // Have to use encodeWithSignature due to overloading parameters. + abi.encodeWithSignature( + "redeem(uint256,address,address,uint256)", + shares, + receiver, + owner, + maxLoss + ) + ), + (uint256) + ); + _postWithdrawHook(assets, shares, receiver, owner, maxLoss); + } + + // Transfer + function transferFrom( + address from, + address to, + uint256 amount + ) public virtual returns (bool success) { + _preTransferHook(from, to, amount); + success = abi.decode( + _delegateCall( + abi.encodeCall( + TokenizedStrategy.transferFrom, + (from, to, amount) + ) + ), + (bool) + ); + _postTransferHook(from, to, amount, success); + } + + // Transfer from + function transfer( + address to, + uint256 amount + ) external virtual returns (bool success) { + _preTransferHook(msg.sender, to, amount); + success = abi.decode( + _delegateCall( + abi.encodeCall(TokenizedStrategy.transfer, (to, amount)) + ), + (bool) + ); + _postTransferHook(msg.sender, to, amount, success); + } +} diff --git a/src/test/BaseHook.t.sol b/src/test/BaseHook.t.sol new file mode 100644 index 0000000..3e6823b --- /dev/null +++ b/src/test/BaseHook.t.sol @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.18; + +import {Setup, IStrategy} from "./utils/Setup.sol"; + +import {MockHooks, HookEvents} from "./mocks/MockHooks.sol"; + +contract BaseHookTest is Setup, HookEvents { + function setUp() public override { + super.setUp(); + + mockStrategy = IStrategy(address(new MockHooks(address(asset)))); + + mockStrategy.setKeeper(keeper); + mockStrategy.setPerformanceFeeRecipient(performanceFeeRecipient); + mockStrategy.setPendingManagement(management); + // Accept management. + vm.prank(management); + mockStrategy.acceptManagement(); + } + + function test_depositHooks(uint256 _amount) public { + vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + + airdrop(asset, user, _amount); + + vm.prank(user); + asset.approve(address(mockStrategy), _amount); + + // Make sure we get both events with the correct amounts. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre deposit wont have a shares amount yet + emit PreDepositHook(_amount, 0, user); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostDepositHook(_amount, _amount, user); + + vm.prank(user); + mockStrategy.deposit(_amount, user); + + assertEq(mockStrategy.balanceOf(user), _amount); + } + + function test_mintHooks(uint256 _amount) public { + vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + + airdrop(asset, user, _amount); + + vm.prank(user); + asset.approve(address(mockStrategy), _amount); + + // Make sure we get both events with the correct amounts. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre mint wont have a assets amount yet + emit PreDepositHook(0, _amount, user); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostDepositHook(_amount, _amount, user); + + vm.prank(user); + mockStrategy.mint(_amount, user); + + assertEq(mockStrategy.balanceOf(user), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + } + + function test_withdrawHooks(uint256 _amount) public { + vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + + mintAndDepositIntoStrategy(mockStrategy, user, _amount); + assertEq(mockStrategy.balanceOf(user), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + + // Make sure we get both events with the correct amounts. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre withdraw wont have a shares amount yet + emit PreWithdrawHook(_amount, 0, user, user, 0); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostWithdrawHook(_amount, _amount, user, user, 0); + + vm.prank(user); + mockStrategy.withdraw(_amount, user, user); + + checkStrategyTotals(mockStrategy, 0, 0, 0); + + // Deposit back in + mintAndDepositIntoStrategy(mockStrategy, user, _amount); + assertEq(mockStrategy.balanceOf(user), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + + // Make sure works on both withdraw versions. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre withdraw wont have a shares amount yet + emit PreWithdrawHook(_amount, 0, user, user, 8); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostWithdrawHook(_amount, _amount, user, user, 8); + + vm.prank(user); + mockStrategy.withdraw(_amount, user, user, 8); + + checkStrategyTotals(mockStrategy, 0, 0, 0); + } + + function test_redeemHooks(uint256 _amount) public { + vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + + mintAndDepositIntoStrategy(mockStrategy, user, _amount); + assertEq(mockStrategy.balanceOf(user), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + + // Make sure we get both events with the correct amounts. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre withdraw wont have a shares amount yet + emit PreWithdrawHook(0, _amount, user, user, MAX_BPS); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostWithdrawHook(_amount, _amount, user, user, MAX_BPS); + + vm.prank(user); + mockStrategy.redeem(_amount, user, user); + checkStrategyTotals(mockStrategy, 0, 0, 0); + + // Deposit back in + mintAndDepositIntoStrategy(mockStrategy, user, _amount); + assertEq(mockStrategy.balanceOf(user), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + + // Make sure works on both withdraw versions. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre withdraw wont have a shares amount yet + emit PreWithdrawHook(0, _amount, user, user, 8); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostWithdrawHook(_amount, _amount, user, user, 8); + + vm.prank(user); + mockStrategy.redeem(_amount, user, user, 8); + + checkStrategyTotals(mockStrategy, 0, 0, 0); + } + + function test_transferHooks(uint256 _amount) public { + vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + + mintAndDepositIntoStrategy(mockStrategy, user, _amount); + + assertEq(mockStrategy.balanceOf(user), _amount); + assertEq(mockStrategy.balanceOf(management), 0); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + + // Make sure we get both events with the correct amounts. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre withdraw wont have a shares amount yet + emit PreTransferHook(user, management, _amount); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostTransferHook(user, management, _amount, true); + + vm.prank(user); + mockStrategy.transfer(management, _amount); + + assertEq(mockStrategy.balanceOf(user), 0); + assertEq(mockStrategy.balanceOf(management), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + } + + function test_transferFromHooks(uint256 _amount) public { + vm.assume(_amount >= minFuzzAmount && _amount <= maxFuzzAmount); + + mintAndDepositIntoStrategy(mockStrategy, user, _amount); + + assertEq(mockStrategy.balanceOf(user), _amount); + assertEq(mockStrategy.balanceOf(management), 0); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + + // Approve daddy to move funds + vm.prank(user); + mockStrategy.approve(daddy, _amount); + + // Make sure we get both events with the correct amounts. + vm.expectEmit(true, true, true, true, address(mockStrategy)); + // Pre withdraw wont have a shares amount yet + emit PreTransferHook(user, management, _amount); + + vm.expectEmit(true, true, true, true, address(mockStrategy)); + emit PostTransferHook(user, management, _amount, true); + + vm.prank(daddy); + mockStrategy.transferFrom(user, management, _amount); + + assertEq(mockStrategy.balanceOf(user), 0); + assertEq(mockStrategy.balanceOf(management), _amount); + checkStrategyTotals(mockStrategy, _amount, 0, _amount); + } +} diff --git a/src/test/mocks/MockHealthCheck.sol b/src/test/mocks/MockHealthCheck.sol index 5f4345a..61a07eb 100644 --- a/src/test/mocks/MockHealthCheck.sol +++ b/src/test/mocks/MockHealthCheck.sol @@ -1,22 +1,17 @@ // SPDX-License-Identifier: GPL-3.0 pragma solidity 0.8.18; -import {BaseHealthCheck, ERC20} from "../../HealthCheck/BaseHealthCheck.sol"; +import {BaseHealthCheck, ERC20} from "../../Bases/HealthCheck/BaseHealthCheck.sol"; contract MockHealthCheck is BaseHealthCheck { bool public healthy = true; constructor(address _asset) BaseHealthCheck(_asset, "Mock Health Check") {} - // `healthy` is already implemented in deposit limit so - // doesn't need to be checked again. function _deployFunds(uint256) internal override {} - // `healthy` is already implemented in withdraw limit so - // doesn't need to be checked again. function _freeFunds(uint256) internal override {} - // Uses `checkHealth` modifier function _harvestAndReport() internal override @@ -26,6 +21,6 @@ contract MockHealthCheck is BaseHealthCheck { } } -import {IBaseHealthCheck} from "../../HealthCheck/IBaseHealthCheck.sol"; +import {IBaseHealthCheck} from "../../Bases/HealthCheck/IBaseHealthCheck.sol"; interface IMockHealthCheck is IBaseHealthCheck {} diff --git a/src/test/mocks/MockHooks.sol b/src/test/mocks/MockHooks.sol new file mode 100644 index 0000000..82adff0 --- /dev/null +++ b/src/test/mocks/MockHooks.sol @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.18; + +import {BaseHooks, ERC20} from "../../Bases/Hooks/BaseHooks.sol"; + +contract HookEvents { + event PreDepositHook(uint256 assets, uint256 shares, address receiver); + + event PostDepositHook(uint256 assets, uint256 shares, address receiver); + + event PreWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ); + + event PostWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ); + + event PreTransferHook(address from, address to, uint256 amount); + + event PostTransferHook( + address from, + address to, + uint256 amount, + bool success + ); +} + +contract MockHooks is BaseHooks, HookEvents { + constructor(address _asset) BaseHooks(_asset, "Hooked") {} + + function _preDepositHook( + uint256 assets, + uint256 shares, + address receiver + ) internal override { + emit PreDepositHook(assets, shares, receiver); + } + + function _postDepositHook( + uint256 assets, + uint256 shares, + address receiver + ) internal override { + emit PostDepositHook(assets, shares, receiver); + } + + function _preWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) internal override { + emit PreWithdrawHook(assets, shares, receiver, owner, maxLoss); + } + + function _postWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) internal override { + emit PostWithdrawHook(assets, shares, receiver, owner, maxLoss); + } + + function _preTransferHook( + address from, + address to, + uint256 amount + ) internal override { + emit PreTransferHook(from, to, amount); + } + + function _postTransferHook( + address from, + address to, + uint256 amount, + bool success + ) internal override { + emit PostTransferHook(from, to, amount, success); + } + + function _deployFunds(uint256) internal override {} + + function _freeFunds(uint256) internal override {} + + function _harvestAndReport() + internal + override + returns (uint256 _totalAssets) + { + _totalAssets = asset.balanceOf(address(this)); + } +} From e720457282fe345193a1684f0704577f381add18 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Mon, 5 Feb 2024 19:28:26 -0700 Subject: [PATCH 2/5] fix: hooks --- src/Bases/Hooks/BaseHooks.sol | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bases/Hooks/BaseHooks.sol b/src/Bases/Hooks/BaseHooks.sol index 9125b3f..c6e0864 100644 --- a/src/Bases/Hooks/BaseHooks.sol +++ b/src/Bases/Hooks/BaseHooks.sol @@ -3,7 +3,7 @@ pragma solidity 0.8.18; import {BaseHealthCheck, ERC20} from "../HealthCheck/BaseHealthCheck.sol"; -abstract contract DepositHooks { +contract DepositHooks { function _preDepositHook( uint256 assets, uint256 shares, @@ -17,7 +17,7 @@ abstract contract DepositHooks { ) internal virtual {} } -abstract contract WithdrawHooks { +contract WithdrawHooks { function _preWithdrawHook( uint256 assets, uint256 shares, @@ -35,7 +35,7 @@ abstract contract WithdrawHooks { ) internal virtual {} } -abstract contract TransferHooks { +contract TransferHooks { function _preTransferHook( address from, address to, @@ -50,7 +50,7 @@ abstract contract TransferHooks { ) internal virtual {} } -abstract contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {} +contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {} /** * @title Base Hooks From e215c455cc317e6fa1c84da7284af5e574f7ac5b Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Tue, 6 Feb 2024 11:49:10 -0700 Subject: [PATCH 3/5] fix: safe approve --- src/test/BaseHook.t.sol | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/test/BaseHook.t.sol b/src/test/BaseHook.t.sol index 3e6823b..725b9f1 100644 --- a/src/test/BaseHook.t.sol +++ b/src/test/BaseHook.t.sol @@ -1,11 +1,14 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.18; -import {Setup, IStrategy} from "./utils/Setup.sol"; +import {Setup, IStrategy, SafeERC20, ERC20} from "./utils/Setup.sol"; import {MockHooks, HookEvents} from "./mocks/MockHooks.sol"; contract BaseHookTest is Setup, HookEvents { + using SafeERC20 for ERC20; + using SafeERC20 for IStrategy; + function setUp() public override { super.setUp(); @@ -24,8 +27,9 @@ contract BaseHookTest is Setup, HookEvents { airdrop(asset, user, _amount); - vm.prank(user); - asset.approve(address(mockStrategy), _amount); + vm.startPrank(user); + asset.safeApprove(address(mockStrategy), _amount); + vm.stopPrank(); // Make sure we get both events with the correct amounts. vm.expectEmit(true, true, true, true, address(mockStrategy)); @@ -46,8 +50,9 @@ contract BaseHookTest is Setup, HookEvents { airdrop(asset, user, _amount); - vm.prank(user); - asset.approve(address(mockStrategy), _amount); + vm.startPrank(user); + asset.safeApprove(address(mockStrategy), _amount); + vm.stopPrank(); // Make sure we get both events with the correct amounts. vm.expectEmit(true, true, true, true, address(mockStrategy)); @@ -176,8 +181,9 @@ contract BaseHookTest is Setup, HookEvents { checkStrategyTotals(mockStrategy, _amount, 0, _amount); // Approve daddy to move funds - vm.prank(user); - mockStrategy.approve(daddy, _amount); + vm.startPrank(user); + mockStrategy.safeApprove(daddy, _amount); + vm.stopPrank(); // Make sure we get both events with the correct amounts. vm.expectEmit(true, true, true, true, address(mockStrategy)); From 0b6cbc76ea5fbddd838b51516c8480054f07d1a3 Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Tue, 6 Feb 2024 15:14:00 -0700 Subject: [PATCH 4/5] chore: organize --- src/Bases/Hooks/BaseHooks.sol | 50 +--------------------------------- src/Bases/Hooks/Hooks.sol | 51 +++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 49 deletions(-) create mode 100644 src/Bases/Hooks/Hooks.sol diff --git a/src/Bases/Hooks/BaseHooks.sol b/src/Bases/Hooks/BaseHooks.sol index c6e0864..6c90ab1 100644 --- a/src/Bases/Hooks/BaseHooks.sol +++ b/src/Bases/Hooks/BaseHooks.sol @@ -1,57 +1,9 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.18; +import {Hooks} from "./Hooks.sol"; import {BaseHealthCheck, ERC20} from "../HealthCheck/BaseHealthCheck.sol"; -contract DepositHooks { - function _preDepositHook( - uint256 assets, - uint256 shares, - address receiver - ) internal virtual {} - - function _postDepositHook( - uint256 assets, - uint256 shares, - address receiver - ) internal virtual {} -} - -contract WithdrawHooks { - function _preWithdrawHook( - uint256 assets, - uint256 shares, - address receiver, - address owner, - uint256 maxLoss - ) internal virtual {} - - function _postWithdrawHook( - uint256 assets, - uint256 shares, - address receiver, - address owner, - uint256 maxLoss - ) internal virtual {} -} - -contract TransferHooks { - function _preTransferHook( - address from, - address to, - uint256 amount - ) internal virtual {} - - function _postTransferHook( - address from, - address to, - uint256 amount, - bool success - ) internal virtual {} -} - -contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {} - /** * @title Base Hooks * @author Yearn.finance diff --git a/src/Bases/Hooks/Hooks.sol b/src/Bases/Hooks/Hooks.sol new file mode 100644 index 0000000..dd070fb --- /dev/null +++ b/src/Bases/Hooks/Hooks.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: AGPL-3.0 +pragma solidity 0.8.18; + +contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {} + +contract DepositHooks { + function _preDepositHook( + uint256 assets, + uint256 shares, + address receiver + ) internal virtual {} + + function _postDepositHook( + uint256 assets, + uint256 shares, + address receiver + ) internal virtual {} +} + +contract WithdrawHooks { + function _preWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) internal virtual {} + + function _postWithdrawHook( + uint256 assets, + uint256 shares, + address receiver, + address owner, + uint256 maxLoss + ) internal virtual {} +} + +contract TransferHooks { + function _preTransferHook( + address from, + address to, + uint256 amount + ) internal virtual {} + + function _postTransferHook( + address from, + address to, + uint256 amount, + bool success + ) internal virtual {} +} From 30330d1574c155d36f6c86e1f5a290051b3705ba Mon Sep 17 00:00:00 2001 From: Schlagonia Date: Tue, 6 Feb 2024 15:19:10 -0700 Subject: [PATCH 5/5] fix: order --- src/Bases/Hooks/Hooks.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Bases/Hooks/Hooks.sol b/src/Bases/Hooks/Hooks.sol index dd070fb..9425df6 100644 --- a/src/Bases/Hooks/Hooks.sol +++ b/src/Bases/Hooks/Hooks.sol @@ -1,8 +1,6 @@ // SPDX-License-Identifier: AGPL-3.0 pragma solidity 0.8.18; -contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {} - contract DepositHooks { function _preDepositHook( uint256 assets, @@ -49,3 +47,5 @@ contract TransferHooks { bool success ) internal virtual {} } + +contract Hooks is DepositHooks, WithdrawHooks, TransferHooks {}