def rebase(badger: BadgerSystem, account): digg = badger.digg supplyBefore = digg.token.totalSupply() print("spfBefore", digg.token._sharesPerFragment()) print("supplyBefore", digg.token.totalSupply()) print(digg.cpiMedianOracle.getData.call()) sushi = SushiswapSystem() pair = sushi.getPair(digg.token, registry.tokens.wbtc) uni = UniswapSystem() uniPair = uni.getPair(digg.token, registry.tokens.wbtc) last_rebase_time = digg.uFragmentsPolicy.lastRebaseTimestampSec() min_rebase_time = digg.uFragmentsPolicy.minRebaseTimeIntervalSec() in_rebase_window = digg.uFragmentsPolicy.inRebaseWindow() now = chain.time() time_since_last_rebase = now - last_rebase_time min_time_passed = (last_rebase_time + min_rebase_time) < now console.print({ "last_rebase_time": last_rebase_time, "in_rebase_window": in_rebase_window, "now": now, "time_since_last_rebase": time_since_last_rebase, "min_time_passed": min_time_passed, }) # Rebase if sufficient time has passed since last rebase and we are in the window. # Give adequate time between TX attempts if time_since_last_rebase > hours( 2) and in_rebase_window and min_time_passed: console.print( "[bold yellow]===== 📈 Rebase! 📉=====[/bold yellow]") print("pair before", pair.getReserves()) print("uniPair before", uniPair.getReserves()) tx_timer.start_timer(account, "Rebase") tx = digg.orchestrator.rebase({"from": account}) tx_timer.end_timer() if rpc.is_active(): chain.mine() print(tx.call_trace()) print(tx.events) supplyAfter = digg.token.totalSupply() print("spfAfter", digg.token._sharesPerFragment()) print("supplyAfter", supplyAfter) print("supplyChange", supplyAfter / supplyBefore) print("supplyChangeOtherWay", supplyBefore / supplyAfter) print("pair after", pair.getReserves()) print("uniPair after", uniPair.getReserves()) else: console.print("[white]===== No Rebase =====[/white]")
def fetch_params(self): params = sett_config.uni.uniDiggWbtc.params uniswap = UniswapSystem() # TODO: Pull digg token addr from registry once its deployed. if uniswap.hasPair(self.digg.token, registry.tokens.wbtc): params.want = uniswap.getPair(self.digg.token, registry.tokens.wbtc) else: params.want = uniswap.createPair( self.digg.token, registry.tokens.wbtc, self.deployer, ) want = params.want params.token = self.digg.token self.badger.deploy_logic("DiggRewardsFaucet", DiggRewardsFaucet, test=True) self.rewards = self.badger.deploy_digg_rewards_faucet( self.key, self.digg.token) params.geyser = self.rewards return (params, want)
def main(): badger = connect_badger("deploy-final.json") deployer = badger.deployer controller = badger.getController("native") governance = badger.devMultisig strategist = badger.deployer keeper = badger.keeper guardian = badger.guardian for (key, strategyName, isUniswap) in [ ("native.sushiWbtcIbBtc", "StrategySushiLpOptimizer", False), # ("native.uniWbtcIbBtc", "StrategyUniGenericLp", True), ]: if isUniswap: params = sett_config.uni.uniGenericLp.params swap = UniswapSystem() else: params = sett_config.sushi.sushiWbtcIbBtc.params params.badgerTree = badger.badgerTree swap = SushiswapSystem() if swap.hasPair(registry.tokens.ibbtc, registry.tokens.wbtc): params.want = swap.getPair(registry.tokens.ibbtc, registry.tokens.wbtc) else: params.want = swap.createPair( registry.tokens.ibbtc, registry.tokens.wbtc, deployer, ) # NB: Work w/ sushi team to setup sushi reward allocations. vault = badger.deploy_sett( key, params.want, controller, governance=governance, strategist=strategist, keeper=keeper, guardian=guardian, ) time.sleep(sleep_between_tx) strategy = badger.deploy_strategy( key, strategyName, controller, params, governance=governance, strategist=strategist, keeper=keeper, guardian=guardian, ) time.sleep(sleep_between_tx) badger.wire_up_sett(vault, strategy, controller) # TODO: Unpause vault. assert vault.paused()
def pre_deploy_setup(self): """ Deploy StakingRewards for Strategy """ uniswap = UniswapSystem() want = uniswap.getPair(self.badger.token, registry.tokens.wbtc) self.rewards = self.badger.deploy_sett_staking_rewards( self.key, want, self.badger.token)
def fetch_params(self): params = sett_config.uni.uniGenericLp.params uniswap = UniswapSystem() want = uniswap.getPair(*self.tokens) params.want = want return (params, want)
def fetch_params(self): params = sett_config.native.uniBadgerWbtc.params uniswap = UniswapSystem() want = uniswap.getPair(self.badger.token, registry.tokens.wbtc) params.want = want params.geyser = self.rewards return (params, want)
def deploy_uni_digg_wbtc_lp_sett(badger, digg): """ If test mode, add initial liquidity and distribute to test user """ deployer = badger.deployer key = "native.uniDiggWbtc" params = sett_config.uni.uniDiggWbtc.params uniswap = UniswapSystem() params.want = uniswap.getPair(digg.token, registry.tokens.wbtc) params.token = digg.token rewards = badger.deploy_digg_rewards_faucet(key, digg.token) params.geyser = rewards time.sleep(sleep_between_tx) deploy_sett_by_key( badger, key, "StrategyDiggLpMetaFarm", SettType.DEFAULT, params, deployer=deployer, governance=badger.devMultisig, strategist=badger.deployer, keeper=badger.keeper, guardian=badger.guardian, ) # assert False strategy = badger.getStrategy(key) rewards.grantRole(PAUSER_ROLE, badger.keeper, {"from": deployer}) rewards.grantRole(UNPAUSER_ROLE, badger.devMultisig, {"from": deployer}) # Make strategy the recipient of the DIGG faucet rewards.initializeRecipient(strategy, {"from": deployer})
class DiggSystem: def __init__(self, config, deployer, devProxyAdmin, daoProxyAdmin, owner=None): self.config = config self.contracts_static = [] self.contracts_upgradeable = {} # These contracts adhere to the Ownable iface and belong to the # owner of the digg system (in prod it's the DAO). Note that this # is ONLY tracked on deploy as we will not modify ownership when # connecting to an existing system. self.contracts_ownable = [] # Token is set when digg token (UFragments) is deployed. self.token = None self.logic = DotMap() # Store uniswap trading pairs addresses. # Expected key syntax is `tokenA_tokenB`. self.uniswap_trading_pair_addrs = DotMap() if rpc.is_active(): print("RPC Active") self.owner = accounts.at(owner, force=True) else: print("RPC Inactive") # owner_key = decouple.config("DIGG_OWNER_PRIVATE_KEY") # self.owner = accounts.add(owner_key) if deployer == None: console.print( "[yellow]No deployer specified, using Owner[/yellow]") self.deployer = self.owner else: self.deployer = deployer if env_config.debug: print("deployer / owner", deployer, owner, self.deployer, self.owner) # self.owner="" # self.deployer=self.owner self.connect_proxy_admins(devProxyAdmin, daoProxyAdmin) self.connect_dao() self.connect_multisig() def track_contract_static(self, contract): self.contracts_static.append(contract) def track_contract_upgradeable(self, key, contract): self.contracts_upgradeable[key] = contract def track_contract_ownable(self, contract): self.contracts_ownable.append(contract) # ===== Contract Connectors ===== def connect_proxy_admins(self, devProxyAdmin, daoProxyAdmin): abi = artifacts.open_zeppelin["ProxyAdmin"]["abi"] self.devProxyAdmin = Contract.from_abi( "ProxyAdmin", web3.toChecksumAddress(devProxyAdmin), abi, ) self.daoProxyAdmin = Contract.from_abi( "ProxyAdmin", web3.toChecksumAddress(daoProxyAdmin), abi, ) def connect_centralized_oracle(self, address): self.centralizedOracle = connect_gnosis_safe(address) def connect_dao(self): deployer = self.deployer self.dao = DotMap(agent=Contract.from_abi( "Agent", badger_config.dao.agent, artifacts.aragon.Agent["abi"], deployer, ), ) def connect_multisig(self): deployer = self.deployer if env_config.debug: print("Deploy Dev Multisig") self.devMultisig = connect_gnosis_safe(badger_config.multisig.address) def connect_uniswap_system(self): self.uniswap_system = UniswapSystem() def connect_uniswap_pair(self, pair_name, tokenA_addr, tokenB_addr): self.uniswap_trading_pair_addrs[ pair_name] = self.uniswap_system.getPair(tokenA_addr, tokenB_addr) def connect(self, attr, BrownieArtifact, address, upgradeable=True): contract = BrownieArtifact.at(address) setattr(self, attr, contract) if upgradeable: self.track_contract_upgradeable(attr, contract) else: self.track_contract_static(contract) def connect_logic(self, logic): for name, address in logic.items(): if env_config.debug: print("ConnectLogic:", name, address) Artifact = contract_name_to_artifact(name) self.logic[name] = Artifact.at(address) # ===== Deployers ===== def deploy_core_logic(self): deployer = self.deployer self.logic = DotMap( # UFragments=UFragments.deploy({"from": deployer}), UFragments=UFragments.at( "0xfabec03b04279c6e73f27aaf25866acc844448ae"), UFragmentsPolicy=UFragmentsPolicy.at( "0x4750caa4999404cb26ff6db2d0abc09b000122e0"), # Timelock & Vesting: Use logic from existing badger deploy SimpleTimelock=SimpleTimelock.at( "0x4e3f56bb996ed91ba8d97ea773d3f818730d1a6f"), SmartVesting=SmartVesting.at( "0x07c0E4f4C977a29c46Fb26597ea8C9105ca50b42"), # DiggDistributor=DiggDistributor.deploy({"from": deployer}, publish_source=True), ) def deploy_orchestrator(self): deployer = self.deployer self.orchestrator = Orchestrator.deploy(self.uFragmentsPolicy, {"from": deployer}) self.track_contract_static(self.orchestrator) self.track_contract_ownable(self.orchestrator) def deploy_digg_policy(self): deployer = self.deployer self.uFragmentsPolicy = deploy_proxy( "UFragmentsPolicy", UFragmentsPolicy.abi, self.logic.UFragmentsPolicy.address, self.devProxyAdmin.address, self.logic.UFragmentsPolicy.initialize.encode_input( self.owner, self.uFragments, self.config.baseCpi, ), deployer, ) config = self.config # TODO: F/u on why these values are not being set. self.uFragmentsPolicy.setDeviationThreshold(config.deviationThreshold, {"from": deployer}) self.uFragmentsPolicy.setRebaseLag(config.rebaseLag, {"from": deployer}) self.uFragmentsPolicy.setRebaseTimingParameters( config.minRebaseTimeIntervalSec, config.rebaseWindowOffsetSec, config.rebaseWindowLengthSec, {"from": deployer}, ) self.track_contract_upgradeable("uFragmentsPolicy", self.uFragmentsPolicy) self.track_contract_ownable(self.uFragmentsPolicy) def deploy_digg_token(self): deployer = self.owner self.uFragments = deploy_proxy( "UFragments", UFragments.abi, self.logic.UFragments.address, self.devProxyAdmin.address, self.logic.UFragments.initialize.encode_input(self.owner, ), deployer, ) self.track_contract_upgradeable("uFragments", self.uFragments) self.track_contract_ownable(self.uFragments) # Set the digg system token after deploying. # TODO: Move this to a better place. self.token = self.uFragments def deploy_constant_oracle(self): deployer = self.deployer self.constantOracle = ConstantOracle.deploy( self.cpiMedianOracle, {"from": deployer}, ) # self.constantOracle = ConstantOracle.deploy( # self.cpiMedianOracle, {"from": deployer}, publish_source=True, # ) self.track_contract_static(self.constantOracle) def deploy_cpi_median_oracle(self): deployer = self.deployer print("deploy_cpi_median_oracle", deployer) self.cpiMedianOracle = MedianOracle.deploy( self.config.cpiOracleParams.reportExpirationTimeSec, self.config.cpiOracleParams.reportDelaySec, self.config.cpiOracleParams.minimumProviders, {"from": deployer}, ) self.track_contract_static(self.cpiMedianOracle) self.track_contract_ownable(self.cpiMedianOracle) def deploy_market_median_oracle(self): deployer = self.deployer self.marketMedianOracle = MedianOracle.deploy( self.config.marketOracleParams.reportExpirationTimeSec, self.config.marketOracleParams.reportDelaySec, self.config.marketOracleParams.minimumProviders, {"from": deployer}, ) self.track_contract_static(self.marketMedianOracle) self.track_contract_ownable(self.marketMedianOracle) def deploy_dao_digg_timelock(self): deployer = self.deployer print( self.token, self.dao.agent, self.config.startTime + self.config.tokenLockParams.lockDuration, chain.time(), ) self.daoDiggTimelock = deploy_proxy( "SimpleTimelock", SimpleTimelock.abi, self.logic.SimpleTimelock.address, self.devProxyAdmin.address, self.logic.SimpleTimelock.initialize.encode_input( self.token, self.dao.agent, self.config.startTime + self.config.tokenLockParams.lockDuration, ), deployer, ) self.track_contract_upgradeable("daoDiggTimelock", self.daoDiggTimelock) def deploy_digg_team_vesting(self): deployer = self.deployer print( self.token, self.devMultisig, self.dao.agent, self.config.startTime, self.config.teamVestingParams.cliffDuration, self.config.teamVestingParams.totalDuration, chain.time(), ) self.diggTeamVesting = deploy_proxy( "SmartVesting", SmartVesting.abi, self.logic.SmartVesting.address, self.devProxyAdmin.address, self.logic.SmartVesting.initialize.encode_input( self.token, self.devMultisig, self.dao.agent, self.config.startTime, self.config.teamVestingParams.cliffDuration, self.config.teamVestingParams.totalDuration, ), deployer, ) self.track_contract_upgradeable("teamVesting", self.diggTeamVesting) def deploy_airdrop_distributor(self, root, rewardsEscrow, reclaimAllowedTimestamp): deployer = self.deployer self.diggDistributor = deploy_proxy( "DiggDistributor", DiggDistributor.abi, self.logic.DiggDistributor.address, self.devProxyAdmin.address, self.logic.DiggDistributor.initialize.encode_input( self.token, root, rewardsEscrow, reclaimAllowedTimestamp), deployer, ) self.track_contract_upgradeable("diggDistributor", self.diggDistributor) def deploy_airdrop_distributor_no_initialize(self): deployer = self.deployer self.diggDistributor = deploy_proxy_uninitialized( "DiggDistributor", DiggDistributor.abi, self.logic.DiggDistributor.address, self.devProxyAdmin.address, deployer, ) self.track_contract_upgradeable("diggDistributor", self.diggDistributor) def deploy_uniswap_pairs(self, test=False): # TODO: read these from config, hard configured for now. (Not set on init because token is lazily populated) pairs = [("digg_wbtc", self.token.address, registry.tokens.wbtc)] for (pair_name, tokenA_addr, tokenB_addr) in pairs: self._deploy_uniswap_pair_idempotent(pair_name, tokenA_addr, tokenB_addr, test=test) def _deploy_uniswap_pair_idempotent(self, pair_name, tokenA_addr, tokenB_addr, test=False): deployer = self.deployer # Deploy digg/wBTC pair if not already deployed. if not self.uniswap_system.hasPair(tokenA_addr, tokenB_addr): self.uniswap_system.createPair(tokenA_addr, tokenB_addr, deployer) self.uniswap_trading_pair_addrs[ pair_name] = self.uniswap_system.getPair(tokenA_addr, tokenB_addr) # In test mode, add liquidity to uniswap. if test: self.uniswap_system.addMaxLiquidity(tokenA_addr, tokenB_addr, deployer) # ===== Administrative functions ===== # Used on DEPLOY ONLY, ownership of ownable contracts to a new owner. def transfer_ownership(self, owner): prevOwner = self.owner self.owner = owner for contract in self.contracts_ownable: contract.transferOwnership(owner, {"from": prevOwner}) # ===== Deploy for TESTING ONLY ===== # requires the market median oracle to be deployed as this feeds it data def deploy_dynamic_oracle(self): deployer = self.deployer self.dynamicOracle = DynamicOracle.deploy( self.marketMedianOracle, {"from": deployer}, ) self.track_contract_static(self.dynamicOracle)
def main(): """ Connect to badger system, and configure multisig for running transactions in local fork without access to accounts """ # Connect badger system from file badger = connect_badger() digg = badger.digg # Sanity check file addresses expectedMultisig = "0xB65cef03b9B89f99517643226d76e286ee999e77" assert badger.devMultisig == expectedMultisig if rpc.is_active(): distribute_test_ether(badger.devMultisig, Wei("5 ether")) # Multisig wrapper # Get price data from sushiswap, uniswap, and coingecko digg_usd_coingecko = 41531.72 btc_usd_coingecko = 32601.13 digg_per_btc = digg_usd_coingecko / btc_usd_coingecko uniTWAP = get_average_daily_price("scripts/oracle/data/uni_digg_hour") sushiTWAP = get_average_daily_price("scripts/oracle/data/sushi_digg_hour") averageTWAP = Average([uniTWAP, sushiTWAP]) console.print({ "uniTWAP": uniTWAP, "sushiTWAP": sushiTWAP, "averageTWAP": averageTWAP }) supplyBefore = digg.token.totalSupply() print("spfBefore", digg.token._sharesPerFragment()) print("supplyBefore", digg.token.totalSupply()) marketValue = Wei(str(averageTWAP) + " ether") print(marketValue) print(int(marketValue * 10**18)) print("digg_per_btc", digg_per_btc, averageTWAP, marketValue) if rpc.is_active(): distribute_test_ether(digg.centralizedOracle, Wei("5 ether")) centralizedMulti = GnosisSafe(digg.centralizedOracle) print(digg.marketMedianOracle.providerReports(digg.centralizedOracle, 0)) print(digg.marketMedianOracle.providerReports(digg.centralizedOracle, 1)) print(digg.cpiMedianOracle.providerReports(digg.constantOracle, 0)) print(digg.cpiMedianOracle.providerReports(digg.constantOracle, 1)) print(digg.cpiMedianOracle.getData.call()) sushi = SushiswapSystem() pair = sushi.getPair(digg.token, registry.tokens.wbtc) uni = UniswapSystem() uniPair = uni.getPair(digg.token, registry.tokens.wbtc) print("pair before", pair.getReserves()) print("uniPair before", uniPair.getReserves()) tx = centralizedMulti.execute( MultisigTxMetadata(description="Set Market Data"), { "to": digg.marketMedianOracle.address, "data": digg.marketMedianOracle.pushReport.encode_input(marketValue), }, ) chain.mine() print(tx.call_trace()) print(tx.events) chain.sleep(hours(0.4)) chain.mine() in_rebase_window = digg.uFragmentsPolicy.inRebaseWindow() while not in_rebase_window: print("Not in rebase window...") chain.sleep(hours(0.1)) chain.mine() in_rebase_window = digg.uFragmentsPolicy.inRebaseWindow() tx = digg.orchestrator.rebase({"from": accounts[0]}) chain.mine() supplyAfter = digg.token.totalSupply() print("spfAfter", digg.token._sharesPerFragment()) print("supplyAfter", supplyAfter) print("supplyChange", supplyAfter / supplyBefore) print("supplyChangeOtherWay", supplyBefore / supplyAfter) print("pair after", pair.getReserves()) print("uniPair after", uniPair.getReserves())
def create_uniswap_pair(token0, token1, signer): uniswap = UniswapSystem() if not uniswap.hasPair(token0, token1): uniswap.createPair(token0, token1, signer) return uniswap.getPair(token0, token1)