def combine_rewards(rewardsList,cycle, badgerTree): totals = RewardsList(cycle,badgerTree) for rewards in rewardsList: for user,claims in rewards.claims.items(): for token,claim in claims.items(): totals.increase_user_rewards(user,token,claim) return totals
def process_sushi_events(badger,startBlock,endBlock,events,name,nextCycle): xSushiTokenAddress = "0x8798249c2e607446efb7ad49ec89dd1865ff4272" start = startBlock end = int(events[0]["blockNumber"]) totalHarvested = 0 rewards = RewardsList(nextCycle,badger.badgerTree) for i in tqdm(range(len(events))): xSushiRewards = int(events[i]["toBadgerTree"]) user_state = calc_meta_farm_rewards(badger,name,start,end) console.log("Processing between blocks {} and {}, distributing {} to users".format( start, end, xSushiRewards/1e18 )) totalHarvested += xSushiRewards/1e18 console.print("{} total xSushi processed".format(totalHarvested)) totalShareSeconds = sum([u.shareSeconds for u in user_state]) xSushiUnit = xSushiRewards/totalShareSeconds for user in user_state: rewards.increase_user_rewards(web3.toChecksumAddress(user.address),web3.toChecksumAddress(xSushiTokenAddress),xSushiUnit * user.shareSeconds) rewardsLogger.add_user_share_seconds(user.address,name,user.shareSeconds) rewardsLogger.add_user_token(user.address,name,xSushiTokenAddress,xSushiUnit * user.shareSeconds) if i+1 < len(events): start = int(events[i]["blockNumber"]) end = int(events[i+1]["blockNumber"]) totalXSushi = sum([list(v.values())[0]/1e18 for v in list(rewards.claims.values()) ]) distr = {} distr[xSushiTokenAddress] = totalXSushi rewardsLogger.add_distribution_info(name,distr) return rewards
def combine_rewards(list, cycle, badgerTree): totals = RewardsList(cycle, badgerTree) total = 0 # For each rewards list entry for key, rewardsSet in list.items(): # Get the claims data # claims = rewardsSet["claims"] for user, userData in rewardsSet.claims.items(): # For each token for token, tokenAmount in userData.items(): totals.increase_user_rewards(user, token, tokenAmount) total += tokenAmount totals.badgerSum = total # totals.printState() return totals
def fetch_current_harvest_rewards(badger, startBlock, endBlock, nextCycle): farmTokenAddress = "0xa0246c9032bC3A600820415aE600c6388619A14D" harvestEvents = fetch_harvest_farm_events() rewards = RewardsList(nextCycle, badger.badgerTree) def filter_events(e): return int(e["blockNumber"]) > startBlock and int( e["blockNumber"]) < endBlock unprocessedEvents = list(filter(filter_events, harvestEvents)) console.log("Processing {} farm events".format(len(unprocessedEvents))) if len(unprocessedEvents) == 0: return rewards start = get_latest_event_block(unprocessedEvents[0], harvestEvents) end = int(unprocessedEvents[0]["blockNumber"]) totalHarvested = 0 for i in tqdm(range(len(unprocessedEvents))): console.log("Processing between {} and {}".format( startBlock, endBlock)) harvestEvent = unprocessedEvents[i] user_state = calc_meta_farm_rewards(badger, "harvest.renCrv", start, end) farmRewards = int(harvestEvent["farmToRewards"]) console.print("Processing block {}, distributing {} to users".format( harvestEvent["blockNumber"], farmRewards / 1e18, )) totalHarvested += farmRewards / 1e18 console.print("{} total FARM processed".format(totalHarvested)) totalShareSeconds = sum([u.shareSeconds for u in user_state]) farmUnit = farmRewards / totalShareSeconds for user in user_state: rewards.increase_user_rewards( user.address, web3.toChecksumAddress(farmTokenAddress), farmUnit * user.shareSeconds) if i + 1 < len(unprocessedEvents): start = int(unprocessedEvents[i]["blockNumber"]) end = int(unprocessedEvents[i + 1]["blockNumber"]) totalFarm = sum( [list(v.values())[0] / 1e18 for v in list(rewards.claims.values())]) return rewards
def rewards_to_merkle_tree(rewards: RewardsList, startBlock, endBlock, geyserRewards): (nodes, encodedNodes, entries) = rewards.to_merkle_format() # For each user, encode their data into a node # Put the nodes into a tree # elements = [(index, account, amount) for index, (account, amount) in enumerate(rewards.items())] # nodes = [encode_hex(encode_abi_packed(['uint', 'address', 'uint'], el)) for el in elements] """ 'claims': { user: {'index': index, 'amount': hex(amount), 'proof': tree.get_proof(nodes[index])} for index, user, amount in elements }, """ tree = MerkleTree(encodedNodes) distribution = { "merkleRoot": encode_hex(tree.root), "cycle": nodes[0]["cycle"], "startBlock": str(startBlock), "endBlock": str(endBlock), "tokenTotals": rewards.totals.toDict(), "claims": {}, "metadata": {}, } for entry in entries: node = entry["node"] encoded = entry["encoded"] # console.log(node) distribution["claims"][node["user"]] = { "index": hex(node["index"]), "user": node["user"], "cycle": hex(node["cycle"]), "tokens": node["tokens"], "cumulativeAmounts": node["cumulativeAmounts"], "proof": tree.get_proof(encodedNodes[node["index"]]), "node": encoded, } if len(geyserRewards) > 0: for user, data in geyserRewards.metadata.items(): distribution["metadata"][user] = data.toDict() print(f"merkle root: {encode_hex(tree.root)}") # Print to file with content hash # hash(distribution) # console.log(distribution) return distribution
def process_cumulative_rewards(current, new: RewardsList): result = RewardsList(new.cycle, new.badgerTree) # Add new rewards for user, claims in new.claims.items(): for token, claim in claims.items(): result.increase_user_rewards(user, token, claim) # Add existing rewards for user, userData in current["claims"].items(): for i in range(len(userData["tokens"])): token = userData["tokens"][i] amount = userData["cumulativeAmounts"][i] result.increase_user_rewards(user, token, int(amount)) # result.printState() return result
def sum_rewards(sources, cycle, badgerTree): """ Sum rewards from all given set of rewards' list, returning a single rewards list """ totals = RewardsList(cycle, badgerTree) total = 0 # For each rewards list entry for key, rewardsSet in sources.items(): # Get the claims data claims = rewardsSet["claims"] metadata = rewardsSet["metadata"] # Add values from each user for user, userData in claims.items(): totals.track_user_metadata(user, metadata) # For each token for token, tokenAmount in userData.items(): totals.increase_user_rewards(user, token, tokenAmount) total += tokenAmount totals.badgerSum = total # totals.printState() return totals
def main(): test = True badger = connect_badger(badger_config.prod_json,load_deployer=False) farmTokenAddress = "0xa0246c9032bC3A600820415aE600c6388619A14D" nextCycle = badger.badgerTree.currentCycle() + 1 console.log("next cycle: {}".format(nextCycle)) currentMerkleData = badger.badgerTree.getCurrentMerkleData() console.log(currentMerkleData) timeSinceLastUpdate = chain.time() - currentMerkleData[2] print("Run at", int(time.time())) latestBlock = chain.height harvestEvents = fetch_harvest_farm_events() rewards = RewardsList(nextCycle,badger.badgerTree) console.log(rewards.claims) settStartBlock = 11376266 startBlock = settStartBlock endBlock = int(harvestEvents[0]["blockNumber"]) totalHarvested = 0 for i in tqdm(range(len(harvestEvents))): console.log("Processing between {} and {}".format(startBlock,endBlock)) harvestEvent = harvestEvents[i] user_state = calc_meta_farm_rewards(badger,"harvest.renCrv",startBlock,endBlock) farmRewards = int(harvestEvent["farmToRewards"]) console.print("Processing block {}, distributing {} to users".format( harvestEvent["blockNumber"], farmRewards/1e18, )) totalHarvested += farmRewards/1e18 console.print("{} total FARM processed".format(totalHarvested)) totalShareSeconds = sum([u.shareSeconds for u in user_state]) farmUnit = farmRewards/totalShareSeconds for user in user_state: rewards.increase_user_rewards(web3.toChecksumAddress(user.address),farmTokenAddress,farmUnit * user.shareSeconds) rewardsLogger.add_user_share_seconds(user.address,"harvest.renCrv",user.shareSeconds) rewardsLogger.add_user_token(user.address,"harvest.renCrv",farmTokenAddress,farmUnit* user.shareSeconds) rewardsLogger.add_epoch_data(user_state,"harvest.renCrv",farmTokenAddress,farmUnit,i) if i+1 < len(harvestEvents): startBlock = int(harvestEvent["blockNumber"]) endBlock = int(harvestEvents[i+1]["blockNumber"]) claimsHarvested = sum( [list(v.values())[0] for v in list(rewards.claims.values())]) rewardsLogger.add_distribution_info("harvest.renCrv",{farmTokenAddress:claimsHarvested}) rewardsLogger.save("retroactive-farm") currentRewards = fetch_current_rewards_tree(badger) cumulative_rewards = process_cumulative_rewards(currentRewards,rewards) merkleTree = rewards_to_merkle_tree(cumulative_rewards,settStartBlock,endBlock,{}) # Upload merkle tree rootHash = web3.toHex(web3.keccak(text=merkleTree["merkleRoot"])) console.log(rootHash) contentFileName = "rewards-" + str(chain.id) + "-" + str(merkleTree["merkleRoot"]) + ".json" console.log("Saving merkle tree as {}".format(contentFileName)) with open(contentFileName,"w") as f: json.dump(merkleTree,f,indent=4) farmHarvestedMerkleTree = 0 claims = merkleTree["claims"] for user, claim in claims.items(): if farmTokenAddress in claim["tokens"]: token_index = claim["tokens"].index(farmTokenAddress) amount = claim["cumulativeAmounts"][token_index] console.log("Address {} : {} FARM".format(user,int(float(amount))/1e18)) farmHarvestedMerkleTree += int(float(amount)) console.log("Total Farm Harvested {}".format(farmHarvestedMerkleTree/1e18)) console.log("Claims Harvested From Events {}".format(claimsHarvested/1e18)) console.log("Difference: {}".format((farmHarvestedMerkleTree/1e18) - (claimsHarvested/1e18))) difference = farmHarvestedMerkleTree - claimsHarvested console.log("Difference: {}".format(farmHarvestedMerkleTree - claimsHarvested)) console.log(gas_strategy.get_gas_price()) if abs(difference) < 10000000 and not test: badger.badgerTree.proposeRoot( merkleTree["merkleRoot"], rootHash, nextCycle, {"from" :badger.keeper,"gas_price":gas_strategy}) badger.badgerTree.approveRoot( merkleTree["merkleRoot"], rootHash, nextCycle, {"from" :badger.keeper,"gas_price":gas_strategy})
def calc_harvest_meta_farm_rewards(badger, startBlock, endBlock): # TODO: Add harvest reward return RewardsList()
def calc_sushi_rewards(badger,startBlock,endBlock,nextCycle,retroactive): console.log(startBlock) console.log(endBlock) xSushiTokenAddress = "0x8798249c2e607446efb7ad49ec89dd1865ff4272" sushi_harvest_events = fetch_sushi_harvest_events() def filter_events(e): return int(e["blockNumber"]) > startBlock and int(e["blockNumber"]) < endBlock wbtcEthEvents = list(filter(filter_events,sushi_harvest_events["wbtcEth"])) wbtcBadgerEvents = list(filter(filter_events,sushi_harvest_events["wbtcBadger"])) wBtcDiggEvents = list(filter(filter_events,sushi_harvest_events["wbtcDigg"])) totalxSushi = sum([int(e["toBadgerTree"]) for e in wbtcEthEvents]) \ + sum([int(e["toBadgerTree"]) for e in wbtcBadgerEvents]) \ + sum([int(e["toBadgerTree"]) for e in wBtcDiggEvents]) wbtcEthRewards = RewardsList(nextCycle,badger.badgerTree) wbtcBadgerRewards = RewardsList(nextCycle,badger.badgerTree) wbtcDiggRewards = RewardsList(nextCycle,badger.badgerTree) if len(wbtcEthEvents) > 0: wbtcEthStartBlock = get_latest_event_block(wbtcEthEvents[0],sushi_harvest_events["wbtcEth"]) if wbtcEthStartBlock == -1 or retroactive: wbtcEthStartBlock = 11537600 console.log(wbtcEthStartBlock) console.log("Processing {} wbtcEth sushi events".format(len(wbtcEthEvents))) wbtcEthRewards = process_sushi_events( badger,wbtcEthStartBlock,endBlock,wbtcEthEvents,"native.sushiWbtcEth",nextCycle) if len(wbtcBadgerEvents) > 0: wbtcBadgerStartBlock = get_latest_event_block(wbtcBadgerEvents[0],sushi_harvest_events["wbtcBadger"]) if wbtcBadgerStartBlock == -1 or retroactive: wbtcBadgerStartBlock = 11539529 console.log("Processing {} wbtcBadger sushi events".format(len(wbtcBadgerEvents))) wbtcBadgerRewards = process_sushi_events( badger,wbtcBadgerStartBlock,endBlock,wbtcBadgerEvents,"native.sushiBadgerWbtc",nextCycle) if len(wBtcDiggEvents) > 0: wbtcDiggStartBlock = get_latest_event_block(wBtcDiggEvents[0],sushi_harvest_events["wbtcDigg"]) if wbtcDiggStartBlock == -1 or retroactive: wbtcDiggStartBlock = 11676338 wbtcDiggRewards = process_sushi_events( badger,wbtcDiggStartBlock,endBlock,wBtcDiggEvents,"native.sushiDiggWbtc",nextCycle ) finalRewards = combine_rewards([wbtcEthRewards,wbtcBadgerRewards,wbtcDiggRewards],nextCycle,badger.badgerTree) xSushiFromRewards = 0 for user,claimData in finalRewards.claims.items(): for token,tokenAmount in claimData.items(): if token == web3.toChecksumAddress(xSushiTokenAddress): #console.log("Address {}: {} xSushi".format(user,int(float(tokenAmount))/1e18 )) xSushiFromRewards += int(float(tokenAmount)) console.log("Total xSushi {} from events".format( totalxSushi/1e18 )) console.log("Total xSushi {} from claims".format( xSushiFromRewards/1e18 )) difference = abs(totalxSushi - xSushiFromRewards) console.log("Difference {}".format(abs(totalxSushi/1e18 - xSushiFromRewards/1e18))) assert difference < 10000000 return finalRewards