def test_change_owner(self): old_owner = self.owner() new_owner = DUMMY self.assertReverts(self.nominateOwner, new_owner, old_owner) nominated_tx = self.nominateOwner(old_owner, new_owner) event_data = get_event_data_from_log(self.owned_event_map, nominated_tx.logs[0]) self.assertEqual(event_data['event'], "OwnerNominated") self.assertEqual(event_data['args']['newOwner'], new_owner) self.assertEqual(self.owner(), old_owner) self.assertEqual(self.nominatedOwner(), new_owner) self.assertReverts(self.nominateOwner, new_owner, old_owner) accepted_tx = self.acceptOwnership(new_owner) event_data = get_event_data_from_log(self.owned_event_map, accepted_tx.logs[0]) self.assertEqual(event_data['event'], "OwnerChanged") self.assertEqual(event_data['args']['oldOwner'], old_owner) self.assertEqual(event_data['args']['newOwner'], new_owner) self.assertEqual(self.nominatedOwner(), ZERO_ADDRESS) self.assertEqual(self.owner(), new_owner) self.assertReverts(self.nominateOwner, old_owner, new_owner) self.nominateOwner(new_owner, old_owner) self.acceptOwnership(old_owner) self.assertEqual(self.owner(), old_owner)
def test_transferFrom(self): approver = MASTER spender, receiver = fresh_accounts(2) approver_balance = self.balanceOf(approver) spender_balance = self.balanceOf(spender) receiver_balance = self.balanceOf(receiver) value = 10 * UNIT total_supply = self.totalSupply() # This fails because there has been no approval yet self.assertReverts(self.transferFrom, spender, approver, receiver, value) tx_receipt = self.approve(approver, spender, 2 * value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.erc20_event_dict, tx_receipt.logs[0])['event'], "Approval") self.assertEqual(self.allowance(approver, spender), 2 * value) self.assertReverts(self.transferFrom, spender, approver, receiver, 2 * value + 1) tx_receipt = self.transferFrom(spender, approver, receiver, value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.erc20_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.balanceOf(approver), approver_balance - value) self.assertEqual(self.balanceOf(spender), spender_balance) self.assertEqual(self.balanceOf(receiver), receiver_balance + value) self.assertEqual(self.allowance(approver, spender), value) self.assertEqual(self.totalSupply(), total_supply) # Empty the account tx_receipt = self.transferFrom(spender, approver, receiver, value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.erc20_event_dict, tx_receipt.logs[0])['event'], "Transfer") approver = fresh_account() # This account has no tokens approver_balance = self.balanceOf(approver) self.assertEqual(approver_balance, 0) self.assertEqual(self.allowance(approver, spender), 0) tx_receipt = self.approve(approver, spender, value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.erc20_event_dict, tx_receipt.logs[0])['event'], "Approval") self.assertEqual(self.allowance(approver, spender), value) # This should fail because the approver has no tokens. self.assertReverts(self.transferFrom, spender, approver, receiver, value)
def test_transfer(self): sender = MASTER sender_balance = self.token.balanceOf(sender) receiver = fresh_account() receiver_balance = self.token.balanceOf(receiver) self.assertEqual(receiver_balance, 0) value = 10 * UNIT total_supply = self.token.totalSupply() # This should fail because receiver has no tokens self.assertReverts(self.token.transfer, receiver, sender, value) tx_receipt = self.token.transfer(sender, receiver, value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.token_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.token.balanceOf(receiver), receiver_balance + value) self.assertEqual(self.token.balanceOf(sender), sender_balance - value) # transfers should leave the supply unchanged self.assertEqual(self.token.totalSupply(), total_supply) value = 1001 * UNIT # This should fail because balance < value and balance > totalSupply self.assertReverts(self.token.transfer, sender, receiver, value) # 0 value transfers are allowed. value = 0 pre_sender_balance = self.token.balanceOf(sender) pre_receiver_balance = self.token.balanceOf(receiver) # Disallow transfers to zero, to the contract itself, and to its proxy. self.assertReverts(self.token.transfer, sender, ZERO_ADDRESS, value) self.assertReverts(self.token.transfer, sender, self.token_contract.address, value) self.assertReverts(self.token.transfer, sender, self.proxy.address, value) tx_receipt = self.token.transfer(sender, receiver, value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.token_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.token.balanceOf(receiver), pre_receiver_balance) self.assertEqual(self.token.balanceOf(sender), pre_sender_balance) # It is also possible to send 0 value transfer from an account with 0 balance. no_tokens = fresh_account() self.assertEqual(self.token.balanceOf(no_tokens), 0) tx_receipt = self.token.transfer(no_tokens, receiver, value) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.token_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.token.balanceOf(no_tokens), 0)
def test_closeVote(self): owner = self.owner() voter, suspect = fresh_accounts(2) voting_period = self.votingPeriod() fee_period = self.havvenTargetFeePeriodDurationSeconds() # Give some havven tokens to our voter. self.havvenEndow(owner, voter, 1000) # Fast forward two fee periods 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)) self.beginConfiscationMotion(owner, suspect) # Should not be able to close vote in the voting period. self.assertReverts(self.closeVote, voter, suspect) fast_forward(voting_period) self.assertTrue(self.confirming(suspect)) tx_receipt = self.closeVote(voter, suspect) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.court_event_dict, tx_receipt.logs[0])['event'], "VoteClosed") # Start another confiscation motion. self.beginConfiscationMotion(owner, suspect) self.voteFor(voter, suspect) fast_forward(voting_period) # After vote has closed, voteStarTimes and votesFor/votesAgainst should be 0 and suspect should be waiting. self.closeVote(voter, suspect) self.assertEqual(self.votesFor(suspect), 0) self.assertEqual(self.voteStartTimes(suspect), 0) self.assertTrue(self.waiting(suspect))
def test_donateToFeePool(self): donor, pauper = fresh_accounts(2) self.assertNotEqual(donor, pauper) self.transfer(self.initial_beneficiary, donor, 10 * UNIT) self.withdrawFee(self.fee_authority, self.initial_beneficiary, self.feePool()) # No donations by people with no money... self.assertReverts(self.donateToFeePool, pauper, 10 * UNIT) # ...even if they donate nothing. self.assertReverts(self.donateToFeePool, pauper, 0) # No donations more than you possess. self.assertReverts(self.donateToFeePool, donor, 11 * UNIT) self.assertEqual(self.feePool(), 0) self.assertEqual(self.balanceOf(donor), 10 * UNIT) self.assertTrue(self.donateToFeePool(donor, UNIT)) self.assertEqual(self.feePool(), UNIT) self.assertEqual(self.balanceOf(donor), 9 * UNIT) self.assertTrue(self.donateToFeePool(donor, 5 * UNIT)) self.assertEqual(self.feePool(), 6 * UNIT) self.assertEqual(self.balanceOf(donor), 4 * UNIT) # And it should emit the right event. tx_receipt = self.donateToFeePool(donor, UNIT) self.assertEqual(len(tx_receipt.logs), 1) self.assertEqual( get_event_data_from_log(self.erc20fee_event_dict, tx_receipt.logs[0])['event'], 'FeeDonation')
def test_purgeAccount(self): alice = fresh_account() time = block_time() + 100 self.h_endow(MASTER, self.escrow.address, 1000 * UNIT) self.appendVestingEntry(MASTER, alice, time, 1000) self.assertReverts(self.purgeAccount, alice, alice) self.assertEqual(self.numVestingEntries(alice), 1) self.assertEqual(self.totalVestedBalance(), 1000) self.assertEqual(self.totalVestedAccountBalance(alice), 1000) self.assertEqual(self.getNextVestingIndex(alice), 0) self.assertEqual(self.getNextVestingTime(alice), time) self.assertEqual(self.getNextVestingQuantity(alice), 1000) tx_receipt = self.purgeAccount(MASTER, alice) self.assertEqual( get_event_data_from_log(self.escrow_event_dict, tx_receipt.logs[0])['event'], 'SchedulePurged') self.assertEqual(self.numVestingEntries(alice), 0) self.assertEqual(self.totalVestedBalance(), 0) self.assertEqual(self.totalVestedAccountBalance(alice), 0) self.assertEqual(self.getNextVestingIndex(alice), 0) self.assertEqual(self.getNextVestingTime(alice), 0) self.assertEqual(self.getNextVestingQuantity(alice), 0)
def test_getSetTransferFeeRate(self): transfer_fee_rate = self.feetoken.transferFeeRate() new_transfer_fee_rate = transfer_fee_rate + UNIT // 20 owner = self.feetoken.owner() fake_owner = DUMMY self.assertNotEqual(owner, fake_owner) # Only the owner is able to set the Transfer Fee Rate. self.assertReverts(self.feetoken.setTransferFeeRate, fake_owner, new_transfer_fee_rate) tx_receipt = self.feetoken.setTransferFeeRate(owner, new_transfer_fee_rate) # Check that event is emitted. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "TransferFeeRateUpdated") self.assertEqual(self.feetoken.transferFeeRate(), new_transfer_fee_rate) # Maximum fee rate is UNIT /10. bad_transfer_fee_rate = UNIT self.assertReverts(self.feetoken.setTransferFeeRate, owner, bad_transfer_fee_rate) self.assertEqual(self.feetoken.transferFeeRate(), new_transfer_fee_rate)
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_endow_transfers(self): alice = fresh_account() self.recomputeLastAverageBalance(MASTER) tx_receipt = self.endow(MASTER, alice, 50 * UNIT) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'Transfer')
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_approve(self): approver, spender = fresh_accounts(2) approval_amount = 1 * UNIT tx_receipt = self.approve(approver, spender, approval_amount) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.erc20_event_dict, tx_receipt.logs[0])['event'], "Approval") self.assertEqual(self.allowance(approver, spender), approval_amount) # Any positive approval amount is valid, even greater than total_supply. approval_amount = self.totalSupply() * 100 tx_receipt = self.approve(approver, spender, approval_amount) # Check event is emitted properly. self.assertEqual( get_event_data_from_log(self.erc20_event_dict, tx_receipt.logs[0])['event'], "Approval") self.assertEqual(self.allowance(approver, spender), approval_amount)
def test_veto(self): owner = self.owner() voter, acquitted = fresh_accounts(2) voting_period = self.votingPeriod() fee_period = self.havvenTargetFeePeriodDurationSeconds() controlling_share = self.havvenSupply() // 2 self.havvenEndow(owner, voter, controlling_share) # Fast forward two fee periods 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)) # Cannot veto when there is no vote in progress. self.assertReverts(self.veto, owner, acquitted) self.beginConfiscationMotion(owner, acquitted) # Only owner can veto. self.assertReverts(self.veto, DUMMY, acquitted) self.veto(owner, acquitted) # After veto motion, suspect should be back in the waiting stage. self.assertTrue(self.waiting(acquitted)) self.beginConfiscationMotion(owner, acquitted) self.voteFor(voter, acquitted) self.assertTrue(self.votePasses(acquitted)) fast_forward(voting_period) self.assertTrue(self.confirming(acquitted)) # Once a vote has been passed, the owner can veto it. tx_receipt = self.veto(owner, acquitted) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.court_event_dict, tx_receipt.logs[0])['event'], "VoteClosed") self.assertEqual( get_event_data_from_log(self.court_event_dict, tx_receipt.logs[1])['event'], "Veto") # After veto motion, suspect should be back in the waiting stage. self.assertTrue(self.waiting(acquitted)) # Votes should be reset. self.assertEqual(self.voteStartTimes(acquitted), 0) self.assertEqual(self.votesFor(acquitted), 0) self.assertEqual(self.votesAgainst(acquitted), 0) self.assertTrue(self.waiting(acquitted))
def test_lastAverageBalanceFullPeriod(self): alice = fresh_account() fee_period = self.targetFeePeriodDurationSeconds() # Alice will initially have 20 havvens self.endow(MASTER, alice, 20 * UNIT) self.assertEquals(self.balanceOf(alice), 20 * UNIT) # Fastforward until just before a fee period rolls over. time_remaining = self.targetFeePeriodDurationSeconds( ) + self.feePeriodStartTime() - block_time() fast_forward(time_remaining + 50) tx_receipt = self.transfer(alice, alice, 0) self.assertEquals(self.lastTransferTimestamp(alice), block_time(tx_receipt['blockNumber'])) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover') # roll over the full period fast_forward(fee_period + 50) tx_receipt = self.transfer(alice, alice, 0) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover') self.assertEquals(self.lastTransferTimestamp(alice), block_time(tx_receipt['blockNumber'])) self.assertEqual(self.lastAverageBalance(alice), 20 * UNIT) # Try a half-and-half period time_remaining = self.targetFeePeriodDurationSeconds( ) + self.feePeriodStartTime() - block_time() fast_forward(time_remaining + 50) self.transfer(alice, MASTER, 10 * UNIT) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover') fast_forward(fee_period // 2) tx_receipt = self.transfer(alice, MASTER, 10 * UNIT) fast_forward(fee_period // 2 + 10) self.recomputeLastAverageBalance(alice) self.assertClose(self.lastAverageBalance(alice), 5 * UNIT)
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 test_getSetState(self): new_state = fresh_account() owner = self.owner() self.assertNotEqual(new_state, owner) # Only the owner is able to set the Fee Authority. self.assertReverts(self.setState, new_state, new_state) tx_receipt = self.setState(owner, new_state) # Check that event is emitted. self.assertEqual( get_event_data_from_log(self.token_event_dict, tx_receipt.logs[0])['event'], "StateUpdated") self.assertEqual(self.state(), new_state)
def test_getSetFeeAuthority(self): new_fee_authority = fresh_account() owner = self.owner() # Only the owner is able to set the Fee Authority. self.assertReverts(self.setFeeAuthority, new_fee_authority, new_fee_authority) tx_receipt = self.setFeeAuthority(owner, new_fee_authority) # Check that event is emitted. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "FeeAuthorityUpdated") self.assertEqual(self.feeAuthority(), new_fee_authority)
def test_emptyTokenRecipientTransfer(self): # Ensure the default state is correct sender = MASTER sender_balance = self.token.balanceOf(sender) value = 10 * UNIT # Transfer to the contract tx_receipt = self.token.transfer(sender, self.empty_token_recipient.address, value) # Assert that there's only the Transfer event, and we know the transfer succeeded above or we would have gotten an error. self.assertEqual( get_event_data_from_log(self.token_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(len(tx_receipt.logs), 1)
def test_beginConfiscationMotion(self): owner = self.owner() accounts = fresh_accounts(5) insufficient_standing = accounts[0] sufficient_standing = accounts[1] voter = accounts[2] suspects = accounts[3:] voting_period = self.votingPeriod() fee_period = self.havvenTargetFeePeriodDurationSeconds() controlling_share = self.havvenSupply() // 2 # Give 50% of the havven tokens to voter, enough to pass a confiscation motion on their own. self.havvenEndow(owner, voter, controlling_share) self.assertEqual(self.havvenBalance(voter), controlling_share) # 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)) self.havvenEndow(owner, insufficient_standing, 99 * UNIT) self.havvenEndow(owner, sufficient_standing, 100 * UNIT) # Must have at least 100 havvens to begin a confiscsation motion. self.assertReverts(self.beginConfiscationMotion, insufficient_standing, suspects[0]) tx_receipt = self.beginConfiscationMotion(sufficient_standing, suspects[0]) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.court_event_dict, tx_receipt.logs[0])['event'], "ConfiscationVote") self.assertTrue(self.voting(suspects[0])) # The contract owner can also begin an motion, regardless of the token requirement. self.beginConfiscationMotion(owner, suspects[1]) # Cannot open multiple confiscation motions on one suspect. self.assertReverts(self.beginConfiscationMotion, owner, suspects[0]) self.voteFor(voter, suspects[0]) fast_forward(voting_period) self.approve(owner, suspects[0]) self.assertTrue(self.nominIsFrozen(suspects[0])) # Cannot open a vote on an account that has already been frozen. self.assertReverts(self.beginConfiscationMotion, owner, suspects[0])
def test_cancelVote(self): owner = self.owner() voter, suspect = fresh_accounts(2) voting_period = self.votingPeriod() confirmation_period = self.confirmationPeriod() fee_period = self.havvenTargetFeePeriodDurationSeconds() # Give some havven tokens to our voter. self.havvenEndow(owner, voter, 1000) self.assertEqual(self.havvenBalance(voter), 1000) fast_forward(fee_period + 1) 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, suspect) # Cast a vote in favour of confiscation. self.voteFor(voter, suspect) self.assertEqual(self.votesFor(suspect), 1000) tx_receipt = self.cancelVote(voter, suspect) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.court_event_dict, tx_receipt.logs[0])['event'], "CancelledVote") self.assertEqual(self.votesFor(suspect), 0) self.assertEqual(self.userVote(voter), 0) # Cast a vote against confiscation. self.voteAgainst(voter, suspect) self.assertEqual(self.votesAgainst(suspect), 1000) self.cancelVote(voter, suspect) self.assertEqual(self.votesAgainst(suspect), 0) self.assertEqual(self.userVote(voter), 0) # Cannot cancel a vote during the confirmation period. self.voteFor(voter, suspect) fast_forward(voting_period) self.assertReverts(self.cancelVote, voter, suspect) self.assertEqual(self.userVote(voter), 1) # Can cancel it after the confirmation period. fast_forward(confirmation_period) self.cancelVote(voter, suspect) self.assertEqual(self.userVote(voter), 0)
def test_reentrantTokenRecipientTransfer(self): # Ensure the default state is correct sender = MASTER sender_balance = self.token.balanceOf(sender) value = 10 * UNIT # Approve a bunch of limit to play with. tx_receipt = self.token.approve( sender, self.re_entrant_token_recipient.address, 10 * value) # Kick off a re-entrant transfer tx_receipt = self.token.transfer( sender, self.re_entrant_token_recipient.address, value) # Assert that only the first transfer happened, and the tokenFallback call reverted. self.assertEqual( get_event_data_from_log(self.token_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( self.token.balanceOf(self.re_entrant_token_recipient.address), value) self.assertEqual(self.token.balanceOf(sender), sender_balance - value)
def test_transferFrom(self): approver = self.initial_beneficiary spender, receiver = fresh_accounts(2) self.assertNotEqual(approver, spender) self.assertNotEqual(approver, receiver) approver_balance = self.feetoken.balanceOf(approver) spender_balance = self.feetoken.balanceOf(spender) receiver_balance = self.feetoken.balanceOf(receiver) value = 10 * UNIT amountReceived = self.feetoken.amountReceived(value) fee = value - amountReceived total_supply = self.feetoken.totalSupply() fee_pool = self.feetoken.feePool() # This fails because there has been no approval yet. self.assertReverts(self.feetoken.transferFrom, spender, approver, receiver, value) # Approve amount to transfer. tx_receipt = self.feetoken.approve(approver, spender, value) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Approval") self.assertEqual(self.feetoken.allowance(approver, spender), value) value = UNIT amountReceived = self.feetoken.amountReceived(value) fee = value - amountReceived tx_receipt = self.feetoken.transferFrom(spender, approver, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.allowance(approver, spender), 9 * UNIT) self.assertEqual(self.feetoken.balanceOf(approver), approver_balance - value) self.assertEqual(self.feetoken.balanceOf(spender), spender_balance) self.assertEqual(self.feetoken.balanceOf(receiver), receiver_balance + amountReceived) self.assertEqual(self.feetoken.totalSupply(), total_supply) self.assertEqual(self.feetoken.feePool(), fee_pool + fee) value = 9 * UNIT amountReceived = self.feetoken.amountReceived(value) fee = value - amountReceived tx_receipt = self.feetoken.transferFrom(spender, approver, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.allowance(approver, spender), 0) self.assertEqual(self.feetoken.balanceOf(approver), approver_balance - 10 * UNIT) self.assertEqual(self.feetoken.balanceOf(spender), spender_balance) self.assertEqual( self.feetoken.balanceOf(receiver), receiver_balance + self.feetoken.amountReceived(UNIT) + self.feetoken.amountReceived(9 * UNIT)) self.assertEqual(self.feetoken.totalSupply(), total_supply) totalFees = 9 * UNIT - self.feetoken.amountReceived( 9 * UNIT) + UNIT - self.feetoken.amountReceived(UNIT) self.assertEqual(self.feetoken.feePool(), fee_pool + totalFees) approver = fresh_account() # This account has no tokens. approver_balance = self.feetoken.balanceOf(approver) self.assertEqual(approver_balance, 0) value = 10 * UNIT tx_receipt = self.feetoken.approve(approver, spender, value) self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Approval") # This should fail because the approver has no tokens. self.assertReverts(self.feetoken.transferFrom, spender, approver, receiver, 1)
def test_transfer(self): sender = self.initial_beneficiary sender_balance = self.feetoken.balanceOf(sender) receiver = fresh_account() receiver_balance = self.feetoken.balanceOf(receiver) self.assertEqual(receiver_balance, 0) total_supply = self.feetoken.totalSupply() fee_pool = self.feetoken.feePool() value = 10 * UNIT amountReceived = self.feetoken.amountReceived(value) fee = value - amountReceived # This should fail because receiver has no tokens self.assertReverts(self.feetoken.transfer, receiver, sender, value) tx_receipt = self.feetoken.transfer(sender, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.balanceOf(receiver), receiver_balance + amountReceived) self.assertEqual(self.feetoken.balanceOf(sender), sender_balance - value) self.assertEqual(self.feetoken.totalSupply(), total_supply) self.assertEqual(self.feetoken.feePool(), fee_pool + fee) value = 1001 * UNIT # This should fail because balance < value self.assertReverts(self.feetoken.transfer, sender, receiver, value) # 0 Value transfers are allowed and incur no fee. value = 0 total_supply = self.feetoken.totalSupply() fee_pool = self.feetoken.feePool() tx_receipt = self.feetoken.transfer(sender, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.totalSupply(), total_supply) self.assertEqual(self.feetoken.feePool(), fee_pool) # It is also possible to send 0 value transfer from an account with 0 balance value = 0 no_tokens = fresh_account() self.assertEqual(self.feetoken.balanceOf(no_tokens), 0) fee = self.feetoken.transferFeeIncurred(value) total_supply = self.feetoken.totalSupply() fee_pool = self.feetoken.feePool() # Disallow transfers to zero, to the contract itself, and to its proxy. self.assertReverts(self.feetoken.transfer, sender, ZERO_ADDRESS, value) self.assertReverts(self.feetoken.transfer, sender, self.feetoken_contract.address, value) self.assertReverts(self.feetoken.transfer, sender, self.proxy.address, value) tx_receipt = self.feetoken.transfer(no_tokens, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.balanceOf(no_tokens), 0) self.assertEqual(self.feetoken.totalSupply(), total_supply) self.assertEqual(self.feetoken.feePool(), fee_pool)
def test_lastAverageBalanceFullPeriod(self): alice = fresh_account() self.havven.setIssuer(MASTER, alice, True) fee_period = self.havven.feePeriodDuration() # Alice will initially have 20 havvens self.havven.endow(MASTER, alice, 20 * UNIT) self.havven.setIssuer(MASTER, alice, True) self.havven_updatePrice(MASTER, UNIT, block_time() + 1) self.havven.setIssuanceRatio(MASTER, UNIT) self.havven.issueNomins(alice, 20 * UNIT) self.assertEqual(self.havven.balanceOf(alice), 20 * UNIT) self.assertEqual(self.nomin.balanceOf(alice), 20 * UNIT) # Fastforward until just before a fee period rolls over. time_remaining = self.havven.feePeriodDuration( ) + self.havven.feePeriodStartTime() - block_time() fast_forward(time_remaining + 50) tx_receipt = self.havven.rolloverFeePeriodIfElapsed(alice) self.havven_updatePrice(MASTER, UNIT, block_time()) issue_receipt = self.havven.issueNomins(alice, 0) self.assertEqual(self.havven.issuanceLastModified(alice), block_time(issue_receipt['blockNumber'])) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover') # roll over the full period fast_forward(fee_period + 50) tx_receipt = self.havven.rolloverFeePeriodIfElapsed(MASTER) self.havven_updatePrice(MASTER, UNIT, block_time() + 1) transfer_receipt = self.havven.issueNomins(alice, 0) event = get_event_data_from_log(self.havven_event_dict, tx_receipt.logs[0]) self.assertEqual(event['event'], 'FeePeriodRollover') self.assertEqual(self.havven.issuanceLastModified(alice), block_time(transfer_receipt['blockNumber'])) self.assertEqual(self.havven.issuanceLastAverageBalance(alice), 20 * UNIT) # Try a half-and-half period time_remaining = self.havven.feePeriodDuration( ) + self.havven.feePeriodStartTime() - block_time() fast_forward(time_remaining + 50) self.havven.rolloverFeePeriodIfElapsed(MASTER) self.havven.burnNomins(alice, 10 * UNIT) fast_forward(fee_period // 2 + 10) self.havven.burnNomins(alice, 10 * UNIT) self.havven.rolloverFeePeriodIfElapsed(MASTER) fast_forward(fee_period // 2 + 10) 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') self.havven.rolloverFeePeriodIfElapsed(alice) self.havven.recomputeLastAverageBalance(alice, alice) self.assertClose(self.havven.issuanceLastAverageBalance(alice), 5 * UNIT)
def test_withdrawFees(self): receiver, fee_receiver, not_fee_authority = fresh_accounts(3) self.assertNotEqual(self.fee_authority, not_fee_authority) self.assertNotEqual(self.fee_authority, receiver) self.assertNotEqual(self.fee_authority, fee_receiver) value = 500 * UNIT amountReceived = self.feetoken.amountReceived(value) fee = value - amountReceived tx_receipt = self.feetoken.transfer(self.initial_beneficiary, self.fee_authority, value) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.balanceOf(self.fee_authority), amountReceived) total_supply = self.feetoken.totalSupply() fee_pool = self.feetoken.feePool() fee_authority_balance = self.feetoken.balanceOf(self.fee_authority) receiver_balance = self.feetoken.balanceOf(receiver) fee_receiver_balance = self.feetoken.balanceOf(fee_receiver) value = self.feetoken.balanceOf(self.fee_authority) amountReceived = self.feetoken.amountReceived(value) cumulativeFee = fee + value - amountReceived fee = value - amountReceived tx_receipt = self.feetoken.transfer(self.fee_authority, receiver, fee_authority_balance) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual(self.feetoken.balanceOf(receiver), receiver_balance + amountReceived) self.assertEqual(self.feetoken.balanceOf(self.fee_authority), 0) self.assertEqual(self.feetoken.totalSupply(), total_supply) self.assertEqual(self.feetoken.feePool(), cumulativeFee) fee_pool = self.feetoken.feePool() # This should fail because only the Fee Authority can withdraw fees self.assertReverts(self.feetoken_withdrawFees, not_fee_authority, not_fee_authority, fee_pool) # Failure due to too-large a withdrawal. self.assertReverts(self.feetoken_withdrawFees, self.fee_authority, fee_receiver, fee_pool + 1) # Partial withdrawal leaves stuff in the pool tx_receipt = self.feetoken_withdrawFees(self.fee_authority, fee_receiver, fee_pool // 4) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "FeesWithdrawn") self.assertEqual(3 * fee_pool // 4 + 1, self.feetoken.feePool()) self.assertEqual(self.feetoken.balanceOf(fee_receiver), fee_receiver_balance + fee_pool // 4) # Withdraw the rest tx_receipt = self.feetoken_withdrawFees(self.fee_authority, fee_receiver, 3 * fee_pool // 4) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "FeesWithdrawn") self.assertEqual(self.feetoken.balanceOf(fee_receiver), fee_receiver_balance + fee_pool - 1) self.assertEqual(self.feetoken.totalSupply(), total_supply) self.assertEqual(self.feetoken.feePool(), 1)
def test_withdrawFee(self): receiver, fee_receiver, not_fee_authority = fresh_accounts(3) self.assertNotEqual(self.fee_authority, not_fee_authority) self.assertNotEqual(self.fee_authority, receiver) self.assertNotEqual(self.fee_authority, fee_receiver) value = 500 * UNIT total_value = self.transferPlusFee(value) tx_receipt = self.transfer_byProxy(self.initial_beneficiary, self.fee_authority, total_value) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.balanceOf(self.fee_authority), total_value) fee = self.transferFeeIncurred(value) total_supply = self.totalSupply() fee_pool = self.feePool() fee_authority_balance = self.balanceOf(self.fee_authority) receiver_balance = self.balanceOf(receiver) fee_receiver_balance = self.balanceOf(fee_receiver) tx_receipt = self.transfer_byProxy(self.fee_authority, receiver, value) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.balanceOf(receiver), receiver_balance + value) self.assertEqual(self.balanceOf(self.fee_authority), fee_authority_balance - total_value) self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), fee_pool + fee) fee_pool = self.feePool() # This should fail because only the Fee Authority can withdraw fees self.assertReverts(self.withdrawFee, not_fee_authority, not_fee_authority, fee_pool) # Failure due to too-large a withdrawal. self.assertReverts(self.withdrawFee, self.fee_authority, fee_receiver, fee_pool + 1) # Partial withdrawal leaves stuff in the pool tx_receipt = self.withdrawFee(self.fee_authority, fee_receiver, fee_pool // 4) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "FeesWithdrawn") self.assertEqual(3 * fee_pool // 4, self.feePool()) self.assertEqual(self.balanceOf(fee_receiver), fee_receiver_balance + fee_pool // 4) # Withdraw the rest tx_receipt = self.withdrawFee(self.fee_authority, fee_receiver, 3 * fee_pool // 4) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "FeesWithdrawn") self.assertEqual(self.balanceOf(fee_receiver), fee_receiver_balance + fee_pool) self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), 0)
def test_transferFrom(self): approver = self.initial_beneficiary spender, receiver = fresh_accounts(2) self.assertNotEqual(approver, spender) self.assertNotEqual(approver, receiver) approver_balance = self.balanceOf(approver) spender_balance = self.balanceOf(spender) receiver_balance = self.balanceOf(receiver) value = 10 * UNIT fee = self.transferFeeIncurred(value) total_value = self.transferPlusFee(value) total_supply = self.totalSupply() fee_pool = self.feePool() # This fails because there has been no approval yet. self.assertReverts(self.transferFrom_byProxy, spender, approver, receiver, value) # Approve total amount inclusive of fee. tx_receipt = self.approve(approver, spender, total_value) # Check that event is emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Approval") self.assertEqual(self.allowance(approver, spender), total_value) tx_receipt = self.transferFrom_byProxy(spender, approver, receiver, value // 10) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.allowance(approver, spender), 9 * total_value // 10) self.assertEqual(self.balanceOf(approver), approver_balance - total_value // 10) self.assertEqual(self.balanceOf(spender), spender_balance) self.assertEqual(self.balanceOf(receiver), receiver_balance + value // 10) self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), fee_pool + fee // 10) tx_receipt = self.transferFrom_byProxy(spender, approver, receiver, 9 * value // 10) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.allowance(approver, spender), 0) self.assertEqual(self.balanceOf(approver), approver_balance - total_value) self.assertEqual(self.balanceOf(spender), spender_balance) self.assertEqual(self.balanceOf(receiver), receiver_balance + value) self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), fee_pool + fee) approver = fresh_account() # This account has no tokens. approver_balance = self.balanceOf(approver) self.assertEqual(approver_balance, 0) tx_receipt = self.approve(approver, spender, total_value) self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Approval") # This should fail because the approver has no tokens. self.assertReverts(self.transferFrom_byProxy, spender, approver, receiver, value)
def test_transfer(self): sender = self.initial_beneficiary sender_balance = self.balanceOf(sender) receiver = fresh_account() receiver_balance = self.balanceOf(receiver) self.assertEqual(receiver_balance, 0) value = 10 * UNIT fee = self.transferFeeIncurred(value) total_value = self.transferPlusFee(value) total_supply = self.totalSupply() fee_pool = self.feePool() # This should fail because receiver has no tokens self.assertReverts(self.transfer_byProxy, receiver, sender, value) tx_receipt = self.transfer_byProxy(sender, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.balanceOf(receiver), receiver_balance + value) self.assertEqual(self.balanceOf(sender), sender_balance - total_value) self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), fee_pool + fee) value = 1001 * UNIT # This should fail because balance < value self.assertReverts(self.transfer_byProxy, sender, receiver, value) # 0 Value transfers are allowed and incur no fee. value = 0 total_supply = self.totalSupply() fee_pool = self.feePool() tx_receipt = self.transfer_byProxy(sender, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), fee_pool) # It is also possible to send 0 value transfer from an account with 0 balance value = 0 no_tokens = fresh_account() self.assertEqual(self.balanceOf(no_tokens), 0) fee = self.transferFeeIncurred(value) total_supply = self.totalSupply() fee_pool = self.feePool() tx_receipt = self.transfer_byProxy(no_tokens, receiver, value) # Check that events are emitted properly. self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[0])['event'], "Transfer") self.assertEqual( get_event_data_from_log(self.feetoken_event_dict, tx_receipt.logs[1])['event'], "TransferFeePaid") self.assertEqual(self.balanceOf(no_tokens), 0) self.assertEqual(self.totalSupply(), total_supply) self.assertEqual(self.feePool(), fee_pool)