Exemple #1
0
def test_preemptive_crowdsourcer_contributions_disputed_wins(localFixture, universe, market, reputationToken):
    # We can pre-emptively stake REP in case someone disputes our initial report
    preemptiveBondSize = 200 * 10 ** 18

    # We'll have one user buy all the stake that will award an ROI and another user buy the remaining stake which will not
    initialStake = market.getParticipantStake()
    realBondSize = initialStake * 3
    assert market.contributeToTentative([0, market.getNumTicks(), 0], realBondSize, "")
    assert market.contributeToTentative([0, market.getNumTicks(), 0], preemptiveBondSize - realBondSize, "", sender = localFixture.accounts[1])
    preemptiveDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer())

    # Now we'll dispute the intial report
    proceedToNextRound(localFixture, market)

    # By disputing we actually cause the preemptive bond to get placed.
    assert market.getParticipantStake() == preemptiveBondSize + initialStake * 3

    # We'll simply move time forward and let this bond placed on the initial report outcome win
    disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
    assert market.finalize()

    # The account which placed stake first and got normal tokens will make the normal 40% ROI
    expectedWinnings = realBondSize * .4
    with TokenDelta(reputationToken, realBondSize + expectedWinnings, localFixture.accounts[0], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[0])

    # The account which placed stake later and got overload tokens will not make any ROI
    with TokenDelta(reputationToken, preemptiveBondSize - realBondSize, localFixture.accounts[1], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[1])
def test_fork_bonus(contractsFixture, market, universe):
    # proceed to forking
    while (market.getForkingMarket() == longToHexString(0)):
        proceedToNextRound(contractsFixture, market)

    reputationToken = contractsFixture.applySignature('ReputationToken', universe.getReputationToken())
    payoutHash = market.derivePayoutDistributionHash([market.getNumTicks(), 0], False)
    childUniverse = contractsFixture.applySignature("Universe", universe.createChildUniverse([market.getNumTicks(), 0], False))
    childReputationToken = contractsFixture.applySignature("ReputationToken", childUniverse.getReputationToken())

    # We'll transfer some additional REP to the initial reporter contract to try and get a larger bonus
    initialReporterAddress = market.getInitialReporter()
    extraAmount = 10000
    assert reputationToken.transfer(initialReporterAddress, extraAmount)

    # When we redeem the bonus we will only be given a bonus relative to the legitimate stake in the bond
    designatedReportCost = universe.getOrCacheDesignatedReportStake()
    initialReporter = contractsFixture.applySignature('InitialReporter', initialReporterAddress)

    # Skip to after the fork end to not deal with 5% bonus math
    contractsFixture.contracts["Time"].setTimestamp(universe.getForkEndTime() + 1)

    expectedPayout = designatedReportCost + (designatedReportCost / 2) + extraAmount
    with TokenDelta(childReputationToken, expectedPayout, tester.a0, "Redeeming forked bond didn't result in the expected amount"):
        assert initialReporter.forkAndRedeem()
Exemple #3
0
def test_fork_migration_no_report(localFixture, universe, market):
    # Proceed to Forking for the yesNo market but don't go all the way so that we can create the new market still
    for i in range(10):
        proceedToNextRound(localFixture, market)

    # Create a market before the fork occurs which has an end date past the forking window
    endTime = localFixture.contracts["Time"].getTimestamp() + timedelta(
        days=90).total_seconds()
    longMarket = localFixture.createYesNoMarket(universe, endTime, 1, 0,
                                                localFixture.accounts[0])

    # Go to the forking period
    proceedToFork(localFixture, market, universe)

    # Now finalize the fork so migration can occur
    finalize(localFixture, market, universe)

    # Now when we migrate the market through the fork we'll place a new bond in the winning universe's REP
    oldReputationToken = localFixture.applySignature(
        "ReputationToken", universe.getReputationToken())
    oldBalance = oldReputationToken.balanceOf(longMarket.address)
    newUniverse = localFixture.applySignature(
        "Universe",
        universe.getChildUniverse(market.getWinningPayoutDistributionHash()))
    newReputationToken = localFixture.applySignature(
        "ReputationToken", newUniverse.getReputationToken())
    with TokenDelta(oldReputationToken, 0, longMarket.address,
                    "Migrating didn't disavow old no show bond"):
        with TokenDelta(newReputationToken, oldBalance, longMarket.address,
                        "Migrating didn't place new no show bond"):
            assert longMarket.migrateThroughOneFork([], "")
Exemple #4
0
def test_preemptive_crowdsourcer_contributions_disputed_loses(localFixture, universe, market, reputationToken):
    # We can pre-emptively stake REP in case someone disputes our initial report
    preemptiveBondSize = 200 * 10 ** 18
    assert market.contributeToTentative([0, market.getNumTicks(), 0], preemptiveBondSize, "")

    initialStake = market.getParticipantStake()
    preemptiveDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer())

    # Now we'll dispute the intial report
    proceedToNextRound(localFixture, market)

    # By disputing we actually cause the preemptive bond to get placed.
    assert market.getParticipantStake() == preemptiveBondSize + initialStake * 3

    # We'll dispute this newly placed bond made from the preemptive contributions
    proceedToNextRound(localFixture, market)

    # And now we'll let the dispute win
    disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
    assert market.finalize()

    # The preemptive bond has been liquidated
    assert reputationToken.balanceOf(preemptiveDisputeCrowdsourcer.address) == 0
Exemple #5
0
def test_crowdsourcer_minimum_remaining(localFixture, universe, market):
    proceedToNextRound(localFixture, market, moveTimeForward = False)

    payoutNumerators = [0, 0, market.getNumTicks()]
    initialReporter = localFixture.applySignature('InitialReporter', market.getInitialReporter())
    initialReportSize = initialReporter.getSize()
    totalBondSize = initialReportSize * 2

    # We cannot leave only 1 attoREP remaining to fill
    with raises(TransactionFailed):
        market.contribute(payoutNumerators, totalBondSize - 1, "")

    # We cannot leave anything less than the initial report size left to fill in fact
    with raises(TransactionFailed):
        market.contribute(payoutNumerators, totalBondSize - initialReportSize + 1, "")

    # Lets fill up to the initial report size
    mintLog = {
        "target": localFixture.accounts[0],
        "market": market.address,
        "amount": totalBondSize - initialReportSize,
        "totalSupply": totalBondSize - initialReportSize
    }
    with AssertLog(localFixture, "TokensMinted", mintLog):
        assert market.contribute(payoutNumerators, totalBondSize - initialReportSize, "")

    # Now we'll completely fill the bond
    assert market.contribute(payoutNumerators, initialReportSize, "")
def test_finalized_fork_migration(localFixture, universe, market,
                                  categoricalMarket):
    # Make the categorical market finalized
    proceedToNextRound(localFixture, categoricalMarket)
    feeWindow = localFixture.applySignature('FeeWindow',
                                            categoricalMarket.getFeeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert categoricalMarket.finalize()

    # Proceed to Forking for the yesNo market and finalize it
    proceedToFork(localFixture, market, universe)
    finalizeFork(localFixture, market, universe)

    # The categorical market is finalized and cannot be migrated to the new universe
    with raises(TransactionFailed):
        categoricalMarket.migrateThroughOneFork()

    # We also can't disavow the crowdsourcers for this market
    with raises(TransactionFailed):
        categoricalMarket.disavowCrowdsourcers()

    # The forking market may not migrate or disavow crowdsourcers either
    with raises(TransactionFailed):
        market.migrateThroughOneFork()

    with raises(TransactionFailed):
        market.disavowCrowdsourcers()
Exemple #7
0
def test_preemptive_crowdsourcer_contributions_disputed_wins(localFixture, universe, market, reputationToken):
    # We can pre-emptively stake REP in case someone disputes our initial report
    preemptiveBondSize = 200 * 10 ** 18

    # We'll have one user buy all the stake that will award an ROI and another user buy the remaining stake which will not
    initialStake = market.getParticipantStake()
    realBondSize = initialStake * 3
    assert market.contributeToTentative([0, market.getNumTicks(), 0], realBondSize, "")
    assert market.contributeToTentative([0, market.getNumTicks(), 0], preemptiveBondSize - realBondSize, "", sender = localFixture.accounts[1])
    preemptiveDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer())

    # Now we'll dispute the intial report
    proceedToNextRound(localFixture, market)

    # By disputing we actually cause the preemptive bond to get placed.
    assert market.getParticipantStake() == preemptiveBondSize + initialStake * 3

    # We'll simply move time forward and let this bond placed on the initial report outcome win
    disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
    assert market.finalize()

    # Both accounts will get a lower than 40% ROI for their contributions to the tentative outcome
    expectedReturn = reputationToken.balanceOf(preemptiveDisputeCrowdsourcer.address) * realBondSize / preemptiveDisputeCrowdsourcer.totalSupply()
    with TokenDelta(reputationToken, expectedReturn, localFixture.accounts[0], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[0])

    expectedReturn = reputationToken.balanceOf(preemptiveDisputeCrowdsourcer.address) * (preemptiveBondSize - realBondSize) / preemptiveDisputeCrowdsourcer.totalSupply()
    with TokenDelta(reputationToken, expectedReturn, localFixture.accounts[1], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[1])
