def wire_up_sett_multisig(self, vault, strategy, controller): multi = GnosisSafe(self.devMultisig, testMode=True) want = strategy.want() vault_want = vault.token() assert vault_want == want id = multi.addTx( MultisigTxMetadata( description="Set Vault for {} on Controller".format(want) ), { "to": controller.address, "data": controller.setVault.encode_input( want, vault ), }, ) multi.executeTx(id) id = multi.addTx( MultisigTxMetadata( description="Approve Strategy for {} on Controller".format(want) ), { "to": controller.address, "data": controller.approveStrategy.encode_input( want, strategy ), }, ) multi.executeTx(id) id = multi.addTx( MultisigTxMetadata( description="Set Strategy for {} on Controller".format(want) ), { "to": controller.address, "data": controller.setStrategy.encode_input( want, strategy ), }, ) multi.executeTx(id)
def upgrade_sett(self, id, newLogic): sett = self.getSett(id) multi = GnosisSafe(self.devMultisig) id = multi.addTx( MultisigTxMetadata(description="Upgrade timelock"), { "to": self.proxyAdmin.address, "data": self.proxyAdmin.upgrade.encode_input(sett, newLogic), }, ) tx = multi.executeTx(id)
def governance_queue_transaction(self, target, signature, data, eta, eth=0) -> str: multi = GnosisSafe(self.devMultisig) id = multi.addTx( MultisigTxMetadata(description="Queue timelock transaction"), { "to": self.governanceTimelock.address, "data": self.governanceTimelock.queueTransaction.encode_input( target, eth, signature, data, eta, ), }, ) multi.executeTx(id) txHash = Web3.solidityKeccak( [ "address", "uint256", "string", "bytes", "uint256", ], [ target, eth, signature, data, eta, ], ).hex() txFilename = "{}.json".format(txHash) with open(os.path.join(TIMELOCK_DIR, txFilename), "w") as f: # Dump tx data to timelock pending tx dir. txData = { "target": target, "eth": eth, "signature": signature, "data": data.hex(), "eta": eta, } f.write(json.dumps(txData, indent=4, sort_keys=True)) return txFilename
def configure_bridge(badger: BadgerSystem, bridge: BridgeSystem): """ Configures bridge to use curve token wrapper. """ multi = GnosisSafe(badger.devMultisig) id = multi.addTx( MultisigTxMetadata(description="Set curve token wrapper on adapter",), { "to": bridge.adapter.address, "data": bridge.adapter.setCurveTokenWrapper.encode_input( bridge.curveTokenWrapper.address ), }, ) multi.executeTx(id)
def whitelist_adapter_crv_sett( badger: BadgerSystem, bridge: BridgeSystem, multi: GnosisSafe, settID: str, ): sett = badger.sett_system.vaults[settID] id = multi.addTx( MultisigTxMetadata( description="Approve adapter access to sett {}".format(settID) ), { "to": sett.address, "data": sett.approveContractAccess.encode_input(bridge.adapter.address), }, ) multi.executeTx(id)
def governance_execute_transaction(self, txFilename): multi = GnosisSafe(self.devMultisig) with open(os.path.join(TIMELOCK_DIR, txFilename), "r") as f: txData = json.load(f) id = multi.addTx( MultisigTxMetadata(description="Execute timelock transaction"), { "to": self.governanceTimelock.address, "data": self.governanceTimelock.executeTransaction.encode_input( txData["target"], txData["eth"], txData["signature"], txData["data"], txData["eta"], ), }, ) if multisig_success(multi.executeTx(id)): os.remove(os.path.join(TIMELOCK_DIR, txFilename))
def transfer(self, token, amount, recipient): rewardsEscrow = self.badger.rewardsEscrow multi = GnosisSafe(self.badger.devMultisig) # Approve Geyser as recipient if required if not rewardsEscrow.isApproved(recipient): multi.execute( MultisigTxMetadata(description="Approve Recipient " + recipient.address), { "to": rewardsEscrow.address, "data": rewardsEscrow.approveRecipient.encode_input(recipient), }, ) before = token.balanceOf(recipient) # Top up Tree # TODO: Make the amount based on what we'll require for the next week id = multi.addTx( MultisigTxMetadata(description="Send {} {} to {}".format( token, amount, recipient)), { "to": rewardsEscrow.address, "data": rewardsEscrow.transfer.encode_input(token, recipient, amount), }, ) tx = multi.executeTx(id) print(tx.call_trace()) after = token.balanceOf(recipient) console.print({"before": before, "after": after}) assert after == before + amount
def swap_transfer(recipient, params): badger = connect_badger("deploy-final.json") expectedMultisig = "0xB65cef03b9B89f99517643226d76e286ee999e77" assert badger.devMultisig == expectedMultisig multi = GnosisSafe(badger.devMultisig) one_wei = Wei("1") end_token = interface.IERC20(params["path"][-1]) console.print("Executing Swap:", style="yellow") console.print(params) # === Approve Uniswap Router on Rewards Escrow if not approved === uniswap = UniswapSystem() assert badger.rewardsEscrow.isApproved(badger.token) assert badger.rewardsEscrow.isApproved(uniswap.router) # === Approve UNI Router for Badger === # Note: The allowance must first be set to 0 id = multi.addTx( MultisigTxMetadata( description="Approve UNI Router to send BADGER", operation="call", callInfo={ 'address': uniswap.router, 'amount': params["max_in"] // 2 }, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.call.encode_input( badger.token, 0, badger.token.approve.encode_input(uniswap.router, 0), ), }, ) tx = multi.executeTx(id) # Set proper allowance id = multi.addTx( MultisigTxMetadata( description="Approve UNI Router to send BADGER", operation="call", callInfo={ 'address': uniswap.router, 'amount': params["max_in"] // 2 }, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.call.encode_input( badger.token, 0, badger.token.approve.encode_input(uniswap.router, params["max_in"]), ), }, ) tx = multi.executeTx(id) console.print({ "rewardsEscrowBalance": val(badger.token.balanceOf(badger.rewardsEscrow)), "rewardsEscrowRouterAllowance": val(badger.token.allowance(badger.rewardsEscrow, uniswap.router)), "max_in": val(params["max_in"]), }) assert badger.token.balanceOf(badger.rewardsEscrow) > params["max_in"] assert (badger.token.allowance(badger.rewardsEscrow, uniswap.router) >= params["max_in"]) # === Trade Badger for USDC through WBTC === before = end_token.balanceOf(badger.rewardsEscrow) beforeBadger = badger.token.balanceOf(badger.rewardsEscrow) console.print({"EAO": params["exact_amount_out"]}) expiration = chain.time() + 8000 id = multi.addTx( MultisigTxMetadata( description="Trade Badger for output token", operation="call", callInfo={}, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.call.encode_input( uniswap.router, 0, uniswap.router.swapTokensForExactTokens.encode_input( params["exact_amount_out"], MaxUint256, params["path"], badger.rewardsEscrow, expiration, ), ), }, ) tx = multi.executeTx(id) print(tx.call_trace()) print(tx.events) printUniTrade( method="swapTokensForExactTokens", params=( params["exact_amount_out"], params["max_in"], params['path'], badger.rewardsEscrow, expiration, ), ) console.log("=== Post Trade ===") console.print({ 'before_input_coin': beforeBadger, 'after_input_coin': badger.token.balanceOf(badger.rewardsEscrow), 'before_output_coin': before, 'post_output_coin': end_token.balanceOf(badger.rewardsEscrow), 'end_token': end_token, 'chain_time_before': chain.time() }) assert end_token.balanceOf( badger.rewardsEscrow) >= params["exact_amount_out"] # === Approve Recipient if not approved === if not badger.rewardsEscrow.isApproved(recipient): id = multi.addTx( MultisigTxMetadata( description="Approve the transfer recipient", operation="approveRecipient", callInfo={}, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.approveRecipient.encode_input(recipient), }, ) multi.executeTx(id) assert badger.rewardsEscrow.isApproved(recipient) # === Test Payment to recipient === before = end_token.balanceOf(recipient) id = multi.addTx( MultisigTxMetadata( description="Test payment to recipientt", operation="transfer", callInfo={ "to": recipient, "amount": one_wei }, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.transfer.encode_input(end_token, recipient, one_wei), }, ) multi.executeTx(id) after = end_token.balanceOf(recipient) assert after == before + one_wei # === Full Payment to recipient === rest = params["exact_amount_out"] - 1 before = end_token.balanceOf(recipient) id = multi.addTx( MultisigTxMetadata( description="$12k payment to auditor, in USDC", operation="transfer", callInfo={ "to": recipient, "amount": rest }, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.transfer.encode_input(end_token, recipient, rest), }, ) multi.executeTx(id) after = end_token.balanceOf(recipient) assert after == before + rest print(before, after, before + params["exact_amount_out"]) console.print("\n[green] ✅ Actions Complete [/green]")
def testTransactions(self): rewardsEscrow = self.badger.rewardsEscrow multi = GnosisSafe(self.badger.devMultisig) opsMulti = GnosisSafe(self.badger.opsMultisig) # Setup accounts[7].transfer(multi.get_first_owner(), Wei("2 ether")) print( "Supplied ETH", accounts.at(multi.get_first_owner(), force=True).balance(), ) badger = self.badger tree = self.badger.badgerTree before = badger.token.balanceOf(tree) top_up = Wei("100000 ether") top_up_digg = Wei("40 gwei") harvest_badger = Wei("30000 ether") harvest_digg = Wei("40 gwei") # Top up Tree # TODO: Make the amount based on what we'll require for the next week id = multi.addTx( MultisigTxMetadata(description="Top up badger tree with Badger"), { "to": rewardsEscrow.address, "data": rewardsEscrow.transfer.encode_input(badger.token, tree, top_up), }, ) tx = multi.executeTx(id) after = badger.token.balanceOf(tree) assert after == before + top_up before = badger.digg.token.balanceOf(tree) tx = multi.execute( MultisigTxMetadata(description="Top up badger tree with DIGG"), { "to": rewardsEscrow.address, "data": rewardsEscrow.transfer.encode_input(badger.digg.token, tree, top_up_digg), }, ) print(tx.call_trace(), before, after) after = badger.digg.token.balanceOf(tree) assert after == before + top_up_digg # multi.execute( # MultisigTxMetadata(description="Top up rewards manager with Badger"), # { # "to": rewardsEscrow.address, # "data": rewardsEscrow.transfer.encode_input( # badger.token, badger.badgerRewardsManager, harvest_badger # ), # }, # ) multi.execute( MultisigTxMetadata(description="Top up rewards manager with DIGG"), { "to": rewardsEscrow.address, "data": rewardsEscrow.transfer.encode_input( badger.digg.token, badger.badgerRewardsManager, harvest_digg), }, ) # grant_token_locking_permission(self.badger, self.badger.unlockScheduler) geyserDists = [] for key, distribution in self.distributions.items(): if distribution.hasGeyserDistribution() == True: print("has geyser distribution", key) dist = GeyserDistributor() dists = dist.generate( badger, multi, key, distributions=distribution.getGeyserDistributions(), start=self.start, duration=self.duration, end=self.end, ) geyserDists.extend(dists) console.log("after " + key, geyserDists) # Add unlock schedeules inbulk console.log(geyserDists) tx = opsMulti.execute( MultisigTxMetadata(description="Signal unlock schedules"), { "to": badger.unlockScheduler.address, "data": badger.unlockScheduler.signalTokenLocks.encode_input( geyserDists), }, ) print(tx.call_trace()) tokens = [self.badger.token.address, self.badger.digg.token.address] for key in geyser_keys: print(key) geyser = self.badger.getGeyser(key) for token in tokens: print(token) console.log( "{} schedules for {}".format(token, key), geyser.getUnlockSchedulesFor(token), )
def swap_transfer(recipient, params): badger = connect_badger("deploy-final.json") badger.paymentsMultisig = connect_gnosis_safe( "0xD4868d98849a58F743787c77738D808376210292" ) expectedMultisig = "0xB65cef03b9B89f99517643226d76e286ee999e77" assert badger.devMultisig == expectedMultisig multi = GnosisSafe(badger.paymentsMultisig) one_wei = Wei("1") end_token = interface.IERC20(params["path"][-1]) console.print("Executing Swap:", style="yellow") console.print(params) # === Approve Uniswap Router on Rewards Escrow if not approved === uniswap = UniswapSystem() # === Approve UNI Router for Badger === # Note: The allowance must first be set to 0 id = multi.addTx( MultisigTxMetadata( description="Approve UNI Router to send BADGER", operation="call", ), params={ "to": badger.token.address, "data": badger.token.approve.encode_input(uniswap.router, 0), }, ) tx = multi.executeTx(id) # Set proper allowance id = multi.addTx( MultisigTxMetadata( description="Approve UNI Router to send BADGER", operation="call", ), params={ "to": badger.token.address, "data": badger.token.approve.encode_input( uniswap.router, int(params["max_in"] * 1.5) ), }, ) tx = multi.executeTx(id) console.print( { "rewardsEscrowBalance": val( badger.token.balanceOf(badger.paymentsMultisig) ), "rewardsEscrowRouterAllowance": val( badger.token.allowance(badger.paymentsMultisig, uniswap.router) ), "max_in": val(params["max_in"]), } ) assert badger.token.balanceOf(badger.paymentsMultisig) > params["max_in"] assert ( badger.token.allowance(badger.paymentsMultisig, uniswap.router) >= params["max_in"] ) # === Trade Badger === before = end_token.balanceOf(badger.paymentsMultisig) beforeBadger = badger.token.balanceOf(badger.paymentsMultisig) console.print({"EAO": params["exact_amount_out"]}) expiration = chain.time() + 8000 id = multi.addTx( MultisigTxMetadata( description="Trade Badger for output token", operation="call", callInfo={}, ), params={ "to": uniswap.router.address, "data": uniswap.router.swapTokensForExactTokens.encode_input( params["exact_amount_out"], int(params["max_in"] * 1.5), params["path"], badger.paymentsMultisig, expiration, ), }, ) tx = multi.executeTx(id) print(tx.call_trace()) print(tx.events) printUniTrade( method="swapTokensForExactTokens", params=( params["exact_amount_out"], int(params["max_in"] * 1.5), params["path"], badger.paymentsMultisig, expiration, ), ) console.log("=== Post Trade ===") console.print( { "before_input_coin": val(beforeBadger), "after_input_coin": val(badger.token.balanceOf(badger.paymentsMultisig)), "change_input_coin": val( beforeBadger - badger.token.balanceOf(badger.paymentsMultisig) ), "before_output_coin": val(before, decimals=end_token.decimals()), "post_output_coin": val( end_token.balanceOf(badger.paymentsMultisig), decimals=end_token.decimals(), ), "end_token": end_token, "chain_time_before": chain.time(), } ) assert end_token.balanceOf(badger.paymentsMultisig) >= params["exact_amount_out"] console.print("\n[green] ✅ Actions Complete [/green]")
def transfer_badger(recipient, params): badger = connect_badger("deploy-final.json") expectedMultisig = "0xB65cef03b9B89f99517643226d76e286ee999e77" assert badger.devMultisig == expectedMultisig multi = GnosisSafe(badger.devMultisig) one_wei = Wei("1") end_token = badger.token # === Approve Recipient if not approved === if not badger.rewardsEscrow.isApproved(recipient): id = multi.addTx( MultisigTxMetadata( description="Approve the transfer recipient", operation="approveRecipient", callInfo={}, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.approveRecipient.encode_input(recipient), }, ) multi.executeTx(id) assert badger.rewardsEscrow.isApproved(recipient) # === Test Payment to recipient === before = end_token.balanceOf(recipient) if params["use_test_payment"]: id = multi.addTx( MultisigTxMetadata( description="Test payment: {} badger to {}".format( one_wei, recipient), operation="transfer", callInfo={ "to": recipient, "amount": one_wei }, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.transfer.encode_input( end_token, recipient, one_wei), }, ) multi.executeTx(id) after = end_token.balanceOf(recipient) assert after == before + one_wei # === Full Payment to recipient === rest = 0 if params["use_test_payment"]: rest = params["amount"] - 1 else: rest = params["amount"] before = end_token.balanceOf(recipient) id = multi.addTx( MultisigTxMetadata( description="Full payment, {} badger to {}".format( val(rest), recipient), operation="transfer", callInfo={ "to": recipient, "amount": rest }, ), params={ "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.transfer.encode_input(end_token, recipient, rest), }, ) multi.executeTx(id) after = end_token.balanceOf(recipient) assert after == before + rest print(before, after, before + params["amount"]) console.print("\n[green] ✅ Actions Complete [/green]")
def testTransactions(self): rewardsEscrow = self.badger.rewardsEscrow multi = GnosisSafe(self.badger.devMultisig) # Setup accounts[7].transfer(multi.get_first_owner(), Wei("2 ether")) print( "Supplied ETH", accounts.at(multi.get_first_owner(), force=True).balance(), ) badger = self.badger tree = self.badger.badgerTree before = badger.token.balanceOf(tree) top_up = Wei("200000 ether") # Top up Tree # TODO: Make the amount based on what we'll require for the next week id = multi.addTx( MultisigTxMetadata( description="Top up badger tree", operation="Top Up Badger Tree", ), { "to": rewardsEscrow.address, "data": rewardsEscrow.transfer.encode_input(badger.token, tree, top_up), }, ) tx = multi.executeTx(id) after = badger.token.balanceOf(tree) assert after == before + top_up for key, distribution in self.distributions.items(): console.print("===== Distributions for {} =====".format(key), style="bold yellow") # == Distribute to Geyser == geyser = self.badger.getGeyser(key) # Approve Geyser as recipient if required if not rewardsEscrow.isApproved(geyser): id = multi.addTx( MultisigTxMetadata( description="Approve StakingRewards " + key, operation="transfer", ), { "to": rewardsEscrow.address, "data": rewardsEscrow.approveRecipient.encode_input(geyser), }, ) multi.executeTx(id) numSchedules = geyser.unlockScheduleCount(self.badger.token) console.print( "Geyser Distribution for {}: {}".format( key, val(distribution.toGeyser)), style="yellow", ) id = multi.addTx( MultisigTxMetadata( description="Signal unlock schedule for " + key, operation="signalTokenLock", ), { "to": rewardsEscrow.address, "data": rewardsEscrow.signalTokenLock.encode_input( geyser, self.badger.token, distribution.toGeyser, self.duration, self.start, ), }, ) multi.executeTx(id) # Verify Results numSchedulesAfter = geyser.unlockScheduleCount(self.badger.token) console.print( "Schedule Addition", { "numSchedules": numSchedules, "numSchedulesAfter": numSchedulesAfter }, ) assert numSchedulesAfter == numSchedules + 1 unlockSchedules = geyser.getUnlockSchedulesFor(self.badger.token) schedule = unlockSchedules[-1] print(schedule) assert schedule[0] == distribution.toGeyser assert schedule[1] == self.end assert schedule[2] == self.duration assert schedule[3] == self.start # == Distribute to StakingRewards, if relevant == if distribution.toStakingRewards > 0: stakingRewards = self.badger.getSettRewards(key) console.print( "Staking Rewards Distribution for {}: {}".format( key, val(distribution.toStakingRewards)), 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 = self.badger.token.balanceOf(stakingRewards) if preBal < distribution.toStakingRewards: required = distribution.toStakingRewards - 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(distribution.toStakingRewards), ), style="blue", ) id = multi.addTx( MultisigTxMetadata( description="Top up tokens for staking rewards " + key, operation="transfer", ), { "to": rewardsEscrow.address, "data": rewardsEscrow.transfer.encode_input( self.badger.token, stakingRewards, required), }, ) multi.executeTx(id) assert (self.badger.token.balanceOf(stakingRewards) >= distribution.toStakingRewards) # 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, distribution.toStakingRewards, ), }, ) 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": distribution.toStakingRewards // rewardsDuration, "rewardsRateDiff": rewardRate - distribution.toStakingRewards // rewardsDuration, "oldRewardsRate": oldRewardsRate, "howTheRateChanged": (distribution.toStakingRewards // rewardsDuration) / oldRewardsRate, "howWeExpectedItToChange": Wei("35000 ether") / Wei("50000 ether"), "lastUpdate": to_utc_date(lastUpdate), }) assert lastUpdate == self.start assert rewardsDuration == self.duration assert rewardRate == distribution.toStakingRewards // rewardsDuration assert periodFinish == self.start + self.duration bal = self.badger.token.balanceOf(stakingRewards) assert bal >= distribution.toStakingRewards if bal > distribution.toStakingRewards * 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 = self.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})
def init_prod_digg(badger: BadgerSystem, user): deployer = badger.deployer digg = badger.digg multi = GnosisSafe(badger.devMultisig) digg_liquidity_amount = 1000000000 wbtc_liquidity_amount = 100000000 print("TOKEN_LOCKER_ROLE", TOKEN_LOCKER_ROLE) locker_role = "0x4bf6f2cdcc8ad6c087a7a4fbecf46150b3686b71387234cac2b3e2e6dc70e345" # TODO: Have this as proxy in real deploy seederLogic = DiggSeeder.deploy({"from": deployer}) seeder = deploy_proxy( "DiggSeeder", DiggSeeder.abi, seederLogic.address, badger.devProxyAdmin.address, seederLogic.initialize.encode_input(digg.diggDistributor), deployer, ) # # Take initial liquidity from DAO # aragon = AragonSystem() # voting = aragon.getVotingAt("0xdc344bfb12522bf3fa58ef0d6b9a41256fc79a1b") # PROD: Configure DIGG digg.uFragmentsPolicy.setCpiOracle( digg.cpiMedianOracle, {"from": deployer}, ) digg.uFragmentsPolicy.setMarketOracle( digg.marketMedianOracle, {"from": deployer}, ) digg.uFragmentsPolicy.setOrchestrator( digg.orchestrator, {"from": deployer}, ) digg.uFragments.setMonetaryPolicy( digg.uFragmentsPolicy, {"from": deployer}, ) # ===== Upgrade DAOTimelock to allow voting ===== # print(badger.logic.SimpleTimelockWithVoting.address) # timelockWithVotingLogic = SimpleTimelockWithVoting.at(badger.logic.SimpleTimelockWithVoting.address) # timelock = interface.ISimpleTimelockWithVoting(badger.daoBadgerTimelock.address) # multi.execute( # MultisigTxMetadata(description="Upgrade DAO Badger Timelock to Allow voting",), # { # "to": badger.devProxyAdmin.address, # "data": badger.devProxyAdmin.upgrade.encode_input( # badger.daoBadgerTimelock, timelockWithVotingLogic # ), # }, # ) # # ===== Vote to move initial liquidity funds to multisig ===== # tx = multi.execute( # MultisigTxMetadata(description="Vote on DAO Timelock from multisig",), # { # "to": timelock.address, # "data": timelock.vote.encode_input(0, True, True) # }, # ) # # Approve DAO voting as recipient # multi.execute( # MultisigTxMetadata(description="Approve DAO voting as recipient",), # { # "to": badger.rewardsEscrow.address, # "data": badger.rewardsEscrow.approveRecipient.encode_input(voting), # }, # ) # # Vote on DAO voting as rewardsEscrow # before = badger.token.balanceOf(badger.rewardsEscrow) # tx = multi.execute( # MultisigTxMetadata(description="Vote on Rewards Escrow from multisig",), # { # "to": badger.rewardsEscrow.address, # "data": badger.rewardsEscrow.call.encode_input( # voting, 0, voting.vote.encode_input(0, True, True) # ), # }, # ) # after = badger.token.balanceOf(badger.rewardsEscrow) # print(tx.call_trace()) # assert after == before # crvRen = interface.IERC20(registry.curve.pools.renCrv.token) wbtc = interface.IERC20(registry.tokens.wbtc) # assert crvRen.balanceOf(badger.devMultisig) >= wbtc_liquidity_amount * 10 ** 10 * 2 # crvPool = interface.ICurveZap(registry.curve.pools.renCrv.swap) # # crvPool.Remove_liquidity_one_coin( # # wbtc_liquidity_amount * 10 ** 10, 1, wbtc_liquidity_amount # # ) # # ===== Convert crvRen to wBTC on multisig ===== # tx = multi.execute( # MultisigTxMetadata(description="Withdraw crvRen for 100% WBTC",), # { # "to": crvPool.address, # "data": crvPool.remove_liquidity_one_coin.encode_input( # wbtc_liquidity_amount * 10 ** 10 * 2, 1, wbtc_liquidity_amount * 2 # ), # }, # ) # assert wbtc.balanceOf(badger.devMultisig) >= wbtc_liquidity_amount * 2 # ===== Move initial liquidity funds to Seeder ===== multi.execute( MultisigTxMetadata( description="Transfer initial liquidity WBTC to the Seeder", ), { "to": wbtc.address, "data": wbtc.transfer.encode_input(seeder, 200000000), }, ) # ===== Move DIGG to Seeder ===== digg.token.transfer(seeder, digg.token.totalSupply(), {"from": deployer}) # ===== Move Required Badger to Seeder from RewardsEscrow ===== multi.execute( MultisigTxMetadata( description="Move Required Badger to Seeder from RewardsEscrow", ), { "to": badger.rewardsEscrow.address, "data": badger.rewardsEscrow.transfer.encode_input(badger.token, seeder, Wei("30000 ether")), }, ) # ===== Add DIGG token to all geyser distribution lists ===== # (Also, add Seeder as approved schedule creator) geyser_keys = [ "native.badger", "native.renCrv", "native.sbtcCrv", "native.tbtcCrv", "native.uniBadgerWbtc", "harvest.renCrv", "native.sushiWbtcEth", "native.sushiBadgerWbtc", "native.uniDiggWbtc", "native.sushiDiggWbtc", ] for key in geyser_keys: geyser = badger.getGeyser(key) print(key, geyser) id = multi.addTx( MultisigTxMetadata( description="Add DIGG token to distribution tokens on {} geyser" .format(key), ), { "to": geyser.address, "data": geyser.addDistributionToken.encode_input(digg.token), }, ) tx = multi.executeTx(id) assert geyser.hasRole(DEFAULT_ADMIN_ROLE, badger.devMultisig) multi.execute( MultisigTxMetadata( description="Allow Seeder to set unlock schedules on {} geyser" .format(key), ), { "to": geyser.address, "data": geyser.grantRole.encode_input(locker_role, seeder), }, ) assert geyser.hasRole(locker_role, seeder) # Seeder needs to have admin role to config Faucets. Remove role as part of seed. rewards_keys = [ "native.digg", "native.uniDiggWbtc", "native.sushiDiggWbtc", ] for key in rewards_keys: rewards = badger.getSettRewards(key) rewards.grantRole(DEFAULT_ADMIN_ROLE, seeder, {"from": deployer}) rewards.grantRole(DEFAULT_ADMIN_ROLE, badger.devMultisig, {"from": deployer}) rewards.renounceRole(DEFAULT_ADMIN_ROLE, deployer, {"from": deployer}) # print(digg.token.balanceOf(deployer)) # assert digg.token.balanceOf(deployer) == digg.token.totalSupply() # digg.token.transfer(seeder, digg.token.totalSupply(), {"from": deployer}) # wbtc = interface.IERC20(token_registry.wbtc) # wbtc.transfer(seeder, 200000000, {"from": user}) # ===== Seed Prep ===== print("wbtc.balanceOf(seeder)", wbtc.balanceOf(seeder)) assert digg.token.balanceOf(seeder) >= digg.token.totalSupply() assert wbtc.balanceOf(seeder) >= 200000000 print(digg.diggDistributor.address) print("digg.diggDistributor", digg.diggDistributor.isOpen()) digg.diggDistributor.transferOwnership(seeder, {"from": deployer}) print("prePreSeed", digg.token.balanceOf(seeder)) seeder.preSeed({"from": deployer}) print("postPreSeed", digg.token.balanceOf(seeder)) seeder.seed({"from": deployer}) # seeder.transferOwnership(badger.devMultisig, {'from': deployer}) # tx = multi.execute( # MultisigTxMetadata(description="Withdraw crvRen for 100% WBTC",), # { # "to": seeder.address, # "data": seeder.preSeed.encode_input(), # }, # ) # seeder.initialize({"from": deployer}) # Unpause all Setts setts_to_unpause = [ "native.digg", "native.uniDiggWbtc", "native.sushiDiggWbtc", ] for key in setts_to_unpause: sett = badger.getSett(key) id = multi.addTx( MultisigTxMetadata(description="Unpause Sett {}".format(key), ), { "to": sett.address, "data": sett.unpause.encode_input(), }, ) tx = multi.executeTx(id) assert sett.paused() == False
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})