def combine_rewards(rewardsList, cycle, badgerTree): combinedRewards = RewardsList(cycle, badgerTree) for rewards in rewardsList: for user, claims in rewards.claims.items(): for token, claim in claims.items(): combinedRewards.increase_user_rewards(user, token, claim) return combinedRewards
def process_rewards(badger, events, name, nextCycle, token): totalFromEvents = sum([int(e["rewardAmount"]) for e in events]) / 1e18 rewards = RewardsList(nextCycle, badger.badgerTree) total = 0 for event in events: userState = calc_meta_farm_rewards(badger, name, event["blockNumber"]) totalBalance = sum([u.balance for u in userState]) total += int(event["rewardAmount"]) console.log("{} total {} processed".format(total / 1e18, token)) rewardsUnit = int(event["rewardAmount"]) / totalBalance for user in userState: rewards.increase_user_rewards( web3.toChecksumAddress(user.address), web3.toChecksumAddress(token), rewardsUnit * user.balance, ) totalFromRewards = sum( [list(v.values())[0] / 1e18 for v in list(rewards.claims.values())]) rewardsLog.add_total_token_dist(name, token, totalFromRewards) # Calc diff of rewardsTotal and add assertion for checking rewards rewardsDiff = abs(totalFromRewards - totalFromRewards) * 1e18 console.log( "Total from Rewards: {} \nTotal from Events: {}\n Diff: {}".format( totalFromRewards, totalFromEvents, rewardsDiff)) if abs(totalFromEvents - totalFromRewards) > 100000: assert False, "Incorrect total rewards" 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_rewards(badger, startBlock, endBlock, events, name, nextCycle, token): endBlock = int(events[0]["blockNumber"]) totalFromEvents = sum([int(e["rewardAmount"]) for e in events]) / 1e18 rewards = RewardsList(nextCycle, badger.badgerTree) total = 0 for i in tqdm(range(len(events))): event = events[i] userState = calc_meta_farm_rewards(badger, name, startBlock, endBlock) totalBalance = sum([u.balance for u in userState]) total += int(event["rewardAmount"]) console.log("{} total {} processed".format(total / 1e18, token)) rewardsUnit = int(event["rewardAmount"]) / totalBalance for addr, balance in userState.items(): rewards.increase_user_rewards( web3.toChecksumAddress(addr), web3.toChecksumAddress(token), rewardsUnit * user, ) if i + 1 < len(events): startBlock = int(events[i]["blockNumber"]) endBlock = int(events[i + 1]["blockNumber"]) totalFromRewards = sum( [list(v.values())[0] / 1e18 for v in list(rewards.claims.values())]) # Calc diff of rewardsTotal and add assertion for checking rewards rewardsDiff = abs(totalFromRewards - totalFromRewards) * 1e18 console.log( "Total from Rewards: {} \nTotal from Events: {}\n Diff: {}".format( totalFromRewards, totalFromEvents, rewardsDiff)) if abs(totalFromEvents - totalFromRewards) > 100000: assert False, "Incorrect total rewards" distr = {} distr[token] = totalFromRewards rewardsLog.add_distribution_info(name, distr) return rewards
def calc_rewards(badger, start, end, nextCycle, events, name, token): def filter_events(e): return int(e["blockNumber"]) > start and int(e["blockNumber"]) < end filteredEvents = list(filter(filter_events, events)) rewards = RewardsList(nextCycle, badger.badgerTree) if len(filteredEvents) > 0: console.log(filteredEvents) console.log("{} events to process for {}".format( len(filteredEvents), name)) rewards = process_rewards(badger, filteredEvents, name, nextCycle, token) else: console.log("No events to process for {}".format(name)) return rewards
def calc_rewards(badger, start, end, nextCycle, events, name, token, retroactive, retroactiveStart): def filter_events(e): return int(e["blockNumber"]) > start and int(e["blockNumber"]) < end filteredEvents = list(filter(filter_events, events)) rewards = RewardsList(nextCycle, badger.badgerTree) if len(filteredEvents) > 0: console.log(filteredEvents) console.log("{} events to process for {}".format( len(filteredEvents), name)) startBlock = get_latest_event_block(filteredEvents[0], events) if retroactive: startBlock = retroactiveStart rewards = process_rewards(badger, startBlock, end, filteredEvents, name, nextCycle, token) else: console.log("No events to process") return rewards
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 calc_snapshot( badger, name, startBlock, endBlock, nextCycle, boosts, unclaimedBalances ): digg = interface.IDigg(DIGG) console.log("==== Processing rewards for {} at {} ====".format(name, endBlock)) rewards = RewardsList(nextCycle, badger.badgerTree) sett = badger.getSett(name) startTime = web3.eth.getBlock(startBlock)["timestamp"] endTime = web3.eth.getBlock(endBlock)["timestamp"] userBalances = calculate_sett_balances(badger, name, endBlock) apyBoosts = {} if name in NON_NATIVE_SETTS: console.log( "{} users out of {} boosted in {}".format( len(userBalances), len(boosts), name ) ) preBoost = {} for user in userBalances: preBoost[user.address] = userBalances.percentage_of_total(user.address) for user in userBalances: boostAmount = boosts.get(user.address, 1) user.boost_balance(boostAmount) for user in userBalances: postBoost = userBalances.percentage_of_total(user.address) apyBoosts[user.address] = postBoost / preBoost[user.address] schedulesByToken = parse_schedules( badger.rewardsLogger.getAllUnlockSchedulesFor(sett) ) for token, schedules in schedulesByToken.items(): endDist = get_distributed_for_token_at(token, endTime, schedules, name) startDist = get_distributed_for_token_at(token, startTime, schedules, name) tokenDistribution = int(endDist) - int(startDist) # Distribute to users with rewards list # Make sure there are tokens to distribute (some geysers only # distribute one token) if token == DIGG: # if name in NATIVE_DIGG_SETTS: # tokenDistribution = tokenDistribution * diggAllocation # else: # tokenDistribution = tokenDistribution * (1 - diggAllocation) fragments = digg.sharesToFragments(tokenDistribution) / 1e9 console.log( "{} DIGG tokens distributed".format( digg.sharesToFragments(tokenDistribution) / 1e9 ) ) rewardsLog.add_total_token_dist(name, token, fragments) elif token == "0x20c36f062a31865bED8a5B1e512D9a1A20AA333A": console.log("{} DFD tokens distributed".format(tokenDistribution / 1e18)) rewardsLog.add_total_token_dist(name, token, tokenDistribution / 1e18) else: badgerAmount = tokenDistribution / 1e18 console.log("{} Badger token distributed".format(badgerAmount)) rewardsLog.add_total_token_dist(name, token, tokenDistribution / 1e18) if tokenDistribution > 0: sumBalances = sum([b.balance for b in userBalances]) rewardsUnit = tokenDistribution / sumBalances totalRewards = 0 console.log("Processing rewards for {} addresses".format(len(userBalances))) for user in userBalances: addr = web3.toChecksumAddress(user.address) token = web3.toChecksumAddress(token) rewardAmount = user.balance * rewardsUnit totalRewards += rewardAmount ## If giving rewards to tree , distribute them to users with unlcaimed bals if addr == BADGER_TREE: if name == "native.cvx": console.log( "Distributing {} rewards to {} unclaimed bCvx holders".format( rewardAmount / 1e18, len(unclaimedBalances["bCvx"]) ) ) totalbCvxBal = sum(unclaimedBalances["bCvx"].values()) cvxRewardsUnit = rewardAmount / totalbCvxBal for addr, bal in unclaimedBalances["bCvx"].items(): rewards.increase_user_rewards( web3.toChecksumAddress(addr), token, int(cvxRewardsUnit * bal), ) if name == "native.cvxCrv": console.log( "Distributing {} rewards to {} unclaimed bCvxCrv holders".format( rewardAmount / 1e18, len(unclaimedBalances["bCvxCrv"]) ) ) totalbCvxCrvBal = sum(unclaimedBalances["bCvxCrv"].values()) bCvxCrvRewardsUnit = rewardAmount / totalbCvxCrvBal for addr, bal in unclaimedBalances["bCvxCrv"].items(): rewards.increase_user_rewards( web3.toChecksumAddress(addr), token, int(bCvxCrvRewardsUnit * bal), ) else: rewards.increase_user_rewards(addr, token, int(rewardAmount)) console.log( "Token Distribution: {}\nRewards Released: {}".format( tokenDistribution / 1e18, totalRewards / 1e18 ) ) console.log("Diff {}\n\n".format((abs(tokenDistribution - totalRewards)))) return rewards, apyBoosts
def calc_tree_rewards(badger, startBlock, endBlock, nextCycle): # sharesPerFragment = badger.digg.logic.UFragments._sharesPerFragment() # _, _2, ibbtc_balances = fetch_wallet_balances(sharesPerFragment, endBlock) treeDists = fetch_tree_distributions(startBlock, endBlock) console.log( "Calculating rewards for {} harvests between {} and {}".format( len(treeDists), startBlock, endBlock ) ) rewards = RewardsList(nextCycle, badger.badgerTree) rewardsData = {} for dist in treeDists: blockNumber = dist["blockNumber"] strategy = dist["id"].split("-")[0] token = dist["token"]["address"] symbol = dist["token"]["symbol"] amountToDistribute = int(dist["amount"]) console.log("Processing harvest...") console.log("Token:{}".format(symbol)) console.log("Amount:{} \n".format(amountToDistribute / 1e18)) if symbol not in rewardsData: rewardsData[symbol] = 0 rewardsData[symbol] += amountToDistribute / 1e18 settName = badger.getSettFromStrategy(strategy) balances = calculate_sett_balances(badger, settName, int(blockNumber)) totalBalance = sum([u.balance for u in balances]) rewardsUnit = amountToDistribute / totalBalance rewardsLog.add_total_token_dist( settName, web3.toChecksumAddress(token), amountToDistribute / 1e18 ) # totalIbbtcBalance = sum(ibbtc_balances.values()) for user in balances: userReward = rewardsUnit * user.balance # if user.address in [a.lower() for a in PEAK_ADDRESSES]: # ibbtcRewardsUnit = userReward / totalIbbtcBalance # console.log( # "Distributing {} {} to {} ibbtc holders from {}".format( # userReward / 1e18, symbol, len(ibbtc_balances), settName # ) # ) # # Redistribute peak addresses rewards to ibbtc users # for addr, balance in ibbtc_balances.items(): # rewards.increase_user_rewards( # web3.toChecksumAddress(addr), # token, # int(ibbtcRewardsUnit * balance), # ) # else: rewards.increase_user_rewards( web3.toChecksumAddress(user.address), web3.toChecksumAddress(token), int(userReward), ) console.log(rewardsData) return rewards