Skip to content

Commit

Permalink
bytecode under limit
Browse files Browse the repository at this point in the history
  • Loading branch information
haythemsellami committed Jun 18, 2024
1 parent 18756aa commit 3282709
Show file tree
Hide file tree
Showing 12 changed files with 485 additions and 94 deletions.
6 changes: 5 additions & 1 deletion src/Dispatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ abstract contract Dispatch is RewardsModule, HooksModule {
address public immutable MODULE_REWARDS;
address public immutable MODULE_HOOKS;
address public immutable MODULE_FEE;
address public immutable MODULE_ALLOCATION_POINTS;

constructor(address _rewardsModule, address _hooksModule, address _feeModule) Shared() {
constructor(address _rewardsModule, address _hooksModule, address _feeModule, address _allocationPointsModule)
Shared()
{
MODULE_REWARDS = _rewardsModule;
MODULE_HOOKS = _hooksModule;
MODULE_FEE = _feeModule;
MODULE_ALLOCATION_POINTS = _allocationPointsModule;
}

// Modifier proxies the function call to a module and low-level returns the result
Expand Down
86 changes: 15 additions & 71 deletions src/FourSixTwoSixAgg.sol
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ contract FourSixTwoSixAgg is ERC4626Upgradeable, AccessControlEnumerableUpgradea
event SetStrategyCap(address indexed strategy, uint256 cap);
event Rebalance(address indexed strategy, uint256 _amountToRebalance, bool _isDeposit);

constructor(address _rewardsModule, address _hooksModule, address _feeModule)
Dispatch(_rewardsModule, _hooksModule, _feeModule)
constructor(address _rewardsModule, address _hooksModule, address _feeModule, address _allocationPointsModule)
Dispatch(_rewardsModule, _hooksModule, _feeModule, _allocationPointsModule)
{}

struct InitParams {
Expand Down Expand Up @@ -195,91 +195,35 @@ contract FourSixTwoSixAgg is ERC4626Upgradeable, AccessControlEnumerableUpgradea
/// @param _newPoints new strategy's points
function adjustAllocationPoints(address _strategy, uint256 _newPoints)
external
nonReentrant
use(MODULE_ALLOCATION_POINTS)
onlyRole(STRATEGY_MANAGER)
{
AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

Strategy memory strategyDataCache = $.strategies[_strategy];

if (!strategyDataCache.active) {
revert ErrorsLib.InactiveStrategy();
}

$.strategies[_strategy].allocationPoints = _newPoints.toUint120();
$.totalAllocationPoints = $.totalAllocationPoints + _newPoints - strategyDataCache.allocationPoints;

emit AdjustAllocationPoints(_strategy, strategyDataCache.allocationPoints, _newPoints);
}
{}

/// @notice Set cap on strategy allocated amount.
/// @dev By default, cap is set to 0, not activated.
/// @param _strategy Strategy address.
/// @param _cap Cap amount
function setStrategyCap(address _strategy, uint256 _cap) external nonReentrant onlyRole(STRATEGY_MANAGER) {
AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

if (!$.strategies[_strategy].active) {
revert ErrorsLib.InactiveStrategy();
}

$.strategies[_strategy].cap = _cap.toUint120();

emit SetStrategyCap(_strategy, _cap);
}
function setStrategyCap(address _strategy, uint256 _cap)
external
use(MODULE_ALLOCATION_POINTS)
onlyRole(STRATEGY_MANAGER)
{}

/// @notice Add new strategy with it's allocation points.
/// @dev Can only be called by an address that have STRATEGY_ADDER.
/// @param _strategy Address of the strategy
/// @param _allocationPoints Strategy's allocation points
function addStrategy(address _strategy, uint256 _allocationPoints) external nonReentrant onlyRole(STRATEGY_ADDER) {
AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

if ($.strategies[_strategy].active) {
revert ErrorsLib.StrategyAlreadyExist();
}

if (IERC4626(_strategy).asset() != asset()) {
revert ErrorsLib.InvalidStrategyAsset();
}

_callHooksTarget(ADD_STRATEGY, _msgSender());

$.strategies[_strategy] =
Strategy({allocated: 0, allocationPoints: _allocationPoints.toUint120(), active: true, cap: 0});

$.totalAllocationPoints += _allocationPoints;
IWithdrawalQueue($.withdrawalQueue).addStrategyToWithdrawalQueue(_strategy);

emit AddStrategy(_strategy, _allocationPoints);
}
function addStrategy(address _strategy, uint256 _allocationPoints)
external
use(MODULE_ALLOCATION_POINTS)
onlyRole(STRATEGY_ADDER)
{}

/// @notice Remove strategy and set its allocation points to zero.
/// @dev This function does not pull funds, `harvest()` needs to be called to withdraw
/// @dev Can only be called by an address that have the STRATEGY_REMOVER
/// @param _strategy Address of the strategy
function removeStrategy(address _strategy) external nonReentrant onlyRole(STRATEGY_REMOVER) {
if (_strategy == address(0)) revert ErrorsLib.CanNotRemoveCashReserve();

AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

Strategy storage strategyStorage = $.strategies[_strategy];

if (!strategyStorage.active) {
revert ErrorsLib.AlreadyRemoved();
}

_callHooksTarget(REMOVE_STRATEGY, _msgSender());

$.totalAllocationPoints -= strategyStorage.allocationPoints;
strategyStorage.active = false;
strategyStorage.allocationPoints = 0;

// remove from withdrawalQueue
IWithdrawalQueue($.withdrawalQueue).removeStrategyFromWithdrawalQueue(_strategy);

emit RemoveStrategy(_strategy);
}
function removeStrategy(address _strategy) external use(MODULE_ALLOCATION_POINTS) onlyRole(STRATEGY_REMOVER) {}

/// @notice update accrued interest
function updateInterestAccrued() external {
Expand Down
41 changes: 23 additions & 18 deletions src/FourSixTwoSixAggFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,35 @@ contract FourSixTwoSixAggFactory {
address public immutable evc;
address public immutable balanceTracker;
/// core modules
address public immutable rewardsImpl;
address public immutable hooksImpl;
address public immutable rewardsModuleImpl;
address public immutable hooksModuleImpl;
address public immutable feeModuleImpl;
address public immutable allocationpointsModuleImpl;
/// peripheries
/// @dev Rebalancer periphery, one instance can serve different aggregation vaults
address public immutable rebalancer;
address public immutable rebalancerAddr;
/// @dev Withdrawal queue perihperhy, need to be deployed per aggregation vault
address public immutable withdrawalQueueImpl;
address public immutable withdrawalQueueAddr;

constructor(
address _evc,
address _balanceTracker,
address _rewardsImpl,
address _hooksImpl,
address _rewardsModuleImpl,
address _hooksModuleImpl,
address _feeModuleImpl,
address _rebalancer,
address _withdrawalQueueImpl
address _allocationpointsModuleImpl,
address _rebalancerAddr,
address _withdrawalQueueAddr
) {
evc = _evc;
balanceTracker = _balanceTracker;
rewardsImpl = _rewardsImpl;
hooksImpl = _hooksImpl;
rewardsModuleImpl = _rewardsModuleImpl;
hooksModuleImpl = _hooksModuleImpl;
feeModuleImpl = _feeModuleImpl;
allocationpointsModuleImpl = _allocationpointsModuleImpl;

rebalancer = _rebalancer;
withdrawalQueueImpl = _withdrawalQueueImpl;
rebalancerAddr = _rebalancerAddr;
withdrawalQueueAddr = _withdrawalQueueAddr;
}

// TODO: decrease bytecode size, use clones or something
Expand All @@ -51,21 +54,23 @@ contract FourSixTwoSixAggFactory {
uint256 _initialCashAllocationPoints
) external returns (address) {
// cloning core modules
address rewardsImplAddr = Clones.clone(rewardsImpl);
address hooks = Clones.clone(hooksImpl);
address feeModule = Clones.clone(feeModuleImpl);
address rewardsModuleAddr = Clones.clone(rewardsModuleImpl);
address hooksModuleAddr = Clones.clone(hooksModuleImpl);
address feeModuleAddr = Clones.clone(feeModuleImpl);
address allocationpointsModuleAddr = Clones.clone(allocationpointsModuleImpl);

// cloning peripheries
WithdrawalQueue withdrawalQueue = WithdrawalQueue(Clones.clone(withdrawalQueueImpl));
WithdrawalQueue withdrawalQueue = WithdrawalQueue(Clones.clone(withdrawalQueueAddr));

// deploy new aggregation vault
FourSixTwoSixAgg fourSixTwoSixAgg = new FourSixTwoSixAgg(rewardsImplAddr, hooks, feeModule);
FourSixTwoSixAgg fourSixTwoSixAgg =
new FourSixTwoSixAgg(rewardsModuleAddr, hooksModuleAddr, feeModuleAddr, allocationpointsModuleAddr);

FourSixTwoSixAgg.InitParams memory aggregationVaultInitParams = FourSixTwoSixAgg.InitParams({
evc: evc,
balanceTracker: balanceTracker,
withdrawalQueuePeriphery: address(withdrawalQueue),
rebalancerPerihpery: rebalancer,
rebalancerPerihpery: rebalancerAddr,
aggregationVaultOwner: msg.sender,
asset: _asset,
name: _name,
Expand Down
96 changes: 96 additions & 0 deletions src/Shared.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.0;

import {StorageLib, AggregationVaultStorage, HooksStorage} from "./lib/StorageLib.sol";
import {ErrorsLib} from "./lib/ErrorsLib.sol";
import {IEVC} from "ethereum-vault-connector/utils/EVCUtil.sol";
import {IHookTarget} from "evk/src/interfaces/IHookTarget.sol";
import {HooksLib} from "./lib/HooksLib.sol";

contract Shared {
using HooksLib for uint32;

uint8 internal constant REENTRANCYLOCK__UNLOCKED = 1;
uint8 internal constant REENTRANCYLOCK__LOCKED = 2;

uint32 public constant DEPOSIT = 1 << 0;
uint32 public constant WITHDRAW = 1 << 1;
uint32 public constant ADD_STRATEGY = 1 << 2;
uint32 public constant REMOVE_STRATEGY = 1 << 3;

uint32 constant ACTIONS_COUNTER = 1 << 4;
uint256 constant HOOKS_MASK = 0x00000000000000000000000000000000000000000000000000000000FFFFFFFF;

event SetHooksConfig(address indexed hooksTarget, uint32 hookedFns);

modifier nonReentrant() {
AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

if ($.locked == REENTRANCYLOCK__LOCKED) revert ErrorsLib.Reentrancy();

$.locked = REENTRANCYLOCK__LOCKED;
_;
$.locked = REENTRANCYLOCK__UNLOCKED;
}

function _msgSender() internal view virtual returns (address) {
address sender = msg.sender;
AggregationVaultStorage storage $ = StorageLib._getAggregationVaultStorage();

if (sender == address($.evc)) {
(sender,) = IEVC($.evc).getCurrentOnBehalfOfAccount(address(0));
}

return sender;
}

function _setHooksConfig(address _hooksTarget, uint32 _hookedFns) internal {
if (_hooksTarget != address(0) && IHookTarget(_hooksTarget).isHookTarget() != IHookTarget.isHookTarget.selector)
{
revert ErrorsLib.NotHooksContract();
}
if (_hookedFns != 0 && _hooksTarget == address(0)) {
revert ErrorsLib.InvalidHooksTarget();
}
if (_hookedFns >= ACTIONS_COUNTER) revert ErrorsLib.InvalidHookedFns();

HooksStorage storage $ = StorageLib._getHooksStorage();
$.hooksConfig = (uint256(uint160(_hooksTarget)) << 32) | uint256(_hookedFns);

emit SetHooksConfig(_hooksTarget, _hookedFns);
}

/// @notice Checks whether a hook has been installed for the function and if so, invokes the hook target.
/// @param _fn Function to call the hook for.
/// @param _caller Caller's address.
function _callHooksTarget(uint32 _fn, address _caller) internal {
HooksStorage storage $ = StorageLib._getHooksStorage();

(address target, uint32 hookedFns) = _getHooksConfig($.hooksConfig);

if (hookedFns.isNotSet(_fn)) return;

(bool success, bytes memory data) = target.call(abi.encodePacked(msg.data, _caller));

if (!success) _revertBytes(data);
}

/// @notice Get the hooks contract and the hooked functions.
/// @return address Hooks contract.
/// @return uint32 Hooked functions.
function _getHooksConfig(uint256 _hooksConfig) internal pure returns (address, uint32) {
return (address(uint160(_hooksConfig >> 32)), uint32(_hooksConfig & HOOKS_MASK));
}

/// @dev Revert with call error or EmptyError
/// @param _errorMsg call revert message
function _revertBytes(bytes memory _errorMsg) private pure {
if (_errorMsg.length > 0) {
assembly {
revert(add(32, _errorMsg), mload(_errorMsg))
}
}

revert ErrorsLib.EmptyError();
}
}
4 changes: 4 additions & 0 deletions src/lib/ErrorsLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,8 @@ library ErrorsLib {
error NotSupported();
error AlreadyEnabled();
error AlreadyDisabled();
error InvalidHooksTarget();
error NotHooksContract();
error InvalidHookedFns();
error EmptyError();
}
Loading

0 comments on commit 3282709

Please sign in to comment.