Пример #1
0
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()
Пример #2
0
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()
Пример #3
0
def test_fork_migration_no_report(localFixture, universe, market, cash):
    # 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 = long(localFixture.contracts["Time"].getTimestamp() +
                   timedelta(days=90).total_seconds())
    longMarket = localFixture.createYesNoMarket(universe, endTime, 1, cash,
                                                tester.a0)

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

    # Now finalize the fork so migration can occur
    finalizeFork(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([], False, "")
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)
Пример #5
0
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)
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)
Пример #7
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([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)
Пример #8
0
def test_forking_values(localFixture, universe, market, cash):
    reputationToken = localFixture.applySignature(
        "ReputationToken", universe.getReputationToken())

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

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

    # We can see that the theoretical total REP supply in the winning child universe is higher than the initial REP supply
    winningPayoutHash = market.getWinningPayoutDistributionHash()
    childUniverse = localFixture.applySignature(
        "Universe", universe.getChildUniverse(winningPayoutHash))
    childUniverseReputationToken = localFixture.applySignature(
        "ReputationToken", childUniverse.getReputationToken())
    childUniverseTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply(
    )
    assert childUniverseTheoreticalSupply > reputationToken.getTotalTheoreticalSupply(
    )

    # In fact it will be approximately the bonus REP migrated into the new universe more.
    delta = childUniverseTheoreticalSupply - reputationToken.getTotalTheoreticalSupply(
    )
    migrationBonus = long(childUniverseReputationToken.getTotalMigrated() /
                          20L)
    participantIndex = 0
    while True:
        try:
            reportingParticipant = localFixture.applySignature(
                "DisputeCrowdsourcer",
                market.getReportingParticipant(participantIndex))
            participantIndex += 1
            if reportingParticipant.getPayoutDistributionHash(
            ) != winningPayoutHash:
                continue
            migrationBonus += long(reportingParticipant.getSize() / 2L)
        except TransactionFailed:
            break
    assert delta == migrationBonus - 5  # rounding error dust buildup

    # The universe needs to be nudged to actually update values since there are potentially unbounded universes and updating the values derived by this total is not essential as a matter of normal procedure
    assert childUniverse.getForkReputationGoal(
    ) == universe.getForkReputationGoal()
    assert childUniverse.getDisputeThresholdForFork(
    ) == universe.getDisputeThresholdForFork()
    assert childUniverse.getInitialReportMinValue(
    ) == universe.getInitialReportMinValue()

    # The universe uses this theoretical total to calculate values such as the fork goal, fork dispute threshhold and the initial reporting defaults and floors
    assert childUniverse.updateForkValues()
    assert childUniverse.getForkReputationGoal(
    ) == childUniverseTheoreticalSupply / 2
    assert childUniverse.getDisputeThresholdForFork() == long(
        childUniverseTheoreticalSupply / 40L)
    assert childUniverse.getInitialReportMinValue() == long(
        childUniverse.getDisputeThresholdForFork() / 3L / 2**18 + 1)

    # Now we'll fork again and confirm it still takes only 20 dispute rounds in the worst case
    newMarket = localFixture.createReasonableBinaryMarket(childUniverse, cash)
    proceedToFork(localFixture, newMarket, childUniverse)
    assert newMarket.getNumParticipants() == 21

    # finalize the fork
    finalizeFork(localFixture, newMarket, childUniverse)

    # The total theoretical supply is again larger.
    childWinningPayoutHash = newMarket.getWinningPayoutDistributionHash()
    leafUniverse = localFixture.applySignature(
        "Universe", childUniverse.getChildUniverse(childWinningPayoutHash))
    leafUniverseReputationToken = localFixture.applySignature(
        "ReputationToken", leafUniverse.getReputationToken())
    leafUniverseTheoreticalSupply = leafUniverseReputationToken.getTotalTheoreticalSupply(
    )
    assert leafUniverseTheoreticalSupply > childUniverseReputationToken.getTotalTheoreticalSupply(
    )

    # We can make the child universe theoretical total more accurate by asking for a recomputation given a specific sibling universe to deduct from
    losingPayoutHash = market.derivePayoutDistributionHash(
        [0, market.getNumTicks()], False)
    siblingUniverse = localFixture.applySignature(
        "Universe", universe.getChildUniverse(losingPayoutHash))
    siblingReputationToken = localFixture.applySignature(
        "ReputationToken", siblingUniverse.getReputationToken())
    assert childUniverseReputationToken.updateSiblingMigrationTotal(
        siblingReputationToken.address)
    newChildTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply(
    )
    siblingMigrationAmount = siblingReputationToken.getTotalMigrated()
    assert childUniverseTheoreticalSupply - newChildTheoreticalSupply == siblingMigrationAmount

    # Now that the child universe has been updated we can ask the leaf universe to recompute based on its parent's new theoretical total supply
    assert leafUniverseReputationToken.updateParentTotalTheoreticalSupply()
    newLeafTheoreticalSupply = leafUniverseReputationToken.getTotalTheoreticalSupply(
    )
    assert leafUniverseTheoreticalSupply - newLeafTheoreticalSupply == siblingMigrationAmount
Пример #9
0
def test_forking(finalizeByMigration, manuallyDisavow, localFixture, universe,
                 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,
                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)

    # 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
    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
    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()
Пример #10
0
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
    for i in range(market.getNumParticipants()):
        reportingParticipant = localFixture.applySignature(
            "DisputeCrowdsourcer", market.getReportingParticipant(i))
        with PrintGasUsed(localFixture, "Fork:", 0):
            reportingParticipant.fork(startgas=long(6.7 * 10**6))

    # 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,
                                                  startgas=long(6.7 * 10**6))

    # 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,
                                            startgas=long(6.7 * 10**6))