def test_finalized_fork_migration(localFixture, universe, market, categoricalMarket):
    # Make the categorical market finalized
    proceedToNextRound(localFixture, categoricalMarket)
    feeWindow = localFixture.applySignature('FeeWindow', categoricalMarket.getFeeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert categoricalMarket.finalize()

    # Proceed to Forking for the binary market and finalize it
    proceedToFork(localFixture, market, universe)
    finalizeFork(localFixture, market, universe)

    # The categorical market is finalized and cannot be migrated to the new universe
    with raises(TransactionFailed):
        categoricalMarket.migrateThroughOneFork()

    # We also can't disavow the crowdsourcers for this market
    with raises(TransactionFailed):
        categoricalMarket.disavowCrowdsourcers()

    # The forking market may not migrate or disavow crowdsourcers either
    with raises(TransactionFailed):
        market.migrateThroughOneFork()

    with raises(TransactionFailed):
        market.disavowCrowdsourcers()
def test_redeem_reporting_participants(kitchenSinkFixture, market, categoricalMarket, scalarMarket, universe, cash):
    reputationToken = kitchenSinkFixture.applySignature("ReputationToken", universe.getReputationToken())
    constants = kitchenSinkFixture.contracts["Constants"]

    # Initial Report
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)

    # Get the winning reporting participants
    initialReporter = kitchenSinkFixture.applySignature('InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = kitchenSinkFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(2))
    winningDisputeCrowdsourcer2 = kitchenSinkFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(4))

    # Fast forward time until the new fee window is over and we can redeem
    feeWindow = kitchenSinkFixture.applySignature("FeeWindow", market.getFeeWindow())
    kitchenSinkFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    expectedFees = getExpectedFees(kitchenSinkFixture, cash, winningDisputeCrowdsourcer1, 4)
    expectedFees += getExpectedFees(kitchenSinkFixture, cash, winningDisputeCrowdsourcer2, 2)
    expectedFees += getExpectedFees(kitchenSinkFixture, cash, initialReporter, 5)
    expectedRep = long(winningDisputeCrowdsourcer2.getStake() + winningDisputeCrowdsourcer1.getStake())
    expectedRep = long(expectedRep + expectedRep / 2)
    expectedRep += long(initialReporter.getStake() + initialReporter.getStake() / 2)
    with TokenDelta(reputationToken, expectedRep, tester.a0, "Redeeming didn't refund REP"):
        with PrintGasUsed(kitchenSinkFixture, "Universe Redeem:", 0):
            assert universe.redeemStake([initialReporter.address, winningDisputeCrowdsourcer1.address, winningDisputeCrowdsourcer2.address], [])
Exemple #10
0
def test_redeem_reporting_participants(kitchenSinkFixture, market,
                                       categoricalMarket, scalarMarket,
                                       universe, cash):
    redeemStake = kitchenSinkFixture.contracts["RedeemStake"]
    reputationToken = kitchenSinkFixture.applySignature(
        "ReputationToken", universe.getReputationToken())
    constants = kitchenSinkFixture.contracts["Constants"]

    # Initial Report
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)

    # Get the winning reporting participants
    initialReporter = kitchenSinkFixture.applySignature(
        'InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = kitchenSinkFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(2))
    winningDisputeCrowdsourcer2 = kitchenSinkFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(4))

    # Fast forward time until the new dispute window is over and we can redeem
    disputeWindow = kitchenSinkFixture.applySignature(
        "DisputeWindow", market.getDisputeWindow())

    # Purchase PTs and inject fees into the window
    ptAmount = 10**18
    additionalfees = 10**18
    assert cash.faucet(additionalfees)
    assert cash.transfer(disputeWindow.address, additionalfees)
    assert disputeWindow.buy(ptAmount)

    kitchenSinkFixture.contracts["Time"].setTimestamp(
        disputeWindow.getEndTime() + 1)
    assert market.finalize()

    expectedRep = winningDisputeCrowdsourcer2.getStake(
    ) + winningDisputeCrowdsourcer1.getStake() + initialReporter.getStake()
    expectedRep = expectedRep + expectedRep * 2 / 5
    expectedRep += ptAmount
    expectedRep -= 1  # Rounding error
    fees = cash.balanceOf(disputeWindow.address)
    with TokenDelta(reputationToken, expectedRep,
                    kitchenSinkFixture.accounts[0],
                    "Redeeming didn't refund REP"):
        with TokenDelta(cash, fees, kitchenSinkFixture.accounts[0],
                        "Redeeming didn't pay out fees"):
            with PrintGasUsed(kitchenSinkFixture, "Universe Redeem:", 0):
                assert redeemStake.redeemStake([
                    initialReporter.address,
                    winningDisputeCrowdsourcer1.address,
                    winningDisputeCrowdsourcer2.address
                ], [disputeWindow.address])
def test_marketFinalization(localFixture, universe, market):
    proceedToNextRound(localFixture, market)

    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)

    with PrintGasUsed(localFixture, "Market:finalize", MARKET_FINALIZATION):
        assert market.finalize()
Exemple #12
0
def test_marketFinalization(localFixture, universe, market):
    proceedToNextRound(localFixture, market)

    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)

    with PrintGasUsed(localFixture, "Market:finalize", MARKET_FINALIZATION):
        assert market.finalize()
Exemple #13
0
def test_roundsOfReporting(rounds, localFixture, market, universe):
    disputeWindow = universe.getOrCreateCurrentDisputeWindow(False)

    marketRepBond = market.repBond()

    # Do the initial report
    proceedToNextRound(localFixture, market, moveTimeForward = False)

    initialDisputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())
    assert initialDisputeWindow.duration() == localFixture.contracts["Constants"].INITIAL_DISPUTE_ROUND_DURATION_SECONDS()

    # Do the first round outside of the loop and test logging
    crowdsourcerCreatedLog = {
        "universe": universe.address,
        "market": market.address,
        "size": marketRepBond * 2,
        "payoutNumerators": [0, 0, market.getNumTicks()],
    }

    crowdsourcerContributionLog = {
        "universe": universe.address,
        "reporter": localFixture.accounts[0],
        "market": market.address,
        "amountStaked": marketRepBond * 2,
        "description": "Clearly incorrect",
        "payoutNumerators": [0, 0, market.getNumTicks()],
        "currentStake": marketRepBond * 2,
        "stakeRemaining": 0,
    }

    disputeWindow = localFixture.applySignature("DisputeWindow", universe.getOrCreateNextDisputeWindow(False))
    crowdsourcerCompletedLog = {
        "universe": universe.address,
        "market": market.address,
        "nextWindowStartTime": disputeWindow.getStartTime(),
        "nextWindowEndTime": disputeWindow.getEndTime(),
        "totalRepStakedInMarket": marketRepBond * 3,
        "disputeRound": 2,
        "payoutNumerators": [0, 0, market.getNumTicks()],
        "totalRepStakedInPayout": marketRepBond * 2,
    }

    with AssertLog(localFixture, "DisputeCrowdsourcerCreated", crowdsourcerCreatedLog):
        with AssertLog(localFixture, "DisputeCrowdsourcerContribution", crowdsourcerContributionLog):
            with AssertLog(localFixture, "DisputeCrowdsourcerCompleted", crowdsourcerCompletedLog):
                market.contribute([0, 0, market.getNumTicks()], universe.getInitialReportMinValue() * 2, "Clearly incorrect", sender=localFixture.accounts[0])

    newDisputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())
    assert newDisputeWindow.duration() == localFixture.contracts["Constants"].DISPUTE_ROUND_DURATION_SECONDS()

    # proceed through several rounds of disputing
    for i in range(rounds - 2):
        proceedToNextRound(localFixture, market)
        assert disputeWindow != market.getDisputeWindow()
        disputeWindow = market.getDisputeWindow()
        assert disputeWindow == universe.getOrCreateCurrentDisputeWindow(False)
def test_redeem_participation_tokens(kitchenSinkFixture, universe, market, cash):
    reputationToken = kitchenSinkFixture.applySignature("ReputationToken", universe.getReputationToken())

    # proceed to the next round and buy some more fee window tokens
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)

    feeWindow = kitchenSinkFixture.applySignature('FeeWindow', market.getFeeWindow())

    # We'll make the window active then purchase some participation tokens
    kitchenSinkFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1)
    feeWindowAmount = 100

    # Distribute REP
    for testAccount in [tester.a1, tester.a2, tester.a3]:
        reputationToken.transfer(testAccount, 1 * 10**6 * 10**18)

    assert feeWindow.buy(feeWindowAmount, sender=tester.k1)
    assert feeWindow.buy(feeWindowAmount, sender=tester.k2)
    assert feeWindow.buy(feeWindowAmount, sender=tester.k3)

    # proceed to the next round and buy some more fee window tokens
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees = True)

    newFeeWindow = kitchenSinkFixture.applySignature('FeeWindow', market.getFeeWindow())

    assert newFeeWindow.buy(feeWindowAmount, sender=tester.k1)
    assert newFeeWindow.buy(feeWindowAmount, sender=tester.k2)
    assert newFeeWindow.buy(feeWindowAmount, sender=tester.k3)

    # Now end the window
    kitchenSinkFixture.contracts["Time"].setTimestamp(newFeeWindow.getEndTime() + 1)

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

    expectedParticipationFees = reporterFees * feeWindowAmount * 2 / totalStake

    # Cashing out Participation tokens will awards fees proportional to the total winning stake in the window
    with TokenDelta(reputationToken, feeWindowAmount * 2, tester.a3, "Redeeming participation tokens didn't refund REP"):
        with TokenDelta(feeWindow, -feeWindowAmount, tester.a3, "Redeeming participation tokens didn't decrease participation token balance correctly"):
            with EtherDelta(expectedParticipationFees, tester.a3, kitchenSinkFixture.chain, "Redeeming participation tokens didn't increase ETH correctly"):
                with PrintGasUsed(kitchenSinkFixture, "Universe Redeem:", 0):
                    assert universe.redeemStake([], [feeWindow.address, newFeeWindow.address], sender = tester.k3)

    with TokenDelta(reputationToken, feeWindowAmount * 2, 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, kitchenSinkFixture.chain, "Redeeming participation tokens didn't increase ETH correctly"):
                assert universe.redeemStake([], [feeWindow.address, newFeeWindow.address], sender = tester.k1)

    with TokenDelta(reputationToken, feeWindowAmount * 2, 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, kitchenSinkFixture.chain, "Redeeming participation tokens didn't increase ETH correctly"):
                assert universe.redeemStake([], [feeWindow.address, newFeeWindow.address], sender = tester.k2)
