def test_cannotExchangeNominsForHavvensIfPriceStale(self): exchanger = self.participantAddresses[0] nominsToTransfer = 20 * UNIT self.issuanceController.setPriceStalePeriod(self.contractOwner, 1) # Set up the contract so it contains some nomins and havvens self.nomin.giveNomins(MASTER, exchanger, nominsToTransfer) self.assertEqual(self.nomin.balanceOf(exchanger), nominsToTransfer) self.havven.endow(MASTER, self.issuanceControllerContract.address, 1000 * UNIT) self.assertEqual( self.havven.balanceOf(self.issuanceControllerContract.address), 1000 * UNIT) timeSent = block_time() self.issuanceController.updatePrices(self.oracleAddress, self.usdToEthPrice, self.usdToHavPrice, timeSent) fast_forward(2) # Attempt transfer self.nomin.approve(exchanger, self.issuanceControllerContract.address, nominsToTransfer) self.assertReverts(self.issuanceController.exchangeNominsForHavvens, exchanger, nominsToTransfer) self.assertEqual(self.nomin.balanceOf(exchanger), nominsToTransfer) self.assertEqual( self.havven.balanceOf(self.issuanceControllerContract.address), 1000 * UNIT)
def give_master_nomins(self, amt): fast_forward( 1) # fast forward to allow price to not clash with previous block self.n_updatePrice(MASTER, UNIT, self.now_block_time()) self.n_replenishPool(MASTER, amt * UNIT, 2 * amt * ETHER) ethercost = self.n_purchaseCostEther(amt * UNIT) self.n_buy(MASTER, amt * UNIT, ethercost)
def test_hasVoted(self): owner = self.owner() voter, suspect = fresh_accounts(2) fee_period = self.havvenTargetFeePeriodDurationSeconds() # Give 1000 havven tokens to our voter. self.havvenEndow(owner, voter, 1000) self.assertEqual(self.havvenBalance(voter), 1000) # Fast forward to update the vote weight. fast_forward(fee_period + 1) self.havvenCheckFeePeriodRollover(DUMMY) self.havvenAdjustFeeEntitlement(voter, voter, self.havvenBalance(voter)) # This should fail because no confiscation motion has begun. self.assertFalse(self.hasVoted(voter)) self.beginConfiscationMotion(owner, suspect) # This should return false because the voter has not voted yet. self.assertFalse(self.hasVoted(voter)) self.voteFor(voter, suspect) # This should return true because the voter has voted. self.assertTrue(self.hasVoted(voter)) # And false when they cancel their vote. self.cancelVote(voter, suspect) self.assertFalse(self.hasVoted(voter)) # And true again if they vote against. self.voteFor(voter, suspect) self.assertTrue(self.hasVoted(voter))
def test_escrowedFees(self): self.havven.endow(MASTER, self.escrow.contract.address, self.havven.totalSupply()) self.escrow.appendVestingEntry(MASTER, MASTER, block_time() + 100000, self.havven.totalSupply()) self.havven_updatePrice(self.havven.oracle(), UNIT, self.havven.currentTime() + 1) self.havven.setIssuer(MASTER, MASTER, True) self.havven.issueNomins(MASTER, UNIT) # generate 1 UNIT of fees self.nomin.donateToFeePool(MASTER, UNIT) fees = self.nomin.feePool() # Skip a period so we have a full period with no transfers fast_forward(self.havven.feePeriodDuration() + 100) self.havven.rolloverFeePeriodIfElapsed(MASTER) self.havven.recomputeLastAverageBalance(MASTER, MASTER) # Skip a period so we have a full period with no transfers fast_forward(self.havven.feePeriodDuration() + 100) self.havven.rolloverFeePeriodIfElapsed(MASTER) self.havven.recomputeLastAverageBalance(MASTER, MASTER) self.assertEqual(fees, self.havven.lastFeesCollected()) self.havven.withdrawFees(MASTER) self.assertEqual(self.nomin.feePool(), 0) self.assertEqual(self.nomin.balanceOf(MASTER), fees)
def test_issue_revert_conditions(self): alice = fresh_account() self.havven.endow(MASTER, alice, 1000 * UNIT) self.havven_updatePrice(self.havven.oracle(), UNIT, self.havven.currentTime() + 1) self.assertReverts(self.havven.issueNomins, alice, 10 * UNIT) # reverts, as not an issuer self.havven.setIssuer(MASTER, alice, True) fast_forward(days=1) # fast forward to make price stale self.assertReverts(self.havven.issueNomins, alice, 10 * UNIT) # reverts, as price is stale self.havven_updatePrice(self.havven.oracle(), UNIT, self.havven.currentTime() + 1) self.assertReverts(self.havven.issueNomins, alice, 1000 * UNIT) # reverts, as too many nomins being issued self.havven.setIssuanceRatio(MASTER, 0) self.assertReverts(self.havven.issueNomins, alice, 10 * UNIT) # reverts, as CMAX too low (0) self.havven.setIssuanceRatio(MASTER, int(0.05 * UNIT)) self.havven.issueNomins(alice, self.havven.maxIssuableNomins(alice)) self.assertEqual(self.havven.nominsIssued(alice), 50 * UNIT) self.assertReverts(self.havven.issueNomins, alice, self.havven.maxIssuableNomins(alice)) self.assertEqual(self.havven.remainingIssuableNomins(alice), 0) self.havven.issueNomins(alice, self.havven.remainingIssuableNomins(alice))
def test_cannotExchangeEtherForHavvensIfPriceStale(self): amount = 10 * UNIT havvenAmount = 10000 * UNIT exchanger = self.participantAddresses[0] startingFundsWalletEthBalance = get_eth_balance(self.fundsWallet) # Push a price update self.issuanceController.setPriceStalePeriod(self.contractOwner, 1) timeSent = block_time() self.issuanceController.updatePrices(self.oracleAddress, self.usdToEthPrice, self.usdToHavPrice, timeSent) # Wait so the lastPriceUpdateTime is different to now fast_forward(2) # Set up the contract so it contains some havvens for folks to convert Ether for self.havven.endow(MASTER, self.issuanceControllerContract.address, havvenAmount) self.assertEqual( self.havven.balanceOf(self.issuanceControllerContract.address), havvenAmount) # Attempt transfer self.assertReverts(self.issuanceController.exchangeEtherForHavvens, exchanger, amount) endingFundsWalletEthBalance = get_eth_balance(self.fundsWallet) self.assertEqual( self.havven.balanceOf(self.issuanceControllerContract.address), havvenAmount) self.assertEqual(self.havven.balanceOf(exchanger), 0) self.assertEqual(startingFundsWalletEthBalance, endingFundsWalletEthBalance)
def test_totalVestedBalance(self): alice, bob = fresh_accounts(2) time = block_time() self.havven.endow(MASTER, self.escrow.contract.address, 100 * UNIT) self.assertEqual(self.escrow.totalVestedBalance(), 0) self.escrow.appendVestingEntry(MASTER, bob, time + 100, UNIT) self.assertEqual(self.escrow.totalVestedBalance(), UNIT) self.escrow.appendVestingEntry(MASTER, alice, time + 100, UNIT) self.assertEqual(self.escrow.totalVestedBalance(), 2 * UNIT) self.escrow.purgeAccount(MASTER, alice) self.assertEqual(self.escrow.totalVestedBalance(), UNIT) k = 5 for n in [100 * 2**i for i in range(k)]: self.escrow.appendVestingEntry(MASTER, alice, time + n, n) self.assertEqual(self.escrow.totalVestedBalance(), UNIT + 100 * (2**k - 1)) fast_forward(110) self.escrow.vest(alice) self.assertEqual(self.escrow.totalVestedBalance(), UNIT + 100 * (2**k - 1) - 100)
def test_cannotExchangeEtherForNominsIfPriceStale(self): amount = 10 * UNIT nominsBalance = (amount * self.usdToEthPrice) // UNIT base = self.nomin.amountReceived(nominsBalance) self.issuanceController.setPriceStalePeriod(self.contractOwner, 1) timeSent = block_time() self.issuanceController.updatePrices(self.oracleAddress, self.usdToEthPrice, self.usdToHavPrice, timeSent) exchanger = self.participantAddresses[0] startingFundsWalletEthBalance = get_eth_balance(self.fundsWallet) fast_forward(2) # Wait so the lastPriceUpdateTime is different to now # Set up the contract so it contains some nomins for folks to convert Ether for self.nomin.giveNomins(MASTER, self.issuanceControllerContract.address, nominsBalance) self.assertEqual( self.nomin.balanceOf(self.issuanceControllerContract.address), nominsBalance) # Attmpt transfer self.assertReverts(self.issuanceController.exchangeEtherForNomins, exchanger, amount) endingFundsWalletEthBalance = get_eth_balance(self.fundsWallet) self.assertEqual( self.nomin.balanceOf(self.issuanceControllerContract.address), nominsBalance) self.assertEqual(self.nomin.balanceOf(exchanger), 0) self.assertEqual(self.nomin.feePool(), 0) self.assertEqual(startingFundsWalletEthBalance, endingFundsWalletEthBalance)
def test_currentBalanceSum(self): # Testing the value of currentBalanceSum works as intended, # Further testing involving this and fee collection will be done # in scenario testing fee_period = self.havven.feePeriodDuration() delay = int(fee_period / 10) alice = fresh_account() self.assertEqual(self.havven.balanceOf(alice), 0) start_amt = UNIT * 50 self.havven.endow(MASTER, alice, start_amt) self.havven.setIssuer(MASTER, alice, True) self.havven_updatePrice(MASTER, UNIT, block_time() + 1) self.havven.setIssuanceRatio(MASTER, UNIT) self.havven.issueNomins(alice, start_amt) self.assertEqual(self.havven.balanceOf(alice), start_amt) self.assertEqual(self.nomin.balanceOf(alice), start_amt) self.assertEqual(self.havven.issuanceCurrentBalanceSum(alice), 0) start_time = block_time() fast_forward(delay) self.havven.recomputeLastAverageBalance(alice, alice) end_time = block_time() balance_sum = (end_time - start_time) * start_amt self.assertEqual(self.havven.issuanceCurrentBalanceSum(alice), balance_sum) self.havven.burnNomins(alice, start_amt) self.assertEqual(self.nomin.balanceOf(alice), 0) fast_forward(delay) self.havven.recomputeLastAverageBalance(alice, alice) self.assertClose(self.havven.issuanceCurrentBalanceSum(alice), balance_sum)
def test_selfDestruct(self): owner = self.havven.owner() notowner = DUMMY self.assertNotEqual(owner, notowner) # The contract cannot be self-destructed before the SD has been initiated. self.assertReverts(self.unproxied_havven.selfDestruct, owner) tx = self.unproxied_havven.initiateSelfDestruct(owner) self.assertEventEquals(self.event_map, tx.logs[0], "SelfDestructInitiated", {"selfDestructDelay": self.sd_duration}, location=self.havven_contract.address) # Neither owners nor non-owners may not self-destruct before the time has elapsed. self.assertReverts(self.unproxied_havven.selfDestruct, notowner) self.assertReverts(self.unproxied_havven.selfDestruct, owner) fast_forward(seconds=self.sd_duration, days=-1) self.assertReverts(self.unproxied_havven.selfDestruct, notowner) self.assertReverts(self.unproxied_havven.selfDestruct, owner) fast_forward(seconds=10, days=1) # Non-owner should not be able to self-destruct even if the time has elapsed. self.assertReverts(self.unproxied_havven.selfDestruct, notowner) address = self.unproxied_havven.contract.address tx = self.unproxied_havven.selfDestruct(owner) self.assertEventEquals(self.event_map, tx.logs[0], "SelfDestructed", {"beneficiary": owner}, location=self.havven_contract.address) # Check contract not exist self.assertEqual(W3.eth.getCode(address), b'\x00')
def test_withdrawHalfFees(self): self.havven.endow(MASTER, self.escrow.contract.address, self.havven.totalSupply()) self.escrow.appendVestingEntry(MASTER, MASTER, block_time() + 100000, self.havven.totalSupply() // 2) self.escrow.appendVestingEntry(MASTER, DUMMY, block_time() + 100000, self.havven.totalSupply() // 2) self.havven_updatePrice(self.havven.oracle(), UNIT, self.havven.currentTime() + 1) self.havven.setIssuer(MASTER, MASTER, True) self.havven.issueNomins(MASTER, UNIT) # generate 1 UNIT of fees self.havven.setIssuer(MASTER, DUMMY, True) self.havven.issueNomins(DUMMY, UNIT) self.nomin.donateToFeePool(DUMMY, UNIT) fees = self.nomin.feePool() # Skip a period so we have a full period with no transfers fast_forward(self.havven.feePeriodDuration() + 100) self.havven.rolloverFeePeriodIfElapsed(MASTER) self.havven.recomputeLastAverageBalance(MASTER, MASTER) # Since escrow contract has most of the global supply, and half of the # escrowed balance, they should get half of the fees. self.havven.withdrawFees(MASTER) self.assertClose(self.nomin.balanceOf(MASTER) - UNIT, fees / 2) self.havven.withdrawFees(DUMMY) self.assertClose(self.nomin.balanceOf(DUMMY), fees / 2)
def test_withdrawHalfFees(self): self.h_endow(MASTER, self.escrow.address, self.h_totalSupply() - (100 * UNIT)) self.h_endow(MASTER, MASTER, 100 * UNIT) self.appendVestingEntry(MASTER, MASTER, block_time() + 100000, self.h_totalSupply() // 2) self.appendVestingEntry(MASTER, DUMMY, block_time() + 100000, self.h_totalSupply() // 2) self.make_nomin_velocity() uncollected = self.n_feePool() self.assertClose(uncollected, 36 * UNIT) self.assertEqual(self.feePool(), 0) # Skip a period so we have a full period with no transfers target_period = self.h_targetFeePeriodDurationSeconds() + 1000 fast_forward(seconds=target_period) # Zero value transfer to roll over the fee period self.h_transfer(MASTER, self.escrow.address, 0) fast_forward(seconds=target_period) # Since escrow contract has most of the global supply, and half of the # escrowed balance, they should get half of the fees. self.withdrawFees(MASTER) self.assertClose(self.n_balanceOf(MASTER), self.n_priceToSpend(18 * UNIT))
def test_event_FeePeriodRollover(self): fee_period = self.havven.feePeriodDuration() fast_forward(fee_period + 10) tx = self.havven.rolloverFeePeriodIfElapsed(MASTER) time = block_time(tx.blockNumber) self.assertEventEquals(self.event_map, tx.logs[0], "FeePeriodRollover", {"timestamp": time}, self.havven_proxy.address)
def test_currentBalanceSum(self): """ Testing the value of currentBalanceSum works as intended, Further testing involving this and fee collection will be done in scenario testing """ fee_period = self.targetFeePeriodDurationSeconds() delay = int(fee_period / 10) alice = fresh_account() self.assertEquals(self.balanceOf(alice), 0) start_amt = UNIT * 50 self.endow(MASTER, alice, start_amt) self.assertEquals(self.balanceOf(alice), start_amt) self.assertEquals(self.currentBalanceSum(alice), 0) start_time = block_time() fast_forward(delay) self.adjustFeeEntitlement(alice, alice, self.balanceOf(alice)) end_time = block_time() balance_sum = (end_time - start_time) * start_amt self.assertEquals(self.currentBalanceSum(alice), balance_sum) self.transfer(alice, self.havven_real.address, start_amt) self.assertEquals(self.balanceOf(alice), 0) fast_forward(delay) self.adjustFeeEntitlement(alice, alice, self.balanceOf(alice)) self.assertClose(self.currentBalanceSum(alice), balance_sum)
def test_voteFor(self): owner = self.owner() accounts = fresh_accounts(4) voter = accounts[0] no_tokens = accounts[1] suspects = accounts[2:] voting_period = self.votingPeriod() fee_period = self.havvenTargetFeePeriodDurationSeconds() # Give some havven tokens to our voter. self.havvenEndow(owner, voter, 1000) self.assertEqual(self.havvenBalance(voter), 1000) # Cannot vote unless there is a confiscation motion. self.assertReverts(self.voteFor, voter, suspects[0]) # Fast forward to update the voter's weight. fast_forward(fee_period + 1) self.havvenCheckFeePeriodRollover(DUMMY) fast_forward(fee_period + 1) self.havvenCheckFeePeriodRollover(DUMMY) self.havvenAdjustFeeEntitlement(voter, voter, self.havvenBalance(voter)) # Begin a confiscation motion against the suspect. self.beginConfiscationMotion(owner, suspects[0]) self.assertTrue(self.voting(suspects[0])) # Cast a vote in favour of confiscation. tx_receipt = self.voteFor(voter, suspects[0]) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.court_event_dict, tx_receipt.logs[0])['event'], "VoteFor") self.assertEqual(self.votesFor(suspects[0]), 1000) # Our voter should not be able to vote in more than one motion at a time. self.beginConfiscationMotion(owner, suspects[1]) self.assertReverts(self.voteFor, voter, suspects[1]) # It should not be possible to vote without any tokens. self.assertReverts(self.voteFor, no_tokens, suspects[0])
def test_transferRollsOver(self): alice = fresh_account() self.endow(MASTER, alice, 50 * UNIT) fast_forward(seconds=self.targetFeePeriodDurationSeconds() + 100) tx_receipt = self.transfer(alice, MASTER, 25 * UNIT) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover')
def test_withdraw_multiple_periods(self): alice = fresh_account() self.havven.withdrawFees(alice) fast_forward(self.havven.feePeriodDuration() * 2) self.havven.rolloverFeePeriodIfElapsed(DUMMY) self.havven.withdrawFees(alice) fast_forward(self.havven.feePeriodDuration() * 2) self.havven.rolloverFeePeriodIfElapsed(DUMMY)
def test_withdraw_multiple_periods(self): alice = fresh_account() self.withdrawFeeEntitlement(alice) fast_forward(self.targetFeePeriodDurationSeconds() * 2) self.rolloverFeePeriod(DUMMY) self.withdrawFeeEntitlement(alice) fast_forward(self.targetFeePeriodDurationSeconds() * 2) self.rolloverFeePeriod(DUMMY)
def test_votePasses(self): owner = self.owner() accounts = fresh_accounts(11) suspect = accounts[0] voters = accounts[1:] required_participation = self.requiredParticipation() required_majority = self.requiredMajority() fee_period = self.havvenTargetFeePeriodDurationSeconds() tokens = self.havvenSupply() // 20 # Give 1/20th of the token supply to each of our 10 voters. In total 50% of tokens distributed. for voter in voters: self.havvenEndow(owner, voter, tokens) self.assertEqual(self.havvenBalance(voter), tokens) # Fast forward to update the vote weights. fast_forward(fee_period + 1) self.havvenCheckFeePeriodRollover(DUMMY) fast_forward(fee_period + 1) self.havvenCheckFeePeriodRollover(DUMMY) # Begin a confiscation motion against the suspect. self.beginConfiscationMotion(owner, suspect) self.assertFalse(self.votePasses(suspect)) # 100% in favour and 0% against (50% participation). for voter in voters: self.havvenAdjustFeeEntitlement(voter, voter, self.havvenBalance(voter)) self.voteFor(voter, suspect) self.assertTrue(self.votePasses(suspect)) self.assertEqual(self.votesFor(suspect), self.havvenSupply() // 2) # All cancel votes. for voter in voters: self.cancelVote(voter, suspect) self.assertFalse(self.votePasses(suspect)) self.assertEqual(self.votesFor(suspect), 0) # 100% against and 0% in favour (50% participation). for voter in voters: self.voteAgainst(voter, suspect) self.assertFalse(self.votePasses(suspect)) self.assertEqual(self.votesAgainst(suspect), self.havvenSupply() // 2) # All cancel votes. for voter in voters: self.cancelVote(voter, suspect) self.assertEqual(self.votesAgainst(suspect), 0) # 60% in favour and 0% against (30% participation) for voter in voters[:6]: self.voteFor(voter, suspect) # Required participation must be > than 30%. self.assertFalse(self.votePasses(suspect)) # But if another user votes in favour, participation = 35% which is sufficient for a vote to pass. self.voteFor(voters[7], suspect) self.assertTrue(self.votePasses(suspect)) # The last 3 vote against, 70% in favour and 30% against (required majority is 2/3). for voter in voters[8:]: self.voteAgainst(voter, suspect) self.assertTrue(self.votePasses(suspect)) # If one changes their vote for to against, should not pass since 60% in favour 40% against (less than the min required majority of 2/3). self.cancelVote(voters[7], suspect) self.voteAgainst(voters[7], suspect) self.assertFalse(self.votePasses(suspect))
def test_addRegularVestingSchedule(self): alice, bob, carol, tim, pim = fresh_accounts(5) self.h_endow(MASTER, self.escrow.address, 100 * UNIT) time = block_time() self.addRegularVestingSchedule(MASTER, alice, time + to_seconds(weeks=52), 100 * UNIT, 4) self.assertEqual(self.numVestingEntries(alice), 4) self.vest(alice) self.assertEqual(self.h_balanceOf(alice), 0) fast_forward(to_seconds(weeks=13) + 10) self.vest(alice) self.assertEqual(self.h_balanceOf(alice), 25 * UNIT) fast_forward(to_seconds(weeks=13) + 10) self.vest(alice) self.assertEqual(self.h_balanceOf(alice), 50 * UNIT) fast_forward(to_seconds(weeks=13) + 10) self.vest(alice) self.assertEqual(self.h_balanceOf(alice), 75 * UNIT) fast_forward(to_seconds(weeks=13) + 10) self.vest(alice) self.assertEqual(self.h_balanceOf(alice), 100 * UNIT) fast_forward(to_seconds(weeks=13) + 10) self.vest(alice) self.assertEqual(self.h_balanceOf(alice), 100 * UNIT) time = block_time() + 10000000 bob_periods = 7 self.addRegularVestingSchedule(MASTER, bob, time, UNIT, 7) q = sum(self.getVestingQuantity(bob, i) for i in range(bob_periods)) self.assertEqual(q, UNIT) self.assertEqual(self.getVestingTime(bob, bob_periods - 1), time, UNIT) self.assertReverts(self.addRegularVestingSchedule, MASTER, carol, block_time() - 1, UNIT, 5) self.assertReverts(self.addRegularVestingSchedule, MASTER, carol, 0, UNIT, 5) self.assertReverts(self.addRegularVestingSchedule, MASTER, carol, block_time() + 100000, UNIT, 0) time = block_time() + 10000 self.appendVestingEntry(MASTER, tim, time, UNIT) self.addRegularVestingSchedule(MASTER, pim, time, UNIT, 1) self.assertEqual(self.numVestingEntries(tim), self.numVestingEntries(pim)) self.assertEqual(self.getVestingTime(tim, 0), self.getVestingTime(pim, 0)) self.assertEqual(self.getVestingQuantity(tim, 0), self.getVestingQuantity(pim, 0))
def rollover_and_validate(self, duration=None): time = duration if duration is not None else self.havven.feePeriodDuration( ) + 1 fast_forward(time) tx = self.havven.rolloverFeePeriodIfElapsed(DUMMY) rollover_time = block_time(tx.blockNumber) self.assertEventEquals(self.event_map, tx.logs[0], "FeePeriodRollover", {"timestamp": rollover_time}, self.havven_proxy.address)
def test_endow_currentBalanceSum(self): amount = 50 * UNIT # Force updates. self.endow(MASTER, self.havven_real.address, 0) havven_balanceSum = self.currentBalanceSum(self.havven_real.address) alice = fresh_account() fast_forward(seconds=60) self.endow(MASTER, alice, amount) self.assertGreater(self.currentBalanceSum(self.havven_real.address), havven_balanceSum)
def test_event_SelfDestructed(self): owner = self.sd.owner() beneficiary = self.sd.selfDestructBeneficiary() self.sd.initiateSelfDestruct(owner) fast_forward(self.sd_duration + 1) tx = self.sd.selfDestruct(owner) self.assertEventEquals(self.event_map, tx.logs[0], "SelfDestructed", {"beneficiary": beneficiary}, location=self.sd_contract.address)
def setUpClass(cls): cls.havven_proxy, cls.proxied_havven, cls.nomin_proxy, cls.proxied_nomin, cls.havven_contract, cls.nomin_contract = cls.deployContracts( ) cls.event_map = cls.event_maps['Havven'] cls.havven = PublicHavvenInterface(cls.proxied_havven, "Havven") cls.nomin = PublicNominInterface(cls.proxied_nomin, "Nomin") fast_forward(weeks=102)
def test_lastAverageBalance(self): # set the block time to be at least 30seconds away from the end of the fee_period fee_period = self.havven.feePeriodDuration() # fast forward next block with some extra padding delay = fee_period + 1 fast_forward(delay) self.havven.rolloverFeePeriodIfElapsed(DUMMY) alice = fresh_account() self.assertEqual(self.havven.balanceOf(alice), 0) start_amt = UNIT * 50 self.havven.endow(MASTER, alice, start_amt) self.havven.setIssuer(MASTER, alice, True) self.havven_updatePrice(MASTER, UNIT, block_time() + 1) self.havven.setIssuanceRatio(MASTER, UNIT) tx_receipt = self.havven.issueNomins(alice, start_amt) self.assertEqual(self.havven.balanceOf(alice), start_amt) self.assertEqual(self.havven.issuanceCurrentBalanceSum(alice), 0) self.assertEqual(self.havven.issuanceLastAverageBalance(alice), 0) self.assertEqual(self.havven.issuanceLastModified(alice), block_time(tx_receipt['blockNumber'])) fast_forward(delay) self.havven.rolloverFeePeriodIfElapsed(DUMMY) fast_forward(fee_period // 2) tx_receipt = self.havven.recomputeLastAverageBalance(alice, alice) block_number = tx_receipt['blockNumber'] duration_since_rollover = block_time( block_number) - self.havven.feePeriodStartTime() balance_sum = duration_since_rollover * start_amt actual = self.havven.issuanceCurrentBalanceSum(alice) expected = balance_sum self.assertClose(actual, expected) time_remaining = self.havven.feePeriodDuration( ) + self.havven.feePeriodStartTime() - block_time() fast_forward(time_remaining - 5) self.havven.burnNomins(alice, start_amt // 2) time_remaining = self.havven.feePeriodDuration( ) + self.havven.feePeriodStartTime() - block_time() fast_forward(time_remaining + 10) self.havven.rolloverFeePeriodIfElapsed(alice) self.havven.recomputeLastAverageBalance(alice, alice) actual = self.havven.issuanceLastAverageBalance(alice) expected = (start_amt * delay) // (self.havven.feePeriodStartTime() - self.havven.lastFeePeriodStartTime()) self.assertClose(actual, expected)
def test_transferFromRollsOver(self): alice = fresh_account() self.havven.endow(MASTER, alice, 50 * UNIT) self.havven.approve(alice, MASTER, 25 * UNIT) fast_forward(seconds=self.havven.feePeriodDuration() + 100) self.havven.transferFrom(MASTER, alice, MASTER, 25 * UNIT) tx_receipt = self.havven.rolloverFeePeriodIfElapsed(MASTER) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover')
def setUpClass(cls): cls.initial_price = UNIT // 2 cls.havven_proxy, cls.proxied_havven, cls.nomin_proxy, cls.proxied_nomin, cls.havven_contract, cls.nomin_contract, cls.escrow_contract = cls.deployContracts( ) cls.havven = PublicHavvenInterface(cls.proxied_havven, "Havven") cls.nomin = PublicNominInterface(cls.proxied_nomin, "Nomin") cls.escrow = PublicHavvenEscrowInterface(cls.escrow_contract, "HavvenEscrow") cls.havven.setIssuanceRatio(MASTER, UNIT // 20) fast_forward(weeks=102)
def test_appendVestingEntry(self): alice, bob = fresh_accounts(2) escrow_balance = 20 * UNIT amount = 10 self.havven.endow(MASTER, self.escrow.contract.address, escrow_balance) time = block_time() # Should not be able to add a vestingEntry > havven.totalSupply() self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time + to_seconds(weeks=2), self.havven.totalSupply() + 1) # Should not be able to add a vestingEntry > balanceOf escrow account self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time + to_seconds(weeks=2), escrow_balance + 1) # Should not be able to vest in the past self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, 0, UNIT) self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time - 1, UNIT) self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time, UNIT) # Vesting quantities should be nonzero self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time + to_seconds(weeks=2), 0) self.escrow.appendVestingEntry(MASTER, alice, time + to_seconds(weeks=2), amount) self.escrow.vest(alice) self.assertEqual(self.havven.balanceOf(alice), 0) fast_forward(weeks=3) self.escrow.vest(alice) self.assertEqual(self.havven.balanceOf(alice), amount) self.havven.transfer(alice, MASTER, amount) time = block_time() t1 = time + to_seconds(weeks=1) t2 = time + to_seconds(weeks=2) self.escrow.appendVestingEntry(MASTER, alice, t1, amount) self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time + to_seconds(days=1), amount) self.assertReverts(self.escrow.appendVestingEntry, MASTER, alice, time + to_seconds(weeks=1), amount) self.escrow.appendVestingEntry(MASTER, alice, t2, amount + 1) self.assertEqual(self.escrow.getVestingQuantity(alice, 1), amount) self.assertEqual(self.escrow.getVestingQuantity(alice, 2), amount + 1) self.assertEqual(self.escrow.getVestingTime(alice, 1), t1) self.assertEqual(self.escrow.getVestingTime(alice, 2), t2) self.assertEqual(self.escrow.numVestingEntries(alice), 3)
def setUp(self): self.snapshot = take_snapshot() time_remaining = self.h_targetFeePeriodDurationSeconds( ) + self.h_feePeriodStartTime() - block_time() fast_forward(time_remaining + 1) self.h_recomputeLastAverageBalance(MASTER) # Reset the price at the start of tests so that it's never stale. self.n_updatePrice(self.n_oracle(), self.n_etherPrice()) # Reset the liquidation timestamp so that it's never active. owner = self.n_owner() self.n_forceLiquidation(owner) self.n_terminateLiquidation(owner)
def test_lastAverageBalance(self): # set the block time to be at least 30seconds away from the end of the fee_period fee_period = self.targetFeePeriodDurationSeconds() time_remaining = self.targetFeePeriodDurationSeconds( ) + self.feePeriodStartTime() - block_time() if time_remaining < 30: fast_forward(50) time_remaining = self.targetFeePeriodDurationSeconds( ) + self.feePeriodStartTime() - block_time() # fast forward next block with some extra padding delay = time_remaining + 100 alice = fresh_account() self.assertEquals(self.balanceOf(alice), 0) start_amt = UNIT * 50 tx_receipt = self.endow(MASTER, alice, start_amt) self.assertEquals(self.balanceOf(alice), start_amt) self.assertEquals(self.currentBalanceSum(alice), 0) self.assertEquals(self.lastAverageBalance(alice), 0) self.assertEquals(self.lastTransferTimestamp(alice), block_time(tx_receipt['blockNumber'])) fast_forward(delay) self._checkFeePeriodRollover(DUMMY) fast_forward(fee_period // 2) tx_receipt = self.adjustFeeEntitlement(alice, alice, self.balanceOf(alice)) block_number = tx_receipt['blockNumber'] duration_since_rollover = block_time( block_number) - self.feePeriodStartTime() balance_sum = duration_since_rollover * start_amt actual = self.currentBalanceSum(alice) expected = balance_sum self.assertClose(actual, expected) time_remaining = self.targetFeePeriodDurationSeconds( ) + self.feePeriodStartTime() - block_time() fast_forward(time_remaining - 5) self.transfer(alice, MASTER, start_amt // 2) time_remaining = self.targetFeePeriodDurationSeconds( ) + self.feePeriodStartTime() - block_time() fast_forward(time_remaining + 10) actual = self.lastAverageBalance(alice) expected = (start_amt * delay) // (self.feePeriodStartTime() - self.lastFeePeriodStartTime()) self.assertClose(actual, expected)