Ejemplo n.º 1
0
def test_multiple_contributors_crowdsourcer_fees(localFixture, universe,
                                                 market, cash,
                                                 reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())

    # We'll make the window active
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll have testers push markets into the next round by funding dispute crowdsourcers
    amount = market.getTotalStake()
    with TokenDelta(reputationToken, -amount, tester.a1,
                    "Disputing did not reduce REP balance correctly"):
        assert market.contribute([0, market.getNumTicks()],
                                 False,
                                 amount,
                                 sender=tester.k1,
                                 startgas=long(6.7 * 10**6))
    with TokenDelta(reputationToken, -amount, tester.a2,
                    "Disputing did not reduce REP balance correctly"):
        assert market.contribute([0, market.getNumTicks()],
                                 False,
                                 amount,
                                 sender=tester.k2,
                                 startgas=long(6.7 * 10**6))

    newFeeWindowAddress = market.getFeeWindow()
    assert newFeeWindowAddress != feeWindow.address

    # fast forward time to the fee new window and generate additional fees
    feeWindow = localFixture.applySignature('FeeWindow', newFeeWindowAddress)
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # Fast forward time until the new fee window is over and we can redeem our winning stake, and dispute bond tokens and receive fees
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    marketDisputeCrowdsourcer = localFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(1))

    # The dispute crowdsourcer contributors locked in REP for 2 rounds and staked twice the initial reporter so they split 2/3 of the total stake
    expectedFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(
        universe.getOrCreateFeeWindowBefore(feeWindow.address))
    expectedFees = expectedFees / 3 * 2

    expectedRep = long(amount + amount / 2)
    with TokenDelta(reputationToken, expectedRep, tester.a1,
                    "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees / 2, tester.a1, localFixture.chain,
                        "Redeeming didn't increase ETH correctly"):
            assert marketDisputeCrowdsourcer.redeem(tester.a1)

    with TokenDelta(reputationToken, expectedRep + 1, tester.a2,
                    "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees - expectedFees / 2, tester.a2,
                        localFixture.chain,
                        "Redeeming didn't increase ETH correctly"):
            assert marketDisputeCrowdsourcer.redeem(tester.a2)
Ejemplo n.º 2
0
def test_participation_tokens(kitchenSinkFixture, universe, market, cash):
    reputationToken = kitchenSinkFixture.applySignature(
        "ReputationToken", universe.getReputationToken())

    disputeWindow = kitchenSinkFixture.applySignature(
        "DisputeWindow", universe.getOrCreateNextDisputeWindow(False))

    # Generate Fees
    generateFees(kitchenSinkFixture, universe, market)

    # We can't buy participation tokens until the window starts
    with raises(TransactionFailed):
        disputeWindow.buy(300)

    # Fast forward time until the new dispute window starts and we can buy some tokens
    assert reputationToken.transfer(kitchenSinkFixture.accounts[1], 100)
    kitchenSinkFixture.contracts["Time"].setTimestamp(
        disputeWindow.getStartTime() + 1)
    with TokenDelta(reputationToken, -300, kitchenSinkFixture.accounts[0],
                    "Buying sisnt take REP"):
        with TokenDelta(disputeWindow, 300, kitchenSinkFixture.accounts[0],
                        "Buying didnt give PTs"):
            assert disputeWindow.buy(300)
    with TokenDelta(reputationToken, -100, kitchenSinkFixture.accounts[1],
                    "Buying sisnt take REP"):
        with TokenDelta(disputeWindow, 100, kitchenSinkFixture.accounts[1],
                        "Buying didnt give PTs"):
            assert disputeWindow.buy(100,
                                     sender=kitchenSinkFixture.accounts[1])

    # We can't redeem until the window is over
    with raises(TransactionFailed):
        disputeWindow.redeem(kitchenSinkFixture.accounts[0])

    # Fast forward time until the new dispute window is over and we can redeem
    kitchenSinkFixture.contracts["Time"].setTimestamp(
        disputeWindow.getEndTime() + 1)

    totalFees = cash.balanceOf(disputeWindow.address)

    with TokenDelta(reputationToken, 300, kitchenSinkFixture.accounts[0],
                    "Redeeming didn't refund REP"):
        with TokenDelta(cash, totalFees * 3 / 4,
                        kitchenSinkFixture.accounts[0],
                        "Redeeming didn't give fees"):
            with TokenDelta(disputeWindow, -300,
                            kitchenSinkFixture.accounts[0],
                            "Redeeming didn't burn PTs"):
                assert disputeWindow.redeem(kitchenSinkFixture.accounts[0])

    with TokenDelta(reputationToken, 100, kitchenSinkFixture.accounts[1],
                    "Redeeming didn't refund REP"):
        with TokenDelta(cash, totalFees * 1 / 4,
                        kitchenSinkFixture.accounts[1],
                        "Redeeming didn't give fees"):
            with TokenDelta(disputeWindow, -100,
                            kitchenSinkFixture.accounts[1],
                            "Redeeming didn't burn PTs"):
                assert disputeWindow.redeem(kitchenSinkFixture.accounts[1])