Exemple #15
0
def test_fees_from_trades(finalized, contractsFixture, cash, market):
    createOrder = contractsFixture.contracts['CreateOrder']
    trade = contractsFixture.contracts['Trade']
    orders = contractsFixture.contracts['Orders']
    completeSets = contractsFixture.contracts['CompleteSets']
    firstShareToken = contractsFixture.applySignature('ShareToken', market.getShareToken(0))
    secondShareToken = contractsFixture.applySignature('ShareToken', market.getShareToken(1))

    if finalized:
        proceedToNextRound(contractsFixture, market)
        disputeWindow = contractsFixture.applySignature('DisputeWindow', market.getDisputeWindow())
        contractsFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
        assert market.finalize()

    # buy complete sets for both users
    numTicks = market.getNumTicks()
    with BuyWithCash(cash, fix('1', numTicks), tester.k1, "buy complete set"):
        assert completeSets.publicBuyCompleteSets(market.address, fix(1), sender=tester.k1)
    with BuyWithCash(cash, fix('1', numTicks), tester.k2, "buy complete set"):
        assert completeSets.publicBuyCompleteSets(market.address, fix(1), sender=tester.k2)
    assert firstShareToken.balanceOf(tester.a1) == firstShareToken.balanceOf(tester.a2) == fix(1)
    assert secondShareToken.balanceOf(tester.a1) == secondShareToken.balanceOf(tester.a2) == fix(1)

    # create order with shares
    orderID = createOrder.publicCreateOrder(ASK, fix(1), 6000, market.address, 0, longTo32Bytes(0), longTo32Bytes(0), longTo32Bytes(42), False, nullAddress, sender=tester.k1)
    assert orderID

    expectedAffiliateFees = fix(10000) * 0.01 * .25
    cash.faucet(fix(6000), sender=tester.k2)
    # Trade and specify an affiliate address.
    if finalized:
        with TokenDelta(cash, expectedAffiliateFees, tester.a3, "Affiliate did not recieve the correct fees"):
            assert trade.publicFillBestOrder(BID, market.address, 0, fix(1), 6000, "43", 6, False, tester.a3, nullAddress, sender=tester.k2) == 0
    else:
        assert trade.publicFillBestOrder(BID, market.address, 0, fix(1), 6000, "43", 6, False, tester.a3, nullAddress, sender=tester.k2) == 0

    assert firstShareToken.balanceOf(tester.a1) == 0
    assert secondShareToken.balanceOf(tester.a1) == fix(1)

    # The second user sold the complete set they ended up holding from this transaction, which extracts fees
    assert firstShareToken.balanceOf(tester.a2) == fix(1)
    assert secondShareToken.balanceOf(tester.a2) == fix(0)

    if not finalized:
        # We can confirm that the 3rd test account has an affiliate fee balance of 25% of the market creator fee 1% taken from the 1 ETH order
        assert market.affiliateFeesAttoCash(tester.a3) == expectedAffiliateFees

        # The affiliate can withdraw their fees
        with TokenDelta(cash, expectedAffiliateFees, tester.a3, "Affiliate did not recieve the correct fees"):
            market.withdrawAffiliateFees(tester.a3)

    # No more fees can be withdrawn
    with TokenDelta(cash, 0, tester.a3, "Affiliate double received fees"):
        market.withdrawAffiliateFees(tester.a3)
def test_forking(localFixture, universe, market, categoricalMarket, cash, reputationToken):
    # Let's do some initial disputes for the categorical market
    proceedToNextRound(localFixture, categoricalMarket, tester.k1, moveTimeForward = False)

    # Get to a fork
    testers = [tester.k0, tester.k1, tester.k2, tester.k3]
    testerIndex = 1
    while (market.getForkingMarket() == longToHexString(0)):
        proceedToNextRound(localFixture, market, testers[testerIndex], True)
        testerIndex += 1
        testerIndex = testerIndex % len(testers)

    # Have the participants fork and create new child universes
    reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(0))
    ReportingParticipantDisavowedLog = {
        "universe": universe.address,
        "market": market.address,
        "reportingParticipant": reportingParticipant.address,
    }
    with AssertLog(localFixture, "ReportingParticipantDisavowed", ReportingParticipantDisavowedLog):
        reportingParticipant.fork()

    for i in range(1, market.getNumParticipants()):
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))
        reportingParticipant.fork()

    # Finalize the fork
    finalizeFork(localFixture, market, universe)

    categoricalDisputeCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", categoricalMarket.getReportingParticipant(1))

    # Migrate the categorical market into the winning universe. This will disavow the dispute crowdsourcer on it, letting us redeem for original universe rep and eth
    assert categoricalMarket.migrateThroughOneFork()

    expectedRep = categoricalDisputeCrowdsourcer.getStake()
    expectedEth = getExpectedFees(localFixture, cash, categoricalDisputeCrowdsourcer, 2)
    with EtherDelta(expectedEth, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
        with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't increase REP correctly"):
            categoricalDisputeCrowdsourcer.redeem(tester.a1)

    # Now we'll redeem the forked reporting participants
    testers = [tester.a0, tester.a1, tester.a2, tester.a3]
    for i in range(market.getNumParticipants()):
        account = testers[i % 4]
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))
        expectedRep = reportingParticipant.getStake()
        expectedRep += expectedRep / localFixture.contracts["Constants"].FORK_MIGRATION_PERCENTAGE_BONUS_DIVISOR()
        expectedRep += reportingParticipant.getStake() / 2
        expectedEth = cash.balanceOf(reportingParticipant.address)
        newReputationToken = localFixture.applySignature("ReputationToken", reportingParticipant.getReputationToken())
        with EtherDelta(expectedEth, account, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            with TokenDelta(newReputationToken, expectedRep, account, "Redeeming didn't increase REP correctly"):
                reportingParticipant.redeem(account)
def test_market_escape_hatch_partial_fees(localFixture, market, reputationToken, constants, controller):
    reputationToken.transfer(tester.a1, 1 * 10**6 * 10**18)

    proceedToNextRound(localFixture, market, contributor = tester.k1)

    # Emergency Stop
    assert controller.emergencyStop()

    # We will only get back the validity bond since our REP bond and first reporter bond were forfeit already
    with EtherDelta(constants.DEFAULT_VALIDITY_BOND(), market.getOwner(), localFixture.chain, "Remaining ETH balance was not given to the market owner"):
        with TokenDelta(reputationToken, 0, market.getOwner(), "REP balance was somehow given to the market owner"):
            assert market.withdrawInEmergency()
Exemple #18
0
def test_redeem_reporting_participants(kitchenSinkFixture, market,
                                       categoricalMarket, scalarMarket,
                                       universe, cash):
    reputationToken = kitchenSinkFixture.applySignature(
        "ReputationToken", universe.getReputationToken())
    constants = kitchenSinkFixture.contracts["Constants"]

    # Initial Report
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)

    # Get the winning reporting participants
    initialReporter = kitchenSinkFixture.applySignature(
        'InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = kitchenSinkFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(2))
    winningDisputeCrowdsourcer2 = kitchenSinkFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(4))

    # Fast forward time until the new fee window is over and we can redeem
    feeWindow = kitchenSinkFixture.applySignature("FeeWindow",
                                                  market.getFeeWindow())
    kitchenSinkFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() +
                                                      1)
    assert market.finalize()

    expectedFees = getExpectedFees(kitchenSinkFixture, cash,
                                   winningDisputeCrowdsourcer1, 4)
    expectedFees += getExpectedFees(kitchenSinkFixture, cash,
                                    winningDisputeCrowdsourcer2, 2)
    expectedFees += getExpectedFees(kitchenSinkFixture, cash, initialReporter,
                                    5)
    expectedRep = long(winningDisputeCrowdsourcer2.getStake() +
                       winningDisputeCrowdsourcer1.getStake())
    expectedRep = long(expectedRep + expectedRep / 2)
    expectedRep += long(initialReporter.getStake() +
                        initialReporter.getStake() / 2)
    expectedGasBond = 2 * constants.GAS_TO_REPORT(
    ) * constants.DEFAULT_REPORTING_GAS_PRICE()
    with TokenDelta(reputationToken, expectedRep, tester.a0,
                    "Redeeming didn't refund REP"):
        with PrintGasUsed(kitchenSinkFixture, "Universe Redeem:", 0):
            assert universe.redeemStake([
                initialReporter.address, winningDisputeCrowdsourcer1.address,
                winningDisputeCrowdsourcer2.address
            ], [])
