예제 #1
0
 def print_recipients(self):
     table = []
     for recipient in self.recipients:
         table.append([
             recipient.name,
             recipient.address,
             val(
                 recipient.get_amount("usdc"),
                 decimals=token_metadata.get_decimals(
                     asset_to_address("usdc")),
             ),
             val(
                 recipient.get_amount("badger"),
                 decimals=token_metadata.get_decimals(
                     asset_to_address("badger")),
             ),
         ])
     table.append([
         "Totals",
         "-",
         val(
             self.totals["usdc"],
             decimals=token_metadata.get_decimals(asset_to_address("usdc")),
         ),
         val(
             self.totals["badger"],
             decimals=token_metadata.get_decimals(
                 asset_to_address("badger")),
         ),
     ])
     print("===== LTCC Payments for {} =====".format(self.date_range))
     print(tabulate(table, headers=["name", "address", "usdc", "badger"]))
예제 #2
0
    def generate(self, badger, multi, key, distributions, start=0, duration=0, end=0):
        dists = []
        for asset, dist in distributions.items():
            if dist == 0:
                continue
            console.print(
                "===== Distributions for asset {} on {} =====".format(asset, key),
                style="bold yellow",
            )

            token = asset_to_address(asset)

            # == Distribute to Geyser ==
            geyser = badger.getGeyser(key)
            rewardsEscrow = badger.rewardsEscrow
            multi = GnosisSafe(badger.devMultisig)
            opsMulti = GnosisSafe(badger.opsMultisig)

            print(key, geyser, rewardsEscrow)

            if rewardsEscrow.isApproved(geyser) == False:
                multi.execute(
                    MultisigTxMetadata(
                        description="Approve Recipient"
                    ),
                    {
                        "to": rewardsEscrow.address,
                        "data": rewardsEscrow.approveRecipient.encode_input(geyser),
                    },
                )

            # Approve Geyser as recipient if required
            if not rewardsEscrow.isApproved(geyser):
                multi.execute(
                    MultisigTxMetadata(
                        description="Approve StakingRewards " + key,
                        operation="transfer",
                    ),
                    {
                        "to": rewardsEscrow.address,
                        "data": rewardsEscrow.approveRecipient.encode_input(geyser),
                    },
                )

            numSchedules = geyser.unlockScheduleCount(token)
            console.print(
                "Geyser Distribution for {}: {}".format(key, val(dist)), style="yellow",
            )
            
            dists.append((geyser, asset_to_address(asset), dist, duration, start))
            
        console.log(key, dists)
        return dists
    def __init__(self,
                 badger,
                 multi,
                 key,
                 distributions,
                 start=0,
                 duration=0,
                 end=0):
        # == Distribute to Geyser ==
        geyser = badger.getGeyser(key)
        rewardsEscrow = badger.rewardsEscrow

        self.start = start
        self.duration = duration
        self.end = end

        multi = GnosisSafe(badger.devMultisig)
        for asset, dist in distributions.items():
            token = asset_to_address(asset)
            self.validate_staking_rewards_emission(key, asset)

            stakingRewards = badger.getSettRewards(key)
            console.print(
                "Staking Rewards Distribution for asset {} on {}: {}".format(
                    asset, key, val(dist)),
                style="yellow",
            )

            # Approve if not approved
            if not rewardsEscrow.isApproved(stakingRewards):
                id = multi.addTx(
                    MultisigTxMetadata(
                        description="Approve StakingRewards " + key,
                        operation="transfer",
                    ),
                    {
                        "to":
                        rewardsEscrow.address,
                        "data":
                        rewardsEscrow.approveRecipient.encode_input(
                            stakingRewards),
                    },
                )

                multi.executeTx(id)

                assert rewardsEscrow.isApproved(stakingRewards) == True

            # Add tokens if insufficent tokens
            preBal = badger.token.balanceOf(stakingRewards)
            print("PreBalance", val(preBal))

            if preBal < dist:
                required = dist - preBal
                console.print(
                    "⊁ We need to add {} to the {} Badger supply of {} to reach the goal of {} Badger"
                    .format(
                        val(required),
                        key,
                        val(preBal),
                        val(dist),
                    ),
                    style="blue",
                )

                id = multi.addTx(
                    MultisigTxMetadata(
                        description="Top up tokens for staking rewards " + key,
                        operation="transfer",
                    ),
                    {
                        "to":
                        rewardsEscrow.address,
                        "data":
                        rewardsEscrow.transfer.encode_input(
                            badger.token, stakingRewards, required),
                    },
                )

                multi.executeTx(id)

            assert badger.token.balanceOf(stakingRewards) >= dist

            # Modify the rewards duration, if necessary
            if stakingRewards.rewardsDuration() != self.duration:
                id = multi.addTx(
                    MultisigTxMetadata(
                        description="Modify Staking Rewards duration for " +
                        key,
                        operation="call.notifyRewardAmount",
                    ),
                    {
                        "to":
                        stakingRewards.address,
                        "data":
                        stakingRewards.setRewardsDuration.encode_input(
                            self.duration),
                    },
                )
                tx = multi.executeTx(id)

            # assert stakingRewards.rewardsDuration() == self.duration

            # Notify Rewards Amount
            id = multi.addTx(
                MultisigTxMetadata(
                    description="Distribute Staking Rewards For " + key,
                    operation="call.notifyRewardAmount",
                ),
                {
                    "to":
                    stakingRewards.address,
                    "data":
                    stakingRewards.notifyRewardAmount.encode_input(
                        self.start,
                        dist,
                    ),
                },
            )

            tx = multi.executeTx(id)
            console.print(tx.call_trace())
            console.print("notify rewards events", tx.events)

            # Verify Results

            rewardsDuration = stakingRewards.rewardsDuration()
            rewardRate = stakingRewards.rewardRate()
            periodFinish = stakingRewards.periodFinish()
            lastUpdate = stakingRewards.lastUpdateTime()

            oldRewardsRate = Wei("50000 ether") // rewardsDuration

            console.log({
                "start":
                to_utc_date(self.start),
                "end":
                to_utc_date(self.end),
                "finish":
                to_utc_date(periodFinish),
                "rewardRate":
                rewardRate,
                "expectedRewardRate":
                dist // rewardsDuration,
                "rewardsRateDiff":
                rewardRate - dist // rewardsDuration,
                "oldRewardsRate":
                oldRewardsRate,
                "howTheRateChanged":
                (dist // rewardsDuration) / oldRewardsRate,
                "howWeExpectedItToChange":
                Wei("35000 ether") / Wei("50000 ether"),
                "lastUpdate":
                to_utc_date(lastUpdate),
            })

            assert lastUpdate == self.start
            assert rewardsDuration == self.duration
            assert rewardRate == dist // rewardsDuration
            assert periodFinish == self.start + self.duration

            bal = badger.token.balanceOf(stakingRewards)
            assert bal >= dist

            if bal > dist * 2:
                console.print(
                    "[red] Warning: Staking rewards for {} has excessive coins [/red]"
                    .format(key))

            # Harvest the rewards and ensure the amount updated is appropriate
            strategy = badger.getStrategy(key)
            keeper = accounts.at(strategy.keeper(), force=True)

            before = strategy.balance()
            chain.sleep(self.start - chain.time() + 2)
            strategy.harvest({"from": keeper})
            after = strategy.balance()

            print({"before": before, "after": after})