diff --git a/contracts/core/tokens/rebalancing-v2/RebalancingStart.sol b/contracts/core/tokens/rebalancing-v2/RebalancingStart.sol index e83a15bf8..5cb51cc1c 100644 --- a/contracts/core/tokens/rebalancing-v2/RebalancingStart.sol +++ b/contracts/core/tokens/rebalancing-v2/RebalancingStart.sol @@ -17,6 +17,7 @@ pragma solidity 0.5.7; pragma experimental "ABIEncoderV2"; +import { ERC20 } from "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol"; import { Math } from "openzeppelin-solidity/contracts/math/Math.sol"; import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol"; @@ -32,6 +33,7 @@ import { RebalancingSetState } from "./RebalancingSetState.sol"; * Implementation of Rebalancing Set Token V2 start rebalance functionality */ contract RebalancingStart is + ERC20, RebalancingSetState { using SafeMath for uint256; @@ -62,6 +64,12 @@ contract RebalancingStart is "Interval not elapsed" ); + // Must be a positive supply of the Set + require( + totalSupply() > 0, + "Invalid supply" + ); + // New proposed Set must be a valid Set created by Core require( core.validSets(address(_nextSet)), diff --git a/test/contracts/core/tokens/rebalancing-v2/rebalancingSetState.spec.ts b/test/contracts/core/tokens/rebalancing-v2/rebalancingSetState.spec.ts index a536026e6..3129e1f44 100644 --- a/test/contracts/core/tokens/rebalancing-v2/rebalancingSetState.spec.ts +++ b/test/contracts/core/tokens/rebalancing-v2/rebalancingSetState.spec.ts @@ -140,13 +140,16 @@ contract('RebalancingSetState', accounts => { liquidatorMock = await liquidatorHelper.deployLiquidatorMockAsync(); await coreHelper.addAddressToWhiteList(liquidatorMock.address, liquidatorWhitelist); - [ initialSetToken, nextSetToken ] = await rebalancingHelper.createSetTokensAsync( coreMock, factory.address, transferProxy.address, - 2 + 2, + undefined, + managerAccount, ); + + manager = managerAccount; liquidator = liquidatorMock.address; initialUnitShares = DEFAULT_UNIT_SHARES; @@ -181,6 +184,8 @@ contract('RebalancingSetState', accounts => { entryFee, ] ); + + await coreMock.addSet.sendTransactionAsync(rebalancingSetToken.address, txnFrom(deployerAccount)); }); afterEach(async () => { @@ -625,16 +630,16 @@ contract('RebalancingSetState', accounts => { describe('when startRebalance is called from Rebalance State', async () => { beforeEach(async () => { - const nextSetTokenComponentAddresses = await nextSetToken.getComponents.callAsync(); - await coreHelper.addTokensToWhiteList(nextSetTokenComponentAddresses, rebalancingComponentWhiteList); - - await rebalancingHelper.transitionToRebalanceV2Async( - coreMock, - rebalancingComponentWhiteList, - rebalancingSetToken, - nextSetToken, - managerAccount - ); + const nextSetTokenComponentAddresses = await nextSetToken.getComponents.callAsync(); + await coreHelper.addTokensToWhiteList(nextSetTokenComponentAddresses, rebalancingComponentWhiteList); + + await rebalancingHelper.transitionToRebalanceV2Async( + coreMock, + rebalancingComponentWhiteList, + rebalancingSetToken, + nextSetToken, + managerAccount + ); }); it('should revert', async () => { diff --git a/test/contracts/core/tokens/rebalancing-v2/rebalancingStart.spec.ts b/test/contracts/core/tokens/rebalancing-v2/rebalancingStart.spec.ts index 0224ab861..63a63c2f7 100644 --- a/test/contracts/core/tokens/rebalancing-v2/rebalancingStart.spec.ts +++ b/test/contracts/core/tokens/rebalancing-v2/rebalancingStart.spec.ts @@ -372,6 +372,20 @@ contract('StartRebalance', accounts => { }); }); + describe('when the rebalancing set supply is 0', async () => { + beforeEach(async () => { + // Redeem all supply + await coreMock.redeem.sendTransactionAsync( + rebalancingSetToken.address, + rebalancingSetQuantityToIssue + ); + }); + + it('should revert', async () => { + await expectRevertError(subject()); + }); + }); + describe('when the rebalance interval has not elapsed', async () => { beforeEach(async () => { subjectTimeFastForward = ONE_DAY_IN_SECONDS.sub(10); diff --git a/utils/helpers/rebalancingHelper.ts b/utils/helpers/rebalancingHelper.ts index 0e77ef7c1..7d862b876 100644 --- a/utils/helpers/rebalancingHelper.ts +++ b/utils/helpers/rebalancingHelper.ts @@ -153,8 +153,8 @@ export class RebalancingHelper { let naturalUnit: BigNumber; const setTokenArray: SetTokenContract[] = []; - const components = await this._erc20Helper.deployTokensAsync(tokenCount + 1, this._tokenOwnerAddress); - await this._erc20Helper.approveTransfersAsync(components, transferProxy); + const components = await this._erc20Helper.deployTokensAsync(tokenCount + 1, from); + await this._erc20Helper.approveTransfersAsync(components, transferProxy, from); const indexArray = _.times(tokenCount, Number); for (const index in indexArray) { @@ -189,6 +189,12 @@ export class RebalancingHelper { naturalUnit, ); + await setToken.approve.sendTransactionAsync( + transferProxy, + UNLIMITED_ALLOWANCE_IN_BASE_UNITS, + txnFrom(from) + ); + setTokenArray.push(setToken); } diff --git a/utils/helpers/rebalancingSetV2Helper.ts b/utils/helpers/rebalancingSetV2Helper.ts index f818c8cdc..b49ee72ac 100644 --- a/utils/helpers/rebalancingSetV2Helper.ts +++ b/utils/helpers/rebalancingSetV2Helper.ts @@ -26,8 +26,8 @@ import { ZERO, } from '../constants'; import { extractNewSetTokenAddressFromLogs } from '../contract_logs/core'; - -import { getWeb3, getContractInstance } from '../web3Helper'; +import { ether } from '@utils/units'; +import { getWeb3, getContractInstance, txnFrom } from '../web3Helper'; import { RebalancingHelper } from './rebalancingHelper'; @@ -172,6 +172,27 @@ export class RebalancingSetV2Helper extends RebalancingHelper { liquidatorData: string = EMPTY_BYTESTRING, ): Promise { + const currentSupply = await rebalancingSetToken.totalSupply.callAsync(); + if (currentSupply.eq(new BigNumber(0))) { + const currentSetMintQuantity = ether(8); + const currentSetToken = await rebalancingSetToken.currentSet.callAsync(); + + // Issue currentSetToken + await core.issue.sendTransactionAsync( + currentSetToken, + currentSetMintQuantity, + txnFrom(caller) + ); + + // Use issued currentSetToken to issue rebalancingSetToken + const rebalancingSetQuantityToIssue = ether(7); + await core.issue.sendTransactionAsync( + rebalancingSetToken.address, + rebalancingSetQuantityToIssue, + txnFrom(caller) + ); + } + const nextSetTokenComponentAddresses = await nextSetToken.getComponents.callAsync(); await this._coreHelper.addTokensToWhiteList( nextSetTokenComponentAddresses,