def test_forking(finalizeByMigration, manuallyDisavow, localFixture, universe,
                 market, categoricalMarket):
    # Let's go into the one dispute round for the categorical market
    proceedToNextRound(localFixture, categoricalMarket)
    proceedToNextRound(localFixture, categoricalMarket)

    # proceed to forking
    proceedToFork(localFixture, market, universe)

    with raises(TransactionFailed,
                message="We cannot migrate until the fork is finalized"):
        categoricalMarket.migrateThroughOneFork()

    # confirm that we can manually create a child universe from an outcome no one asserted was true during dispute
    numTicks = market.getNumTicks()
    childUniverse = universe.createChildUniverse(
        [numTicks / 4, numTicks * 3 / 4], False)

    # confirm that before the fork is finalized we can redeem stake in other markets crowdsourcers, which are disavowable
    categoricalDisputeCrowdsourcer = localFixture.applySignature(
        "DisputeCrowdsourcer", categoricalMarket.getReportingParticipant(1))

    if manuallyDisavow:
        assert categoricalMarket.disavowCrowdsourcers()
        # We can redeem before the fork finalizes since disavowal has occured
        assert categoricalDisputeCrowdsourcer.redeem(tester.a0)

    # finalize the fork
    finalizeFork(localFixture, market, universe, finalizeByMigration)

    # The categorical market can be migrated to the winning universe
    assert categoricalMarket.migrateThroughOneFork()

    # The dispute crowdsourcer has been disavowed
    newUniverse = localFixture.applySignature("Universe",
                                              categoricalMarket.getUniverse())
    assert newUniverse.address != universe.address
    assert categoricalDisputeCrowdsourcer.isDisavowed()
    assert not universe.isContainerForReportingParticipant(
        categoricalDisputeCrowdsourcer.address)
    assert not newUniverse.isContainerForReportingParticipant(
        categoricalDisputeCrowdsourcer.address)

    # The initial report is still present however
    categoricalInitialReport = localFixture.applySignature(
        "InitialReporter", categoricalMarket.getReportingParticipant(0))
    assert categoricalMarket.getReportingParticipant(
        0) == categoricalInitialReport.address
    assert not categoricalInitialReport.isDisavowed()
    assert not universe.isContainerForReportingParticipant(
        categoricalInitialReport.address)
    assert newUniverse.isContainerForReportingParticipant(
        categoricalInitialReport.address)
Exemple #20
0
def test_dispute_pacing_threshold(localFixture, universe, market):
    # We'll dispute until we reach the dispute pacing threshold
    while not market.getDisputePacingOn():
        proceedToNextRound(localFixture, market, moveTimeForward = False)

    # Now if we try to immediately dispute without the newly assigned dispute window being active the tx will fail
    with raises(TransactionFailed):
        market.contribute([0, market.getNumTicks(), 0], 1, "")

    # If we move time forward to the dispute window start we succeed
    disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())
    assert localFixture.contracts["Time"].setTimestamp(disputeWindow.getStartTime() + 1)
    assert market.contribute([0, market.getNumTicks(), 0], 1, "")
Exemple #21
0
def test_preemptive_crowdsourcer_after_initial(localFixture, universe, market, reputationToken):
    initialStake = market.getParticipantStake()
    # First we'll dispute the intial report
    proceedToNextRound(localFixture, market)

    # Now we'll place a large pre-emptive bond
    largeBond = initialStake * 50
    assert market.contributeToTentative([0, 0, market.getNumTicks()], largeBond, "")
    preemptiveDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer())

    # Now we'll dispute the dispute
    proceedToNextRound(localFixture, market)

    # By disputing we actually cause the preemptive bond to get placed.
    assert market.getParticipantStake() == largeBond + initialStake * 6

    # We'll dispute this newly placed bond made from the preemptive contributions
    proceedToNextRound(localFixture, market)

    # And now we'll do one more dispute in favor of the initial dispute
    proceedToNextRound(localFixture, market)

    # Now we finalize the market
    disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
    assert market.finalize()

    # Because the overloaded bond was disputed there is now sufficient REP to award the overload tokens with ROI as well
    with TokenDelta(reputationToken, largeBond * 1.4, localFixture.accounts[0], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[0])
def test_forkAndRedeem(localFixture, universe, market, categoricalMarket, cash, reputationToken):
    # Let's do some initial disputes for the categorical market
    proceedToNextRound(localFixture, categoricalMarket, tester.k1, moveTimeForward = False)

    # Get to a fork
    testers = [tester.k0, tester.k1, tester.k2, tester.k3]
    testerIndex = 1
    while (market.getForkingMarket() == longToHexString(0)):
        proceedToNextRound(localFixture, market, testers[testerIndex], True)
        testerIndex += 1
        testerIndex = testerIndex % len(testers)

    # Have the participants fork and create new child universes
    for i in range(market.getNumParticipants()):
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))

    # Finalize the fork
    finalizeFork(localFixture, market, universe)

    categoricalDisputeCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", categoricalMarket.getReportingParticipant(1))

    # Migrate the categorical market into the winning universe. This will disavow the dispute crowdsourcer on it, letting us redeem for original universe rep and eth
    assert categoricalMarket.migrateThroughOneFork()

    expectedRep = categoricalDisputeCrowdsourcer.getStake()
    expectedEth = getExpectedFees(localFixture, cash, categoricalDisputeCrowdsourcer, 2)
    with EtherDelta(expectedEth, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
        with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't increase REP correctly"):
            categoricalDisputeCrowdsourcer.redeem(tester.a1)

    noPayoutNumerators = [0] * market.getNumberOfOutcomes()
    noPayoutNumerators[0] = market.getNumTicks()
    yesPayoutNumerators = noPayoutNumerators[::-1]
    noUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(noPayoutNumerators, False))
    yesUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(yesPayoutNumerators, False))
    noUniverseReputationToken = localFixture.applySignature('ReputationToken', noUniverse.getReputationToken())
    yesUniverseReputationToken = localFixture.applySignature('ReputationToken', yesUniverse.getReputationToken())

    # Now we'll fork and redeem the reporting participants
    for i in range(market.getNumParticipants()):
        account = localFixture.testerAddress[i % 4]
        key = localFixture.testerKey[i % 4]
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))
        expectedRep = reportingParticipant.getStake()
        expectedRep += expectedRep / localFixture.contracts["Constants"].FORK_MIGRATION_PERCENTAGE_BONUS_DIVISOR()
        expectedRep += reportingParticipant.getStake() / 2
        repToken = noUniverseReputationToken if i % 2 == 0 else yesUniverseReputationToken
        with TokenDelta(repToken, expectedRep, account, "Redeeming didn't increase REP correctly for " + str(i)):
            assert reportingParticipant.forkAndRedeem(sender=key)
Exemple #23
0
def test_preemptive_crowdsourcer_contributions_dont_fill_bonds(localFixture, universe, market, reputationToken):
    # We can pre-emptively stake REP in case someone disputes our initial report
    preemptiveBondSize = 1

    initialStake = market.getParticipantStake()
    realBondSize = initialStake * 3
    assert market.contributeToTentative([0, market.getNumTicks(), 0], preemptiveBondSize, "")
    preemptiveDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer())

    # Now we'll dispute the initial report
    proceedToNextRound(localFixture, market)

    # We can see that the tentative winning outcome is the one suggested in the dispute still since not enouhg pre-emptive REP was placed to fill the bond
    assert market.getWinningReportingParticipant() != preemptiveDisputeCrowdsourcer.address
    assert market.getCrowdsourcer(preemptiveDisputeCrowdsourcer.getPayoutDistributionHash()) == preemptiveDisputeCrowdsourcer.address
def test_forkAndRedeem(localFixture, universe, market, categoricalMarket, cash, reputationToken):
    # Let's do some initial disputes for the categorical market
    proceedToNextRound(localFixture, categoricalMarket, tester.k1, moveTimeForward = False)

    # Get to a fork
    testers = [tester.k0, tester.k1, tester.k2, tester.k3]
    testerIndex = 1
    while (market.getForkingMarket() == longToHexString(0)):
        proceedToNextRound(localFixture, market, testers[testerIndex], True)
        testerIndex += 1
        testerIndex = testerIndex % len(testers)

    # Have the participants fork and create new child universes
    for i in range(market.getNumParticipants()):
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))

    # Finalize the fork
    finalizeFork(localFixture, market, universe)

    categoricalDisputeCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", categoricalMarket.getReportingParticipant(1))

    # Migrate the categorical market into the winning universe. This will disavow the dispute crowdsourcer on it, letting us redeem for original universe rep and eth
    assert categoricalMarket.migrateThroughOneFork([0,0,categoricalMarket.getNumTicks()], False, "")

    expectedRep = categoricalDisputeCrowdsourcer.getStake()
    expectedEth = getExpectedFees(localFixture, cash, categoricalDisputeCrowdsourcer, 1)
    with EtherDelta(expectedEth, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
        with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't increase REP correctly"):
            categoricalDisputeCrowdsourcer.redeem(tester.a1)

    noPayoutNumerators = [0] * market.getNumberOfOutcomes()
    noPayoutNumerators[0] = market.getNumTicks()
    yesPayoutNumerators = noPayoutNumerators[::-1]
    noUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(noPayoutNumerators, False))
    yesUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(yesPayoutNumerators, False))
    noUniverseReputationToken = localFixture.applySignature('ReputationToken', noUniverse.getReputationToken())
    yesUniverseReputationToken = localFixture.applySignature('ReputationToken', yesUniverse.getReputationToken())

    # Now we'll fork and redeem the reporting participants
    for i in range(market.getNumParticipants()):
        account = localFixture.testerAddress[i % 4]
        key = localFixture.testerKey[i % 4]
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))
        expectedRep = reportingParticipant.getStake()
        expectedRep += reportingParticipant.getStake() / 2
        repToken = noUniverseReputationToken if i % 2 == 0 else yesUniverseReputationToken
        with TokenDelta(repToken, expectedRep, account, "Redeeming didn't increase REP correctly for " + str(i)):
            assert reportingParticipant.forkAndRedeem(sender=key)
