Skip to content
This repository has been archived by the owner on Jan 18, 2023. It is now read-only.

Commit

Permalink
First pass at refactoring propose function into library.
Browse files Browse the repository at this point in the history
  • Loading branch information
bweick committed Dec 18, 2018
1 parent 700b47a commit 28c2f77
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 80 deletions.
4 changes: 4 additions & 0 deletions contracts/core/lib/RebalancingHelperLibrary.sol
Expand Up @@ -29,6 +29,10 @@ pragma experimental "ABIEncoderV2";

library RebalancingHelperLibrary {

/* ============ Enums ============ */

enum State { Default, Proposal, Rebalance }

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

struct AuctionPriceParameters {
Expand Down
112 changes: 32 additions & 80 deletions contracts/core/tokens/RebalancingSetToken.sol
Expand Up @@ -32,6 +32,7 @@ import { IRebalancingSetFactory } from "../interfaces/IRebalancingSetFactory.sol
import { ISetToken } from "../interfaces/ISetToken.sol";
import { IVault } from "../interfaces/IVault.sol";
import { RebalancingHelperLibrary } from "../lib/RebalancingHelperLibrary.sol";
import { StandardProposeLibrary } from "./StandardProposeLibrary.sol";


/**
Expand Down Expand Up @@ -76,7 +77,7 @@ contract RebalancingSetToken is
// as possible.
uint256 public naturalUnit = REBALANCING_NATURAL_UNIT;
address public manager;
State public rebalanceState;
RebalancingHelperLibrary.State public rebalanceState;

// State updated after every rebalance
address public currentSet;
Expand Down Expand Up @@ -195,15 +196,14 @@ contract RebalancingSetToken is
proposalPeriod = _proposalPeriod;
rebalanceInterval = _rebalanceInterval;
lastRebalanceTimestamp = block.timestamp;
rebalanceState = State.Default;
rebalanceState = RebalancingHelperLibrary.State.Default;
}

/* ============ Public Functions ============ */

/**
* Function used to set the terms of the next rebalance and start the proposal period
*
*
* @param _nextSet The Set to rebalance into
* @param _auctionLibrary The library used to calculate the Dutch Auction price
* @param _auctionTimeToPivot The amount of time for the auction to go ffrom start to pivot price
Expand All @@ -219,80 +219,32 @@ contract RebalancingSetToken is
)
external
{
// Make sure it is manager that is proposing the rebalance
require(
msg.sender == manager,
"RebalancingSetToken.propose: Sender must be manager"
);

// New proposal cannot be made during a rebalance period
require(
rebalanceState != State.Rebalance,
"RebalancingSetToken.propose: State must not be Rebalance"
);

// Make sure enough time has passed from last rebalance to start a new proposal
require(
block.timestamp >= lastRebalanceTimestamp.add(rebalanceInterval),
"RebalancingSetToken.propose: Rebalance interval not elapsed"
);

// Check that new proposed Set is valid Set created by Core
require(
coreInstance.validSets(_nextSet),
"RebalancingSetToken.propose: Invalid or disabled proposed SetToken address"
);

// Check that the auction library is a valid priceLibrary tracked by Core
require(
coreInstance.validPriceLibraries(_auctionLibrary),
"RebalancingSetToken.propose: Invalid or disabled PriceLibrary address"
);

// Check that time to pivot is greater than 6 hours
require(
_auctionTimeToPivot > MIN_AUCTION_TIME_TO_PIVOT,
"RebalancingSetToken.propose: Invalid time to pivot, must be greater than 6 hours"
);

// Check that time to pivot is less than 3 days
require(
_auctionTimeToPivot < MAX_AUCTION_TIME_TO_PIVOT,
"RebalancingSetToken.propose: Invalid time to pivot, must be less than 3 days"
);

// Set auction parameters
nextSet = _nextSet;
auctionLibrary = _auctionLibrary;
auctionParameters = RebalancingHelperLibrary.AuctionPriceParameters({
auctionTimeToPivot: _auctionTimeToPivot,
auctionStartPrice: _auctionStartPrice,
auctionPivotPrice: _auctionPivotPrice,
auctionStartTime: 0
});

// Check that pivot price is compliant with library restrictions
IAuctionPriceCurve(_auctionLibrary).validateAuctionPriceParameters(
auctionParameters
);

// Check that the propoosed set natural unit is a multiple of current set natural unit, or vice versa.
// Done to make sure that when calculating token units there will are no rounding errors.
uint256 currentNaturalUnit = ISetToken(currentSet).naturalUnit();
uint256 nextSetNaturalUnit = ISetToken(_nextSet).naturalUnit();
require(
Math.max(currentNaturalUnit, nextSetNaturalUnit) %
Math.min(currentNaturalUnit, nextSetNaturalUnit) == 0,
"RebalancingSetToken.propose: Invalid proposed Set natural unit"
// Create ProposeAuctionParameters
StandardProposeLibrary.ProposeAuctionParameters memory proposeParameters =
StandardProposeLibrary.ProposeAuctionParameters({
core: core,
manager: manager,
currentSet: currentSet,
lastRebalanceTimestamp: lastRebalanceTimestamp,
rebalanceInterval: rebalanceInterval,
rebalanceState: rebalanceState
});

// Validate proposal inputs and initialize auctionParameters
auctionParameters = StandardProposeLibrary.propose(
_nextSet,
_auctionLibrary,
_auctionTimeToPivot,
_auctionStartPrice,
_auctionPivotPrice,
proposeParameters
);

// Set auction parameters
// Update state parameters
nextSet = _nextSet;
auctionLibrary = _auctionLibrary;

// Update state parameters
proposalStartTime = block.timestamp;
rebalanceState = State.Proposal;
rebalanceState = RebalancingHelperLibrary.State.Proposal;

emit RebalanceProposed(
_nextSet,
Expand All @@ -310,7 +262,7 @@ contract RebalancingSetToken is
{
// Must be in "Proposal" state before going into "Rebalance" state
require(
rebalanceState == State.Proposal,
rebalanceState == RebalancingHelperLibrary.State.Proposal,
"RebalancingSetToken.rebalance: State must be Proposal"
);

Expand All @@ -328,7 +280,7 @@ contract RebalancingSetToken is

// Update state parameters
auctionParameters.auctionStartTime = block.timestamp;
rebalanceState = State.Rebalance;
rebalanceState = RebalancingHelperLibrary.State.Rebalance;

emit RebalanceStarted(currentSet, nextSet);
}
Expand All @@ -343,7 +295,7 @@ contract RebalancingSetToken is
{
// Must be in Rebalance state to call settlement
require(
rebalanceState == State.Rebalance,
rebalanceState == RebalancingHelperLibrary.State.Rebalance,
"RebalancingSetToken.settleRebalance: State must be Rebalance"
);

Expand Down Expand Up @@ -387,7 +339,7 @@ contract RebalancingSetToken is
unitShares = nextUnitShares;
currentSet = nextSet;
lastRebalanceTimestamp = block.timestamp;
rebalanceState = State.Default;
rebalanceState = RebalancingHelperLibrary.State.Default;
}

/*
Expand All @@ -412,7 +364,7 @@ contract RebalancingSetToken is

// Confirm in Rebalance State
require(
rebalanceState == State.Rebalance,
rebalanceState == RebalancingHelperLibrary.State.Rebalance,
"RebalancingSetToken.placeBid: State must be Rebalance"
);

Expand Down Expand Up @@ -456,7 +408,7 @@ contract RebalancingSetToken is
{
// Confirm in Rebalance State
require(
rebalanceState == State.Rebalance,
rebalanceState == RebalancingHelperLibrary.State.Rebalance,
"RebalancingSetToken.getBidPrice: State must be Rebalance"
);

Expand Down Expand Up @@ -545,7 +497,7 @@ contract RebalancingSetToken is

// Check that set is not in Rebalancing State
require(
rebalanceState != State.Rebalance,
rebalanceState != RebalancingHelperLibrary.State.Rebalance,
"RebalancingSetToken.mint: Cannot mint during Rebalance"
);

Expand Down Expand Up @@ -596,7 +548,7 @@ contract RebalancingSetToken is

// Check that set is not in Rebalancing State
require(
rebalanceState != State.Rebalance,
rebalanceState != RebalancingHelperLibrary.State.Rebalance,
"RebalancingSetToken.burn: Cannot burn during Rebalance"
);

Expand Down
141 changes: 141 additions & 0 deletions contracts/core/tokens/StandardProposeLibrary.sol
@@ -0,0 +1,141 @@
/*
Copyright 2018 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.4.25;
pragma experimental "ABIEncoderV2";

import { Math } from "openzeppelin-solidity/contracts/math/Math.sol";
import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol";
import { IAuctionPriceCurve } from "../lib/auction-price-libraries/IAuctionPriceCurve.sol";
import { ICore } from "../interfaces/ICore.sol";
import { ISetToken } from "../interfaces/ISetToken.sol";
import { RebalancingHelperLibrary } from "../lib/RebalancingHelperLibrary.sol";


library StandardProposeLibrary {
using SafeMath for uint256;

/* ============ Constants ============ */
uint256 constant MIN_AUCTION_TIME_TO_PIVOT = 21600;
uint256 constant MAX_AUCTION_TIME_TO_PIVOT = 259200;

/* ============ Structs ============ */
struct ProposeAuctionParameters {
address core;
address manager;
address currentSet;
uint256 lastRebalanceTimestamp;
uint256 rebalanceInterval;
RebalancingHelperLibrary.State rebalanceState;
}

/* ============ Internal Functions ============ */

/**
* Function used to validate inputs to propose function and initialize auctionParameters struct
*
* @param _nextSet The Set to rebalance into
* @param _auctionLibrary The library used to calculate the Dutch Auction price
* @param _auctionTimeToPivot The amount of time for the auction to go ffrom start to pivot price
* @param _auctionStartPrice The price to start the auction at
* @param _auctionPivotPrice The price at which the price curve switches from linear to exponential
* @param _proposeParameters Rebalancing Set Token state parameters needed to execute logic
*/
function propose(
address _nextSet,
address _auctionLibrary,
uint256 _auctionTimeToPivot,
uint256 _auctionStartPrice,
uint256 _auctionPivotPrice,
ProposeAuctionParameters memory _proposeParameters
)
internal
returns (RebalancingHelperLibrary.AuctionPriceParameters)
{
// Set up coreInstance
ICore coreInstance = ICore(_proposeParameters.core);

// Make sure it is manager that is proposing the rebalance
require(
msg.sender == _proposeParameters.manager,
"RebalancingSetToken.propose: Sender must be manager"
);

// New proposal cannot be made during a rebalance period
require(
_proposeParameters.rebalanceState != RebalancingHelperLibrary.State.Rebalance,
"RebalancingSetToken.propose: State must not be Rebalance"
);

// Make sure enough time has passed from last rebalance to start a new proposal
require(
block.timestamp >= _proposeParameters.lastRebalanceTimestamp.add(
_proposeParameters.rebalanceInterval
),
"RebalancingSetToken.propose: Rebalance interval not elapsed"
);

// Check that new proposed Set is valid Set created by Core
require(
coreInstance.validSets(_nextSet),
"RebalancingSetToken.propose: Invalid or disabled proposed SetToken address"
);

// Check that the auction library is a valid priceLibrary tracked by Core
require(
coreInstance.validPriceLibraries(_auctionLibrary),
"RebalancingSetToken.propose: Invalid or disabled PriceLibrary address"
);

// Check that time to pivot is greater than 6 hours
require(
_auctionTimeToPivot > MIN_AUCTION_TIME_TO_PIVOT,
"RebalancingSetToken.propose: Invalid time to pivot, must be greater than 6 hours"
);

// Check that time to pivot is less than 3 days
require(
_auctionTimeToPivot < MAX_AUCTION_TIME_TO_PIVOT,
"RebalancingSetToken.propose: Invalid time to pivot, must be less than 3 days"
);

// Check that the propoosed set natural unit is a multiple of current set natural unit, or vice versa.
// Done to make sure that when calculating token units there will are no rounding errors.
uint256 currentNaturalUnit = ISetToken(_proposeParameters.currentSet).naturalUnit();
uint256 nextSetNaturalUnit = ISetToken(_nextSet).naturalUnit();
require(
Math.max(currentNaturalUnit, nextSetNaturalUnit) %
Math.min(currentNaturalUnit, nextSetNaturalUnit) == 0,
"RebalancingSetToken.propose: Invalid proposed Set natural unit"
);

// Set auction parameters
RebalancingHelperLibrary.AuctionPriceParameters memory auctionParameters =
RebalancingHelperLibrary.AuctionPriceParameters({
auctionTimeToPivot: _auctionTimeToPivot,
auctionStartPrice: _auctionStartPrice,
auctionPivotPrice: _auctionPivotPrice,
auctionStartTime: 0
});

// Check that pivot price is compliant with library restrictions
IAuctionPriceCurve(_auctionLibrary).validateAuctionPriceParameters(
auctionParameters
);

return auctionParameters;
}
}

0 comments on commit 28c2f77

Please sign in to comment.