Пример #11
0
def test_forking_values(localFixture, universe, market):
    reputationToken = localFixture.applySignature("ReputationToken", universe.getReputationToken())

    # Give some REP to another account
    reputationToken.transfer(tester.a1, 100)

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

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

    # We can see that the theoretical total REP supply in the winning child universe is equal to the parent supply
    winningPayoutHash = market.getWinningPayoutDistributionHash()
    childUniverse = localFixture.applySignature("Universe", universe.getChildUniverse(winningPayoutHash))
    childUniverseReputationToken = localFixture.applySignature("ReputationToken", childUniverse.getReputationToken())
    childUniverseTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply()
    assert childUniverseTheoreticalSupply == reputationToken.getTotalTheoreticalSupply()

    # If we nudge the reputation token to update its theoretical balance we can see a lower total to account for sibling migrations
    assert childUniverseReputationToken.updateTotalTheoreticalSupply()
    assert childUniverseReputationToken.getTotalTheoreticalSupply() <= childUniverseTheoreticalSupply
    childUniverseTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply()

    # If we migrate some REP to another Universe we can recalculate and see that amount deducted from the theoretical supply
    losingPayoutNumerators = [0, 0, market.getNumTicks()]
    losingUniverse =  localFixture.applySignature('Universe', universe.createChildUniverse(losingPayoutNumerators))
    losingUniverseReputationToken = localFixture.applySignature('ReputationToken', losingUniverse.getReputationToken())
    assert reputationToken.migrateOut(losingUniverseReputationToken.address, 100, sender=tester.k1)
    assert childUniverseReputationToken.updateTotalTheoreticalSupply()
    lowerChildUniverseTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply()
    assert lowerChildUniverseTheoreticalSupply == childUniverseTheoreticalSupply - 100

    # If we move past the forking window end time and we update the theoretical supply however we will see that some REP was trapped in the parent and deducted from the supply
    localFixture.contracts["Time"].setTimestamp(universe.getForkEndTime() + 1)
    assert childUniverseReputationToken.updateTotalTheoreticalSupply()
    childUniverseTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply()
    assert childUniverseTheoreticalSupply < lowerChildUniverseTheoreticalSupply

    # The universe needs to be nudged to actually update values since there are potentially unbounded universes and updating the values derived by this total is not essential as a matter of normal procedure
    # In a forked universe the total supply will be different so its childrens goals will not be the same initially
    if not localFixture.subFork:
        assert childUniverse.getForkReputationGoal() == universe.getForkReputationGoal()
        assert childUniverse.getDisputeThresholdForFork() == universe.getDisputeThresholdForFork()
        assert childUniverse.getInitialReportMinValue() == universe.getInitialReportMinValue()

    # The universe uses this theoretical total to calculate values such as the fork goal, fork dispute threshhold and the initial reporting defaults and floors
    assert childUniverse.updateForkValues()
    assert childUniverse.getForkReputationGoal() == childUniverseTheoreticalSupply / 2
    assert childUniverse.getDisputeThresholdForFork() == long(childUniverseTheoreticalSupply / 40L)
    assert childUniverse.getInitialReportMinValue() == long(childUniverse.getDisputeThresholdForFork() / 3L / 2**18 + 1)

    # Now we'll fork again and confirm it still takes only 20 dispute rounds in the worst case
    newMarket = localFixture.createReasonableYesNoMarket(childUniverse)
    proceedToFork(localFixture, newMarket, childUniverse)
    assert newMarket.getNumParticipants() == 21

    # finalize the fork
    finalizeFork(localFixture, newMarket, childUniverse)

    # The total theoretical supply is again the same as the parents during the fork
    childWinningPayoutHash = newMarket.getWinningPayoutDistributionHash()
    leafUniverse = localFixture.applySignature("Universe", childUniverse.getChildUniverse(childWinningPayoutHash))
    leafUniverseReputationToken = localFixture.applySignature("ReputationToken", leafUniverse.getReputationToken())
    leafUniverseTheoreticalSupply = leafUniverseReputationToken.getTotalTheoreticalSupply()
    assert leafUniverseTheoreticalSupply == childUniverseReputationToken.getTotalTheoreticalSupply()

    # After the fork window ends however we can again recalculate
    localFixture.contracts["Time"].setTimestamp(childUniverse.getForkEndTime() + 1)
    assert leafUniverseReputationToken.updateTotalTheoreticalSupply()
    leafUniverseTheoreticalSupply = leafUniverseReputationToken.getTotalTheoreticalSupply()
    assert leafUniverseTheoreticalSupply < childUniverseReputationToken.getTotalTheoreticalSupply()