Exemple #25
0
def test_market_escape_hatch_partial_fees(localFixture, market,
                                          reputationToken, constants,
                                          controller):
    reputationToken.transfer(tester.a1, 1 * 10**6 * 10**18)

    proceedToNextRound(localFixture, market, contributor=tester.k1)

    # Emergency Stop
    assert controller.emergencyStop()

    # We will only get back the validity bond since our REP bond and first reporter bond were forfeit already
    with EtherDelta(constants.DEFAULT_VALIDITY_BOND(), market.getOwner(),
                    localFixture.chain,
                    "Remaining ETH balance was not given to the market owner"):
        with TokenDelta(reputationToken, 0, market.getOwner(),
                        "REP balance was somehow given to the market owner"):
            assert market.withdrawInEmergency()
Exemple #26
0
def test_forkAndRedeem(localFixture, universe, market, categoricalMarket, cash, reputationToken):
    # Let's do some initial disputes for the categorical market
    proceedToNextRound(localFixture, categoricalMarket, localFixture.accounts[1], moveTimeForward = False)

    # Get to a fork
    testers = [localFixture.accounts[0], localFixture.accounts[1], localFixture.accounts[2], localFixture.accounts[3]]
    testerIndex = 1
    while (market.getForkingMarket() == longToHexString(0)):
        proceedToNextRound(localFixture, market, testers[testerIndex], True)
        testerIndex += 1
        testerIndex = testerIndex % len(testers)

    # Have the participants fork and create new child universes
    for i in range(market.getNumParticipants()):
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))

    # Finalize the fork
    finalize(localFixture, market, universe)

    categoricalDisputeCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", categoricalMarket.getReportingParticipant(1))

    # Migrate the categorical market into the winning universe. This will disavow the dispute crowdsourcer on it, letting us redeem for original universe rep
    assert categoricalMarket.migrateThroughOneFork([0,0,0,categoricalMarket.getNumTicks()], "")

    expectedRep = categoricalDisputeCrowdsourcer.getStake()
    with TokenDelta(reputationToken, expectedRep, localFixture.accounts[1], "Redeeming didn't increase REP correctly"):
        categoricalDisputeCrowdsourcer.redeem(localFixture.accounts[1])

    noPayoutNumerators = [0] * market.getNumberOfOutcomes()
    noPayoutNumerators[1] = market.getNumTicks()
    yesPayoutNumerators = [0] * market.getNumberOfOutcomes()
    yesPayoutNumerators[2] = market.getNumTicks()
    noUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(noPayoutNumerators))
    yesUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(yesPayoutNumerators))
    noUniverseReputationToken = localFixture.applySignature('ReputationToken', noUniverse.getReputationToken())
    yesUniverseReputationToken = localFixture.applySignature('ReputationToken', yesUniverse.getReputationToken())

    # Now we'll fork and redeem the reporting participants
    for i in range(market.getNumParticipants()):
        account = localFixture.accounts[i % 4]
        reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(i))
        expectedRep = reputationToken.balanceOf(reportingParticipant.address) * 7 / 5 # * 1.4 to account for the minting reward of 40%
        repToken = noUniverseReputationToken if i % 2 == 0 else yesUniverseReputationToken
        with TokenDelta(repToken, expectedRep, account, "Redeeming didn't increase REP correctly for " + str(i)):
            assert reportingParticipant.forkAndRedeem(sender=account)
Exemple #27
0
def test_redeem_reporting_participants(kitchenSinkFixture, market,
                                       categoricalMarket, scalarMarket,
                                       universe, cash):
    reputationToken = kitchenSinkFixture.applySignature(
        "ReputationToken", universe.getReputationToken())
    constants = kitchenSinkFixture.contracts["Constants"]

    # Initial Report
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Losing
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)
    # Initial Report Winning
    proceedToNextRound(kitchenSinkFixture, market, doGenerateFees=True)

    # Get the winning reporting participants
    initialReporter = kitchenSinkFixture.applySignature(
        'InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = kitchenSinkFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(2))
    winningDisputeCrowdsourcer2 = kitchenSinkFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(4))

    # Fast forward time until the new dispute window is over and we can redeem
    disputeWindow = kitchenSinkFixture.applySignature(
        "DisputeWindow", market.getDisputeWindow())
    kitchenSinkFixture.contracts["Time"].setTimestamp(
        disputeWindow.getEndTime() + 1)
    assert market.finalize()

    expectedRep = winningDisputeCrowdsourcer2.getStake(
    ) + winningDisputeCrowdsourcer1.getStake() + initialReporter.getStake()
    expectedRep = expectedRep + expectedRep * 2 / 5
    expectedRep -= 1  # Rounding error
    with TokenDelta(reputationToken, expectedRep, tester.a0,
                    "Redeeming didn't refund REP"):
        with PrintGasUsed(kitchenSinkFixture, "Universe Redeem:", 0):
            assert universe.redeemStake([
                initialReporter.address, winningDisputeCrowdsourcer1.address,
                winningDisputeCrowdsourcer2.address
            ])
Exemple #28
0
def test_multiple_round_crowdsourcer(localFixture, universe, market, cash, reputationToken):
    constants = localFixture.contracts["Constants"]

    # Initial Report disputed
    proceedToNextRound(localFixture, market, localFixture.accounts[1], True)
    # Initial Report winning
    proceedToNextRound(localFixture, market, localFixture.accounts[2], True)
    # Initial Report disputed
    proceedToNextRound(localFixture, market, localFixture.accounts[1], True, randomPayoutNumerators=True)
    # Initial Report winning
    proceedToNextRound(localFixture, market, localFixture.accounts[3], True)

    # Get all the winning Reporting Participants
    initialReporter = localFixture.applySignature('InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(2))
    winningDisputeCrowdsourcer2 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(4))

    # Get losing Reporting Participants
    losingDisputeCrowdsourcer1 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1))
    losingDisputeCrowdsourcer2 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(3))

    # We can't redeem yet as the market isn't finalized
    with raises(TransactionFailed):
        initialReporter.redeem(localFixture.accounts[0])

    with raises(TransactionFailed):
        winningDisputeCrowdsourcer1.redeem(localFixture.accounts[2])

    # Fast forward time until the new dispute window is over
    disputeWindow = localFixture.applySignature("DisputeWindow", market.getDisputeWindow())
    localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
    assert market.finalize()

    expectedRep = initialReporter.getStake() + initialReporter.getStake() * 2 / 5
    with TokenDelta(reputationToken, expectedRep, localFixture.accounts[0], "Redeeming didn't refund REP"):
        assert initialReporter.redeem(localFixture.accounts[0])

    expectedRep = winningDisputeCrowdsourcer1.getStake() + winningDisputeCrowdsourcer1.getStake() * 2 / 5
    with TokenDelta(reputationToken, expectedRep, localFixture.accounts[2], "Redeeming didn't refund REP"):
        assert winningDisputeCrowdsourcer1.redeem(localFixture.accounts[2])

    expectedRep = winningDisputeCrowdsourcer2.getStake() + winningDisputeCrowdsourcer2.getStake() * 2 / 5
    with TokenDelta(reputationToken, expectedRep, localFixture.accounts[3], "Redeeming didn't refund REP"):
        assert winningDisputeCrowdsourcer2.redeem(localFixture.accounts[3])

    # The losing reports get no REP
    with TokenDelta(reputationToken, 0, localFixture.accounts[1], "Redeeming refunded REP"):
        assert losingDisputeCrowdsourcer1.redeem(localFixture.accounts[1])

    with TokenDelta(reputationToken, 0, localFixture.accounts[1], "Redeeming refunded REP"):
        assert losingDisputeCrowdsourcer2.redeem(localFixture.accounts[1])
def test_redeem(localFixture, universe, cash, market):
    # Initial report
    proceedToNextRound(localFixture, market)
    # Initial losing
    proceedToNextRound(localFixture, market)
    # Initial Winning
    proceedToNextRound(localFixture, market, doGenerateFees = True)

    initialReporter = localFixture.applySignature('InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(2))
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())

    assert feeWindow.buy(100)

    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    with PrintGasUsed(localFixture, "InitialReporter:redeem", INITIAL_REPORT_REDEMPTION):
        initialReporter.redeem(tester.a0)

    with PrintGasUsed(localFixture, "DisputeCrowdsourcer:redeem", CROWDSOURCER_REDEMPTION):
        winningDisputeCrowdsourcer1.redeem(tester.a0)

    with PrintGasUsed(localFixture, "FeeWindow:redeem", PARTICIPATION_TOKEN_REDEMPTION):
        feeWindow.redeem(tester.a0)
def test_reporting_participant_escape_hatch(localFixture, controller, reputationToken, market, constants, cash):
    # Initial Reporting
    proceedToNextRound(localFixture, market)
    # Crowdsourcer 1
    proceedToNextRound(localFixture, market)
    # Crowdsourcer 2
    proceedToNextRound(localFixture, market)

    initialReporter = localFixture.applySignature("InitialReporter", market.getReportingParticipant(0))
    crowdsourcer1 = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(1))
    crowdsourcer2 = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(2))

    # We cannot call the escape hatches yet
    with raises(TransactionFailed):
        initialReporter.withdrawInEmergency()

    with raises(TransactionFailed):
        crowdsourcer1.withdrawInEmergency()

    with raises(TransactionFailed):
        crowdsourcer2.withdrawInEmergency()

    # Emergency Stop
    assert controller.emergencyStop()

    # We can now call the escape hatch
    with TokenDelta(reputationToken, reputationToken.balanceOf(initialReporter.address), tester.a0, "REP was not given back"):
        assert initialReporter.withdrawInEmergency()

    with TokenDelta(reputationToken, reputationToken.balanceOf(crowdsourcer1.address), tester.a0, "REP was not given back"):
        assert crowdsourcer1.withdrawInEmergency()

    with TokenDelta(reputationToken, reputationToken.balanceOf(crowdsourcer2.address), tester.a0, "REP was not given back"):
        assert crowdsourcer2.withdrawInEmergency()
