示例#1
0
    def test_findMultipleEntities(self):
        g = Generator()
        airdropAmount1 = 777
        recipients1 = g.getExistingAddresses(20)
        recipientsAggregated1 = recipients1[:15]

        airdropAmount2 = 1000
        recipients2 = g.getExistingAddresses(100)
        recipientsAggregated2 = recipients2[:30]

        collectors = g.getExistingAddresses(2)

        g.addAirdrop('0xdistributor1', recipients1, airdropAmount1)
        g.addAggregation(recipientsAggregated1, collectors[0], airdropAmount1)

        g.addAirdrop('0xdistributor2', recipients2, airdropAmount2)
        g.addAggregation(recipientsAggregated2, collectors[1], airdropAmount2)

        transfers = g.getGraphEdgeDF()

        result = findEntities(transfers,
                              minRecipients=10,
                              maxBlockDiff=2,
                              minAggregations=10)
        # there are (15 + 1) + (30 + 1) addresses in the entity table
        self.assertEqual(len(result), 15 + 1 + 30 + 1)
        # they belong to two different entities
        self.assertEqual(result.entity.nunique(), 2)
 def test_findNoEntity(self):
     result = findEntities(self.transfers,
                           minRecipients=10,
                           maxBlockDiff=2,
                           minAggregations=10)
     # there are no addresses in the entity table
     self.assertEqual(len(result), 0)
示例#3
0
    def test_findSingleEntityInTwoNetworks(self):

        g1 = Generator(address="0xFirstNetwork")
        airdropAmount1 = 777
        recipients1 = g1.getExistingAddresses(100)
        # first airdrop has one aggregation to 15 addresses
        recipientsAggregated1 = recipients1[:15]

        g2 = Generator(address="0xSecondNetwork")
        airdropAmount2 = 1000
        # second airdrop has 50 recipients of the first airdrop
        recipients2 = recipients1[:50]
        # note that the aggregation overlaps with addresses of the first one
        recipientsAggregated2 = recipients1[10:20]

        collectors = g1.getExistingAddresses(2)

        g1.addAirdrop('0xdistributor1', recipients1, airdropAmount1)
        g1.addAggregation(recipientsAggregated1, collectors[0], airdropAmount1)

        g2.addAirdrop('0xdistributor2', recipients2, airdropAmount2)
        g2.addAggregation(recipientsAggregated2, collectors[1], airdropAmount2)

        transfers = g1.getGraphEdgeDF().append(g2.getGraphEdgeDF())

        result = findEntities(transfers,
                              minRecipients=10,
                              maxBlockDiff=2,
                              minAggregations=10)
        # there are (15 + 1) + (30 + 1) addresses in the entity table
        self.assertEqual(
            len(result),
            len(set(recipientsAggregated1 + recipientsAggregated2)) + 2)
        # there is just one identified entity!
        self.assertEqual(result.entity.nunique(), 1)
示例#4
0
    def test_findSingleEntityGivenIDEX(self):
        # IDEX is not an active EOA, so we shouldn't find it

        g1 = Generator(address="0xFirstNetwork")
        airdropAmount1 = 777
        recipients1 = g1.getExistingAddresses(100)
        # one aggregation of 20 addresses
        recipientsAggregated1 = recipients1[:20]
        # and another one that isn't a real one
        # instead, its individuals sending their tokens to IDEX (exchange)
        recipientsAggregated2 = recipients1[30:80]

        collector = g1.getExistingAddresses(1)[0]

        IDEX = "0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208"

        g1.addAirdrop('0xdistributor1', recipients1, airdropAmount1)

        g1.addAggregation(recipientsAggregated1, collector, airdropAmount1)
        g1.addAggregation(recipientsAggregated2, IDEX, airdropAmount1)

        # the collector of the airdrop also sent the airdrop amount to IDEX
        # it could now seem like IDEX collected from many addresses
        g1.addTransfer('0xcollector1', IDEX, airdropAmount1)

        transfers = g1.getGraphEdgeDF()

        result = findEntities(transfers,
                              minRecipients=10,
                              maxBlockDiff=2,
                              minAggregations=10)
        # there are (15 + 1) addresses in the entity table
        self.assertEqual(len(result), len(recipientsAggregated1) + 1)
        # there is just one identified entity!
        self.assertEqual(result.entity.nunique(), 1)
示例#5
0
 def test_findSingleEntity(self):
     result = findEntities(self.transfers,
                           minRecipients=10,
                           maxBlockDiff=2,
                           minAggregations=10)
     # there are 16 (15+1) addresses in the entity table
     self.assertEqual(len(result), 16)
     # they are all the same entity
     self.assertEqual(result.entity.nunique(), 1)
示例#6
0
 def test_noEntitiesInEmptyGraph(self):
     transfers = pd.DataFrame(columns=[
         'address',
         'blockNumber',
         'eventName',
         'source',
         'target',
         'amount',
     ])
     result = findEntities(transfers, 1, 1, 1)
     self.assertEqual(len(result), 0)