Пример #12
0
def test_forking(finalizeByMigration, manuallyDisavow, localFixture, universe, 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([0,0,0,categoricalMarket.getNumTicks()], "")

    with raises(TransactionFailed, message="We cannot create markets during a fork"):
        time = localFixture.contracts["Time"].getTimestamp()
        localFixture.createYesNoMarket(universe, time + 1000, 1, 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([0, numTicks/ 4, numTicks * 3 / 4])

    # 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 liquidate it
    with raises(TransactionFailed):
        categoricalDisputeCrowdsourcer.liquidateLosing()

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

    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([0,2,2,categoricalMarket.getNumTicks()-4], 1, "")

    # We cannot purchase new Participation Tokens during a fork
    disputeWindowAddress = universe.getCurrentDisputeWindow()
    disputeWindow = localFixture.applySignature("DisputeWindow", disputeWindowAddress)

    # 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([0,2,2,categoricalMarket.getNumTicks()-4], 1, "")

    newUniverseAddress = universe.getWinningChildUniverse()

    # buy some complete sets to change OI
    completeSets = localFixture.contracts['CompleteSets']
    numSets = 10
    cost = categoricalMarket.getNumTicks() * numSets
    assert completeSets.publicBuyCompleteSets(categoricalMarket.address, 10, sender=tester.k1, value=cost)
    assert universe.getOpenInterestInAttoEth() == cost

    marketMigratedLog = {
        "market": categoricalMarket.address,
        "newUniverse": newUniverseAddress,
        "originalUniverse": universe.address,
    }
    with AssertLog(localFixture, "MarketMigrated", marketMigratedLog):
        assert categoricalMarket.migrateThroughOneFork([0,0,0,categoricalMarket.getNumTicks()], "")

    assert universe.getOpenInterestInAttoEth() == 0


    # 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)
    assert newUniverse.getOpenInterestInAttoEth() == cost

    # 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 dispute window since it was initially reported on and may be disputed now
    categoricalMarketDisputeWindowAddress = categoricalMarket.getDisputeWindow()
    categoricalMarketDisputeWindow = localFixture.applySignature("DisputeWindow", categoricalMarketDisputeWindowAddress)

    proceedToNextRound(localFixture, categoricalMarket)

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

    assert categoricalMarket.finalize()

    # We can migrate a market that has not had its initial reporting completed as well, and confirm that the report is now made in the new universe
    reputationToken = localFixture.applySignature("ReputationToken", universe.getReputationToken())
    previousREPBalance = reputationToken.balanceOf(scalarMarket.address)
    assert previousREPBalance > 0
    assert scalarMarket.migrateThroughOneFork([0,0,scalarMarket.getNumTicks()], "")
    newUniverseREP = localFixture.applySignature("ReputationToken", newUniverse.getReputationToken())
    initialReporter = localFixture.applySignature('InitialReporter', scalarMarket.getInitialReporter())
    assert newUniverseREP.balanceOf(initialReporter.address) == newUniverse.getOrCacheDesignatedReportNoShowBond()

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

    assert scalarMarket.finalize()
Пример #13
0
def test_forking_values(localFixture, universe, market, cash):
    reputationToken = localFixture.applySignature("ReputationToken", universe.getReputationToken())

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

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

    # We can see that the theoretical total REP supply in the winning child universe is higher than the initial REP supply
    winningPayoutHash = market.getWinningPayoutDistributionHash()
    childUniverse = localFixture.applySignature("Universe", universe.getChildUniverse(winningPayoutHash))
    childUniverseReputationToken = localFixture.applySignature("ReputationToken", childUniverse.getReputationToken())
    childUniverseTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply()
    assert childUniverseTheoreticalSupply > reputationToken.getTotalTheoreticalSupply()

    # In fact it will be approximately the bonus REP migrated into the new universe more.
    delta = childUniverseTheoreticalSupply - reputationToken.getTotalTheoreticalSupply()
    migrationBonus = long(childUniverseReputationToken.getTotalMigrated() / 20L)
    participantIndex = 0
    while True:
        try:
            reportingParticipant = localFixture.applySignature("DisputeCrowdsourcer", market.getReportingParticipant(participantIndex))
            participantIndex += 1
            if reportingParticipant.getPayoutDistributionHash() != winningPayoutHash:
                continue
            migrationBonus += long(reportingParticipant.getSize() / 2L)
        except TransactionFailed:
            break
    assert delta == migrationBonus - 5 # rounding error dust buildup

    # The universe needs to be nudged to actually update values since there are potentially unbounded universes and updating the values derived by this total is not essential as a matter of normal procedure
    assert childUniverse.getForkReputationGoal() == universe.getForkReputationGoal()
    assert childUniverse.getDisputeThresholdForFork() == universe.getDisputeThresholdForFork()
    assert childUniverse.getInitialReportMinValue() == universe.getInitialReportMinValue()

    # The universe uses this theoretical total to calculate values such as the fork goal, fork dispute threshhold and the initial reporting defaults and floors
    assert childUniverse.updateForkValues()
    assert childUniverse.getForkReputationGoal() == childUniverseTheoreticalSupply / 2
    assert childUniverse.getDisputeThresholdForFork() == long(childUniverseTheoreticalSupply / 40L)
    assert childUniverse.getInitialReportMinValue() == long(childUniverse.getDisputeThresholdForFork() / 3L / 2**18 + 1)

    # Now we'll fork again and confirm it still takes only 20 dispute rounds in the worst case
    newMarket = localFixture.createReasonableBinaryMarket(childUniverse, cash)
    proceedToFork(localFixture, newMarket, childUniverse)
    assert newMarket.getNumParticipants() == 21

    # finalize the fork
    finalizeFork(localFixture, newMarket, childUniverse)

    # The total theoretical supply is again larger.
    childWinningPayoutHash = newMarket.getWinningPayoutDistributionHash()
    leafUniverse = localFixture.applySignature("Universe", childUniverse.getChildUniverse(childWinningPayoutHash))
    leafUniverseReputationToken = localFixture.applySignature("ReputationToken", leafUniverse.getReputationToken())
    leafUniverseTheoreticalSupply = leafUniverseReputationToken.getTotalTheoreticalSupply()
    assert leafUniverseTheoreticalSupply > childUniverseReputationToken.getTotalTheoreticalSupply()

    # We can make the child universe theoretical total more accurate by asking for a recomputation given a specific sibling universe to deduct from
    losingPayoutHash = market.derivePayoutDistributionHash([0, market.getNumTicks()], False)
    siblingUniverse = localFixture.applySignature("Universe", universe.getChildUniverse(losingPayoutHash))
    siblingReputationToken = localFixture.applySignature("ReputationToken", siblingUniverse.getReputationToken())
    assert childUniverseReputationToken.updateSiblingMigrationTotal(siblingReputationToken.address)
    newChildTheoreticalSupply = childUniverseReputationToken.getTotalTheoreticalSupply()
    siblingMigrationAmount = siblingReputationToken.getTotalMigrated()
    assert childUniverseTheoreticalSupply - newChildTheoreticalSupply == siblingMigrationAmount

    # Now that the child universe has been updated we can ask the leaf universe to recompute based on its parent's new theoretical total supply
    assert leafUniverseReputationToken.updateParentTotalTheoreticalSupply()
    newLeafTheoreticalSupply = leafUniverseReputationToken.getTotalTheoreticalSupply()
    assert leafUniverseTheoreticalSupply - newLeafTheoreticalSupply == siblingMigrationAmount
Пример #14
0
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()