Ejemplo n.º 3
0
def test_one_round_crowdsourcer_fees(localFixture, universe, market, cash, reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())
    constants = localFixture.contracts["Constants"]

    # We'll make the window active
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll have testers push markets into the next round by funding dispute crowdsourcers
    amount = 2 * market.getParticipantStake()
    with TokenDelta(reputationToken, -amount, tester.a1, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([0, market.getNumTicks()], False, amount, "", sender=tester.k1)

    newFeeWindowAddress = market.getFeeWindow()
    assert newFeeWindowAddress != feeWindow.address

    # fast forward time to the fee new window and generate additional fees
    feeWindow = localFixture.applySignature('FeeWindow', newFeeWindowAddress)
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # Fast forward time until the new fee window is over and we can redeem our winning stake, and dispute bond tokens and receive fees
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    initialReporter = localFixture.applySignature('InitialReporter', market.getReportingParticipant(0))
    marketDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1))

    # The dispute crowdsourcer contributor locked in REP for 2 rounds, as did the Initial Reporter
    expectedTotalFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address))

    expectedFees = expectedTotalFees * 2 / 3
    expectedRep = market.getParticipantStake()
    assert expectedRep == long(marketDisputeCrowdsourcer.getStake() + marketDisputeCrowdsourcer.getStake() / 2)
    disputeCrowdsourcerRedeemedLog = {
        "reporter": bytesToHexString(tester.a1),
        "disputeCrowdsourcer": marketDisputeCrowdsourcer.address,
        "amountRedeemed": marketDisputeCrowdsourcer.getStake(),
        "repReceived": expectedRep,
        "reportingFeesReceived": expectedFees,
        "payoutNumerators": [0, market.getNumTicks()],
        "universe": universe.address,
        "market": market.address
    }
    with AssertLog(localFixture, "DisputeCrowdsourcerRedeemed", disputeCrowdsourcerRedeemedLog):
        with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't refund REP"):
            with EtherDelta(expectedFees, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
                assert marketDisputeCrowdsourcer.redeem(tester.a1, sender=tester.k1)

    # The initial reporter gets fees even though they were not correct. They do not get their REP back though
    expectedFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address))
    with TokenDelta(reputationToken, 0, tester.a0, "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees, tester.a0, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert initialReporter.redeem(tester.a0)
def test_one_round_crowdsourcer_fees(localFixture, universe, market, cash, reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())
    constants = localFixture.contracts["Constants"]

    # We'll make the window active
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll have testers push markets into the next round by funding dispute crowdsourcers
    amount = 2 * market.getParticipantStake()
    with TokenDelta(reputationToken, -amount, tester.a1, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([0, market.getNumTicks()], False, amount, sender=tester.k1)

    newFeeWindowAddress = market.getFeeWindow()
    assert newFeeWindowAddress != feeWindow.address

    # fast forward time to the fee new window and generate additional fees
    feeWindow = localFixture.applySignature('FeeWindow', newFeeWindowAddress)
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # Fast forward time until the new fee window is over and we can redeem our winning stake, and dispute bond tokens and receive fees
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    initialReporter = localFixture.applySignature('InitialReporter', market.getReportingParticipant(0))
    marketDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1))

    # The dispute crowdsourcer contributor locked in REP for 2 rounds, as did the Initial Reporter
    expectedTotalFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address))

    expectedFees = expectedTotalFees * 2 / 3
    expectedRep = market.getParticipantStake()
    assert expectedRep == long(marketDisputeCrowdsourcer.getStake() + marketDisputeCrowdsourcer.getStake() / 2)
    disputeCrowdsourcerRedeemedLog = {
        "reporter": bytesToHexString(tester.a1),
        "disputeCrowdsourcer": marketDisputeCrowdsourcer.address,
        "amountRedeemed": marketDisputeCrowdsourcer.getStake(),
        "repReceived": expectedRep,
        "reportingFeesReceived": expectedFees,
        "payoutNumerators": [0, market.getNumTicks()],
        "universe": universe.address,
        "market": market.address
    }
    with AssertLog(localFixture, "DisputeCrowdsourcerRedeemed", disputeCrowdsourcerRedeemedLog):
        with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't refund REP"):
            with EtherDelta(expectedFees, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
                assert marketDisputeCrowdsourcer.redeem(tester.a1, sender=tester.k1)

    # The initial reporter gets fees even though they were not correct. They do not get their REP back though
    expectedFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address))
    with TokenDelta(reputationToken, 0, tester.a0, "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees, tester.a0, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert initialReporter.redeem(tester.a0)
Ejemplo n.º 5
0
def test_failed_crowdsourcer_fees(finalize, localFixture, universe, market, cash, reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll make the window active
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll have testers contribute to a dispute but not reach the target
    amount = market.getParticipantStake()

    # confirm we can contribute 0
    assert market.contribute([1, market.getNumTicks()-1], False, 0, "", sender=tester.k1)

    with TokenDelta(reputationToken, -amount + 1, tester.a1, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([1, market.getNumTicks()-1], False, amount - 1, "", sender=tester.k1)

    with TokenDelta(reputationToken, -amount + 1, tester.a2, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([1, market.getNumTicks()-1], False, amount - 1, "", sender=tester.k2)

    assert market.getFeeWindow() == feeWindow.address

    payoutDistributionHash = market.derivePayoutDistributionHash([1, market.getNumTicks()-1], False)
    failedCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", market.getCrowdsourcer(payoutDistributionHash))

    # confirm we cannot contribute directly to a crowdsourcer without going through the market
    with raises(TransactionFailed):
        failedCrowdsourcer.contribute(tester.a0, 1)

    if finalize:
        # Fast forward time until the fee window is over and we can redeem to recieve the REP back and fees
        localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
        expectedTotalFees = getExpectedFees(localFixture, cash, failedCrowdsourcer, 1)
    else:
        # Continue to the next round which will disavow failed crowdsourcers and let us redeem once the window is over
        market.contribute([0, market.getNumTicks()], False, amount * 2, "")
        assert market.getFeeWindow() != feeWindow.address
        localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
        expectedTotalFees = getExpectedFees(localFixture, cash, failedCrowdsourcer, 1)

    with TokenDelta(reputationToken, amount - 1, tester.a1, "Redeeming did not refund REP"):
        with EtherDelta(expectedTotalFees / 2, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert failedCrowdsourcer.redeem(tester.a1)

    with TokenDelta(reputationToken, amount - 1, tester.a2, "Redeeming did not refund REP"):
        with EtherDelta(cash.balanceOf(failedCrowdsourcer.address), tester.a2, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert failedCrowdsourcer.redeem(tester.a2)
def test_failed_crowdsourcer_fees(finalize, localFixture, universe, market, cash, reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll make the window active
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll have testers contribute to a dispute but not reach the target
    amount = market.getParticipantStake()

    # confirm we can contribute 0
    assert market.contribute([1, market.getNumTicks()-1], False, 0, sender=tester.k1)

    with TokenDelta(reputationToken, -amount + 1, tester.a1, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([1, market.getNumTicks()-1], False, amount - 1, sender=tester.k1)

    with TokenDelta(reputationToken, -amount + 1, tester.a2, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([1, market.getNumTicks()-1], False, amount - 1, sender=tester.k2)

    assert market.getFeeWindow() == feeWindow.address

    payoutDistributionHash = market.derivePayoutDistributionHash([1, market.getNumTicks()-1], False)
    failedCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", market.getCrowdsourcer(payoutDistributionHash))

    # confirm we cannot contribute directly to a crowdsourcer without going through the market
    with raises(TransactionFailed):
        failedCrowdsourcer.contribute(tester.a0, 1)

    if finalize:
        # Fast forward time until the fee window is over and we can redeem to recieve the REP back and fees
        localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
        expectedTotalFees = getExpectedFees(localFixture, cash, failedCrowdsourcer, 1)
    else:
        # Continue to the next round which will disavow failed crowdsourcers and let us redeem once the window is over
        market.contribute([0, market.getNumTicks()], False, amount * 2)
        assert market.getFeeWindow() != feeWindow.address
        localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
        expectedTotalFees = getExpectedFees(localFixture, cash, failedCrowdsourcer, 1)

    with TokenDelta(reputationToken, amount - 1, tester.a1, "Redeeming did not refund REP"):
        with EtherDelta(expectedTotalFees / 2, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert failedCrowdsourcer.redeem(tester.a1)

    with TokenDelta(reputationToken, amount - 1, tester.a2, "Redeeming did not refund REP"):
        with EtherDelta(cash.balanceOf(failedCrowdsourcer.address), tester.a2, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert failedCrowdsourcer.redeem(tester.a2)
def test_multiple_contributors_crowdsourcer_fees(localFixture, universe, market, cash, reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())

    # We'll make the window active
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll have testers push markets into the next round by funding dispute crowdsourcers
    amount = market.getParticipantStake()
    with TokenDelta(reputationToken, -amount, tester.a1, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([0, market.getNumTicks()], False, amount, sender=tester.k1)
    with TokenDelta(reputationToken, -amount, tester.a2, "Disputing did not reduce REP balance correctly"):
        assert market.contribute([0, market.getNumTicks()], False, amount, sender=tester.k2)

    newFeeWindowAddress = market.getFeeWindow()
    assert newFeeWindowAddress != feeWindow.address

    # fast forward time to the fee new window and generate additional fees
    feeWindow = localFixture.applySignature('FeeWindow', newFeeWindowAddress)
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)

    # Fast forward time until the new fee window is over and we can redeem our winning stake, and dispute bond tokens and receive fees
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    marketDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1))

    # The dispute crowdsourcer contributors locked in REP for 2 rounds and staked twice the initial reporter so they split 2/3 of the total stake
    expectedFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address))
    expectedFees = expectedFees / 3 * 2

    expectedRep = long(amount + amount / 2)
    with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees / 2, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert marketDisputeCrowdsourcer.redeem(tester.a1)

    with TokenDelta(reputationToken, expectedRep + 1, tester.a2, "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees - expectedFees / 2, tester.a2, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert marketDisputeCrowdsourcer.redeem(tester.a2)
Ejemplo n.º 8
0
def test_buyback_from_reporting_fees(localFixture, universe, auction, reputationToken, time, market, cash):
    # We'll quickly do the bootstrap auction and seed it with some ETH
    startTime = auction.getAuctionStartTime()
    assert time.setTimestamp(startTime)

    # Buy 5000 REP
    repSalePrice = auction.getRepSalePriceInAttoEth()
    repAmount = 5000 * 10 ** 18
    cost = repAmount * repSalePrice / 10 ** 18
    with BuyWithCash(cash, cost, tester.k0, "trade eth for rep"):
        assert auction.tradeEthForRep(repAmount)

    # Now we'll go to the first real auction
    endTime = auction.getAuctionEndTime()
    assert time.setTimestamp(endTime + 1)

    startTime = auction.getAuctionStartTime()
    assert time.setTimestamp(startTime)

    # Generate some fees
    generateFees(localFixture, universe, market)
    feesGenerated = auction.feeBalance()

    # Now we'll sell some REP and we can see that the fees that were collected were used and that the REP provided was burned
    ethSalePrice = auction.getEthSalePriceInAttoRep()
    ethAmount = feesGenerated / 2
    cost = ethAmount * ethSalePrice / 10 ** 18
    totalRepSupply = reputationToken.totalSupply()
    assert auction.tradeRepForEth(ethAmount)

    assert totalRepSupply - reputationToken.totalSupply() == cost
    assert auction.feeBalance() == feesGenerated / 2

    # If we now sell some REP again but do so by selling more than could be covered by remaining fees only a proportional amount of REP is actually burned
    ethAmount = feesGenerated
    cost = ethAmount * ethSalePrice / 10 ** 18
    totalRepSupply = reputationToken.totalSupply()
    assert auction.tradeRepForEth(ethAmount)

    assert totalRepSupply - reputationToken.totalSupply() == cost / 2
    assert auction.feeBalance() == 0
Ejemplo n.º 9
0
def test_initial_report_and_participation_fee_collection(
        localFixture, universe, market, categoricalMarket, scalarMarket, cash,
        reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())
    constants = localFixture.contracts["Constants"]

    # We cannot purchase participation tokens yet since the window isn't active
    with raises(TransactionFailed):
        feeWindow.buy(1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll make the window active then purchase some participation tokens
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)
    feeWindowAmount = 100
    with TokenDelta(reputationToken, -feeWindowAmount, tester.a0,
                    "Buying participation tokens didn't deduct REP correctly"):
        with TokenDelta(
                feeWindow, feeWindowAmount, tester.a0,
                "Buying participation tokens didn't increase participation token balance correctly"
        ):
            assert feeWindow.buy(feeWindowAmount)

    # As other testers we'll buy some more
    assert feeWindow.buy(feeWindowAmount, sender=tester.k1)
    assert feeWindow.buy(feeWindowAmount, sender=tester.k2)
    assert feeWindow.buy(feeWindowAmount, sender=tester.k3)

    # We can't redeem the participation tokens yet since the window isn't over
    with raises(TransactionFailed):
        feeWindow.redeem(False)

    # Now end the window and finalize
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)

    assert market.finalize()
    assert categoricalMarket.finalize()
    assert scalarMarket.finalize()

    marketInitialReport = localFixture.applySignature(
        'InitialReporter', market.getInitialReporter())
    categoricalInitialReport = localFixture.applySignature(
        'InitialReporter', categoricalMarket.getInitialReporter())
    scalarInitialReport = localFixture.applySignature(
        'InitialReporter', scalarMarket.getInitialReporter())

    reporterFees = 1000 * market.getNumTicks(
    ) / universe.getOrCacheReportingFeeDivisor()
    totalStake = feeWindow.getTotalFeeStake()
    assert cash.balanceOf(feeWindow.address) == reporterFees

    expectedParticipationFees = reporterFees * feeWindowAmount / totalStake

    # Cashing out Participation tokens will awards fees proportional to the total winning stake in the window
    with TokenDelta(reputationToken, feeWindowAmount, tester.a0,
                    "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(
                feeWindow, -feeWindowAmount, tester.a0,
                "Redeeming participation tokens didn't decrease participation token balance correctly"
        ):
            with EtherDelta(
                    expectedParticipationFees, tester.a0, localFixture.chain,
                    "Redeeming participation tokens didn't increase ETH correctly"
            ):
                assert feeWindow.redeem(tester.a0)

    with TokenDelta(reputationToken, feeWindowAmount, tester.a1,
                    "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(
                feeWindow, -feeWindowAmount, tester.a1,
                "Redeeming participation tokens didn't decrease participation token balance correctly"
        ):
            with EtherDelta(
                    expectedParticipationFees, tester.a1, localFixture.chain,
                    "Redeeming participation tokens didn't increase ETH correctly"
            ):
                assert feeWindow.redeem(tester.a1)

    with TokenDelta(reputationToken, feeWindowAmount, tester.a2,
                    "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(
                feeWindow, -feeWindowAmount, tester.a2,
                "Redeeming participation tokens didn't decrease participation token balance correctly"
        ):
            with EtherDelta(
                    expectedParticipationFees, tester.a2, localFixture.chain,
                    "Redeeming participation tokens didn't increase ETH correctly"
            ):
                assert feeWindow.redeem(tester.a2)

    logs = []
    captureFilteredLogs(localFixture.chain.head_state,
                        localFixture.contracts['Augur'], logs)

    marketStake = marketInitialReport.getStake()
    expectedFees = reporterFees * marketStake / totalStake
    winningsRedeemedLog = {
        "reporter": bytesToHexString(tester.a0),
        "reportingParticipant": marketInitialReport.address,
        "amountRedeemed": marketStake,
        "reportingFeesReceived": expectedFees,
        "payoutNumerators": [market.getNumTicks(), 0],
        "universe": universe.address,
        "market": market.address
    }
    with AssertLog(localFixture, "WinningsRedeemed", winningsRedeemedLog):
        with TokenDelta(reputationToken, marketStake, tester.a0,
                        "Redeeming didn't refund REP"):
            with EtherDelta(expectedFees, tester.a0, localFixture.chain,
                            "Redeeming didn't increase ETH correctly"):
                assert marketInitialReport.redeem(tester.a0)

    categoricalMarketStake = categoricalInitialReport.getStake()
    expectedFees = reporterFees * categoricalMarketStake / totalStake
    with TokenDelta(reputationToken, categoricalMarketStake, tester.a0,
                    "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees, tester.a0, localFixture.chain,
                        "Redeeming didn't increase ETH correctly"):
            assert categoricalInitialReport.redeem(tester.a0)
def test_initial_report_and_participation_fee_collection(localFixture, universe, market, categoricalMarket, scalarMarket, cash, reputationToken):
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())
    constants = localFixture.contracts["Constants"]

    # We cannot purchase participation tokens yet since the window isn't active
    with raises(TransactionFailed):
        feeWindow.buy(1)

    # generate some fees
    generateFees(localFixture, universe, market)

    # We'll make the window active then purchase some participation tokens
    localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)
    feeWindowAmount = 100
    with TokenDelta(reputationToken, -feeWindowAmount, tester.a0, "Buying participation tokens didn't deduct REP correctly"):
        with TokenDelta(feeWindow, feeWindowAmount, tester.a0, "Buying participation tokens didn't increase participation token balance correctly"):
            assert feeWindow.buy(feeWindowAmount)

    # As other testers we'll buy some more
    assert feeWindow.buy(feeWindowAmount, sender=tester.k1)
    assert feeWindow.buy(feeWindowAmount, sender=tester.k2)
    assert feeWindow.buy(feeWindowAmount, sender=tester.k3)

    # We can't redeem the participation tokens yet since the window isn't over
    with raises(TransactionFailed):
        feeWindow.redeem(False)

    # Now end the window and finalize
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)

    assert market.finalize()
    assert categoricalMarket.finalize()
    assert scalarMarket.finalize()

    marketInitialReport = localFixture.applySignature('InitialReporter', market.getInitialReporter())
    categoricalInitialReport = localFixture.applySignature('InitialReporter', categoricalMarket.getInitialReporter())
    scalarInitialReport = localFixture.applySignature('InitialReporter', scalarMarket.getInitialReporter())

    reporterFees = 1000 * market.getNumTicks() / universe.getOrCacheReportingFeeDivisor()
    totalStake = feeWindow.getTotalFeeStake()
    assert cash.balanceOf(feeWindow.address) == reporterFees

    expectedParticipationFees = reporterFees * feeWindowAmount / totalStake

    # Cashing out Participation tokens will awards fees proportional to the total winning stake in the window
    with TokenDelta(reputationToken, feeWindowAmount, tester.a0, "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(feeWindow, -feeWindowAmount, tester.a0, "Redeeming participation tokens didn't decrease participation token balance correctly"):
            with EtherDelta(expectedParticipationFees, tester.a0, localFixture.chain, "Redeeming participation tokens didn't increase ETH correctly"):
                assert feeWindow.redeem(tester.a0)

    with TokenDelta(reputationToken, feeWindowAmount, tester.a1, "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(feeWindow, -feeWindowAmount, tester.a1, "Redeeming participation tokens didn't decrease participation token balance correctly"):
            with EtherDelta(expectedParticipationFees, tester.a1, localFixture.chain, "Redeeming participation tokens didn't increase ETH correctly"):
                assert feeWindow.redeem(tester.a1)

    with TokenDelta(reputationToken, feeWindowAmount, tester.a2, "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(feeWindow, -feeWindowAmount, tester.a2, "Redeeming participation tokens didn't decrease participation token balance correctly"):
            with EtherDelta(expectedParticipationFees, tester.a2, localFixture.chain, "Redeeming participation tokens didn't increase ETH correctly"):
                assert feeWindow.redeem(tester.a2)

    marketStake = marketInitialReport.getStake()
    expectedFees = reporterFees * marketStake / totalStake
    initialReporterRedeemedLog = {
        "reporter": bytesToHexString(tester.a0),
        "amountRedeemed": marketStake,
        "repReceived": marketStake,
        "reportingFeesReceived": expectedFees,
        "payoutNumerators": [market.getNumTicks(), 0],
        "universe": universe.address,
        "market": market.address
    }
    with AssertLog(localFixture, "InitialReporterRedeemed", initialReporterRedeemedLog):
        with TokenDelta(reputationToken, marketStake, tester.a0, "Redeeming didn't refund REP"):
            with EtherDelta(expectedFees, tester.a0, localFixture.chain, "Redeeming didn't increase ETH correctly"):
                assert marketInitialReport.redeem(tester.a0)

    categoricalMarketStake = categoricalInitialReport.getStake()
    expectedFees = reporterFees * categoricalMarketStake / totalStake
    with TokenDelta(reputationToken, categoricalMarketStake, tester.a0, "Redeeming didn't refund REP"):
        with EtherDelta(expectedFees, tester.a0, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert categoricalInitialReport.redeem(tester.a0)