示例#7
0
    def test_noEntitiesInZeroAmountAirdrop(self):
        from networkgenerator.generator import Generator
        g = Generator()
        airdropAmount = 0
        recipients = g.generateNewAddresses(20)
        recipientsAggregated = recipients[:15]

        g.addAirdrop('0xdistributor', recipients, airdropAmount)
        g.addAggregation(recipientsAggregated, "0xcollector", airdropAmount)

        transfers = g.getGraphEdgeDF()
        result = findEntities(transfers,
                              minRecipients=10,
                              maxBlockDiff=2,
                              minAggregations=10)
        self.assertEqual(len(result), 0)
    def test_noEntityWhenForwardToExchangeContract(self):
        g = Generator(addressLength=2)
        airdropAmount = 7777
        recipients = g.generateNewAddresses(20)
        recipientsAggregated = recipients[:15]
        IDEX = "0x2a0c0dbecc7e4d658f48e01e3fa353f44050c208"

        g.addAirdrop('0xdistributor', recipients, airdropAmount)
        g.addAggregation(recipientsAggregated, IDEX, airdropAmount)

        transfers = g.getGraphEdgeDF()

        result = findEntities(transfers,
                              minRecipients=10,
                              maxBlockDiff=2,
                              minAggregations=10)
        # there are no addresses in the entity table
        self.assertEqual(len(result), 0)
    def test_noEntityWhenForwardToDeposit(self):
        g = Generator(addressLength=2)
        airdropAmount = 7777
        recipients = g.generateNewAddresses(20)
        depositAdresses = g.generateNewAddresses(15)

        g.addAirdrop('0xdistributor', recipients, airdropAmount)
        for i, depositAdress in enumerate(depositAdresses):
            # airdropped tokens are sent to exchange deposit addresses
            g.addTransfer(recipients[i], depositAdress, airdropAmount)
            # and then forwarded to the exchange itself
            g.addTransfer(depositAdress, "0xchange", airdropAmount)

        transfers = g.getGraphEdgeDF()

        result = findEntities(transfers,
                              minRecipients=10,
                              maxBlockDiff=2,
                              minAggregations=10)
        # there are no addresses in the entity table
        self.assertEqual(len(result), 0)
示例#10
0
def main():

    if args.prepare:
        if (os.path.exists(config.dbFile)):
            if (query_yes_no("A database already exists, want to delete it?")):
                os.remove(config.dbFile)
                prepare()
            else:
                print("skipping prepare")
        else:
            prepare()

    if args.ethdeposit:
        triplets = getETHDepositTriplets(config.transactionsFile,
                                         config.blocksFile,
                                         config.exchangesFile,
                                         config.maxBlockDiff,
                                         config.maxETHDiff)
        triplets.to_csv("data/output/ethdeposittriplets.csv", index=False)
        print("Done.")

    if args.tokendeposit:
        print("Retrieving all token network addresses")
        cnx = sqlite3.connect(config.dbFile)
        tokenAddresses = pd.read_sql(
            "SELECT DISTINCT address FROM tokentransfers;", cnx).address

        print("Reading exchanges file")
        exchanges = pd.read_csv(config.exchangesFile)
        exchanges = exchanges[(exchanges.accountType == 'eoa')
                              & (exchanges.type == 'Exchange')].address

        result_list = []
        print("Starting analysis for each token network.")
        for address in tqdm(list(tokenAddresses)):
            transfers = pd.read_sql(
                "select * from tokentransfers WHERE address = '{}'".format(
                    address), cnx)
            res = getTokenDepositTripletChunk(transfers, exchanges,
                                              config.maxBlockDiff)
            result_list.append(res)
        triplets = pd.concat(result_list)
        triplets.to_csv("data/output/tokendeposittriplets.csv", index=False)
        cnx.close()
        print("Done.")

    if args.airdrop:
        cnx = sqlite3.connect(config.dbFile)
        tokenAddresses = pd.read_sql(
            "SELECT address FROM (select address, count(*) AS count from tokentransfers GROUP BY address)a WHERE count >= {}"
            .format(config.minAirDropRecipients), cnx).address
        tokenAddressCount = len(tokenAddresses)

        result_list = []
        for address in tqdm(list(tokenAddresses)):
            transfers = pd.read_sql(
                "select * from tokentransfers WHERE address = '{}'".format(
                    address), cnx)
            res = findEntities(transfers,
                               minRecipients=config.minAirDropRecipients,
                               maxBlockDiff=config.maxMedianAirdropBlockDiff,
                               minAggregations=config.minAggregations)
            res['network'] = address
            result_list.append(res)
            #print((num+1)/(tokenAddressCount), len(res))
        result = pd.concat(result_list)

        result.to_csv("data/output/airdrop-entities.csv", index=False)
        cnx.close()
示例#11
0
 def test_findNothingWithHighRequirements(self):
     result = findEntities(self.transfers,
                           minRecipients=21,
                           maxBlockDiff=2,
                           minAggregations=10)
     self.assertEqual(len(result), 0)