Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
fab902d
Make all revert reason strings < 32bytes
cgewecke Apr 16, 2021
1e74243
Remove _normalizedTargetMethod getter
cgewecke Apr 16, 2021
d43c5ae
Encapsulate _noTokensToSell#canSell logic as internal method
cgewecke Apr 16, 2021
2053ac0
Encapsulate _allTargetsMet#targetUnmet logic in internal method
cgewecke Apr 16, 2021
ef484a6
Validate exchange adapter when setting & store name as bytes32 hash
cgewecke Apr 19, 2021
1b8def4
Consolidate position state and timestamp updates
cgewecke Apr 19, 2021
de523b9
Validate params for external view methods
cgewecke Apr 19, 2021
62795dd
Make all external setter method names use prefix `set`
cgewecke Apr 19, 2021
70ae790
Add RebalanceStarted event
cgewecke Apr 19, 2021
0e19bf8
Add inline comments and normalize line spacing
cgewecke Apr 19, 2021
b637a06
Remove _caller param from onlyAllowedTrader modifier
cgewecke Apr 19, 2021
2a8efd0
Add getDefaultPositionRealUnit getter
cgewecke Apr 19, 2021
fe71725
Revert use bytes32 hash for exchange adapter id in #setExchanges
cgewecke Apr 20, 2021
eb52c56
Encapsulate setter methods param validation logic
cgewecke Apr 20, 2021
233dcb4
Encapsulate data aggregation logic in #startRebalance in own method
cgewecke Apr 20, 2021
d5b6bdb
Prohibit external positions for components in #initialize and #startR…
cgewecke Apr 20, 2021
bd71c56
Use TradeModule var naming for sellAmount, netBuyAmount in trade methods
cgewecke Apr 20, 2021
3f18496
Rename _componentQuantityLimit to _minComponentReceived in #tradeRema…
cgewecke Apr 21, 2021
3f0112d
Refactor #createTradeInfo methods and use TradeModule naming conventi…
cgewecke Apr 21, 2021
e9f704b
Fix external position module tests
cgewecke Apr 21, 2021
c520f00
Revert `isSell`, `minReceiveQuantity` var name changes
cgewecke Apr 21, 2021
c0f1dad
Declare tradeInfo return param in #_createTrade.. #_getDefaultTrade..…
cgewecke Apr 21, 2021
344e6c8
Make weth state variable immutable
cgewecke Apr 21, 2021
90cf09d
Fix typos detected in audit
cgewecke Apr 21, 2021
bb0f3ff
Add PositionMultiplierUpdated event and emit in #raiseAssetTargets
cgewecke Apr 21, 2021
f62d5f2
Optimize external position checks in #startRebalance and #initialize
cgewecke Apr 21, 2021
23ce583
Delegate modifier logic to internal helpers in ModuleBase and General…
cgewecke Apr 22, 2021
181753b
Restrict #_getAggregateComponentsAndUnits state mutability to pure
cgewecke Apr 22, 2021
5fbbf43
Delete trader permissions on module removal / add removeModule tests
cgewecke Apr 22, 2021
c3fe5ab
Add #validatePairsWithArray methods to AddressArrayUtils library
cgewecke Apr 22, 2021
7f02665
Use AddressArrayUtils #validatePairs... methods in GeneralIndexModule
cgewecke Apr 22, 2021
ef185b8
Add false trader status case to #removeModule tests for coverage report
cgewecke Apr 22, 2021
52a4b08
Add approximatelyEquals helper in PreciseUnitMath and use in #_target…
cgewecke Apr 22, 2021
1ff05b5
Fix file newlines & TS error, normalize permissions comments naming
cgewecke Apr 22, 2021
00f49b8
Rename PositionMultiplierUpdated event to AssetTargetsRaised
cgewecke Apr 22, 2021
280417c
Fix validatePairsWithArray bytes method / update lib changelogs
cgewecke Apr 22, 2021
215b6ef
Remove trader from permissionInfo.tradersHistory when they are de-aut…
cgewecke Apr 22, 2021
493c6a6
Inline protocol fee comment in _calculateTradeSizeAndDirection
cgewecke Apr 22, 2021
d1ebe6e
Use #removeStorage instead of #remove in #_updateTradersHistory
cgewecke Apr 22, 2021
770b584
Add getAllowedTraders method and make tradersHistory contain unique e…
cgewecke Apr 22, 2021
7229465
Fix TS error
cgewecke Apr 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 75 additions & 2 deletions contracts/lib/AddressArrayUtils.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ pragma solidity 0.6.10;
* @author Set Protocol
*
* Utility functions to handle Address Arrays
*
* CHANGELOG:
* - 4/21/21: Added validatePairsWithArray methods
*/
library AddressArrayUtils {

Expand Down Expand Up @@ -74,7 +77,7 @@ library AddressArrayUtils {

/**
* @param A The input array to search
* @param a The address to remove
* @param a The address to remove
* @return Returns the array with the object removed.
*/
function remove(address[] memory A, address a)
Expand Down Expand Up @@ -149,4 +152,74 @@ library AddressArrayUtils {
}
return newAddresses;
}
}