Exemple #31
0
def test_redeem(localFixture, universe, cash, market):
    # Initial report
    proceedToNextRound(localFixture, market)
    # Initial losing
    proceedToNextRound(localFixture, market)
    # Initial Winning
    proceedToNextRound(localFixture, market, doGenerateFees=True)

    initialReporter = localFixture.applySignature(
        'InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = localFixture.applySignature(
        'DisputeCrowdsourcer', market.getReportingParticipant(2))
    feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow())

    assert feeWindow.buy(100)

    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    with PrintGasUsed(localFixture, "InitialReporter:redeem",
                      INITIAL_REPORT_REDEMPTION):
        initialReporter.redeem(tester.a0)

    with PrintGasUsed(localFixture, "DisputeCrowdsourcer:redeem",
                      CROWDSOURCER_REDEMPTION):
        winningDisputeCrowdsourcer1.redeem(tester.a0)

    with PrintGasUsed(localFixture, "FeeWindow:redeem",
                      PARTICIPATION_TOKEN_REDEMPTION):
        feeWindow.redeem(tester.a0)
Exemple #32
0
def test_roundsOfReporting(rounds, localFixture, market, universe):
    disputeWindow = universe.getOrCreateCurrentDisputeWindow(False)

    # Do the initial report
    proceedToNextRound(localFixture, market, moveTimeForward=False)

    initialDisputeWindow = localFixture.applySignature(
        'DisputeWindow', market.getDisputeWindow())
    assert initialDisputeWindow.duration() == localFixture.contracts[
        "Constants"].INITIAL_DISPUTE_ROUND_DURATION_SECONDS()

    # Do the first round outside of the loop and test logging
    crowdsourcerCreatedLog = {
        "universe": universe.address,
        "market": market.address,
        "size": universe.getInitialReportMinValue() * 2,
        "payoutNumerators": [0, 0, market.getNumTicks()],
    }

    crowdsourcerContributionLog = {
        "universe": universe.address,
        "reporter": bytesToHexString(tester.a0),
        "market": market.address,
        "amountStaked": universe.getInitialReportMinValue() * 2,
        "description": "Clearly incorrect",
    }

    crowdsourcerCompletedLog = {
        "universe": universe.address,
        "market": market.address
    }

    with AssertLog(localFixture, "DisputeCrowdsourcerCreated",
                   crowdsourcerCreatedLog):
        with AssertLog(localFixture, "DisputeCrowdsourcerContribution",
                       crowdsourcerContributionLog):
            with AssertLog(localFixture, "DisputeCrowdsourcerCompleted",
                           crowdsourcerCompletedLog):
                proceedToNextRound(localFixture,
                                   market,
                                   description="Clearly incorrect")

    newDisputeWindow = localFixture.applySignature('DisputeWindow',
                                                   market.getDisputeWindow())
    assert newDisputeWindow.duration(
    ) == localFixture.contracts["Constants"].DISPUTE_ROUND_DURATION_SECONDS()

    # proceed through several rounds of disputing
    for i in range(rounds - 2):
        proceedToNextRound(localFixture, market)
        assert disputeWindow != market.getDisputeWindow()
        disputeWindow = market.getDisputeWindow()
        assert disputeWindow == universe.getCurrentDisputeWindow(False)
Exemple #33
0
def test_reporting(kitchenSinkFixture, augur, cash, market):
    hotLoading = kitchenSinkFixture.contracts[
        "HotLoadingUniversal"] if kitchenSinkFixture.paraAugur else kitchenSinkFixture.contracts[
            "HotLoading"]
    if kitchenSinkFixture.paraAugur:
        augur = kitchenSinkFixture.contracts["ParaAugur"]
    fillOrder = kitchenSinkFixture.contracts["FillOrder"]
    orders = kitchenSinkFixture.contracts["Orders"]
    account = kitchenSinkFixture.accounts[0]

    # Get to Designated Reporting
    proceedToDesignatedReporting(kitchenSinkFixture, market)
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 1
    assert marketData.disputeRound == 0

    # Get to Open Reporting
    proceedToInitialReporting(kitchenSinkFixture, market)
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 2
    assert marketData.disputeRound == 0

    # Get to Disputing
    proceedToNextRound(kitchenSinkFixture, market)
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 3
    assert marketData.disputeRound == 0

    # Proceed to next round
    proceedToNextRound(kitchenSinkFixture, market)
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 3
    assert marketData.disputeRound == 1

    # Get to Awaiting Next Window
    while not market.getDisputePacingOn():
        proceedToNextRound(kitchenSinkFixture, market, moveTimeForward=False)
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 4
    assert marketData.disputeRound == 11

    # Get to AwaitingFinalization
    kitchenSinkFixture.contracts["Time"].incrementTimestamp(30 * 24 * 60 * 60)
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 5

    # get to Finalized
    market.finalize()
    marketData = getMarketData(hotLoading, augur, market, fillOrder, orders)
    assert marketData.reportingState == 6
def test_crowdsourcer_transfer(contractsFixture, market, universe):
    proceedToNextRound(contractsFixture, market)
    proceedToNextRound(contractsFixture, market)
    proceedToNextRound(contractsFixture, market)

    crowdsourcer = contractsFixture.applySignature(
        "DisputeCrowdsourcer", market.getWinningReportingParticipant())

    transferAmount = 1
    tester0Balance = crowdsourcer.balanceOf(
        contractsFixture.accounts[0]) - transferAmount
    tester1Balance = crowdsourcer.balanceOf(
        contractsFixture.accounts[1]) + transferAmount

    crowdsourcerTokenTransferLog = {
        'from': contractsFixture.accounts[0],
        'to': contractsFixture.accounts[1],
        'token': crowdsourcer.address,
        'universe': universe.address,
        'tokenType': 1,
        'value': transferAmount,
    }

    crowdsourcerTokenBalance0Log = {
        'owner': contractsFixture.accounts[0],
        'token': crowdsourcer.address,
        'universe': universe.address,
        'tokenType': 1,
        'balance': tester0Balance,
    }

    crowdsourcerTokenBalance1Log = {
        'owner': contractsFixture.accounts[1],
        'token': crowdsourcer.address,
        'universe': universe.address,
        'tokenType': 1,
        'balance': tester1Balance,
    }

    with AssertLog(contractsFixture, "TokensTransferred",
                   crowdsourcerTokenTransferLog):
        with AssertLog(contractsFixture, "TokenBalanceChanged",
                       crowdsourcerTokenBalance0Log):
            with AssertLog(contractsFixture,
                           "TokenBalanceChanged",
                           crowdsourcerTokenBalance1Log,
                           skip=1):
                assert crowdsourcer.transfer(contractsFixture.accounts[1],
                                             transferAmount)
def test_preemptive_crowdsourcer_contributions_disputed_twice_wins(
        localFixture, universe, market, reputationToken):
    # We can pre-emptively stake REP in case someone disputes our initial report
    preemptiveBondSize = 200 * 10**18

    # We'll have two users buy stake in varying amounts
    initialStake = market.getParticipantStake()
    realBondSize = initialStake * 3
    assert market.contributeToTentative([0, market.getNumTicks(), 0],
                                        realBondSize, "")
    assert market.contributeToTentative([0, market.getNumTicks(), 0],
                                        preemptiveBondSize - realBondSize,
                                        "",
                                        sender=localFixture.accounts[1])
    preemptiveDisputeCrowdsourcer = localFixture.applySignature(
        'DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer())

    # Now we'll dispute the intial report
    proceedToNextRound(localFixture, market)

    # By disputing we actually cause the preemptive bond to get placed.
    assert market.getParticipantStake(
    ) == preemptiveBondSize + initialStake * 3

    # We'll dispute this newly placed bond made from the preemptive contributions
    proceedToNextRound(localFixture, market)

    # And now we'll do one more dispute in favor of the initial report
    proceedToNextRound(localFixture, market)

    # Now we finalize the market
    disputeWindow = localFixture.applySignature('DisputeWindow',
                                                market.getDisputeWindow())

    # Time marches on and the market can be finalized
    localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1)
    assert market.finalize()

    # Because the overloaded bond was disputed there is now sufficient REP to award the overload tokens with ROI as well so both users will receive a 40% ROI
    expectedWinnings = realBondSize * .4
    with TokenDelta(reputationToken, realBondSize + expectedWinnings,
                    localFixture.accounts[0], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[0])

    overloadStake = preemptiveBondSize - realBondSize
    expectedWinnings = overloadStake * .4
    with TokenDelta(reputationToken, overloadStake + expectedWinnings,
                    localFixture.accounts[1], "Redeeming didn't refund REP"):
        assert preemptiveDisputeCrowdsourcer.redeem(localFixture.accounts[1])
