Skip to content

Commit e557187

Browse files
committed
Move management functions into separate contract to get under code size limit
1 parent 08e498a commit e557187

14 files changed

+287
-182
lines changed

foundry.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ out = "out"
44
libs = ["lib"]
55
solc = "0.8.27"
66
optimizer = true
7-
optimizer_runs = 1000000
7+
optimizer_runs = 2500
88
gas_reports = ["*"]
99
fs_permissions = [{ access = "read-write", path = "./"}]
1010

script/DeployProtocol.s.sol

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {EulerSwapRegistry} from "../src/EulerSwapRegistry.sol";
77
import {EulerSwapPeriphery} from "../src/EulerSwapPeriphery.sol";
88
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
99
import {EulerSwap} from "../src/EulerSwap.sol";
10+
import {EulerSwapManagement} from "../src/EulerSwapManagement.sol";
1011

1112
/// @title Script to deploy EulerSwapFactory & EulerSwapPeriphery.
1213
contract DeployProtocol is ScriptUtil {
@@ -21,15 +22,15 @@ contract DeployProtocol is ScriptUtil {
2122

2223
address evc = vm.parseJsonAddress(json, ".evc");
2324
address poolManager = vm.parseJsonAddress(json, ".poolManager");
24-
address evkFactory = vm.parseJsonAddress(json, ".evkFactory");
2525
address feeOwner = vm.parseJsonAddress(json, ".feeOwner");
2626
address feeRecipientSetter = vm.parseJsonAddress(json, ".feeRecipientSetter");
2727
address validVaultPerspective = vm.parseJsonAddress(json, ".validVaultPerspective");
2828
address curator = vm.parseJsonAddress(json, ".curator");
2929

3030
vm.startBroadcast(deployerAddress);
3131

32-
address eulerSwapImpl = address(new EulerSwap(evc, poolManager));
32+
address eulerSwapManagementImpl = address(new EulerSwapManagement(evc));
33+
address eulerSwapImpl = address(new EulerSwap(evc, poolManager, eulerSwapManagementImpl));
3334
address eulerSwapFactory = address(new EulerSwapFactory(evc, eulerSwapImpl, feeOwner, feeRecipientSetter));
3435
new EulerSwapRegistry(evc, eulerSwapFactory, validVaultPerspective, curator);
3536
new EulerSwapPeriphery();

src/EulerSwap.sol

Lines changed: 23 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -4,175 +4,61 @@ pragma solidity ^0.8.27;
44
import {IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
55

66
import {IEulerSwapCallee} from "./interfaces/IEulerSwapCallee.sol";
7-
import {EVCUtil} from "evc/utils/EVCUtil.sol";
8-
import {IEVC} from "evc/interfaces/IEthereumVaultConnector.sol";
97
import {IEVault} from "evk/EVault/IEVault.sol";
108

119
import {IEulerSwap} from "./interfaces/IEulerSwap.sol";
1210
import {UniswapHook} from "./UniswapHook.sol";
1311
import {CtxLib} from "./libraries/CtxLib.sol";
14-
import {FundsLib} from "./libraries/FundsLib.sol";
15-
import {CurveLib} from "./libraries/CurveLib.sol";
1612
import {QuoteLib} from "./libraries/QuoteLib.sol";
1713
import {SwapLib} from "./libraries/SwapLib.sol";
1814

19-
contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook {
15+
contract EulerSwap is IEulerSwap, UniswapHook {
2016
bytes32 public constant curve = bytes32("EulerSwap v2");
17+
address public immutable managementImpl;
2118

22-
error Unauthorized();
23-
error Locked();
24-
error AlreadyActivated();
25-
error BadStaticParam();
26-
error BadDynamicParam();
2719
error AmountTooBig();
28-
error AssetsOutOfOrderOrEqual();
29-
error InvalidAssets();
30-
31-
/// @notice Addresses configured as managers. Managers can reconfigure the pool parameters.
32-
mapping(address manager => bool installed) public managers;
3320

3421
/// @notice Emitted upon EulerSwap instance creation or reconfiguration.
3522
event EulerSwapConfigured(DynamicParams dParams, InitialState initialState);
3623
/// @notice Emitted upon EulerSwap instance creation or reconfiguration.
3724
event EulerSwapManagerSet(address indexed manager, bool installed);
3825

39-
constructor(address evc_, address poolManager_) EVCUtil(evc_) UniswapHook(evc_, poolManager_) {
40-
CtxLib.State storage s = CtxLib.getState();
41-
42-
s.status = 2; // can only be used via delegatecall proxy
26+
constructor(address evc_, address poolManager_, address managementImpl_) UniswapHook(evc_, poolManager_) {
27+
managementImpl = managementImpl_;
4328
}
4429

45-
modifier nonReentrantView() {
46-
CtxLib.State storage s = CtxLib.getState();
47-
require(s.status != 2, Locked());
48-
49-
_;
50-
}
51-
52-
function installDynamicParams(
53-
CtxLib.State storage s,
54-
DynamicParams memory dParams,
55-
InitialState memory initialState
56-
) internal {
57-
require(dParams.minReserve0 <= dParams.equilibriumReserve0, BadDynamicParam());
58-
require(dParams.minReserve1 <= dParams.equilibriumReserve1, BadDynamicParam());
59-
require(dParams.minReserve0 <= initialState.reserve0, BadDynamicParam());
60-
require(dParams.minReserve1 <= initialState.reserve1, BadDynamicParam());
61-
62-
require(dParams.priceX > 0 && dParams.priceY > 0, BadDynamicParam());
63-
require(dParams.priceX <= 1e24 && dParams.priceY <= 1e24, BadDynamicParam());
64-
require(dParams.concentrationX <= 1e18 && dParams.concentrationY <= 1e18, BadDynamicParam());
65-
66-
require(dParams.fee0 <= 1e18 && dParams.fee1 <= 1e18, BadDynamicParam());
67-
68-
require(dParams.swapHookedOperations <= 7, BadDynamicParam());
69-
require(dParams.swapHookedOperations == 0 || dParams.swapHook != address(0), BadDynamicParam());
70-
71-
require(CurveLib.verify(dParams, initialState.reserve0, initialState.reserve1), SwapLib.CurveViolation());
72-
73-
CtxLib.writeDynamicParamsToStorage(dParams);
74-
s.reserve0 = initialState.reserve0;
75-
s.reserve1 = initialState.reserve1;
76-
77-
emit EulerSwapConfigured(dParams, initialState);
30+
function delegateToManagementImpl() internal {
31+
(bool success, bytes memory result) = managementImpl.delegatecall(msg.data);
32+
if (!success) {
33+
assembly {
34+
revert(add(32, result), mload(result))
35+
}
36+
}
7837
}
7938

8039
/// @inheritdoc IEulerSwap
81-
function activate(DynamicParams calldata dParams, InitialState calldata initialState) external {
82-
CtxLib.State storage s = CtxLib.getState();
83-
StaticParams memory sParams = CtxLib.getStaticParams();
84-
85-
require(s.status == 0, AlreadyActivated());
86-
s.status = 1;
87-
88-
// Static parameters
89-
90-
{
91-
address asset0Addr = IEVault(sParams.supplyVault0).asset();
92-
address asset1Addr = IEVault(sParams.supplyVault1).asset();
93-
94-
require(
95-
sParams.borrowVault0 == address(0) || IEVault(sParams.borrowVault0).asset() == asset0Addr,
96-
InvalidAssets()
97-
);
98-
require(
99-
sParams.borrowVault1 == address(0) || IEVault(sParams.borrowVault1).asset() == asset1Addr,
100-
InvalidAssets()
101-
);
102-
103-
require(asset0Addr != address(0) && asset1Addr != address(0), InvalidAssets());
104-
require(asset0Addr < asset1Addr, AssetsOutOfOrderOrEqual());
105-
}
106-
107-
require(sParams.eulerAccount != sParams.feeRecipient, BadStaticParam()); // set feeRecipient to 0 instead
108-
109-
// Dynamic parameters
110-
111-
if (initialState.reserve0 != 0) {
112-
require(
113-
!CurveLib.verify(dParams, initialState.reserve0 - 1, initialState.reserve1), SwapLib.CurveViolation()
114-
);
115-
}
116-
if (initialState.reserve1 != 0) {
117-
require(
118-
!CurveLib.verify(dParams, initialState.reserve0, initialState.reserve1 - 1), SwapLib.CurveViolation()
119-
);
120-
}
121-
122-
installDynamicParams(s, dParams, initialState);
123-
124-
// Configure external contracts
125-
126-
FundsLib.approveVault(sParams.supplyVault0);
127-
FundsLib.approveVault(sParams.supplyVault1);
128-
129-
if (sParams.borrowVault0 != address(0) && sParams.borrowVault0 != sParams.supplyVault0) {
130-
FundsLib.approveVault(sParams.borrowVault0);
131-
}
132-
if (sParams.borrowVault1 != address(0) && sParams.borrowVault1 != sParams.supplyVault1) {
133-
FundsLib.approveVault(sParams.borrowVault1);
134-
}
135-
136-
if (
137-
!IEVC(evc).isCollateralEnabled(sParams.eulerAccount, sParams.supplyVault0)
138-
&& sParams.borrowVault1 != address(0)
139-
) {
140-
IEVC(evc).enableCollateral(sParams.eulerAccount, sParams.supplyVault0);
141-
}
142-
if (
143-
!IEVC(evc).isCollateralEnabled(sParams.eulerAccount, sParams.supplyVault1)
144-
&& sParams.borrowVault0 != address(0)
145-
) {
146-
IEVC(evc).enableCollateral(sParams.eulerAccount, sParams.supplyVault1);
147-
}
40+
function activate(DynamicParams calldata, InitialState calldata) external {
41+
delegateToManagementImpl();
14842

14943
// Uniswap hook activation
15044

151-
if (address(poolManager) != address(0)) activateHook(sParams);
45+
activateHook(CtxLib.getStaticParams());
15246
}
15347

15448
/// @inheritdoc IEulerSwap
155-
function setManager(address manager, bool installed) external {
156-
StaticParams memory sParams = CtxLib.getStaticParams();
157-
158-
require(_msgSender() == sParams.eulerAccount, Unauthorized());
159-
managers[manager] = installed;
49+
function setManager(address, bool) external {
50+
delegateToManagementImpl();
51+
}
16052

161-
emit EulerSwapManagerSet(manager, installed);
53+
/// @inheritdoc IEulerSwap
54+
function reconfigure(DynamicParams calldata, InitialState calldata) external {
55+
delegateToManagementImpl();
16256
}
16357

16458
/// @inheritdoc IEulerSwap
165-
function reconfigure(DynamicParams calldata dParams, InitialState calldata initialState) external nonReentrant {
59+
function managers(address manager) external view returns (bool installed) {
16660
CtxLib.State storage s = CtxLib.getState();
167-
StaticParams memory sParams = CtxLib.getStaticParams();
168-
DynamicParams memory oldDParams = CtxLib.getDynamicParams();
169-
170-
{
171-
address sender = _msgSender();
172-
require(sender == sParams.eulerAccount || managers[sender] || sender == oldDParams.swapHook, Unauthorized());
173-
}
174-
175-
installDynamicParams(s, dParams, initialState);
61+
return s.managers[manager];
17662
}
17763

17864
/// @inheritdoc IEulerSwap
@@ -204,7 +90,7 @@ contract EulerSwap is IEulerSwap, EVCUtil, UniswapHook {
20490
function isInstalled() external view nonReentrantView returns (bool) {
20591
StaticParams memory sParams = CtxLib.getStaticParams();
20692

207-
return IEVC(evc).isAccountOperatorAuthorized(sParams.eulerAccount, address(this));
93+
return evc.isAccountOperatorAuthorized(sParams.eulerAccount, address(this));
20894
}
20995

21096
/// @inheritdoc IEulerSwap

src/EulerSwapBase.sol

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
pragma solidity ^0.8.27;
3+
4+
import {EVCUtil} from "evc/utils/EVCUtil.sol";
5+
6+
import {CtxLib} from "./libraries/CtxLib.sol";
7+
8+
abstract contract EulerSwapBase is EVCUtil {
9+
error Locked();
10+
11+
constructor(address evc_) EVCUtil(evc_) {
12+
CtxLib.State storage s = CtxLib.getState();
13+
s.status = 2; // can only be used via delegatecall proxy
14+
}
15+
16+
modifier nonReentrant() {
17+
CtxLib.State storage s = CtxLib.getState();
18+
require(s.status == 1, Locked());
19+
s.status = 2;
20+
21+
_;
22+
23+
s.status = 1;
24+
}
25+
26+
modifier nonReentrantView() {
27+
CtxLib.State storage s = CtxLib.getState();
28+
require(s.status != 2, Locked());
29+
30+
_;
31+
}
32+
}

0 commit comments

Comments
 (0)