Skip to content

Commit ec7ce83

Browse files
authored
feat: GlobalAuctionRebalanceExtension contract, tests & utils (#153)
* feat: GlobalAuctionRebalanceExtension contract, tests & utils * test: adds cases that increase coverage to 100% * feat: prevent intialization when not ready. * style: update constructor docs.
1 parent c0b860b commit ec7ce83

File tree

4 files changed

+899
-1
lines changed

4 files changed

+899
-1
lines changed
Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
/*
2+
Copyright 2023 Index Coop
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
16+
SPDX-License-Identifier: Apache License, Version 2.0
17+
*/
18+
19+
pragma solidity 0.6.10;
20+
pragma experimental "ABIEncoderV2";
21+
22+
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
23+
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";
24+
25+
import { AddressArrayUtils } from "../lib/AddressArrayUtils.sol";
26+
import { BaseGlobalExtension } from "../lib/BaseGlobalExtension.sol";
27+
import { IAuctionRebalanceModuleV1 } from "../interfaces/IAuctionRebalanceModuleV1.sol";
28+
import { IManagerCore } from "../interfaces/IManagerCore.sol";
29+
import { ISetToken } from "../interfaces/ISetToken.sol";
30+
import { IDelegatedManager } from "../interfaces/IDelegatedManager.sol";
31+
32+
33+
/**
34+
* @title GlobalAuctionRebalanceExtension
35+
* @author Index Coop
36+
*
37+
* @dev Extension contract for interacting with the AuctionRebalanceModuleV1. This contract acts as a pass-through and functions
38+
* are only callable by operator.
39+
*/
40+
contract GlobalAuctionRebalanceExtension is BaseGlobalExtension {
41+
using AddressArrayUtils for address[];
42+
using SafeMath for uint256;
43+
44+
/* ============ Events ============ */
45+
46+
event AuctionRebalanceExtensionInitialized(
47+
address indexed _setToken,
48+
address indexed _delegatedManager
49+
);
50+
51+
52+
/* ============ Structs ============ */
53+
54+
struct AuctionExecutionParams {
55+
uint256 targetUnit; // Target quantity of the component in Set, in precise units (10 ** 18).
56+
string priceAdapterName; // Identifier for the price adapter to be used.
57+
bytes priceAdapterConfigData; // Encoded data for configuring the chosen price adapter.
58+
}
59+
60+
/* ============ State Variables ============ */
61+
62+
IAuctionRebalanceModuleV1 public immutable auctionModule; // AuctionRebalanceModuleV1
63+
64+
65+
/* ============ Constructor ============ */
66+
/*
67+
* Instantiate with ManagerCore address and WrapModuleV2 address.
68+
*
69+
* @param _managerCore Address of ManagerCore contract
70+
* @param _auctionModule Address of AuctionRebalanceModuleV1 contract
71+
*/
72+
constructor(IManagerCore _managerCore, IAuctionRebalanceModuleV1 _auctionModule) public BaseGlobalExtension(_managerCore) {
73+
auctionModule = _auctionModule;
74+
}
75+
76+
/* ============ External Functions ============ */
77+
78+
79+
/**
80+
* @dev ONLY OWNER: Initializes AuctionRebalanceModuleV1 on the SetToken associated with the DelegatedManager.
81+
*
82+
* @param _delegatedManager Instance of the DelegatedManager to initialize the AuctionRebalanceModuleV1 for
83+
*/
84+
function initializeModule(IDelegatedManager _delegatedManager) external onlyOwnerAndValidManager(_delegatedManager) {
85+
require(_delegatedManager.isInitializedExtension(address(this)), "Extension must be initialized");
86+
_initializeModule(_delegatedManager.setToken(), _delegatedManager);
87+
}
88+
89+
/**
90+
* @dev ONLY OWNER: Initializes AuctionRebalanceExtension to the DelegatedManager.
91+
*
92+
* @param _delegatedManager Instance of the DelegatedManager to initialize
93+
*/
94+
function initializeExtension(IDelegatedManager _delegatedManager) external onlyOwnerAndValidManager(_delegatedManager) {
95+
require(_delegatedManager.isPendingExtension(address(this)), "Extension must be pending");
96+
ISetToken setToken = _delegatedManager.setToken();
97+
98+
_initializeExtension(setToken, _delegatedManager);
99+
100+
emit AuctionRebalanceExtensionInitialized(address(setToken), address(_delegatedManager));
101+
}
102+
103+
/**
104+
* @dev ONLY OWNER: Initializes AuctionRebalanceExtension to the DelegatedManager and AuctionRebalanceModuleV1 to the SetToken.
105+
*
106+
* @param _delegatedManager Instance of the DelegatedManager to initialize
107+
*/
108+
function initializeModuleAndExtension(IDelegatedManager _delegatedManager) external onlyOwnerAndValidManager(_delegatedManager){
109+
require(_delegatedManager.isPendingExtension(address(this)), "Extension must be pending");
110+
ISetToken setToken = _delegatedManager.setToken();
111+
112+
_initializeExtension(setToken, _delegatedManager);
113+
_initializeModule(setToken, _delegatedManager);
114+
115+
emit AuctionRebalanceExtensionInitialized(address(setToken), address(_delegatedManager));
116+
}
117+
118+
119+
/**
120+
* @dev ONLY MANAGER: Remove an existing SetToken and DelegatedManager tracked by the AuctionRebalanceExtension
121+
* @dev _removeExtension implements the only manager assertion.
122+
*/
123+
function removeExtension() external override {
124+
IDelegatedManager delegatedManager = IDelegatedManager(msg.sender);
125+
ISetToken setToken = delegatedManager.setToken();
126+
127+
_removeExtension(setToken, delegatedManager);
128+
}
129+
130+
/**
131+
* @dev OPERATOR ONLY: Checks that the old components array matches the current components array and then invokes the
132+
* AuctionRebalanceModuleV1 startRebalance function.
133+
*
134+
* Refer to AuctionRebalanceModuleV1 for function specific restrictions.
135+
*
136+
* @param _quoteAsset ERC20 token used as the quote asset in auctions.
137+
* @param _oldComponents Addresses of existing components in the SetToken.
138+
* @param _newComponents Addresses of new components to be added.
139+
* @param _newComponentsAuctionParams AuctionExecutionParams for new components, indexed corresponding to _newComponents.
140+
* @param _oldComponentsAuctionParams AuctionExecutionParams for existing components, indexed corresponding to
141+
* the current component positions. Set to 0 for components being removed.
142+
* @param _shouldLockSetToken Indicates if the rebalance should lock the SetToken.
143+
* @param _rebalanceDuration Duration of the rebalance in seconds.
144+
* @param _positionMultiplier Position multiplier at the time target units were calculated.
145+
*/
146+
function startRebalance(
147+
ISetToken _setToken,
148+
IERC20 _quoteAsset,
149+
address[] memory _oldComponents,
150+
address[] memory _newComponents,
151+
AuctionExecutionParams[] memory _newComponentsAuctionParams,
152+
AuctionExecutionParams[] memory _oldComponentsAuctionParams,
153+
bool _shouldLockSetToken,
154+
uint256 _rebalanceDuration,
155+
uint256 _positionMultiplier
156+
)
157+
external
158+
onlyOperator(_setToken)
159+
{
160+
address[] memory currentComponents = _setToken.getComponents();
161+
162+
require(currentComponents.length == _oldComponents.length, "Mismatch: old and current components length");
163+
164+
for (uint256 i = 0; i < _oldComponents.length; i++) {
165+
require(currentComponents[i] == _oldComponents[i], "Mismatch: old and current components");
166+
}
167+
168+
bytes memory callData = abi.encodeWithSelector(
169+
IAuctionRebalanceModuleV1.startRebalance.selector,
170+
_setToken,
171+
_quoteAsset,
172+
_newComponents,
173+
_newComponentsAuctionParams,
174+
_oldComponentsAuctionParams,
175+
_shouldLockSetToken,
176+
_rebalanceDuration,
177+
_positionMultiplier
178+
);
179+
180+
_invokeManager(_manager((_setToken)), address(auctionModule), callData);
181+
}
182+
183+
/**
184+
* @dev OPERATOR ONLY: Unlocks SetToken via AuctionRebalanceModuleV1.
185+
* Refer to AuctionRebalanceModuleV1 for function specific restrictions.
186+
*
187+
* @param _setToken Address of the SetToken to unlock.
188+
*/
189+
function unlock(ISetToken _setToken) external onlyOperator(_setToken) {
190+
bytes memory callData = abi.encodeWithSelector(
191+
IAuctionRebalanceModuleV1.unlock.selector,
192+
_setToken
193+
);
194+
195+
_invokeManager(_manager((_setToken)), address(auctionModule), callData);
196+
}
197+
198+
/**
199+
* @dev OPERATOR ONLY: Sets the target raise percentage for all components on AuctionRebalanceModuleV1.
200+
* Refer to AuctionRebalanceModuleV1 for function specific restrictions.
201+
*
202+
* @param _setToken Address of the SetToken to update unit targets of.
203+
* @param _raiseTargetPercentage Amount to raise all component's unit targets by (in precise units)
204+
*/
205+
function setRaiseTargetPercentage(ISetToken _setToken, uint256 _raiseTargetPercentage) external onlyOperator(_setToken) {
206+
bytes memory callData = abi.encodeWithSelector(
207+
IAuctionRebalanceModuleV1.setRaiseTargetPercentage.selector,
208+
_setToken,
209+
_raiseTargetPercentage
210+
);
211+
212+
_invokeManager(_manager((_setToken)), address(auctionModule), callData);
213+
}
214+
215+
/**
216+
* @dev OPERATOR ONLY: Updates the bidding permission status for a list of addresses on AuctionRebalanceModuleV1.
217+
* Refer to AuctionRebalanceModuleV1 for function specific restrictions.
218+
*
219+
* @param _setToken Address of the SetToken to rebalance bidder status of.
220+
* @param _bidders An array of addresses whose bidding permission status is to be toggled.
221+
* @param _statuses An array of booleans indicating the new bidding permission status for each corresponding address in `_bidders`.
222+
*/
223+
function setBidderStatus(
224+
ISetToken _setToken,
225+
address[] memory _bidders,
226+
bool[] memory _statuses
227+
)
228+
external
229+
onlyOperator(_setToken)
230+
{
231+
bytes memory callData = abi.encodeWithSelector(
232+
IAuctionRebalanceModuleV1.setBidderStatus.selector,
233+
_setToken,
234+
_bidders,
235+
_statuses
236+
);
237+
238+
_invokeManager(_manager((_setToken)), address(auctionModule), callData);
239+
}
240+
241+
/**
242+
* @dev OPERATOR ONLY: Sets whether anyone can bid on the AuctionRebalanceModuleV1.
243+
* Refer to AuctionRebalanceModuleV1 for function specific restrictions.
244+
*
245+
* @param _setToken Address of the SetToken to update anyone bid status of.
246+
* @param _status A boolean indicating if anyone can bid.
247+
*/
248+
function setAnyoneBid( ISetToken _setToken, bool _status) external onlyOperator(_setToken) {
249+
bytes memory callData = abi.encodeWithSelector(
250+
IAuctionRebalanceModuleV1.setAnyoneBid.selector,
251+
_setToken,
252+
_status
253+
);
254+
255+
_invokeManager(_manager((_setToken)), address(auctionModule), callData);
256+
}
257+
258+
/* ============ Internal Functions ============ */
259+
260+
/**
261+
* Internal function to initialize AuctionRebalanceModuleV1 on the SetToken associated with the DelegatedManager.
262+
*
263+
* @param _setToken Instance of the SetToken corresponding to the DelegatedManager
264+
* @param _delegatedManager Instance of the DelegatedManager to initialize the AuctionRebalanceModuleV1 for
265+
*/
266+
function _initializeModule(ISetToken _setToken, IDelegatedManager _delegatedManager) internal {
267+
bytes memory callData = abi.encodeWithSelector(IAuctionRebalanceModuleV1.initialize.selector, _setToken);
268+
_invokeManager(_delegatedManager, address(auctionModule), callData);
269+
}
270+
271+
}

0 commit comments

Comments
 (0)