def test_crowdsourcer_transfer(contractsFixture, market, universe):
    proceedToNextRound(contractsFixture, market)
    proceedToNextRound(contractsFixture, market)
    proceedToNextRound(contractsFixture, market)

    crowdsourcer = contractsFixture.applySignature("DisputeCrowdsourcer", market.getWinningReportingParticipant())

    crowdsourcerTokenTransferLog = {
        'from': bytesToHexString(tester.a0),
        'to': bytesToHexString(tester.a1),
        'token': crowdsourcer.address,
        'universe': universe.address,
        'tokenType': 2,
        'value': 0,
    }
    with AssertLog(contractsFixture, "TokensTransferred", crowdsourcerTokenTransferLog):
        assert crowdsourcer.transfer(tester.a1, 0)
def test_contribute(localFixture, universe, cash, market):
    proceedToNextRound(localFixture, market)

    with PrintGasUsed(localFixture, "Market.contribute", FIRST_CONTRIBUTE):
        market.contribute([0, market.getNumTicks()], False, 1)

    with PrintGasUsed(localFixture, "Market.contribute", FIRST_COMPLETED_CONTRIBUTE):
        market.contribute([0, market.getNumTicks()], False, market.getParticipantStake())

    for i in range(9):
        proceedToNextRound(localFixture, market, randomPayoutNumerators = True)

    with PrintGasUsed(localFixture, "Market.contribute", LAST_COMPLETED_CONTRIBUTE):
        proceedToNextRound(localFixture, market, randomPayoutNumerators = True)

    with PrintGasUsed(localFixture, "Market.contribute", FORKING_CONTRIBUTE):
        market.contribute([market.getNumTicks() / 2, market.getNumTicks() / 2], False, market.getParticipantStake())
Exemple #38
0
def test_contribute(localFixture, universe, cash, market):
    proceedToNextRound(localFixture, market)

    with PrintGasUsed(localFixture, "Market.contribute", FIRST_CONTRIBUTE):
        market.contribute([0, market.getNumTicks()], False, 1)

    with PrintGasUsed(localFixture, "Market.contribute", FIRST_COMPLETED_CONTRIBUTE):
        market.contribute([0, market.getNumTicks()], False, market.getParticipantStake())

    for i in range(9):
        proceedToNextRound(localFixture, market, randomPayoutNumerators = True)

    with PrintGasUsed(localFixture, "Market.contribute", LAST_COMPLETED_CONTRIBUTE):
        proceedToNextRound(localFixture, market, randomPayoutNumerators = True)

    with PrintGasUsed(localFixture, "Market.contribute", FORKING_CONTRIBUTE):
        market.contribute([market.getNumTicks() / 2, market.getNumTicks() / 2], False, market.getParticipantStake())
Exemple #39
0
def test_reporting_participant_escape_hatch(localFixture, controller,
                                            reputationToken, market, constants,
                                            cash):
    # Initial Reporting
    proceedToNextRound(localFixture, market)
    # Crowdsourcer 1
    proceedToNextRound(localFixture, market)
    # Crowdsourcer 2
    proceedToNextRound(localFixture, market)

    initialReporter = localFixture.applySignature(
        "InitialReporter", market.getReportingParticipant(0))
    crowdsourcer1 = localFixture.applySignature(
        "DisputeCrowdsourcer", market.getReportingParticipant(1))
    crowdsourcer2 = localFixture.applySignature(
        "DisputeCrowdsourcer", market.getReportingParticipant(2))

    # We cannot call the escape hatches yet
    with raises(TransactionFailed):
        initialReporter.withdrawInEmergency()

    with raises(TransactionFailed):
        crowdsourcer1.withdrawInEmergency()

    with raises(TransactionFailed):
        crowdsourcer2.withdrawInEmergency()

    # Emergency Stop
    assert controller.emergencyStop()

    # We can now call the escape hatch
    with TokenDelta(reputationToken,
                    reputationToken.balanceOf(initialReporter.address),
                    tester.a0, "REP was not given back"):
        assert initialReporter.withdrawInEmergency()

    with TokenDelta(reputationToken,
                    reputationToken.balanceOf(crowdsourcer1.address),
                    tester.a0, "REP was not given back"):
        assert crowdsourcer1.withdrawInEmergency()

    with TokenDelta(reputationToken,
                    reputationToken.balanceOf(crowdsourcer2.address),
                    tester.a0, "REP was not given back"):
        assert crowdsourcer2.withdrawInEmergency()
Exemple #40
0
def test_roundsOfReporting(rounds, localFixture, market, universe):
    feeWindow = universe.getOrCreateCurrentFeeWindow()

    # Do the initial report
    proceedToNextRound(localFixture, market, moveTimeForward=False)

    # We can't contribute to a crowdsourcer now since the new fee window is not yet active
    with raises(TransactionFailed):
        market.contribute([0, market.getNumTicks()], False)

    # Do the first round outside of the loop and test logging
    crowdsourcerCreatedLog = {
        "universe": universe.address,
        "market": market.address,
        "size": universe.getInitialReportMinValue() * 2,
        "payoutNumerators": [0, market.getNumTicks()],
        "invalid": False
    }

    crowdsourcerContributionLog = {
        "universe": universe.address,
        "reporter": bytesToHexString(tester.a0),
        "market": market.address,
        "amountStaked": universe.getInitialReportMinValue() * 2
    }

    crowdsourcerCompletedLog = {
        "universe": universe.address,
        "market": market.address
    }

    with AssertLog(localFixture, "DisputeCrowdsourcerCreated",
                   crowdsourcerCreatedLog):
        with AssertLog(localFixture, "DisputeCrowdsourcerContribution",
                       crowdsourcerContributionLog):
            with AssertLog(localFixture, "DisputeCrowdsourcerCompleted",
                           crowdsourcerCompletedLog):
                proceedToNextRound(localFixture, market)

    # proceed through several rounds of disputing
    for i in range(rounds - 2):
        proceedToNextRound(localFixture, market)
        assert feeWindow != market.getFeeWindow()
        feeWindow = market.getFeeWindow()
        assert feeWindow == universe.getCurrentFeeWindow()
Exemple #41
0
def test_roundsOfReporting(rounds, localFixture, market, universe):
    feeWindow = universe.getOrCreateCurrentFeeWindow()

    # Do the initial report
    proceedToNextRound(localFixture, market, moveTimeForward=False)

    # Do the first round outside of the loop and test logging
    crowdsourcerCreatedLog = {
        "universe": universe.address,
        "market": market.address,
        "size": universe.getInitialReportMinValue() * 2,
        "payoutNumerators": [0, market.getNumTicks()],
        "invalid": False
    }

    crowdsourcerContributionLog = {
        "universe": universe.address,
        "reporter": bytesToHexString(tester.a0),
        "market": market.address,
        "amountStaked": universe.getInitialReportMinValue() * 2,
        "description": "Clearly incorrect",
    }

    crowdsourcerCompletedLog = {
        "universe": universe.address,
        "market": market.address
    }

    with AssertLog(localFixture, "DisputeCrowdsourcerCreated",
                   crowdsourcerCreatedLog):
        with AssertLog(localFixture, "DisputeCrowdsourcerContribution",
                       crowdsourcerContributionLog):
            with AssertLog(localFixture, "DisputeCrowdsourcerCompleted",
                           crowdsourcerCompletedLog):
                proceedToNextRound(localFixture,
                                   market,
                                   description="Clearly incorrect")

    # proceed through several rounds of disputing
    for i in range(rounds - 2):
        proceedToNextRound(localFixture, market)
        assert feeWindow != market.getFeeWindow()
        feeWindow = market.getFeeWindow()
        assert feeWindow == universe.getCurrentFeeWindow()
def test_roundsOfReporting(rounds, localFixture, market, universe):
    feeWindow = universe.getOrCreateCurrentFeeWindow()

    # Do the initial report
    proceedToNextRound(localFixture, market, moveTimeForward = False)

    # We can't contribute to a crowdsourcer now since the new fee window is not yet active
    with raises(TransactionFailed):
        market.contribute([0, market.getNumTicks()], False)

    # Do the first round outside of the loop and test logging
    crowdsourcerCreatedLog = {
        "universe": universe.address,
        "market": market.address,
        "size": universe.getInitialReportMinValue() * 2,
        "payoutNumerators": [0, market.getNumTicks()],
        "invalid": False
    }

    crowdsourcerContributionLog = {
        "universe": universe.address,
        "reporter": bytesToHexString(tester.a0),
        "market": market.address,
        "amountStaked": universe.getInitialReportMinValue() * 2
    }

    crowdsourcerCompletedLog = {
        "universe": universe.address,
        "market": market.address
    }

    with AssertLog(localFixture, "DisputeCrowdsourcerCreated", crowdsourcerCreatedLog):
        with AssertLog(localFixture, "DisputeCrowdsourcerContribution", crowdsourcerContributionLog):
            with AssertLog(localFixture, "DisputeCrowdsourcerCompleted", crowdsourcerCompletedLog):
                proceedToNextRound(localFixture, market)

    # proceed through several rounds of disputing
    for i in range(rounds - 2):
        proceedToNextRound(localFixture, market)
        assert feeWindow != market.getFeeWindow()
        feeWindow = market.getFeeWindow()
        assert feeWindow == universe.getCurrentFeeWindow()