/**
* Validate that address and uint array lengths match. Validate address array is not empty
* and contains no duplicate elements.
*
* @param A Array of addresses
* @param B Array of uint
*/
function validatePairsWithArray(address[] memory A, uint[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}

/**
* Validate that address and bool array lengths match. Validate address array is not empty
* and contains no duplicate elements.
*
* @param A Array of addresses
* @param B Array of bool
*/
function validatePairsWithArray(address[] memory A, bool[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}

/**
* Validate that address and string array lengths match. Validate address array is not empty
* and contains no duplicate elements.
*
* @param A Array of addresses
* @param B Array of strings
*/
function validatePairsWithArray(address[] memory A, string[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}

/**
* Validate that address array lengths match, and calling address array are not empty
* and contain no duplicate elements.
*
* @param A Array of addresses
* @param B Array of addresses
*/
function validatePairsWithArray(address[] memory A, address[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}

/**
* Validate that address and bytes array lengths match. Validate address array is not empty
* and contains no duplicate elements.
*
* @param A Array of addresses
* @param B Array of bytes
*/
function validatePairsWithArray(address[] memory A, bytes[] memory B) internal pure {
require(A.length == B.length, "Array length mismatch");
_validateLengthAndUniqueness(A);
}

/**
* Validate address array is not empty and contains no duplicate elements.
*
* @param A Array of addresses
*/
function _validateLengthAndUniqueness(address[] memory A) internal pure {
require(A.length > 0, "Array length must be > 0");
require(!hasDuplicate(A), "Cannot duplicate addresses");
}
}
18 changes: 13 additions & 5 deletions contracts/lib/PreciseUnitMath.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol"
*
* CHANGELOG:
* - 9/21/20: Added safePower function
* - 4/21/21: Added approximatelyEquals function
*/
library PreciseUnitMath {
using SafeMath for uint256;
Expand Down Expand Up @@ -149,16 +150,16 @@ library PreciseUnitMath {
}

/**
* @dev Multiplies value a by value b where rounding is towards the lesser number.
* (positive values are rounded towards zero and negative values are rounded away from 0).
* @dev Multiplies value a by value b where rounding is towards the lesser number.
* (positive values are rounded towards zero and negative values are rounded away from 0).
*/
function conservativePreciseMul(int256 a, int256 b) internal pure returns (int256) {
return divDown(a.mul(b), PRECISE_UNIT_INT);
}

/**
* @dev Divides value a by value b where rounding is towards the lesser number.
* (positive values are rounded towards zero and negative values are rounded away from 0).
* @dev Divides value a by value b where rounding is towards the lesser number.
* (positive values are rounded towards zero and negative values are rounded away from 0).
*/
function conservativePreciseDiv(int256 a, int256 b) internal pure returns (int256) {
return divDown(a.mul(PRECISE_UNIT_INT), b);
Expand Down Expand Up @@ -187,4 +188,11 @@ library PreciseUnitMath {

return result;
}
}

/**
* @dev Returns true if a =~ b within range, false otherwise.
*/
function approximatelyEquals(uint256 a, uint256 b, uint256 range) internal pure returns (bool) {
return a <= b.add(range) && a >= b.sub(range);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: this returns true if vals are equal up to and including +/- range (preserving the logic at _targetUnmet)

}
22 changes: 21 additions & 1 deletion contracts/mocks/AddressArrayUtilsMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,31 @@ contract AddressArrayUtilsMock {
return A.pop(index);
}

function testValidatePairsWithArrayUint(address[] memory A, uint[] memory a) external view {
A.validatePairsWithArray(a);
}

function testValidatePairsWithArrayBool(address[] memory A, bool[] memory a) external view {
A.validatePairsWithArray(a);
}

function testValidatePairsWithArrayString(address[] memory A, string[] memory a) external view {
A.validatePairsWithArray(a);
}

function testValidatePairsWithArrayAddress(address[] memory A, address[] memory a) external view {
A.validatePairsWithArray(a);
}

function testValidatePairsWithArrayBytes(address[] memory A, bytes[] memory a) external view {
A.validatePairsWithArray(a);
}

function setStorageArray(address[] memory A) external {
storageArray = A;
}

function getStorageArray() external view returns(address[] memory) {
return storageArray;
}
}
}
6 changes: 5 additions & 1 deletion contracts/mocks/PreciseUnitMathMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,8 @@ contract PreciseUnitMathMock {
function safePower(uint256 a, uint256 b) external pure returns(uint256) {
return a.safePower(b);
}
}

function approximatelyEquals(uint256 a, uint256 b, uint256 range) external pure returns (bool) {
return a.approximatelyEquals(b, range);
}
}
75 changes: 59 additions & 16 deletions contracts/protocol/lib/ModuleBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ import { SignedSafeMath } from "@openzeppelin/contracts/math/SignedSafeMath.sol"
* @author Set Protocol
*
* Abstract class that houses common Module-related state and functions.
*
* CHANGELOG:
* - 4/21/21: Delegated modifier logic to internal helpers to reduce contract size
*
*/
abstract contract ModuleBase is IModule {
using AddressArrayUtils for address[];
Expand All @@ -57,35 +61,26 @@ abstract contract ModuleBase is IModule {

/* ============ Modifiers ============ */

modifier onlyManagerAndValidSet(ISetToken _setToken) {
require(isSetManager(_setToken, msg.sender), "Must be the SetToken manager");
require(isSetValidAndInitialized(_setToken), "Must be a valid and initialized SetToken");
modifier onlyManagerAndValidSet(ISetToken _setToken) {
_validateOnlyManagerAndValidSet(_setToken);
_;
}

modifier onlySetManager(ISetToken _setToken, address _caller) {
require(isSetManager(_setToken, _caller), "Must be the SetToken manager");
_validateOnlySetManager(_setToken, _caller);
_;
}

modifier onlyValidAndInitializedSet(ISetToken _setToken) {
require(isSetValidAndInitialized(_setToken), "Must be a valid and initialized SetToken");
_validateOnlyValidAndInitializedSet(_setToken);
_;
}

/**
* Throws if the sender is not a SetToken's module or module not enabled
*/
modifier onlyModule(ISetToken _setToken) {
require(
_setToken.moduleStates(msg.sender) == ISetToken.ModuleState.INITIALIZED,
"Only the module can call"
);

require(
controller.isModule(msg.sender),
"Module must be enabled on controller"
);
_validateOnlyModule(_setToken);
_;
}

Expand All @@ -94,8 +89,7 @@ abstract contract ModuleBase is IModule {
* and that the SetToken is valid
*/
modifier onlyValidAndPendingSet(ISetToken _setToken) {
require(controller.isSet(address(_setToken)), "Must be controller-enabled SetToken");
require(isSetPendingInitialization(_setToken), "Must be pending initialization");
_validateOnlyValidAndPendingSet(_setToken);
_;
}

Expand Down Expand Up @@ -191,4 +185,53 @@ abstract contract ModuleBase is IModule {
function getNameHash(string memory _name) internal pure returns(bytes32) {
return keccak256(bytes(_name));
}

/* ============== Modifier Helpers ===============
* Internal functions used to reduce bytecode size
*/

/**
* Caller must SetToken manager and SetToken must be valid and initialized
*/
function _validateOnlyManagerAndValidSet(ISetToken _setToken) internal view {
require(isSetManager(_setToken, msg.sender), "Must be the SetToken manager");
require(isSetValidAndInitialized(_setToken), "Must be a valid and initialized SetToken");
}

/**
* Caller must SetToken manager
*/
function _validateOnlySetManager(ISetToken _setToken, address _caller) internal view {
require(isSetManager(_setToken, _caller), "Must be the SetToken manager");
}

/**
* SetToken must be valid and initialized
*/
function _validateOnlyValidAndInitializedSet(ISetToken _setToken) internal view {
require(isSetValidAndInitialized(_setToken), "Must be a valid and initialized SetToken");
}

/**
* Caller must be initialized module and module must be enabled on the controller
*/
function _validateOnlyModule(ISetToken _setToken) internal view {
require(
_setToken.moduleStates(msg.sender) == ISetToken.ModuleState.INITIALIZED,
"Only the module can call"
);

require(
controller.isModule(msg.sender),
"Module must be enabled on controller"
);
}

/**
* SetToken must be in a pending state and module must be in pending state
*/
function _validateOnlyValidAndPendingSet(ISetToken _setToken) internal view {
require(controller.isSet(address(_setToken)), "Must be controller-enabled SetToken");
require(isSetPendingInitialization(_setToken), "Must be pending initialization");
}
}
Loading