Skip to content
This repository has been archived by the owner on Apr 1, 2021. It is now read-only.

Commit

Permalink
Removed adapter initialization flow and MutualUpgrade flow. Cosmetic …
Browse files Browse the repository at this point in the history
…… (#19)

Removed adapter initialization flow and MutualUpgrade flow. Cosmetic naming and comment updates. Updated ICManagerV2 -> BaseManager.
  • Loading branch information
bweick authored and asoong committed Feb 27, 2021
1 parent 76cbfe8 commit b22391b
Show file tree
Hide file tree
Showing 15 changed files with 218 additions and 294 deletions.
20 changes: 10 additions & 10 deletions contracts/adapters/FeeSplitAdapter.sol
Expand Up @@ -20,8 +20,8 @@ import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";

import { BaseAdapter } from "../lib/BaseAdapter.sol";
import { IDebtIssuanceModule } from "../interfaces/IDebtIssuanceModule.sol";
import { IICManagerV2 } from "../interfaces/IICManagerV2.sol";
import { IIssuanceModule } from "../interfaces/IIssuanceModule.sol";
import { IBaseManager } from "../interfaces/IBaseManager.sol";
import { ISetToken } from "../interfaces/ISetToken.sol";
import { IStreamingFeeModule } from "../interfaces/IStreamingFeeModule.sol";
import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol";
Expand All @@ -47,24 +47,24 @@ contract FeeSplitAdapter is BaseAdapter, TimeLockUpgrade {

ISetToken public setToken;
IStreamingFeeModule public streamingFeeModule;
IDebtIssuanceModule public debtIssuanceModule;
IIssuanceModule public issuanceModule;

// Percent of fees in precise units (10^16 = 1%) sent to operator, rest to methodologist
uint256 public operatorFeeSplit;

/* ============ Constructor ============ */

constructor(
IICManagerV2 _manager,
IBaseManager _manager,
IStreamingFeeModule _streamingFeeModule,
IDebtIssuanceModule _debtIssuanceModule,
IIssuanceModule _issuanceModule,
uint256 _operatorFeeSplit
)
public
BaseAdapter(_manager)
{
streamingFeeModule = _streamingFeeModule;
debtIssuanceModule = _debtIssuanceModule;
issuanceModule = _issuanceModule;
operatorFeeSplit = _operatorFeeSplit;
setToken = manager.setToken();
}
Expand Down Expand Up @@ -112,24 +112,24 @@ contract FeeSplitAdapter is BaseAdapter, TimeLockUpgrade {
*/
function updateIssueFee(uint256 _newFee) external onlyOperator timeLockUpgrade {
bytes memory callData = abi.encodeWithSignature("updateIssueFee(address,uint256)", manager.setToken(), _newFee);
invokeManager(address(debtIssuanceModule), callData);
invokeManager(address(issuanceModule), callData);
}

/**
* ONLY OPERATOR: Updates redeem fee on IssuanceModule. Only is executed once time lock has passed.
*/
function updateRedeemFee(uint256 _newFee) external onlyOperator timeLockUpgrade {
bytes memory callData = abi.encodeWithSignature("updateRedeemFee(address,uint256)", manager.setToken(), _newFee);
invokeManager(address(debtIssuanceModule), callData);
invokeManager(address(issuanceModule), callData);
}

/**
* ONLY OPERATOR: Updates fee recipient on both streaming fee and debt issuance modules.
* ONLY OPERATOR: Updates fee recipient on both streaming fee and issuance modules.
*/
function updateFeeRecipient(address _newFeeRecipient) external onlyOperator {
bytes memory callData = abi.encodeWithSignature("updateFeeRecipient(address,address)", manager.setToken(), _newFeeRecipient);
invokeManager(address(streamingFeeModule), callData);
invokeManager(address(debtIssuanceModule), callData);
invokeManager(address(issuanceModule), callData);
}

/**
Expand Down
36 changes: 18 additions & 18 deletions contracts/adapters/FlexibleLeverageStrategyAdapter.sol
Expand Up @@ -24,7 +24,7 @@ import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol";

import { BaseAdapter } from "../lib/BaseAdapter.sol";
import { ICErc20 } from "../interfaces/ICErc20.sol";
import { IICManagerV2 } from "../interfaces/IICManagerV2.sol";
import { IBaseManager } from "../interfaces/IBaseManager.sol";
import { IComptroller } from "../interfaces/IComptroller.sol";
import { ICompoundLeverageModule } from "../interfaces/ICompoundLeverageModule.sol";
import { ICompoundPriceOracle } from "../interfaces/ICompoundPriceOracle.sol";
Expand All @@ -36,7 +36,7 @@ import { PreciseUnitMath } from "../lib/PreciseUnitMath.sol";
* @author Set Protocol
*
* Smart contract that enables trustless leverage tokens using the flexible leverage methodology. This adapter is paired with the CompoundLeverageModule from Set
* protocol where module interactions are invoked via the ICManagerV2 contract. Any leveraged token can be constructed as long as the collateral and borrow
* protocol where module interactions are invoked via the IBaseManager contract. Any leveraged token can be constructed as long as the collateral and borrow
* asset is available on Compound. This adapter contract also allows the operator to set an ETH reward to incentivize keepers calling the rebalance function at
* different leverage thresholds.
*/
Expand All @@ -48,29 +48,29 @@ contract FlexibleLeverageStrategyAdapter is BaseAdapter {
/* ============ Enums ============ */

enum ShouldRebalance {
NONE,
REBALANCE,
ITERATE_REBALANCE,
RIPCORD
NONE, // Indicates no rebalance action can be taken
REBALANCE, // Indicates rebalance() function can be successfully called
ITERATE_REBALANCE, // Indicates iterateRebalance() function can be successfully called
RIPCORD // Indicates ripcord() function can be successfully called
}

/* ============ Structs ============ */

struct ActionInfo {
uint256 collateralPrice; // Price of underlying in precise units (10e18)
uint256 borrowPrice; // Price of underlying in precise units (10e18)
uint256 collateralBalance; // Balance of underlying held in Compound in base units (e.g. USDC 10e6)
uint256 borrowBalance; // Balance of underlying borrowed from Compound in base units
uint256 collateralValue; // Valuation in USD adjusted for decimals in precise units (10e18)
uint256 borrowValue; // Valuation in USD adjusted for decimals in precise units (10e18)
uint256 setTotalSupply; // Total supply of SetToken
uint256 collateralPrice; // Price of underlying in precise units (10e18)
uint256 borrowPrice; // Price of underlying in precise units (10e18)
uint256 collateralBalance; // Balance of underlying held in Compound in base units (e.g. USDC 10e6)
uint256 borrowBalance; // Balance of underlying borrowed from Compound in base units
uint256 collateralValue; // Valuation in USD adjusted for decimals in precise units (10e18)
uint256 borrowValue; // Valuation in USD adjusted for decimals in precise units (10e18)
uint256 setTotalSupply; // Total supply of SetToken
}

struct LeverageInfo {
ActionInfo action;
uint256 currentLeverageRatio;
uint256 slippageTolerance;
uint256 twapMaxTradeSize;
uint256 currentLeverageRatio; // Current leverage ratio of Set
uint256 slippageTolerance; // Allowable percent trade slippage in preciseUnits (1% = 10^16)
uint256 twapMaxTradeSize; // Max trade size in collateral units allowed for rebalance action
}

struct ContractSettings {
Expand Down Expand Up @@ -178,14 +178,14 @@ contract FlexibleLeverageStrategyAdapter is BaseAdapter {
/**
* Instantiate addresses, methodology parameters, execution parameters, and incentive parameters.
*
* @param _manager Address of ICManagerV2 contract
* @param _manager Address of IBaseManager contract
* @param _strategy Struct of contract addresses
* @param _methodology Struct containing methodology parameters
* @param _execution Struct containing execution parameters
* @param _incentive Struct containing incentive parameters for ripcord
*/
constructor(
IICManagerV2 _manager,
IBaseManager _manager,
ContractSettings memory _strategy,
MethodologySettings memory _methodology,
ExecutionSettings memory _execution,
Expand Down
24 changes: 24 additions & 0 deletions contracts/interfaces/IAdapter.sol
@@ -0,0 +1,24 @@
/*
Copyright 2021 Set Labs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

pragma solidity 0.6.10;
pragma experimental "ABIEncoderV2";

import { IBaseManager } from "./IBaseManager.sol";

interface IAdapter {
function manager() external view returns (IBaseManager);
}
Expand Up @@ -19,12 +19,12 @@ pragma experimental "ABIEncoderV2";

import { ISetToken } from "./ISetToken.sol";

interface IICManagerV2 {
interface IBaseManager {
function setToken() external returns(ISetToken);

function methodologist() external returns(address);

function operator() external returns(address);

function interactModule(address _module, bytes calldata _encoded) external;
function interactManager(address _module, bytes calldata _encoded) external;
}
Expand Up @@ -25,7 +25,7 @@ import { ISetToken } from "./ISetToken.sol";
*
* Interface for interacting with Debt Issuance module interface.
*/
interface IDebtIssuanceModule {
interface IIssuanceModule {
function updateIssueFee(ISetToken _setToken, uint256 _newIssueFee) external;
function updateRedeemFee(ISetToken _setToken, uint256 _newRedeemFee) external;
function updateFeeRecipient(ISetToken _setToken, address _newRedeemFee) external;
Expand Down
17 changes: 17 additions & 0 deletions contracts/lib/AddressArrayUtils.sol
Expand Up @@ -91,6 +91,23 @@ library AddressArrayUtils {
}
}

/**
* @param A The input array to search
* @param a The address to remove
*/
function removeStorage(address[] storage A, address a)
internal
{
(uint256 index, bool isIn) = indexOf(A, a);
if (!isIn) {
revert("Address not in array.");
} else {
uint256 lastIndex = A.length - 1; // If the array would be empty, the previous line would throw, so no underflow here
if (index != lastIndex) { A[index] = A[lastIndex]; }
A.pop();
}
}

/**
* Removes specified index from array
* @param A The input array to search
Expand Down
10 changes: 5 additions & 5 deletions contracts/lib/BaseAdapter.sol
Expand Up @@ -17,7 +17,7 @@
pragma solidity 0.6.10;

import { AddressArrayUtils } from "../lib/AddressArrayUtils.sol";
import { IICManagerV2 } from "../interfaces/IICManagerV2.sol";
import { IBaseManager } from "../interfaces/IBaseManager.sol";

/**
* @title BaseAdapter
Expand Down Expand Up @@ -52,7 +52,7 @@ abstract contract BaseAdapter {
}

/**
* Throws if caller is a contract
* Throws if caller is a contract, can be used to stop flash loan and sandwich attacks
*/
modifier onlyEOA() {
require(msg.sender == tx.origin, "Caller must be EOA Address");
Expand All @@ -70,7 +70,7 @@ abstract contract BaseAdapter {
/* ============ State Variables ============ */

// Instance of manager contract
IICManagerV2 public manager;
IBaseManager public manager;

// Boolean indicating if anyone can call function
bool public anyoneCallable;
Expand All @@ -80,7 +80,7 @@ abstract contract BaseAdapter {

/* ============ Constructor ============ */

constructor(IICManagerV2 _manager) public { manager = _manager; }
constructor(IBaseManager _manager) public { manager = _manager; }

/* ============ External Functions ============ */

Expand Down Expand Up @@ -133,7 +133,7 @@ abstract contract BaseAdapter {
* @param _encoded Encoded byte data
*/
function invokeManager(address _module, bytes memory _encoded) internal {
manager.interactModule(_module, _encoded);
manager.interactManager(_module, _encoded);
}

/**
Expand Down
Expand Up @@ -17,17 +17,19 @@
pragma solidity 0.6.10;

import { Address } from "@openzeppelin/contracts/utils/Address.sol";
import { ISetToken } from "../interfaces/ISetToken.sol";

import { AddressArrayUtils } from "../lib/AddressArrayUtils.sol";
import { MutualUpgrade } from "../lib/MutualUpgrade.sol";
import { IAdapter } from "../interfaces/IAdapter.sol";
import { ISetToken } from "../interfaces/ISetToken.sol";


/**
* @title ICManagerV2
* @title BaseManager
* @author Set Protocol
*
* Smart contract manager that contains permissions and admin functionality
*/
contract ICManagerV2 is MutualUpgrade {
contract BaseManager {
using Address for address;
using AddressArrayUtils for address[];

Expand Down Expand Up @@ -94,9 +96,6 @@ contract ICManagerV2 is MutualUpgrade {
// Address of methodologist which serves as providing methodology for the index
address public methodologist;

// Indicates whether manager has been initialized
bool public initialized;

/* ============ Constructor ============ */

constructor(
Expand All @@ -113,41 +112,25 @@ contract ICManagerV2 is MutualUpgrade {

/* ============ External Functions ============ */

/**
* OPEERATOR ONLY: Initialize manager by passing in array of valid adapters. Only callable once. All new adapters must be added
* through mutual upgrade.
*
* @param _adapters Array of adapters to add to manager
*/
function initializeAdapters(address[] memory _adapters) external onlyOperator {
require(!initialized, "Manager already initialized");

for (uint256 i = 0; i < _adapters.length; i++) {
require(!isAdapter[_adapters[i]], "Adapter already exists");

isAdapter[_adapters[i]] = true;
}
adapters = _adapters;
initialized = true;
}

/**
* MUTUAL UPGRADE: Update the SetToken manager address. Operator and Methodologist must each call
* this function to execute the update.
*
* @param _newManager New manager address
*/
function setManager(address _newManager) external mutualUpgrade(operator, methodologist) {
function setManager(address _newManager) external onlyOperator {
require(_newManager != address(0), "Zero address not valid");
setToken.setManager(_newManager);
}

/**
* MUTUAL UPGRADE: Add a new adapter that the ICManagerV2 can call.
* MUTUAL UPGRADE: Add a new adapter that the BaseManager can call.
*
* @param _adapter New adapter to add
*/
function addAdapter(address _adapter) external mutualUpgrade(operator, methodologist) {
function addAdapter(address _adapter) external onlyOperator {
require(!isAdapter[_adapter], "Adapter already exists");
require(address(IAdapter(_adapter).manager()) == address(this), "Adapter manager invalid");

adapters.push(_adapter);

Expand All @@ -157,14 +140,14 @@ contract ICManagerV2 is MutualUpgrade {
}

/**
* MUTUAL UPGRADE: Remove an existing adapter tracked by the ICManagerV2.
* MUTUAL UPGRADE: Remove an existing adapter tracked by the BaseManager.
*
* @param _adapter Old adapter to remove
*/
function removeAdapter(address _adapter) external mutualUpgrade(operator, methodologist) {
function removeAdapter(address _adapter) external onlyOperator {
require(isAdapter[_adapter], "Adapter does not exist");

adapters = adapters.remove(_adapter);
adapters.removeStorage(_adapter);

isAdapter[_adapter] = false;

Expand All @@ -177,7 +160,7 @@ contract ICManagerV2 is MutualUpgrade {
* @param _module Module to interact with
* @param _data Byte data of function to call in module
*/
function interactModule(address _module, bytes calldata _data) external onlyAdapter {
function interactManager(address _module, bytes calldata _data) external onlyAdapter {
// Invoke call to module, assume value will always be 0
_module.functionCallWithValue(_data, 0);
}
Expand Down Expand Up @@ -222,6 +205,8 @@ contract ICManagerV2 is MutualUpgrade {
operator = _newOperator;
}

/* ============ External Getters ============ */

function getAdapters() external view returns(address[] memory) {
return adapters;
}
Expand Down

0 comments on commit b22391b

Please sign in to comment.