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_additional_initial_report_stake(contractsFixture, universe, reputationToken, market): # Skip to Designated Reporting contractsFixture.contracts["Time"].setTimestamp(market.getEndTime() + 1) # Designated Report with additional stake specified designatedReportCost = universe.getOrCacheDesignatedReportStake() additionalStake = 500 * 10**18 with TokenDelta( reputationToken, -additionalStake, contractsFixture.accounts[0], "Doing the designated report with additional stake didn't take the additional stake" ): market.doInitialReport([0, market.getNumTicks(), 0], "", additionalStake) # Now let the market resolve with the initial report disputeWindow = contractsFixture.applySignature('DisputeWindow', market.getDisputeWindow()) # Time marches on and the market can be finalized contractsFixture.contracts["Time"].setTimestamp( disputeWindow.getEndTime() + 1) assert market.finalize() # The premptive bond can be redeemed for the REP staked preemptiveDisputeCrowdsourcer = contractsFixture.applySignature( 'DisputeCrowdsourcer', market.preemptiveDisputeCrowdsourcer()) with TokenDelta(reputationToken, additionalStake, contractsFixture.accounts[0], "Redeeming didn't refund REP"): assert preemptiveDisputeCrowdsourcer.redeem( contractsFixture.accounts[0])
def test_redeem_shares_affiliate(kitchenSinkFixture, universe, cash, market): shareToken = kitchenSinkFixture.contracts['ShareToken'] expectedValue = 100 * market.getNumTicks() expectedReporterFees = expectedValue / universe.getOrCacheReportingFeeDivisor() expectedMarketCreatorFees = expectedValue / market.getMarketCreatorSettlementFeeDivisor() expectedSettlementFees = expectedReporterFees + expectedMarketCreatorFees expectedPayout = expectedValue - expectedSettlementFees expectedAffiliateFees = expectedMarketCreatorFees / market.affiliateFeeDivisor() expectedMarketCreatorFees = expectedMarketCreatorFees - expectedAffiliateFees assert universe.getOpenInterestInAttoCash() == 0 affiliateAddress = kitchenSinkFixture.accounts[5] # get YES shares with a1 acquireLongShares(kitchenSinkFixture, cash, market, YES, 100, shareToken.address, sender = kitchenSinkFixture.accounts[1]) # get NO shares with a2 acquireShortShareSet(kitchenSinkFixture, cash, market, YES, 100, shareToken.address, sender = kitchenSinkFixture.accounts[2]) finalizeMarket(kitchenSinkFixture, market, [0, 0, 10**2]) with TokenDelta(cash, expectedMarketCreatorFees, market.getOwner(), "market creator fees not paid"): with TokenDelta(cash, expectedAffiliateFees, affiliateAddress, "affiliate fees not paid"): # redeem shares with a1 shareToken.claimTradingProceeds(market.address, kitchenSinkFixture.accounts[1], affiliateAddress) # redeem shares with a2 shareToken.claimTradingProceeds(market.address, kitchenSinkFixture.accounts[2], affiliateAddress) # assert a1 ends up with cash (minus fees) and a2 does not assert cash.balanceOf(kitchenSinkFixture.accounts[1]) == expectedPayout assert shareToken.balanceOfMarketOutcome(market.address, YES, kitchenSinkFixture.accounts[1]) == 0 assert shareToken.balanceOfMarketOutcome(market.address, YES, kitchenSinkFixture.accounts[2]) == 0 assert shareToken.balanceOfMarketOutcome(market.address, NO, kitchenSinkFixture.accounts[1]) == 0 assert shareToken.balanceOfMarketOutcome(market.address, NO, kitchenSinkFixture.accounts[2]) == 0
def test_one_bid_on_books_buy_partial_order(contractsFixture, cash, market): zeroXTradeToken = contractsFixture.contracts['ZeroXTradeToken'] expirationTime = contractsFixture.contracts['Time'].getTimestamp() + 10000 salt = 5 tradeGroupID = longTo32Bytes(42) yesShareToken = contractsFixture.applySignature("ShareToken", market.getShareToken(YES)) noShareToken = contractsFixture.applySignature("ShareToken", market.getShareToken(NO)) # create signed order cash.faucet(fix('2', '60'), sender=contractsFixture.accounts[1]) rawZeroXOrderData, orderHash = zeroXTradeToken.createZeroXOrder( BID, fix(2), 60, market.address, YES, nullAddress, expirationTime, salt, sender=contractsFixture.accounts[1]) signature = signOrder(orderHash, contractsFixture.privateKeys[1]) # fill signed order orderEventLog = { "eventType": 2, "addressData": [ nullAddress, contractsFixture.accounts[1], contractsFixture.accounts[2] ], "uint256Data": [ 60, 0, YES, 0, 0, 0, fix(1), contractsFixture.contracts['Time'].getTimestamp(), 0, 0 ], } orders = [rawZeroXOrderData] signatures = [signature] cash.faucet(fix('1', '40'), sender=contractsFixture.accounts[2]) expectedAmountRemaining = fix(1) with AssertLog(contractsFixture, "OrderEvent", orderEventLog): with TokenDelta(yesShareToken, fix(1), contractsFixture.accounts[1], "Creator Shares not received"): with TokenDelta(noShareToken, fix(1), contractsFixture.accounts[2], "Taker Shares not received"): with TokenDelta(cash, -fix(1, 60), contractsFixture.accounts[1], "Creator cash not taken"): with TokenDelta(cash, -fix(1, 40), contractsFixture.accounts[2], "Taker cash not taken"): assert zeroXTradeToken.trade( fix(1), nullAddress, tradeGroupID, orders, signatures, sender=contractsFixture.accounts[2]) == 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([], "")
def test_multiple_contributors_crowdsourcer(localFixture, universe, market, cash, reputationToken): disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow()) # We'll make the window active localFixture.contracts["Time"].setTimestamp(disputeWindow.getStartTime() + 1) # We'll have testers push markets into the next round by funding dispute crowdsourcers amount = market.getParticipantStake() with TokenDelta(reputationToken, -amount, localFixture.accounts[1], "Disputing did not reduce REP balance correctly"): assert market.contribute([0, 0, market.getNumTicks()], amount, "", sender=localFixture.accounts[1]) with TokenDelta(reputationToken, -amount, localFixture.accounts[2], "Disputing did not reduce REP balance correctly"): assert market.contribute([0, 0, market.getNumTicks()], amount, "", sender=localFixture.accounts[2]) newDisputeWindowAddress = market.getDisputeWindow() assert newDisputeWindowAddress != disputeWindow.address # fast forward time to the fee new window disputeWindow = localFixture.applySignature('DisputeWindow', newDisputeWindowAddress) localFixture.contracts["Time"].setTimestamp(disputeWindow.getStartTime() + 1) # Fast forward time until the new dispute window is over and we can redeem our winning stake, and dispute bond tokens localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1) assert market.finalize() marketDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1)) expectedRep = amount + amount * 2 / 5 with TokenDelta(reputationToken, expectedRep, localFixture.accounts[1], "Redeeming didn't refund REP"): assert marketDisputeCrowdsourcer.redeem(localFixture.accounts[1]) with TokenDelta(reputationToken, expectedRep, localFixture.accounts[2], "Redeeming didn't refund REP"): assert marketDisputeCrowdsourcer.redeem(localFixture.accounts[2])
def test_warp_sync(contractsFixture, augur, universe, reputationToken, warpSync, cash): account = contractsFixture.accounts[0] time = contractsFixture.contracts["Time"] # See that warp sync market does not exist initially assert warpSync.markets(universe.address) == nullAddress # We can initialize the warp sync market for a universe and be rewarded with REP based on how long since the universe was created expectedCreationReward = warpSync.getCreationReward(universe.address) with PrintGasUsed(contractsFixture, "WS Market Finalization Cost", 0): with TokenDelta(reputationToken, expectedCreationReward, account, "REP reward not minted for initializing universe"): warpSync.initializeUniverse(universe.address) # The market now exists market = contractsFixture.applySignature("Market", warpSync.markets(universe.address)) # Initially there is no warp sync data for this universe assert warpSync.data(universe.address) == [0, 0] # Finalize the warp sync market with some value proceedToDesignatedReporting(contractsFixture, market) numTicks = market.getNumTicks() assert warpSync.doInitialReport(universe.address, [0,0,numTicks], "") disputeWindow = contractsFixture.applySignature("DisputeWindow", market.getDisputeWindow()) time.setTimestamp(disputeWindow.getEndTime()) # Finalizing the warp sync market will award the finalizer REP based on time since it became finalizable expectedFinalizationReward = warpSync.getFinalizationReward(market.address) WarpSyncDataUpdatedLog = { "universe": universe.address, "warpSyncHash": numTicks, "marketEndTime": market.getEndTime() } with AssertLog(contractsFixture, "WarpSyncDataUpdated", WarpSyncDataUpdatedLog): with PrintGasUsed(contractsFixture, "WS Market Finalization Cost", 0): with TokenDelta(reputationToken, expectedFinalizationReward, account, "REP reward not minted for finalizer"): assert market.finalize() # Check Warp Sync contract for universe and see existing value assert warpSync.data(universe.address) == [numTicks, market.getEndTime()] # See new warp sync market newWarpSyncMarket = contractsFixture.applySignature("Market", warpSync.markets(universe.address)) assert newWarpSyncMarket.address != market.address # Finalize it proceedToInitialReporting(contractsFixture, newWarpSyncMarket) numTicks = newWarpSyncMarket.getNumTicks() assert newWarpSyncMarket.doInitialReport([0,1,numTicks-1], "", 0) disputeWindow = contractsFixture.applySignature("DisputeWindow", newWarpSyncMarket.getDisputeWindow()) time.setTimestamp(disputeWindow.getEndTime()) assert newWarpSyncMarket.finalize() # See new warp sync value assert warpSync.data(universe.address) == [numTicks-1, newWarpSyncMarket.getEndTime()] # See another new market assert newWarpSyncMarket.address != warpSync.markets(universe.address)
def test_market_escape_hatch_partial_fees(localFixture, market, reputationToken, reportingWindow, constants, controller): # We'll skip to Limited reporting and make a report localFixture.chain.head_state.timestamp = reportingWindow.getStartTime( ) + 1 stakeToken = localFixture.getStakeToken(market, [0, market.getNumTicks()], False) MarketEtherDelta = constants.DEFAULT_VALIDITY_BOND( ) - localFixture.chain.head_state.get_balance(market.address) with EtherDelta(MarketEtherDelta, market.address, localFixture.chain, "First reporter gas fee was not given to first reporter"): with TokenDelta(reputationToken, -reputationToken.balanceOf(market.address), market.address, "REP balance was not given to the first reporter"): stakeToken.buy(0, sender=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()
def test_openInterestCash_payFees(contractsFixture, augur, universe, cash, market): openInterestCashAddress = universe.openInterestCash() openInterestCash = contractsFixture.applySignature("OICash", openInterestCashAddress) account1 = contractsFixture.accounts[0] account2 = contractsFixture.accounts[1] depositAmount = 10 * 10**18 assert cash.faucet(depositAmount) assert cash.faucet(depositAmount, sender=account2) with TokenDelta(cash, -depositAmount, account1): assert openInterestCash.deposit(depositAmount) with TokenDelta(cash, -depositAmount, account2): assert openInterestCash.deposit(depositAmount, sender=account2) reportingFeeDivisor = universe.getOrCacheReportingFeeDivisor() disputeWindowAddress = universe.getOrCreateNextDisputeWindow(False) halfDepositFees = depositAmount / reportingFeeDivisor / 2 # We'll have account 2 pay half of the deposit amount fee balance with TokenDelta(cash, halfDepositFees, disputeWindowAddress): assert openInterestCash.payFees(halfDepositFees, sender=account2) feesPaid = openInterestCash.feesPaid() assert feesPaid == halfDepositFees # On withdraw account 1 will only have to pay half of the amount owed expectedFees = depositAmount / reportingFeeDivisor / 2 expectedPayout = depositAmount - expectedFees with TokenDelta(cash, expectedPayout, account1): with TokenDelta(cash, expectedFees, disputeWindowAddress): assert openInterestCash.withdraw(depositAmount)
def test_multiple_contributors_crowdsourcer_fees(localFixture, universe, market, cash, reputationToken): feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow()) # We'll make the window active localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1) # generate some fees generateFees(localFixture, universe, market) # We'll have testers push markets into the next round by funding dispute crowdsourcers amount = market.getTotalStake() with TokenDelta(reputationToken, -amount, tester.a1, "Disputing did not reduce REP balance correctly"): assert market.contribute([0, market.getNumTicks()], False, amount, sender=tester.k1, startgas=long(6.7 * 10**6)) with TokenDelta(reputationToken, -amount, tester.a2, "Disputing did not reduce REP balance correctly"): assert market.contribute([0, market.getNumTicks()], False, amount, sender=tester.k2, startgas=long(6.7 * 10**6)) newFeeWindowAddress = market.getFeeWindow() assert newFeeWindowAddress != feeWindow.address # fast forward time to the fee new window and generate additional fees feeWindow = localFixture.applySignature('FeeWindow', newFeeWindowAddress) localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1) # Fast forward time until the new fee window is over and we can redeem our winning stake, and dispute bond tokens and receive fees localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1) assert market.finalize() marketDisputeCrowdsourcer = localFixture.applySignature( 'DisputeCrowdsourcer', market.getReportingParticipant(1)) # The dispute crowdsourcer contributors locked in REP for 2 rounds and staked twice the initial reporter so they split 2/3 of the total stake expectedFees = cash.balanceOf(feeWindow.address) + cash.balanceOf( universe.getOrCreateFeeWindowBefore(feeWindow.address)) expectedFees = expectedFees / 3 * 2 expectedRep = long(amount + amount / 2) with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't refund REP"): with EtherDelta(expectedFees / 2, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"): assert marketDisputeCrowdsourcer.redeem(tester.a1) with TokenDelta(reputationToken, expectedRep + 1, tester.a2, "Redeeming didn't refund REP"): with EtherDelta(expectedFees - expectedFees / 2, tester.a2, localFixture.chain, "Redeeming didn't increase ETH correctly"): assert marketDisputeCrowdsourcer.redeem(tester.a2)
def test_variable_validity_bond(invalid, contractsFixture, universe, cash): # We can't make a market with less than the minimum required validity bond minimumValidityBond = universe.getOrCacheMarketCreationCost() with raises(TransactionFailed): contractsFixture.createReasonableYesNoMarket( universe, validityBond=minimumValidityBond - 1) # No longer testing a higher validity bond, token transfers are token precisely, no ability to send more than required market = contractsFixture.createReasonableYesNoMarket( universe, validityBond=minimumValidityBond) assert market.getValidityBondAttoEth() == minimumValidityBond # If we resolve the market the bond in it's entirety will go to the fee pool or to the market creator if the resolution was not invalid proceedToDesignatedReporting(contractsFixture, market) if invalid: market.doInitialReport([market.getNumTicks(), 0, 0], "") else: market.doInitialReport([0, 0, market.getNumTicks()], "") # Move time forward so we can finalize and see the bond move disputeWindow = contractsFixture.applySignature('DisputeWindow', market.getDisputeWindow()) assert contractsFixture.contracts["Time"].setTimestamp( disputeWindow.getEndTime() + 1) if invalid: with TokenDelta(cash, minimumValidityBond, universe.getAuction(), "Validity bond did not go to the auction"): market.finalize() else: with TokenDelta(cash, minimumValidityBond, market.getOwner(), "Validity bond did not go to the market creator"): market.finalize()
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_initial_report(localFixture, universe, market, categoricalMarket, scalarMarket, cash, reputationToken): disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow()) constants = localFixture.contracts["Constants"] # Now end the window and finalize localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1) assert market.finalize() assert categoricalMarket.finalize() assert scalarMarket.finalize() marketInitialReport = localFixture.applySignature('InitialReporter', market.getInitialReporter()) categoricalInitialReport = localFixture.applySignature('InitialReporter', categoricalMarket.getInitialReporter()) marketStake = marketInitialReport.getStake() initialReporterRedeemedLog = { "reporter": localFixture.accounts[0], "amountRedeemed": marketStake, "repReceived": marketStake, "payoutNumerators": [0, market.getNumTicks(), 0], "universe": universe.address, "market": market.address } with AssertLog(localFixture, "InitialReporterRedeemed", initialReporterRedeemedLog): with TokenDelta(reputationToken, marketStake, localFixture.accounts[0], "Redeeming didn't refund REP"): assert marketInitialReport.redeem(localFixture.accounts[0]) categoricalMarketStake = categoricalInitialReport.getStake() with TokenDelta(reputationToken, categoricalMarketStake, localFixture.accounts[0], "Redeeming didn't refund REP"): assert categoricalInitialReport.redeem(localFixture.accounts[0])
def test_failed_crowdsourcer(finalize, localFixture, universe, market, cash, reputationToken): feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow()) # We'll make the window active localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1) # We'll have testers contribute to a dispute but not reach the target amount = market.getParticipantStake() # confirm we can contribute 0 assert market.contribute([1, market.getNumTicks() - 1], False, 0, "", sender=tester.k1) with TokenDelta(reputationToken, -amount + 1, tester.a1, "Disputing did not reduce REP balance correctly"): assert market.contribute([1, market.getNumTicks() - 1], False, amount - 1, "", sender=tester.k1) with TokenDelta(reputationToken, -amount + 1, tester.a2, "Disputing did not reduce REP balance correctly"): assert market.contribute([1, market.getNumTicks() - 1], False, amount - 1, "", sender=tester.k2) assert market.getFeeWindow() == feeWindow.address payoutDistributionHash = market.derivePayoutDistributionHash( [1, market.getNumTicks() - 1], False) failedCrowdsourcer = localFixture.applySignature( "DisputeCrowdsourcer", market.getCrowdsourcer(payoutDistributionHash)) # confirm we cannot contribute directly to a crowdsourcer without going through the market with raises(TransactionFailed): failedCrowdsourcer.contribute(tester.a0, 1) if finalize: # Fast forward time until the fee window is over and we can redeem to recieve the REP back localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1) else: # Continue to the next round which will disavow failed crowdsourcers and let us redeem once the window is over market.contribute([0, market.getNumTicks()], False, amount * 2, "") assert market.getFeeWindow() != feeWindow.address localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1) with TokenDelta(reputationToken, amount - 1, tester.a1, "Redeeming did not refund REP"): assert failedCrowdsourcer.redeem(tester.a1) with TokenDelta(reputationToken, amount - 1, tester.a2, "Redeeming did not refund REP"): assert failedCrowdsourcer.redeem(tester.a2)
def test_fingerprint(kitchenSinkFixture, universe, cash, market): if kitchenSinkFixture.paraAugur: return affiliates = kitchenSinkFixture.contracts['Affiliates'] affiliateValidator = kitchenSinkFixture.applySignature( "AffiliateValidator", affiliates.createAffiliateValidator()) shareToken = kitchenSinkFixture.getShareToken() accountFingerprint = longTo32Bytes(11) affiliateFingerprint = longTo32Bytes(12) account = kitchenSinkFixture.accounts[0] affiliate = kitchenSinkFixture.accounts[1] affiliates.setFingerprint(accountFingerprint, sender=account) affiliates.setFingerprint(affiliateFingerprint, sender=affiliate) affiliates.setReferrer(affiliate) numSets = 10 cost = numSets * market.getNumTicks() expectedAffiliateFees = cost * .0025 expectedAffiliateFees *= .8 cash.faucet(cost) shareToken.buyCompleteSets(market.address, account, numSets) with TokenDelta(cash, expectedAffiliateFees, affiliate): shareToken.sellCompleteSets(market.address, account, account, numSets, accountFingerprint) # If we pass the affiliate fingerprint we will see that the affiliate fees do not apply and will remain what they were before complete set sale cash.faucet(cost) shareToken.buyCompleteSets(market.address, account, numSets) with TokenDelta(cash, 0, affiliate): shareToken.sellCompleteSets(market.address, account, account, numSets, affiliateFingerprint)
def test_kyc_token(contractsFixture, cash, market, universe, reputationToken): zeroXTradeToken = contractsFixture.contracts['ZeroXTradeToken'] completeSets = contractsFixture.contracts['CompleteSets'] expirationTime = contractsFixture.contracts['Time'].getTimestamp() + 10000 salt = 5 tradeGroupID = longTo32Bytes(42) yesShareToken = contractsFixture.applySignature("ShareToken", market.getShareToken(YES)) noShareToken = contractsFixture.applySignature("ShareToken", market.getShareToken(NO)) # Using the reputation token as "KYC" reputationToken.transfer(contractsFixture.accounts[1], 1) # create signed order cash.faucet(fix('1', '40'), sender=contractsFixture.accounts[1]) rawZeroXOrderData, orderHash = zeroXTradeToken.createZeroXOrder( ASK, fix(1), 60, market.address, YES, reputationToken.address, expirationTime, salt, sender=contractsFixture.accounts[1]) signature = signOrder(orderHash, contractsFixture.privateKeys[1]) orders = [rawZeroXOrderData] signatures = [signature] # without the kyc token we cannot fill the order cash.faucet(fix('1', '60'), sender=contractsFixture.accounts[2]) with raises(TransactionFailed): zeroXTradeToken.trade(fix(1), nullAddress, tradeGroupID, orders, signatures, sender=contractsFixture.accounts[2]) == 0 reputationToken.transfer(contractsFixture.accounts[2], 1) # fill order with TokenDelta(noShareToken, fix(1), contractsFixture.accounts[1], "Creator Shares not taken"): with TokenDelta(yesShareToken, fix(1), contractsFixture.accounts[2], "Taker Shares not received"): with TokenDelta(cash, -fix(1, 40), contractsFixture.accounts[1], "Creator cash not received"): with TokenDelta(cash, -fix(1, 60), contractsFixture.accounts[2], "Taker cash not taken"): assert zeroXTradeToken.trade( fix(1), nullAddress, tradeGroupID, orders, signatures, sender=contractsFixture.accounts[2]) == 0
def test_participation_tokens(kitchenSinkFixture, universe, market, cash): reputationToken = kitchenSinkFixture.applySignature( "ReputationToken", universe.getReputationToken()) disputeWindow = kitchenSinkFixture.applySignature( "DisputeWindow", universe.getOrCreateNextDisputeWindow(False)) # Generate Fees generateFees(kitchenSinkFixture, universe, market) # We can't buy participation tokens until the window starts with raises(TransactionFailed): disputeWindow.buy(300) # Fast forward time until the new dispute window starts and we can buy some tokens assert reputationToken.transfer(kitchenSinkFixture.accounts[1], 100) kitchenSinkFixture.contracts["Time"].setTimestamp( disputeWindow.getStartTime() + 1) with TokenDelta(reputationToken, -300, kitchenSinkFixture.accounts[0], "Buying sisnt take REP"): with TokenDelta(disputeWindow, 300, kitchenSinkFixture.accounts[0], "Buying didnt give PTs"): assert disputeWindow.buy(300) with TokenDelta(reputationToken, -100, kitchenSinkFixture.accounts[1], "Buying sisnt take REP"): with TokenDelta(disputeWindow, 100, kitchenSinkFixture.accounts[1], "Buying didnt give PTs"): assert disputeWindow.buy(100, sender=kitchenSinkFixture.accounts[1]) # We can't redeem until the window is over with raises(TransactionFailed): disputeWindow.redeem(kitchenSinkFixture.accounts[0]) # Fast forward time until the new dispute window is over and we can redeem kitchenSinkFixture.contracts["Time"].setTimestamp( disputeWindow.getEndTime() + 1) totalFees = cash.balanceOf(disputeWindow.address) with TokenDelta(reputationToken, 300, kitchenSinkFixture.accounts[0], "Redeeming didn't refund REP"): with TokenDelta(cash, totalFees * 3 / 4, kitchenSinkFixture.accounts[0], "Redeeming didn't give fees"): with TokenDelta(disputeWindow, -300, kitchenSinkFixture.accounts[0], "Redeeming didn't burn PTs"): assert disputeWindow.redeem(kitchenSinkFixture.accounts[0]) with TokenDelta(reputationToken, 100, kitchenSinkFixture.accounts[1], "Redeeming didn't refund REP"): with TokenDelta(cash, totalFees * 1 / 4, kitchenSinkFixture.accounts[1], "Redeeming didn't give fees"): with TokenDelta(disputeWindow, -100, kitchenSinkFixture.accounts[1], "Redeeming didn't burn PTs"): assert disputeWindow.redeem(kitchenSinkFixture.accounts[1])
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_one_round_crowdsourcer(finalize, localFixture, universe, market, cash, reputationToken): disputeWindow = localFixture.applySignature('DisputeWindow', market.getDisputeWindow()) constants = localFixture.contracts["Constants"] # We'll make the window active localFixture.contracts["Time"].setTimestamp(disputeWindow.getStartTime() + 1) # We'll have testers push markets into the next round by funding dispute crowdsourcers amount = 2 * market.getParticipantStake() with TokenDelta(reputationToken, -amount, localFixture.accounts[1], "Disputing did not reduce REP balance correctly"): assert market.contribute([0, 0, market.getNumTicks()], amount, "", sender=localFixture.accounts[1]) newDisputeWindowAddress = market.getDisputeWindow() assert newDisputeWindowAddress != disputeWindow.address # fast forward time to the fee new window disputeWindow = localFixture.applySignature('DisputeWindow', newDisputeWindowAddress) localFixture.contracts["Time"].setTimestamp(disputeWindow.getStartTime() + 1) # Fast forward time until the new dispute window is over and we can redeem our winning stake, and dispute bond tokens localFixture.contracts["Time"].setTimestamp(disputeWindow.getEndTime() + 1) if finalize: assert market.finalize() initialReporter = localFixture.applySignature('InitialReporter', market.participants(0)) marketDisputeCrowdsourcer = localFixture.applySignature( 'DisputeCrowdsourcer', market.participants(1)) # The initial reporter does not get their REP back with TokenDelta(reputationToken, 0, localFixture.accounts[0], "Redeeming didn't refund REP"): assert initialReporter.redeem(localFixture.accounts[0]) expectedRep = reputationToken.balanceOf(marketDisputeCrowdsourcer.address) disputeCrowdsourcerRedeemedLog = { "reporter": localFixture.accounts[1], "disputeCrowdsourcer": marketDisputeCrowdsourcer.address, "amountRedeemed": marketDisputeCrowdsourcer.getStake(), "repReceived": expectedRep, "payoutNumerators": [0, 0, market.getNumTicks()], "universe": universe.address, "market": market.address } with AssertLog(localFixture, "DisputeCrowdsourcerRedeemed", disputeCrowdsourcerRedeemedLog): with TokenDelta(reputationToken, expectedRep, localFixture.accounts[1], "Redeeming didn't refund REP"): assert marketDisputeCrowdsourcer.redeem( localFixture.accounts[1], sender=localFixture.accounts[1])
def test_fee_pot_exit_partial(contractsFixture, universe, reputationToken, cash): if not contractsFixture.paraAugur: return feePot = contractsFixture.getFeePot(universe) bob = contractsFixture.accounts[0] alice = contractsFixture.accounts[1] reputationToken.faucet(100, sender=bob) reputationToken.faucet(100, sender=alice) cash.faucet(10000) cash.approve(feePot.address, 10000000000000000) reputationToken.approve(feePot.address, 10000000000000000, sender=bob) reputationToken.approve(feePot.address, 10000000000000000, sender=alice) # Alice puts in 1 REP feePot.stake(1, sender=alice) # Bob puts in 2 REP feePot.stake(2, sender=bob) # Nothing owed yet assert feePot.withdrawableFeesOf(alice) == 0 assert feePot.withdrawableFeesOf(bob) == 0 # Put 90 Cash in feePot.depositFees(90) # Alice owed 30 assert feePot.withdrawableFeesOf(alice) == 30 # Bob owed 60 assert feePot.withdrawableFeesOf(bob) == 60 # Bob partial exits and gets 60 Cash and 1 REP with TokenDelta(reputationToken, 1, bob, "Bob didn't get back REP"): with TokenDelta(cash, 60, bob, "Bob didnt get fees"): feePot.exit(1, sender=bob) # Alice owed 30 assert feePot.withdrawableFeesOf(alice) == 30 # Bob owed 0 assert feePot.withdrawableFeesOf(bob) == 0 # Put 100 Cash in feePot.depositFees(100) # Alice owed 80 assert feePot.withdrawableFeesOf(alice) == 80 # Bob owed 50 assert feePot.withdrawableFeesOf(bob) == 50
def test_fee_migration(localFixture, universe, market, categoricalMarket, scalarMarket, cash, reputationToken, reportingWindow): # We'll have testers put up dispute bonds against the designated reports and place stake in other outcomes otherOutcomeStake = 10**18 assert market.disputeDesignatedReport([market.getNumTicks(), 0], otherOutcomeStake, False, sender=tester.k1) assert categoricalMarket.disputeDesignatedReport( [categoricalMarket.getNumTicks(), 0, 0], otherOutcomeStake, False, sender=tester.k2) assert scalarMarket.disputeDesignatedReport( [scalarMarket.getNumTicks(), 0], otherOutcomeStake, False, sender=tester.k3) reporterFees = 1000 * market.getNumTicks( ) / universe.getOrCacheReportingFeeDivisor() totalWinningStake = reportingWindow.getTotalWinningStake() assert cash.balanceOf(reportingWindow.address) == reporterFees # Progress to the Limited dispute phase and dispute one of the markets. This should migrate fees to the reporting window the market migrates to proportional to its stake localFixture.chain.head_state.timestamp = reportingWindow.getDisputeStartTime( ) + 1 nextReportingWindow = localFixture.applySignature( "ReportingWindow", universe.getOrCreateNextReportingWindow()) scalarMarketStake = scalarMarket.getTotalStake() firstDisputeCost = localFixture.contracts[ "Constants"].FIRST_REPORTERS_DISPUTE_BOND_AMOUNT() scalarMarketStakeDelta = firstDisputeCost + otherOutcomeStake totalScalarMarketStakeMoved = scalarMarketStake + scalarMarketStakeDelta migratedFees = reporterFees * (scalarMarketStake + firstDisputeCost) / ( reportingWindow.getTotalStake() + firstDisputeCost) with TokenDelta(cash, -migratedFees, reportingWindow.address, "Disputing in first didn't migrate ETH out correctly"): with TokenDelta(cash, migratedFees, nextReportingWindow.address, "Disputing in first didn't migrate ETH in correctly"): with StakeDelta( scalarMarketStakeDelta, -scalarMarketStake, 0, scalarMarket, reportingWindow, "Disputing in first is not migrating stake out correctly"): with StakeDelta( scalarMarketStakeDelta, totalScalarMarketStakeMoved, 0, scalarMarket, nextReportingWindow, "Disputing in first is not migrating stake in correctly" ): assert scalarMarket.disputeFirstReporters( [scalarMarket.getNumTicks() - 1, 1], otherOutcomeStake, False, sender=tester.k4)
def test_take_order_with_shares_buy_with_cash(contractsFixture, cash, market, universe): zeroXTradeToken = contractsFixture.contracts['ZeroXTradeToken'] completeSets = contractsFixture.contracts['CompleteSets'] expirationTime = contractsFixture.contracts['Time'].getTimestamp() + 10000 salt = 5 tradeGroupID = longTo32Bytes(42) yesShareToken = contractsFixture.applySignature("ShareToken", market.getShareToken(YES)) noShareToken = contractsFixture.applySignature("ShareToken", market.getShareToken(NO)) # buy complete sets account = contractsFixture.accounts[1] with BuyWithCash(cash, fix('1', '100'), account, "buy complete set"): assert completeSets.publicBuyCompleteSets(market.address, fix(1), sender=account) assert yesShareToken.balanceOf(account) == fix(1) # create signed order cash.faucet(fix('1', '40'), sender=account) rawZeroXOrderData, orderHash = zeroXTradeToken.createZeroXOrder( ASK, fix(1), 60, market.address, YES, nullAddress, expirationTime, salt, sender=account) signature = signOrder(orderHash, contractsFixture.privateKeys[1]) # fill order with cash and see that the creator has shares taken orders = [rawZeroXOrderData] signatures = [signature] cash.faucet(fix('1', '60'), sender=contractsFixture.accounts[2]) with TokenDelta(yesShareToken, -fix(1), account, "Creator Shares not taken"): with TokenDelta(yesShareToken, fix(1), contractsFixture.accounts[2], "Taker Shares not received"): with TokenDelta(cash, fix(1, 60), account, "Creator cash not received"): with TokenDelta(cash, -fix(1, 60), contractsFixture.accounts[2], "Taker cash not taken"): assert zeroXTradeToken.trade( fix(1), nullAddress, tradeGroupID, orders, signatures, sender=contractsFixture.accounts[2]) == 0
def test_one_round_crowdsourcer_fees(localFixture, universe, market, cash, reputationToken): feeWindow = localFixture.applySignature('FeeWindow', market.getFeeWindow()) constants = localFixture.contracts["Constants"] # We'll make the window active localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1) # generate some fees generateFees(localFixture, universe, market) # We'll have testers push markets into the next round by funding dispute crowdsourcers amount = 2 * market.getParticipantStake() with TokenDelta(reputationToken, -amount, tester.a1, "Disputing did not reduce REP balance correctly"): assert market.contribute([0, market.getNumTicks()], False, amount, "", sender=tester.k1) newFeeWindowAddress = market.getFeeWindow() assert newFeeWindowAddress != feeWindow.address # fast forward time to the fee new window and generate additional fees feeWindow = localFixture.applySignature('FeeWindow', newFeeWindowAddress) localFixture.contracts["Time"].setTimestamp(feeWindow.getStartTime() + 1) # Fast forward time until the new fee window is over and we can redeem our winning stake, and dispute bond tokens and receive fees localFixture.contracts["Time"].setTimestamp(feeWindow.getEndTime() + 1) assert market.finalize() initialReporter = localFixture.applySignature('InitialReporter', market.getReportingParticipant(0)) marketDisputeCrowdsourcer = localFixture.applySignature('DisputeCrowdsourcer', market.getReportingParticipant(1)) # The dispute crowdsourcer contributor locked in REP for 2 rounds, as did the Initial Reporter expectedTotalFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address)) expectedFees = expectedTotalFees * 2 / 3 expectedRep = market.getParticipantStake() assert expectedRep == long(marketDisputeCrowdsourcer.getStake() + marketDisputeCrowdsourcer.getStake() / 2) disputeCrowdsourcerRedeemedLog = { "reporter": bytesToHexString(tester.a1), "disputeCrowdsourcer": marketDisputeCrowdsourcer.address, "amountRedeemed": marketDisputeCrowdsourcer.getStake(), "repReceived": expectedRep, "reportingFeesReceived": expectedFees, "payoutNumerators": [0, market.getNumTicks()], "universe": universe.address, "market": market.address } with AssertLog(localFixture, "DisputeCrowdsourcerRedeemed", disputeCrowdsourcerRedeemedLog): with TokenDelta(reputationToken, expectedRep, tester.a1, "Redeeming didn't refund REP"): with EtherDelta(expectedFees, tester.a1, localFixture.chain, "Redeeming didn't increase ETH correctly"): assert marketDisputeCrowdsourcer.redeem(tester.a1, sender=tester.k1) # The initial reporter gets fees even though they were not correct. They do not get their REP back though expectedFees = cash.balanceOf(feeWindow.address) + cash.balanceOf(universe.getOrCreateFeeWindowBefore(feeWindow.address)) with TokenDelta(reputationToken, 0, tester.a0, "Redeeming didn't refund REP"): with EtherDelta(expectedFees, tester.a0, localFixture.chain, "Redeeming didn't increase ETH correctly"): assert initialReporter.redeem(tester.a0)
def test_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_mailbox_tokens_failure(localFixture, mailbox, token): # We send some Tokens to the mailbox assert token.faucet(100) with TokenDelta(token, 100, mailbox.address, "Token deposit did not work"): with TokenDelta(token, -100, tester.a0, "Token deposit did not work"): token.transfer(mailbox.address, 100) # Withdrawing as someone other than the owner will fail with raises(TransactionFailed): mailbox.withdrawTokens(token.address, sender=tester.k1)
def test_non_dr_initial_reporter(contractsFixture, universe, reputationToken): account0 = contractsFixture.accounts[0] account1 = contractsFixture.accounts[1] market = contractsFixture.createReasonableYesNoMarket(universe, extraInfo="so extra", designatedReporterAddress=account1) proceedToDesignatedReporting(contractsFixture, market) stake = market.repBond() reputationToken.transfer(account1, stake) with TokenDelta(reputationToken, stake, account0, "Market creator didn't get bond back"): with TokenDelta(reputationToken, -stake, account1, "Designated Reporter did not pay bond"): market.doInitialReport([0, 0, market.getNumTicks()], "", 0, sender=account1)
def finalizeFork(fixture, market, universe, finalizeByMigration = True): reputationToken = fixture.applySignature('ReputationToken', universe.getReputationToken()) # The universe forks and there is now a universe where NO and YES are the respective outcomes of each noPayoutNumerators = [0] * market.getNumberOfOutcomes() noPayoutNumerators[1] = market.getNumTicks() yesPayoutNumerators = [0] * market.getNumberOfOutcomes() yesPayoutNumerators[2] = market.getNumTicks() noUniverse = fixture.applySignature('Universe', universe.createChildUniverse(noPayoutNumerators)) yesUniverse = fixture.applySignature('Universe', universe.createChildUniverse(yesPayoutNumerators)) noUniverseReputationToken = fixture.applySignature('ReputationToken', noUniverse.getReputationToken()) yesUniverseReputationToken = fixture.applySignature('ReputationToken', yesUniverse.getReputationToken()) assert noUniverse.address != universe.address assert yesUniverse.address != universe.address assert yesUniverse.address != noUniverse.address assert noUniverseReputationToken.address != yesUniverseReputationToken.address # Attempting to finalize the fork now will not succeed as no REP has been migrated and not enough time has passed with raises(TransactionFailed): market.finalizeFork() # A Tester moves some of their REP to the YES universe amount = 10 ** 6 * 10 ** 18 with raises(TransactionFailed): reputationToken.migrateOut(yesUniverseReputationToken.address, 0) with TokenDelta(yesUniverseReputationToken, amount, tester.a0, "Yes REP token balance was no correct"): reputationToken.migrateOut(yesUniverseReputationToken.address, amount) # Attempting to finalize the fork now will not succeed as a majority or REP has not yet migrated and fork end time has not been reached with raises(TransactionFailed): market.finalizeFork() if (finalizeByMigration): # Tester 0 moves more than 50% of REP amount = reputationToken.balanceOf(tester.a0) - 20 with TokenDelta(noUniverseReputationToken, amount, tester.a0, "No REP token balance was no correct"): reputationToken.migrateOut(noUniverseReputationToken.address, amount) assert reputationToken.balanceOf(tester.a0) == 20 assert market.getWinningPayoutDistributionHash() == noUniverse.getParentPayoutDistributionHash() else: # Time marches on past the fork end time fixture.contracts["Time"].setTimestamp(universe.getForkEndTime() + 1) assert market.finalize() assert market.getWinningPayoutDistributionHash() == yesUniverse.getParentPayoutDistributionHash() # If the fork is past the fork period we can not migrate with raises(TransactionFailed): reputationToken.migrateOut(yesUniverseReputationToken.address, 1) # Finalize fork cannot be called again with raises(TransactionFailed): market.finalizeFork()
def test_mailbox_tokens_happy_path(localFixture, mailbox, token): # We can send some Tokens to the mailbox assert token.faucet(100) with TokenDelta(token, 100, mailbox.address, "Token deposit did not work"): with TokenDelta(token, -100, tester.a0, "Token deposit did not work"): token.transfer(mailbox.address, 100) # The mailbox owner can withdraw these tokens with TokenDelta(token, 100, tester.a0, "Token withdraw did not work"): with TokenDelta(token, -100, mailbox.address, "Token withdraw did not work"): mailbox.withdrawTokens(token.address)
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_shares_in_binary_market(kitchenSinkFixture, universe, cash, market): claimTradingProceeds = kitchenSinkFixture.contracts['ClaimTradingProceeds'] yesShareToken = kitchenSinkFixture.applySignature('ShareToken', market.getShareToken(YES)) noShareToken = kitchenSinkFixture.applySignature('ShareToken', market.getShareToken(NO)) expectedValue = 1 * market.getNumTicks() expectedReporterFees = expectedValue / universe.getOrCacheReportingFeeDivisor() expectedMarketCreatorFees = expectedValue / market.getMarketCreatorSettlementFeeDivisor() expectedSettlementFees = expectedReporterFees + expectedMarketCreatorFees expectedPayout = long(expectedValue - expectedSettlementFees) assert universe.getOpenInterestInAttoEth() == 0 # get YES shares with a1 acquireLongShares(kitchenSinkFixture, cash, market, YES, 1, claimTradingProceeds.address, sender = tester.k1) assert universe.getOpenInterestInAttoEth() == 1 * market.getNumTicks() # get NO shares with a2 acquireShortShareSet(kitchenSinkFixture, cash, market, YES, 1, claimTradingProceeds.address, sender = tester.k2) assert universe.getOpenInterestInAttoEth() == 2 * market.getNumTicks() finalizeMarket(kitchenSinkFixture, market, [0,10**4]) logs = [] captureFilteredLogs(kitchenSinkFixture.chain.head_state, kitchenSinkFixture.contracts['Augur'], logs) with TokenDelta(cash, expectedMarketCreatorFees, market.getMarketCreatorMailbox(), "Market creator fees not paid"): with TokenDelta(cash, expectedReporterFees, universe.getOrCreateNextFeeWindow(), "Reporter fees not paid"): # redeem shares with a1 initialLongHolderETH = kitchenSinkFixture.chain.head_state.get_balance(tester.a1) claimTradingProceeds.claimTradingProceeds(market.address, tester.a1) # redeem shares with a2 initialShortHolderETH = kitchenSinkFixture.chain.head_state.get_balance(tester.a2) claimTradingProceeds.claimTradingProceeds(market.address, tester.a2) # Confirm claim proceeds logging works correctly assert len(logs) == 6 assert logs[3]['_event_type'] == 'TradingProceedsClaimed' assert logs[3]['market'] == market.address assert logs[3]['shareToken'] == yesShareToken.address assert logs[3]['numPayoutTokens'] == expectedPayout assert logs[3]['numShares'] == 1 assert logs[3]['sender'] == bytesToHexString(tester.a1) assert logs[3]['finalTokenBalance'] == initialLongHolderETH + expectedPayout # assert a1 ends up with cash (minus fees) and a2 does not assert kitchenSinkFixture.chain.head_state.get_balance(tester.a1) == initialLongHolderETH + expectedPayout assert kitchenSinkFixture.chain.head_state.get_balance(tester.a2) == initialShortHolderETH assert yesShareToken.balanceOf(tester.a1) == 0 assert yesShareToken.balanceOf(tester.a2) == 0 assert noShareToken.balanceOf(tester.a1) == 0 assert noShareToken.balanceOf(tester.a2) == 0 assert universe.getOpenInterestInAttoEth() == 1 * market.getNumTicks() # The corresponding share for tester2's complete set has not been redeemed