def test_multiple_round_crowdsourcer_fees(localFixture, universe, market, cash, reputationToken):
    constants = localFixture.contracts["Constants"]

    # Initial Report disputed
    proceedToNextRound(localFixture, market, tester.k1, True)
    # Initial Report winning
    proceedToNextRound(localFixture, market, tester.k2, True)
    # Initial Report disputed
    proceedToNextRound(localFixture, market, tester.k1, True, randomPayoutNumerators=True)
    # Initial Report winning
    proceedToNextRound(localFixture, market, tester.k3, True)

    # Get all the winning Reporting Participants
    initialReporter = localFixture.applySignature('InitialReporter', market.getReportingParticipant(0))
    winningDisputeCrowdsourcer1 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(2))
    winningDisputeCrowdsourcer2 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(4))

    # Get losing Reporting Participants
    losingDisputeCrowdsourcer1 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1))
    losingDisputeCrowdsourcer2 = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(3))

    # We can't redeem yet as the market isn't finalized
    with raises(TransactionFailed):
        initialReporter.redeem(tester.a0)

    with raises(TransactionFailed):
        winningDisputeCrowdsourcer1.redeem(tester.a2)

    # Fast forward time until the new fee window is over and we can receive fees
    feeWindow = localFixture.applySignature("FeeWindow", market.getFeeWindow())
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)
    assert market.finalize()

    # The initial reporter locked in REP for 5 rounds.
    expectedInitialReporterFees = getExpectedFees(localFixture, cash, initialReporter, 5)
    expectedRep = long(initialReporter.getStake() + initialReporter.getStake() / 2)
    with TokenDelta(reputationToken, expectedRep, tester.a0, "Redeeming didn't refund REP"):
        with EtherDelta(expectedInitialReporterFees, tester.a0, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert initialReporter.redeem(tester.a0)

    # The first winning dispute crowdsourcer will get fees for 4 rounds
    expectedWinningDisputeCrowdsourcer1Fees = getExpectedFees(localFixture, cash, winningDisputeCrowdsourcer1, 4)
    expectedRep = long(winningDisputeCrowdsourcer1.getStake() + winningDisputeCrowdsourcer1.getStake() / 2)
    with TokenDelta(reputationToken, expectedRep, tester.a2, "Redeeming didn't refund REP"):
        with EtherDelta(expectedWinningDisputeCrowdsourcer1Fees, tester.a2, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert winningDisputeCrowdsourcer1.redeem(tester.a2)

    # The final winning dispute crowdsourcer will get fees for 2 rounds
    expectedWinningDisputeCrowdsourcer2Fees = getExpectedFees(localFixture, cash, winningDisputeCrowdsourcer2, 2)
    expectedRep = long(winningDisputeCrowdsourcer2.getStake() + winningDisputeCrowdsourcer2.getStake() / 2)
    with TokenDelta(reputationToken, expectedRep, tester.a3, "Redeeming didn't refund REP"):
        with EtherDelta(expectedWinningDisputeCrowdsourcer2Fees, tester.a3, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert winningDisputeCrowdsourcer2.redeem(tester.a3)

    # The losing reports get fees as well but no REP
    # The first losing bond has fees from 5 rounds
    expectedLosingDisputeCrowdsourcer1Fees = getExpectedFees(localFixture, cash, losingDisputeCrowdsourcer1, 5)
    with TokenDelta(reputationToken, 0, tester.a1, "Redeeming refunded REP"):
        with EtherDelta(expectedLosingDisputeCrowdsourcer1Fees, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert losingDisputeCrowdsourcer1.redeem(tester.a1)

    # The second losing bond has fees from 3 rounds
    expectedLosingDisputeCrowdsourcer2Fees = getExpectedFees(localFixture, cash, losingDisputeCrowdsourcer2, 3)
    with TokenDelta(reputationToken, 0, tester.a1, "Redeeming refunded REP"):
        with EtherDelta(expectedLosingDisputeCrowdsourcer2Fees, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"):
            assert losingDisputeCrowdsourcer2.redeem(tester.a1)
def test_forking(finalizeByMigration, manuallyDisavow, localFixture, universe, cash, market, categoricalMarket, scalarMarket):
    # Let's go into the one dispute round for the categorical market
    proceedToNextRound(localFixture, categoricalMarket)
    proceedToNextRound(localFixture, categoricalMarket)

    # proceed to forking
    proceedToFork(localFixture, market, universe)

    with raises(TransactionFailed):
        universe.fork()

    with raises(TransactionFailed, message="We cannot migrate until the fork is finalized"):
        categoricalMarket.migrateThroughOneFork()

    with raises(TransactionFailed, message="We cannot create markets during a fork"):
        time = localFixture.contracts["Time"].getTimestamp()
        localFixture.createBinaryMarket(universe, time + 1000, 1, cash, tester.a0)

    # confirm that we can manually create a child universe from an outcome no one asserted was true during dispute
    numTicks = market.getNumTicks()
    childUniverse = universe.createChildUniverse([numTicks/ 4, numTicks * 3 / 4], False)

    # confirm that before the fork is finalized we can redeem stake in other markets crowdsourcers, which are disavowable
    categoricalDisputeCrowdsourcer = localFixture.applySignature("DisputeCrowdsourcer", categoricalMarket.getReportingParticipant(1))

    # confirm we cannot migrate it
    with raises(TransactionFailed):
        categoricalDisputeCrowdsourcer.migrate()

    # confirm we cannot liquidate it
    with raises(TransactionFailed):
        categoricalDisputeCrowdsourcer.liquidateLosing()

    # confirm we cannot fork it
    with raises(TransactionFailed):
        categoricalDisputeCrowdsourcer.fork()

    if manuallyDisavow:
        marketParticipantsDisavowedLog = {
            "universe": universe.address,
            "market": categoricalMarket.address,
        }
        with AssertLog(localFixture, "MarketParticipantsDisavowed", marketParticipantsDisavowedLog):
            assert categoricalMarket.disavowCrowdsourcers()
        # We can redeem before the fork finalizes since disavowal has occured
        assert categoricalDisputeCrowdsourcer.redeem(tester.a0)

    # We cannot contribute to a crowdsourcer during a fork
    with raises(TransactionFailed):
        categoricalMarket.contribute([2,2,categoricalMarket.getNumTicks()-4], False, 1)

    # We cannot purchase new Participation Tokens during a fork
    feeWindowAddress = universe.getCurrentFeeWindow()
    feeWindow = localFixture.applySignature("FeeWindow", feeWindowAddress)
    with raises(TransactionFailed):
        feeWindow.buy(1)

    # finalize the fork
    marketFinalizedLog = {
        "universe": universe.address,
        "market": market.address,
    }
    with AssertLog(localFixture, "MarketFinalized", marketFinalizedLog):
        finalizeFork(localFixture, market, universe, finalizeByMigration)

    # We cannot contribute to a crowdsourcer in a forked universe
    with raises(TransactionFailed):
        categoricalMarket.contribute([2,2,categoricalMarket.getNumTicks()-4], False, 1)

    # The categorical market can be migrated to the winning universe
    newUniverseAddress = universe.getWinningChildUniverse()
    marketMigratedLog = {
        "market": categoricalMarket.address,
        "newUniverse": newUniverseAddress,
        "originalUniverse": universe.address,
    }
    with AssertLog(localFixture, "MarketMigrated", marketMigratedLog):
        assert categoricalMarket.migrateThroughOneFork()

    # The dispute crowdsourcer has been disavowed
    newUniverse = localFixture.applySignature("Universe", categoricalMarket.getUniverse())
    assert newUniverse.address != universe.address
    assert categoricalDisputeCrowdsourcer.isDisavowed()
    assert not universe.isContainerForReportingParticipant(categoricalDisputeCrowdsourcer.address)
    assert not newUniverse.isContainerForReportingParticipant(categoricalDisputeCrowdsourcer.address)

    # The initial report is still present however
    categoricalInitialReport = localFixture.applySignature("InitialReporter", categoricalMarket.getReportingParticipant(0))
    assert categoricalMarket.getReportingParticipant(0) == categoricalInitialReport.address
    assert not categoricalInitialReport.isDisavowed()
    assert not universe.isContainerForReportingParticipant(categoricalInitialReport.address)
    assert newUniverse.isContainerForReportingParticipant(categoricalInitialReport.address)

    # The categorical market has a new fee window since it was initially reported on and may be disputed now
    categoricalMarketFeeWindowAddress = categoricalMarket.getFeeWindow()
    categoricalMarketFeeWindow = localFixture.applySignature("FeeWindow", categoricalMarketFeeWindowAddress)

    proceedToNextRound(localFixture, categoricalMarket, moveTimeForward = False)

    # We can also purchase Participation Tokens in this fee window
    assert categoricalMarketFeeWindow.buy(1)

    # We will finalize the categorical market in the new universe
    feeWindow = localFixture.applySignature('FeeWindow', categoricalMarket.getFeeWindow())
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)

    assert categoricalMarket.finalize()

    # We can migrate a market that has not had its initial reporting completed as well, and confirm its REP no show bond is in the new universe REP
    reputationToken = localFixture.applySignature("ReputationToken", universe.getReputationToken())
    previousREPBalance = reputationToken.balanceOf(scalarMarket.address)
    assert previousREPBalance > 0
    bonus = previousREPBalance / localFixture.contracts["Constants"].FORK_MIGRATION_PERCENTAGE_BONUS_DIVISOR() if finalizeByMigration else 0
    assert scalarMarket.migrateThroughOneFork()
    newUniverseREP = localFixture.applySignature("ReputationToken", newUniverse.getReputationToken())
    assert newUniverseREP.balanceOf(scalarMarket.address) == previousREPBalance + bonus

    # We can finalize this market as well
    proceedToNextRound(localFixture, scalarMarket)
    feeWindow = localFixture.applySignature('FeeWindow', scalarMarket.getFeeWindow())
    localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1)

    assert scalarMarket.finalize()