def from_dollars(badger, token_address, dollars): """ Get the amount of a given coin required for a given dollar sum at current exchange rate """ # Expected output in dollars # Price: Output <> USD # Price: Input <> Output exchange_rate = fetch_usd_price(token_address) tokens_amount = dollars / exchange_rate decimals = interface.IERC20(token_address).decimals() output = int(tokens_amount * (10**decimals)) console.print({ "exchange_rate": exchange_rate, "dollars": dollars, "token_amount_scaled": tokens_amount, "token_amount_unscaled": output, "decimals": decimals, }) return output
def test_asset_tvl_usdc(v2VaultsTvlAdapter): assetsAddresses = v2VaultsTvlAdapter.assetsAddresses() # for address in assetsAddresses: # tvl = v2VaultsTvlAdapter.assetTvlUsdc(address) / 10 ** 12 # assert tvl > 0 # Print TVL per asset print("-------------") print("V2 Vaults TVL") print("-------------") totalTvl = 0 tvlList = [] for address in assetsAddresses: token = interface.IERC20(address) tvl = v2VaultsTvlAdapter.assetTvlUsdc(address) / 10**6 totalTvl += tvl tvlList.append({"symbol": token.symbol(), "tvl": tvl}) sortedTvlItems = sorted(tvlList, key=itemgetter("tvl"), reverse=True) for item in sortedTvlItems: print(item.get("symbol"), item.get("tvl")) calculatedTotalTvl = v2VaultsTvlAdapter.assetsTvlUsdc() / 10**6 assert round(calculatedTotalTvl) == round(totalTvl) print("Total tvl", totalTvl)
dfd_amt = 100 * 10**18 dusd_amt = 10**18 lp_amt = 0 borrow_dfd_amt = 0 borrow_dusd_amt = 0 # calculate slippage control total_dfd_amt = dfd_amt + borrow_dfd_amt total_dusd_amt = dusd_amt + borrow_dusd_amt dfd_weight = 0.58 dusd_weight = 0.42 ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \ (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1 lp_desired = lp_amt + int(interface.IERC20(lp).totalSupply() * ratio * 0.995) print('lp desired', lp_desired) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp, # lp token [ dfd_amt, # supply DFD dusd_amt, # supply DUSD lp_amt, # supply LP borrow_dfd_amt, # borrow DFD borrow_dusd_amt, # borrow DUSD 0, # borrow LP tokens lp_desired
def test_main(): badger = connect_badger("deploy-final.json") digg = connect_digg("deploy-final.json") distribute_from_whales(badger.keeper) manager = setup() deployer = badger.deployer keeper = badger.keeper badger.token.transfer(manager, Wei("1000 ether"), {"from": badger.keeper}) digg.token.transfer(manager, Wei("100 gwei"), {"from": badger.keeper}) before = badger.token.balanceOf(badger.devMultisig) wbtc = interface.IERC20(registry.tokens.wbtc) badger_swap_amount = Wei("100 ether") digg_swap_amount = Wei("10 gwei") badger_transfer_amount = Wei("10 ether") digg_transfer_amount = Wei("1 gwei") # with brownie.reverts("Initializable: contract is already initialized"): # manager.initialize( # badger.deployer, # badger.keeper, # badger.keeper, # badger.guardian, # badger.devMultisig, # {"from": badger.keeper}, # ), testStrat = badger.getStrategy("native.badger") # # Can add strategy # manager.approveStrategy(testStrat, {"from": deployer}) # assert manager.isApprovedStrategy(testStrat) == True # # Can revoke strategy # manager.revokeStrategy(testStrat, {"from": deployer}) # assert manager.isApprovedStrategy(testStrat) == False # Get tokens before = wbtc.balanceOf(manager) manager.swapExactTokensForTokensUniswap( badger.token, badger_swap_amount, [badger.token, registry.tokens.wbtc], {"from": keeper}, ) after = wbtc.balanceOf(manager) console.print("token swap uni", {"before": before, "after": after}) assert after > before manager.swapExactTokensForTokensSushiswap( badger.token, badger_swap_amount, [badger.token, registry.tokens.wbtc], {"from": keeper}, ) after2 = wbtc.balanceOf(manager) console.print("token swap sushi", { "before": before, "after": after, "after2": after2 }) assert after2 > after for key in strat_keys: console.print("[blue]=== Running for {} ===[/blue]".format(key)) strat = badger.getStrategy(key) # manager.approveStrategy(strat, {"from": deployer}) # ===== Convert And Transfer Assets want = interface.IERC20(strat.want()) # Native Staking if key == "native.badger": before = snap_strategy_balance(strat, manager) manager.transferWant(strat.want(), strat, badger_transfer_amount, {"from": keeper}) after = snap_strategy_balance(strat, manager) diff = diff_numbers_by_key(before, after) console.log("transfer only", key, before, after, diff) if key == "native.digg": before = snap_strategy_balance(strat, manager) manager.transferWant(strat.want(), strat, digg_transfer_amount, {"from": keeper}) after = snap_strategy_balance(strat, manager) diff = diff_numbers_by_key(before, after) console.log("transfer only", key, before, after, diff) startToken = "" amount = 0 if "Badger" in key: startToken = badger.token amount = badger_swap_amount elif "Digg" in key: startToken = digg.token amount = digg_swap_amount # LP Setts if "uni" in key: before = snap_strategy_balance(strat, manager) console.print("PreSwap", { "key": key, "startToken": startToken, "amount": amount }) manager.swapExactTokensForTokensUniswap(startToken, amount, [startToken, wbtc], {"from": keeper}) manager.addLiquidityUniswap(startToken, wbtc, {"from": keeper}) after_swap = snap_strategy_balance(strat, manager) diff_swap = diff_numbers_by_key(before, after_swap) console.log("post swap", key, before, after_swap, diff_swap) manager.transferWant(strat.want(), strat, want.balanceOf(manager), {"from": keeper}) after_transfer = snap_strategy_balance(strat, manager) diff_transfer = diff_numbers_by_key(after_swap, after_transfer) console.log("post transfer", key, after_swap, after_transfer, diff_transfer) if "sushi" in key: before = snap_strategy_balance(strat, manager) manager.swapExactTokensForTokensSushiswap(startToken, amount, [startToken, wbtc], {"from": keeper}) manager.addLiquiditySushiswap(startToken, wbtc, {"from": keeper}) after_swap = snap_strategy_balance(strat, manager) diff_swap = diff_numbers_by_key(before, after_swap) console.log("post swap", key, before, after_swap, diff_swap) manager.transferWant(strat.want(), strat, want.balanceOf(manager), {"from": keeper}) after_transfer = snap_strategy_balance(strat, manager) diff_transfer = diff_numbers_by_key(after_swap, after_transfer) console.log("post transfer", key, after_swap, after_transfer, diff_transfer) tx = manager.deposit(strat, {"from": keeper}) print("deposit events", tx.events) if strat.isTendable(): tx = manager.tend(strat, {"from": keeper}) print("tend events", tx.events) if key != "native.uniBadgerWbtc": tx = manager.harvest(strat, {"from": keeper}) print("harvest events", tx.events)
def printState(self, title): console.print( "\n[yellow]=== 🦡 Rewards Schedule: {} 🦡 ===[/yellow]".format( title)) table = [] rewardsEscrow = self.badger.rewardsEscrow for key, dist in self.distributions.items(): if key == "native.digg": continue print(key, dist) geyser = self.badger.getGeyser(key) print(geyser) assert rewardsEscrow.isApproved(geyser) for asset, value in dist.toGeyser.items(): """ function signalTokenLock( address geyser, address token, uint256 amount, uint256 durationSec, uint256 startTime ) """ encoded = rewardsEscrow.signalTokenLock.encode_input( geyser, asset_to_address(asset), value, self.duration, self.start) asset_contract = interface.IERC20(asset_to_address(asset)) scaled = val(value, decimals=18) if asset == "digg": scaled = val(shares_to_fragments(value), decimals=9) table.append([ key, # geyser, asset, value, scaled, to_utc_date(self.start), to_utc_date(self.end), to_days(self.duration), # geyser.address, # encoded, ]) print( tabulate( table, headers=[ "key", # "geyser", "token", "total amount", "scaled amount", "start time", "end time", "duration", # "rate per day", # "destination", # "encoded call", ], tablefmt="rst", )) print("total distributed for {}: ".format(asset), val(self.totals[asset]))
def getToken1(pair): return interface.IERC20(pair.token1())
def test_bridge_vault(vault): badger = connect_badger(badger_config.prod_json) bridge = connect_bridge(badger, badger_config.prod_json) swap = connect_swap(badger_config.prod_json) _upgrade_bridge(badger, bridge) _upgrade_swap(badger, swap) _deploy_bridge_mocks(badger, bridge) slippage = 0.03 amount = 1 * 10**8 v = vault["address"] if v == AddressZero: v = MockVault.deploy(vault["id"], vault["symbol"], vault["token"], { "from": badger.deployer }).address # Must approve mock vaults to mint/burn to/from. bridge.adapter.setVaultApproval( v, True, {"from": badger.devMultisig}, ) else: badger.sett_system.vaults[vault["id"]].approveContractAccess( bridge.adapter, {"from": badger.devMultisig}, ) # TODO: Can interleave these mints/burns. for accIdx in range(10, 12): account = accounts[accIdx] for i in range(0, 2): balanceBefore = interface.IERC20(v).balanceOf(account) bridge.adapter.mint( vault["inToken"], slippage * 10**4, account.address, v, amount, # Darknode args hash/sig optional since gateway is mocked. "", "", {"from": account}, ) balance = interface.IERC20(v).balanceOf(account) assert balance > balanceBefore interface.IERC20(v).approve( bridge.adapter.address, balance, {"from": account}, ) # Approve mock gateway for transfer of underlying token for "mock" burns. # NB: In the real world, burns don't require approvals as it's just # an internal update the the user's token balance. interface.IERC20(registry.tokens.renbtc).approve( bridge.mocks.BTC.gateway, balance, {"from": bridge.adapter}) bridge.adapter.burn( vault["outToken"], v, slippage * 10**4, account.address, balance, {"from": account}, ) assert interface.IERC20(v).balanceOf(account) == 0
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]")
from brownie import interface UNISWAP_ROUTER = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" SUSHISWAP_ROUTER = "0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f" ETH = interface.IERC20("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") BTC = interface.IERC20("0x2260fac5e5542a773aa44fbcfedf7c193bc2c599") UNI = interface.IERC20("0x1f9840a85d5af5bf1d1762f925bdaddc4201f984") SUSHI = interface.IERC20("0x6b3595068778dd592e39a122f4f5a5cf09c90fe2") ONE_INCH = interface.IERC20("0x111111111117dc0aa78b770fa6a738034120c302") YFI = interface.IERC20("0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e") DAI = interface.IERC20("0x6b175474e89094c44da98b954eedeac495271d0f") USDC = interface.IERC20("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48") USDT = interface.IERC20("0xdac17f958d2ee523a2206206994597c13d831ec7") BUSD = interface.IERC20("0x4fabb145d64652a948d72533023f6e7a623c7c53") UWL = interface.IERC20("0xdbdd6f355a37b94e6c7d32fef548e98a280b8df5") COMP = interface.IERC20("0xc00e94cb662c3520282e6f5717214004a7f26888") LRC = interface.IERC20("0xbbbbca6a901c926f240b89eacb641d8aec7aeafd") AAVE = interface.IERC20("0x7fc66500c84a76ad7e9c93437bfc5ac33e2ddae9") UNI_USDT_ETH = interface.UniswapPair( "0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852") UNI_DAI_ETH = interface.UniswapPair( "0xa478c2975ab1ea89e8196811f51a7b7ade33eb11") UNI_ALPHA_ETH = interface.UniswapPair( "0x411a9b902f364817a0f9c4261ce28b5566a42875") SUSHI_ALPHA_ibETHv2 = interface.UniswapPair( "0xf79a07cd3488bbafb86df1bad09a6168d935c017") SUSHI_ALCX = interface.IERC20("0xdbdb4d16eda451d0503b854cf79d55697f90c8df")
def WETH() -> interface.IERC20: return interface.IERC20( os.environ.get('WETH_ADDRESS', "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"))
def DAI() -> interface.IERC20: return interface.IERC20( os.environ.get('DAI_ADDRESS', "0x6b175474e89094c44da98b954eedeac495271d0f"))
def test_uniswap_add_two_tokens( a, chain, bank, werc20, ufactory, urouter, simple_oracle, oracle, usdc, usdt, UniswapV2SpellV1, UniswapLPOracle, ): spell = UniswapV2SpellV1.deploy(bank, werc20, urouter, {'from': a[0]}) usdc.mint(a[0], 10000000 * 10**6, {'from': a[0]}) usdt.mint(a[0], 10000000 * 10**6, {'from': a[0]}) usdc.approve(urouter, 2**256 - 1, {'from': a[0]}) usdt.approve(urouter, 2**256 - 1, {'from': a[0]}) urouter.addLiquidity( usdc, usdt, 1000000 * 10**6, 1000000 * 10**6, 0, 0, a[0], chain.time() + 60, {'from': a[0]}, ) lp = ufactory.getPair(usdc, usdt) print('admin lp bal', interface.IERC20(lp).balanceOf(a[0])) uniswap_lp_oracle = UniswapLPOracle.deploy(simple_oracle, {'from': a[0]}) print('usdt Px', simple_oracle.getETHPx(usdt)) print('usdc Px', simple_oracle.getETHPx(usdc)) print('lp Px', uniswap_lp_oracle.getETHPx(lp)) oracle.setOracles( [usdc, usdt, lp], [ [simple_oracle, 10000, 10000, 10000], [simple_oracle, 10000, 10000, 10000], [uniswap_lp_oracle, 10000, 10000, 10000], ], {'from': a[0]}, ) usdc.mint(a[1], 10000000 * 10**6, {'from': a[0]}) usdt.mint(a[1], 10000000 * 10**6, {'from': a[0]}) usdc.approve(bank, 2**256 - 1, {'from': a[1]}) usdt.approve(bank, 2**256 - 1, {'from': a[1]}) spell.getPair(usdc, usdt, {'from': a[0]}) tx = bank.execute( 0, spell, spell.addLiquidity.encode_input( usdt, # token 0 usdc, # token 1 [ 40000 * 10**6, # 40000 USDT 50000 * 10**6, # 50000 USDC 0, 1000 * 10**6, # 1000 USDT 200 * 10**6, # 200 USDC 0, # borrow LP tokens 0, # min USDT 0, # min USDC ], ), {'from': a[1]}) position_id = tx.return_value print('tx gas used', tx.gas_used) print('bank collateral size', bank.getPositionInfo(position_id)) print('bank collateral value', bank.getCollateralETHValue(position_id)) print('bank borrow value', bank.getBorrowETHValue(position_id)) print('bank usdt', bank.getBankInfo(usdt)) print('bank usdc', bank.getBankInfo(usdc)) print('usdt Px', simple_oracle.getETHPx(usdt)) print('usdc Px', simple_oracle.getETHPx(usdc)) print('lp Px', uniswap_lp_oracle.getETHPx(lp))
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] usdt = interface.IERC20Ex('0xdac17f958d2ee523a2206206994597c13d831ec7') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x06da0fd433C1A5d7a4faa01111c044910A184553') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') sushi = interface.IERC20('0x6b3595068778dd592e39a122f4f5a5cf09c90fe2') # sushiswap router router = interface.IUniswapV2Router02( '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f') chef = accounts.at('0xc2edad668740f1aa35e4d8f227fb8e17dca888cd', force=True) wchef = WMasterChef.deploy(chef, {'from': admin}) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([usdt, weth], [2**112 // 700, 2**112]) uniswap_oracle = UniswapV2Oracle.deploy(simple_oracle, {'from': admin}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wchef], True, {'from': admin}) core_oracle.setRoute( [usdt, weth, lp], [simple_oracle, simple_oracle, uniswap_oracle], {'from': admin}, ) oracle.setOracles( [usdt, weth, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) homora.addBank(usdt, crusdt, {'from': admin}) # setup initial funds to alice mint_tokens(usdt, alice) mint_tokens(weth, alice) # check alice's funds print(f'Alice usdt balance {usdt.balanceOf(alice)}') print(f'Alice weth balance {weth.balanceOf(alice)}') # Steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) # set approval usdt.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(crusdt, 2**256 - 1, {'from': alice}) weth.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(chef, 2**256 - 1, {'from': bob}) sushiswap_spell = SushiswapSpellV1.deploy(homora, werc20, router, wchef, {'from': admin}) # first time call to reduce gas sushiswap_spell.getPair(weth, usdt, {'from': admin}) # whitelist spell in bank homora.setWhitelistSpells([sushiswap_spell], [True], {'from': admin}) # whitelist lp in spell sushiswap_spell.setWhitelistLPTokens([lp], [True], {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1. add liquidity') prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_wchef = lp.balanceOf(wchef) if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() usdt_amt = 10 * 10**6 weth_amt = 10**18 lp_amt = 0 borrow_usdt_amt = 0 borrow_weth_amt = 0 pid = 0 tx = homora.execute( 0, sushiswap_spell, sushiswap_spell.addLiquidityWMasterChef.encode_input( usdt, # token 0 weth, # token 1 [ usdt_amt, # supply USDT weth_amt, # supply WETH lp_amt, # supply LP borrow_usdt_amt, # borrow USDT borrow_weth_amt, # borrow WETH 0, # borrow LP tokens 0, # min USDT 0 ], # min WETH pid, ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_wchef = lp.balanceOf(wchef) if interface.IUniswapV2Pair(lp).token0() == usdt: curARes, curBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: curBRes, curARes, _ = interface.IUniswapV2Pair(lp).getReserves() print('spell lp balance', lp.balanceOf(sushiswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, totalDebt, totalShare = homora.getBankInfo(usdt) print('bank usdt totalDebt', totalDebt) print('bank usdt totalShare', totalShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('wchef prev LP balance', prevLPBal_wchef) print('wchef cur LP balance', curLPBal_wchef) print('prev usdt res', prevARes) print('cur usdt res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curABal - prevABal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert usdt.balanceOf(sushiswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(sushiswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(sushiswap_spell) == 0, 'non-zero spell LP balance' assert totalDebt == borrow_usdt_amt # check balance and pool reserves assert curABal - prevABal - borrow_usdt_amt == - \ (curARes - prevARes), 'not all USDT tokens go to LP pool' assert almostEqual( curBBal - prevBBal - borrow_weth_amt, -(curBRes - prevBRes)), 'not all WETH tokens go to LP pool' # ##################################################################################### print( '=========================================================================' ) print('Case 2. harvest first time') prevSushiBalance = sushi.balanceOf(alice) print('Alice SUSHI balance before harvest', prevSushiBalance) _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevSushi = sushi.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) pid = 0 tx = interface.IMasterChef(chef).deposit(pid, collSize, {'from': bob}) chain.mine(100) tx = homora.execute(1, sushiswap_spell, sushiswap_spell.harvestWMasterChef.encode_input(), {'from': alice}) print('tx gas used', tx.gas_used) curSushiBalance = sushi.balanceOf(alice) print('Alice SUSHI balance after harvest', curSushiBalance) receivedSushi = curSushiBalance - prevSushiBalance # check with staking directly pid = 0 tx = interface.IMasterChef(chef).withdraw(pid, collSize, {'from': bob}) receivedSushiFromStaking = sushi.balanceOf(bob) - prevSushi print('receivedSushiFromStaking', receivedSushiFromStaking) assert almostEqual(receivedSushi, receivedSushiFromStaking) # ##################################################################################### print( '=========================================================================' ) print('Case 3. harvest second time') prevSushiBalance = sushi.balanceOf(alice) print('Alice SUSHI balance before harvest', prevSushiBalance) prevSushi = sushi.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) # staking directly prevSushi = sushi.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) pid = 0 tx = interface.IMasterChef(chef).deposit(pid, collSize, {'from': bob}) chain.mine(100) tx = homora.execute(1, sushiswap_spell, sushiswap_spell.harvestWMasterChef.encode_input(), {'from': alice}) print('tx gas used', tx.gas_used) curSushiBalance = sushi.balanceOf(alice) print('Alice SUSHI balance after harvest', curSushiBalance) receivedSushi = curSushiBalance - prevSushiBalance # check with staking directly tx = interface.IMasterChef(chef).withdraw(pid, collSize, {'from': bob}) receivedSushiFromStaking = sushi.balanceOf(bob) - prevSushi print('receivedSushiFromStaking', receivedSushiFromStaking) assert almostEqual(receivedSushi, receivedSushiFromStaking)
def main(): badger = connect_badger("deploy-final.json") digg = badger.digg tx_data = { "to": "0x8D29bE29923b68abfDD21e541b9374737B49cdAD", "data": "0x8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000009fe00b65cef03b9b89f99517643226d76e286ee999e7700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024694e80c300000000000000000000000000000000000000000000000000000000000000010019d099670a21bc0a8211a89b84cedf59abb4377f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064beabacc80000000000000000000000003472a5a71965499acd81997a54bba8d852c6e53d000000000000000000000000b65cef03b9b89f99517643226d76e286ee999e7700000000000000000000000000000000000000000000017c5d213c7a8f712f400019d099670a21bc0a8211a89b84cedf59abb4377f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064beabacc8000000000000000000000000798d1be841a82a273720ce31c822c61a67a601c3000000000000000000000000b65cef03b9b89f99517643226d76e286ee999e7700000000000000000000000000000000000000000000000000000001b69e2595003472a5a71965499acd81997a54bba8d852c6e53d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f000000000000000000000000000000000000000000000068bce40cf18444c28000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001244a25d94a000000000000000000000000000000000000000000000002b01ee2a20a8a2a90000000000000000000000000000000000000000000000068bce40cf18444c28000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000b65cef03b9b89f99517643226d76e286ee999e7700000000000000000000000000000000000000000000000000000000604be4d100000000000000000000000000000000000000000000000000000000000000030000000000000000000000003472a5a71965499acd81997a54bba8d852c6e53d0000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c599000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2003472a5a71965499acd81997a54bba8d852c6e53d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b300000000000000000000000019d97d8fa813ee2f51ad4b4e04ea08baf4dffc28000000000000000000000000000000000000000000000113a03d2f890b2c6cc00019d97d8fa813ee2f51ad4b4e04ea08baf4dffc2800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024b6b55f25000000000000000000000000000000000000000000000113a03d2f890b2c6cc000798d1be841a82a273720ce31c822c61a67a601c300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b30000000000000000000000007e7e112a68d8d2e221e11047a72ffc1065c38e1a00000000000000000000000000000000000000000000000000000001b69e2595007e7e112a68d8d2e221e11047a72ffc1065c38e1a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000246c361865000000000000000000000000b65cef03b9b89f99517643226d76e286ee999e77007e7e112a68d8d2e221e11047a72ffc1065c38e1a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024b6b55f2500000000000000000000000000000000000000000000000000000001b69e25950019d97d8fa813ee2f51ad4b4e04ea08baf4dffc2800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f0000000000000000000000000000000000000000000000e203f5dc3c00323a8000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f00000000000000000000000000000000000000000000000777723ca5ab7fcb9000000000000000000000000000000000000000000000000000000000000000c4f305d71900000000000000000000000019d97d8fa813ee2f51ad4b4e04ea08baf4dffc280000000000000000000000000000000000000000000000e203f5dc3c00323a800000000000000000000000000000000000000000000000e203f5dc3c00323a8000000000000000000000000000000000000000000000000777723ca5ab7fcb90000000000000000000000000b65cef03b9b89f99517643226d76e286ee999e7700000000000000000000000000000000000000000000000000000000604be4db007e7e112a68d8d2e221e11047a72ffc1065c38e1a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044095ea7b3000000000000000000000000d9e1ce17f2641f24ae83637ab66a2cca9c378b9f00000000000000000000000000000000000000000000000048ada1feff60844a00d9e1ce17f2641f24ae83637ab66a2cca9c378b9f00000000000000000000000000000000000000000000000777723ca5ab7fcb9000000000000000000000000000000000000000000000000000000000000000c4f305d7190000000000000000000000007e7e112a68d8d2e221e11047a72ffc1065c38e1a00000000000000000000000000000000000000000000000048ada1feff60844a00000000000000000000000000000000000000000000000048ada1feff60844a00000000000000000000000000000000000000000000000777723ca5ab7fcb90000000000000000000000000b65cef03b9b89f99517643226d76e286ee999e7700000000000000000000000000000000000000000000000000000000604be4dd0000", } sushiBbadgerPair = "0x0a54d4b378c8dbfc7bc93be50c85debafdb87439" sushiBDiggPair = "0xf9440fedc72a0b8030861dcdac39a75b544e7a3c" sushiswap = SushiswapSystem() pair = interface.IUniswapV2Pair(sushiBbadgerPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) pair = interface.IUniswapV2Pair(sushiBDiggPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) usd_amount = 500000 weth = interface.IERC20(registry.tokens.weth) console.log("..Before Safe") safe = ApeSafe(badger.devMultisig.address) ops_safe = ApeSafe(badger.opsMultisig.address) console.log("..After Safe Setup") # multi = GnosisSafe(badger.devMultisig) # multi.execute( # MultisigTxMetadata(description="Run TX"), # {"to": tx_data["to"], "data": tx_data["data"], "operation": 1}, # ) after = get_token_balances( [ badger.token, digg.token, interface.IERC20(registry.tokens.usdc), interface.IERC20(sushiBbadgerPair), interface.IERC20(sushiBDiggPair), ], [badger.devMultisig], ) after.print() pair = interface.IUniswapV2Pair(sushiBbadgerPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) pair = interface.IUniswapV2Pair(sushiBDiggPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) router = safe.contract(sushiswap.router.address) rewardsEscrow = safe.contract(badger.rewardsEscrow.address) badgerToken = safe.contract(badger.token.address) diggToken = safe.contract(digg.token.address) digg_to_lp = Wei("8.4 gwei") usd_per_side = 250000 # TODO: Use banteg's nice value calc script. badger_usd = fetch_usd_price(badger.token.address) digg_usd = fetch_usd_price(digg.token.address) eth_usd = fetch_usd_price_eth() console.log(eth_usd) badger_to_swap = Wei(str(95000 / badger_usd) + " ether") badger_to_lp = Wei(str(usd_per_side / badger_usd) + " ether") digg_to_lp = Wei(str(usd_per_side / digg_usd) + " gwei") eth_out = Wei(str(usd_per_side / eth_usd) + " ether") console.print({ "badger_to_swap": badger_to_swap, "badger_to_lp": badger_to_lp, "digg_to_lp": digg_to_lp, "eth_out": eth_out, "badger_usd": badger_usd, "digg_usd": digg_usd, "eth_usd": eth_usd, }) badger_to_get_from_escrow = badger_to_swap + badger_to_lp # Get 250k worth of bBadger + $90k Amount to swap to ETH rewardsEscrow.transfer(badger.token, badger.devMultisig, badger_to_get_from_escrow) # Get 250k worth of bDigg rewardsEscrow.transfer(digg.token, badger.devMultisig, digg_to_lp) # Sell badger for 90k USD exact_eth = Wei(str(90000 / eth_usd) + " ether") console.print("exact_eth", exact_eth) assert badger.token.balanceOf(badger.devMultisig) >= badger_to_swap print("a") badgerToken.approve(sushiswap.router.address, badger_to_swap) print("b") assert (badger.token.allowance(badger.devMultisig, sushiswap.router.address) == badger_to_swap) router.swapTokensForExactETH( exact_eth, int(badger_to_swap * 1.02), [badger.token, registry.tokens.wbtc, registry.tokens.weth], badger.devMultisig, chain.time() + 200000, ) print("d") after = get_token_balances([badger.token, digg.token], [badger.devMultisig]) after.print() # Deposit Badger for bBadger # Deposit DIGG for bDigg bBadger_address = badger.getSett("native.badger").address bDigg_address = badger.getSett("native.digg").address console.print(bBadger_address, bDigg_address) abi = Sett.abi bBadger = safe.contract_from_abi(bBadger_address, "Sett", abi) bDigg = safe.contract_from_abi(bDigg_address, "Sett", abi) badgerToken.approve(bBadger.address, badger_to_lp) print(bBadger) console.print(bBadger) bBadger.deposit(badger_to_lp) diggToken.approve(bDigg.address, digg_to_lp) bDigg.approveContractAccess(badger.devMultisig) tx = bDigg.deposit(digg_to_lp) console.print(tx.events) # tx = bDigg.withdraw(bDigg.balanceOf(badger.devMultisig)) # console.print(tx.events) after = get_token_balances( [ badger.token, digg.token, interface.IERC20(bDigg.address), interface.IERC20(bBadger.address), ], [badger.devMultisig], ) after.print() # Seed pools: 250k worth of bToken, 250k worth of ETH tokenA = bBadger amountA = (badger_to_lp * 10**18) / bBadger.getPricePerFullShare() amountB = eth_out # TODO: Set the amount of ETH to what is required. after = get_token_balances( [ badger.token, digg.token, interface.IERC20(bDigg.address), interface.IERC20(bBadger.address), interface.IERC20(sushiBbadgerPair), interface.IERC20(sushiBDiggPair), ], [badger.devMultisig], ) after.print() safe_tx = safe.multisend_from_receipts() safe.preview(safe_tx) data = safe.print_transaction(safe_tx) safe.post_transaction(safe_tx) """ How do we get exactly 250k worth of each asset? Calculate how much you need to get 250k ===== Normal Assets ===== 250k / USD price of asset ===== For bTokens ===== How much original token to get: 250k / USD price of underlying asset bToken will handle itself """ tokenA.approve(sushiswap.router, amountA) console.print( "addLiquidityETH", { "tokenA": tokenA.address, "amountA": amountA, "amountB": amountB, "badger ppfs": bBadger.getPricePerFullShare(), "original supply": Wei("4000 gwei"), "current supply": digg.token.totalSupply(), }, ) router.addLiquidityETH( tokenA.address, amountA, int(amountA * 0.95), int(eth_out * 0.95), badger.devMultisig, chain.time() + 200000, {"value": eth_out}, ) tokenA = bDigg amountA = ((digg_to_lp * 10**9) * 10**18) / bDigg.getPricePerFullShare() amountA = amountA * (Wei("4000 gwei")) / digg.token.totalSupply() print("expected bDigg", amountA) amountA = bDigg.balanceOf(badger.devMultisig) print("actual bDigg", amountA) tokenA.approve(sushiswap.router, amountA) console.print( "addLiquidityETH", { "tokenA": tokenA.address, "amountA": amountA, "amountB": amountB, "digg ppfs": bDigg.getPricePerFullShare(), }, ) router.addLiquidityETH( tokenA.address, amountA, int(amountA * 0.95), int(eth_out * 0.95), badger.devMultisig, chain.time() + 200000, {"value": eth_out}, ) after = get_token_balances( [ badger.token, digg.token, interface.IERC20(bDigg.address), interface.IERC20(bBadger.address), interface.IERC20(sushiBbadgerPair), interface.IERC20(sushiBDiggPair), ], [badger.devMultisig], ) after.print() safe_tx = safe.multisend_from_receipts() safe.preview(safe_tx) data = safe.print_transaction(safe_tx) safe.post_transaction(safe_tx) pair = interface.IUniswapV2Pair(sushiBbadgerPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) pair = interface.IUniswapV2Pair(sushiBDiggPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) safe.post_transaction(safe_tx) pair = interface.IUniswapV2Pair(sushiBbadgerPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), }) pair = interface.IUniswapV2Pair(sushiBDiggPair) console.print({ "getReserves": pair.getReserves(), "token0": pair.token0(), "token1": pair.token1(), "price0CumulativeLast": pair.price0CumulativeLast(), "price1CumulativeLast": pair.price1CumulativeLast(), })
from brownie import interface from functools import lru_cache TRADERJOE_ROUTER = "0x60aE616a2155Ee3d9A68541Ba4544862310933d4" PANGOLIN_ROUTER = "0xE54Ca86531e17Ef3616d22Ca28b0D458b6C89106" ETH = interface.IERC20("0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB") BTC = interface.IERC20("0x50b7545627a5162f82a992c33b87adc75187b218") USDC = interface.IERC20("0xA7D7079b0FEaD91F3e65f86E8915Cb59c1a4C664") USDT = interface.IERC20("0xc7198437980c041c805a1edcba50c1ce5db95118") DAI = interface.IERC20("0xd586e7f844cea2f87f50152665bcbc2c279d8d70") TIME = interface.IERC20("0xb54f16fb19478766a268f172c9480f8da1a7c9c3") AVAX = interface.IERC20("0xb31f66aa3c1e785363f0875a1b74e27b85fd66c7") crvUSDBTCETH = interface.CurveLPToken( "0x1daB6560494B04473A0BE3E7D83CF3Fdf3a51828") tVaultUSDC = interface.yEarnVault("0x52cE2c4Bd817AdB765c476901cc09621DCACEc62") tVaultDAI = interface.yEarnVault("0xdC808bADe323205f2c794198C1adDa8aEF215E29") tVaultAVAX = interface.yEarnVault("0x83EA27549acc3CB64c3fCda8379d1eA229a02712") tVault3crypto_V2 = interface.yEarnVault( "0x71712Ad47b2cBC4Fb2e814dBaC44A31749A5195e") @lru_cache() def TOKEN_PRICES(): return { "TraderJoe": (TRADERJOE_ROUTER, [ ("WETH.e", ETH), ("WBTC.e", BTC), ("USDC.e", USDC), ("USDT.e", USDT),
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dfd = interface.IERC20Ex('0x20c36f062a31865bED8a5B1e512D9a1A20AA333A') dusd = interface.IERC20Ex('0x5BC25f649fc4e26069dDF4cF4010F9f706c23831') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') lp = interface.IERC20Ex('0xd8e9690eff99e21a2de25e0b148ffaf47f47c972') # pool is lp for balancer pool = interface.IBalancerPool( '0xd8e9690eff99e21a2de25e0b148ffaf47f47c972') lp_dai = interface.IERC20Ex('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') pool_dai = interface.IBalancerPool( '0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') crdfd = MockCErc20.deploy(dfd, {'from': admin}) crdusd = MockCErc20.deploy(dusd, {'from': admin}) crdai = MockCErc20.deploy(dai, {'from': admin}) crweth = MockCErc20.deploy(weth, {'from': admin}) werc20 = WERC20.deploy({'from': admin}) staking = accounts.at('0xf068236ecad5fabb9883bbb26a6445d6c7c9a924', force=True) wstaking = WStakingRewards.deploy(staking, lp, dfd, {'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dfd, dusd], [2**112 // 2 // 700, 2**112 * 2 // 700]) balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': alice}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wstaking], True, {'from': admin}) core_oracle.setRoute( [dfd, dusd, lp], [simple_oracle, simple_oracle, balancer_oracle], {'from': admin}, ) oracle.setOracles( [dfd, dusd, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) homora.addBank(dfd, crdfd, {'from': admin}) homora.addBank(dusd, crdusd, {'from': admin}) # setup initial funds to alice mint_tokens(dfd, alice) mint_tokens(dusd, alice) mint_tokens(weth, alice) mint_tokens(dai, alice) mint_tokens(dfd, crdfd) # check alice's funds print(f'Alice dusd balance {dusd.balanceOf(alice)}') print(f'Alice dfd balance {dfd.balanceOf(alice)}') # Steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) # set approval dfd.approve(homora, 2**256 - 1, {'from': alice}) dfd.approve(crdfd, 2**256 - 1, {'from': alice}) dusd.approve(homora, 2**256 - 1, {'from': alice}) dusd.approve(crdusd, 2**256 - 1, {'from': alice}) dai.approve(homora, 2**256 - 1, {'from': alice}) dai.approve(crdai, 2**256 - 1, {'from': alice}) weth.approve(homora, 2**256 - 1, {'from': alice}) weth.approve(crweth, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(staking, 2**256 - 1, {'from': bob}) balancer_spell = BalancerSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', {'from': admin}) # first time call to reduce gas balancer_spell.getPair(lp, {'from': admin}) # whitelist spell in bank homora.setWhitelistSpells([balancer_spell], [True], {'from': admin}) # whitelist token in bank homora.setWhitelistTokens([dfd], [True], {'from': admin}) # whitelist lp in spell balancer_spell.setWhitelistLPTokens([lp, lp_dai], [True, True], {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = dfd.balanceOf(alice) prevBBal = dusd.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) prevARes = interface.IBalancerPool(lp).getBalance(dfd) prevBRes = interface.IBalancerPool(lp).getBalance(dusd) dfd_amt = 100 * 10**18 dusd_amt = 10**18 lp_amt = 0 borrow_dfd_amt = 10**18 borrow_dusd_amt = 0 # calculate slippage control total_dfd_amt = dfd_amt + borrow_dfd_amt total_dusd_amt = dusd_amt + borrow_dusd_amt dfd_weight = 0.58 dusd_weight = 0.42 ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \ (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1 lp_desired = lp_amt + int( interface.IERC20(lp).totalSupply() * ratio * 0.995) print('lp desired', lp_desired) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp, # lp token [ dfd_amt, # supply DFD dusd_amt, # supply DUSD lp_amt, # supply LP borrow_dfd_amt, # borrow DFD borrow_dusd_amt, # borrow DUSD 0, # borrow LP tokens lp_desired ], # LP desired wstaking), {'from': alice}) curABal = dfd.balanceOf(alice) curBBal = dusd.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) curARes = interface.IBalancerPool(lp).getBalance(dfd) curBRes = interface.IBalancerPool(lp).getBalance(dusd) print('spell lp balance', lp.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd) print('bank dfd dfdDebt', dfdDebt) print('bank dfd dfdShare', dfdShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('staking prev LP balance', prevLPBal_staking) print('staking cur LP balance', curLPBal_staking) print('prev dfd res', prevARes) print('cur dfd res', curARes) print('prev dusd res', prevBRes) print('cur dusd res', curBRes) # alice assert almostEqual(curABal - prevABal, -dfd_amt), 'incorrect DFD amt' assert almostEqual(curBBal - prevBBal, -dusd_amt), 'incorrect DUSD amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance' assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' assert dfdDebt == borrow_dfd_amt # check balance and pool reserves assert almostEqual( curABal - prevABal - borrow_dfd_amt, -(curARes - prevARes)), 'not all DFD tokens go to LP pool' assert almostEqual( curBBal - prevBBal - borrow_dusd_amt, -(curBRes - prevBRes)), 'not all DUSD tokens go to LP pool' _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevDfd = dfd.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob}) chain.sleep(20000) prevAliceDfdBalance = dfd.balanceOf(alice) print('Alice dfd balance', prevAliceDfdBalance) ##################################################################################### print( '=========================================================================' ) print('Case 2. add liquidity (failed tx desired)') weth_amt = 100 * 10**18 dai_amt = 10**18 lp_amt = 0 borrow_weth_amt = 0 borrow_dai_amt = 0 # calculate slippage control total_weth_amt = weth_amt + borrow_weth_amt total_dai_amt = dai_amt + borrow_dai_amt dfd_weight = 0.8 dusd_weight = 0.2 ratio = (((prevARes + total_weth_amt) / prevARes) ** dfd_weight) * \ (((prevBRes + total_dai_amt) / prevBRes) ** dusd_weight) - 1 lp_desired = lp_amt + int( interface.IERC20(lp).totalSupply() * ratio * 0.995) lp_desired = 0 print('lp desired', lp_desired) try: tx = homora.execute( 1, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp_dai, # lp token [ weth_amt, # supply DFD dai_amt, # supply DUSD lp_amt, # supply LP borrow_weth_amt, # borrow DFD borrow_dai_amt, # borrow DUSD 0, # borrow LP tokens lp_desired ], # LP desired wstaking), {'from': alice}) assert False, 'tx should fail' except VirtualMachineError: pass ##################################################################################### print( '=========================================================================' ) print('Case 3. remove liquidity (failed tx desired)') lp_take_amt = 2**256 - 1 # max lp_want = 0 weth_repay = 2**256 - 1 # max dai_repay = 2**256 - 1 # max real_weth_repay = homora.borrowBalanceStored(1, dfd) _, _, _, real_lp_take_amt = homora.getPositionInfo(1) expected_withdraw_dfd = collSize * prevARes // interface.IBalancerPool( lp).totalSupply() print('expected withdraw DFD', expected_withdraw_dfd) try: tx = homora.execute( 1, balancer_spell, balancer_spell.removeLiquidityWStakingRewards.encode_input( lp_dai, # LP token [ lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet weth_repay, # repay DFD dai_repay, # repay DUSD 0, # repay LP 0, # min DFD 0 ], # min DUSD wstaking), {'from': alice}) assert False, 'tx should fail' except VirtualMachineError: pass ##################################################################################### print( '=========================================================================' ) print('Case 4. remove liquidity') # remove liquidity from the same position prevABal = dfd.balanceOf(alice) prevBBal = dusd.balanceOf(alice) prevETHBal = alice.balance() prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) prevETHBal = alice.balance() prevCrdfdBal = lp.balanceOf(crdfd) prevARes = interface.IBalancerPool(lp).getBalance(dfd) prevBRes = interface.IBalancerPool(lp).getBalance(dusd) lp_take_amt = 2**256 - 1 # max lp_want = 0 dfd_repay = 2**256 - 1 # max dusd_repay = 0 real_dfd_repay = homora.borrowBalanceStored(1, dfd) _, _, _, real_lp_take_amt = homora.getPositionInfo(1) expected_withdraw_dfd = collSize * prevARes // interface.IBalancerPool( lp).totalSupply() print('expected withdraw DFD', expected_withdraw_dfd) tx = homora.execute( 1, balancer_spell, balancer_spell.removeLiquidityWStakingRewards.encode_input( lp, # LP token [ lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet dfd_repay, # repay DFD dusd_repay, # repay DUSD 0, # repay LP 0, # min DFD 0 ], # min DUSD wstaking), {'from': alice}) curABal = dfd.balanceOf(alice) curBBal = dusd.balanceOf(alice) curETHBal = alice.balance() curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) curETHBal = alice.balance() curCrdfdBal = lp.balanceOf(crdfd) curARes = interface.IBalancerPool(lp).getBalance(dfd) curBRes = interface.IBalancerPool(lp).getBalance(dusd) print('spell lp balance', lp.balanceOf(balancer_spell)) print('spell dfd balance', dfd.balanceOf(balancer_spell)) print('spell dusd balance', dusd.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta ETH balance', curETHBal - prevETHBal) print('Alice delta LP balance', curLPBal - prevLPBal) print('remove liquidity gas', tx.gas_used) print('bank delta lp balance', curLPBal_bank - prevLPBal_bank) print('bank total lp balance', curLPBal_bank) _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd) print('bank dfd totalDebt', dfdDebt) print('bank dfd totalShare', dfdShare) print('LP want', lp_want) print('bank delta LP amount', curLPBal_bank - prevLPBal_bank) print('LP take amount', lp_take_amt) print('prev staking LP balance', prevLPBal_staking) print('cur staking LP balance', curLPBal_staking) print('real dfd repay', real_dfd_repay) print('curCrdfdBal', curCrdfdBal) print('delta crdfd', curCrdfdBal - prevCrdfdBal) print('A res delta', prevARes - curARes) print('B res delta', prevBRes - curBRes) # alice assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # staking assert almostEqual(curLPBal_staking - prevLPBal_staking, -real_lp_take_amt), 'incorrect staking LP amt' # spell assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance' assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual(curABal - prevABal + real_dfd_repay, -(curARes - prevARes)), 'inconsistent DFD from withdraw' assert almostEqual( curBBal - prevBBal + dusd_repay, -(curBRes - prevBRes)), 'inconsistent DUSD from withdraw' curAliceDfdBalance = dfd.balanceOf(alice) print('Alice dfd balance', curAliceDfdBalance) receivedDfd = curAliceDfdBalance - prevAliceDfdBalance + real_dfd_repay - ( prevARes - curARes) print('received dfd', receivedDfd) # check with staking directly tx = interface.IStakingRewards(staking).getReward({'from': bob}) receivedDfdFromStaking = dfd.balanceOf(bob) - prevDfd print('receivedDfdFromStaking', receivedDfdFromStaking) assert almostEqual(receivedDfd, receivedDfdFromStaking) ##################################################################################### print( '=========================================================================' ) print('Case 5. add & remove all LP') lp_amt = 10 * 10**18 prevLPBal = lp.balanceOf(alice) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp, # lp token [ 0, # supply DAI 0, # supply WETH lp_amt, # supply LP 0, # borrow DAI 0, # borrow WETH 0, # borrow LP tokens 0 ], # LP desired wstaking), {'from': alice}) tx = homora.execute( 2, balancer_spell, balancer_spell.removeLiquidityWStakingRewards.encode_input( lp, # LP token [ 2**256 - 1, # take out LP tokens lp_amt, # withdraw LP tokens to wallet 0, # repay DAI 0, # repay WETH 0, # repay LP 0, # min DAI 0 ], # min WETH wstaking), {'from': alice}) curLPBal = lp.balanceOf(alice) assert prevLPBal == curLPBal, 'incorrect LP Balance' return tx
PANCAKE_SLME_BUSD = interface.UniswapPair( "0xfbd0b87f4132e5a14aa85c21476738c0c13fd06c") PANCAKE_SLME_BNB = interface.UniswapPair( "0xcb645714520080ef4e65de3254d61356262f0818") PANCAKESWAP_ROUTER = "0x05ff2b0db69458a0750badebc4f9e13add608c7f" ICECREAM_USDT_BUSD = interface.UniswapPair( "0x57Bcf3Bb68f6E8DF00b9e6AD6aF8cE58fe7FC350") ICECREAM_BUSD_BNB = interface.UniswapPair( "0x875DfffcBd97f6C7038E97A4959B0590C8714e1c") ICECREAM_ETH_BNB = interface.UniswapPair( "0x68c277E93D9EB923E2EA9bfFC643307E731C044f") ICECREAMSWAP_ROUTER = "0x6728f3c8241C44Cc741C9553Ff7824ba9E932A4A" BSC_DAI = interface.IERC20("0x1af3f329e8be154074d8769d1ffa4ee058b1dbc3") BSC_BUSD = interface.IERC20("0xe9e7cea3dedca5984780bafc599bd69add087d56") BSC_USDT = interface.IERC20("0x55d398326f99059ff775485246999027b3197955") BSC_USDC = interface.IERC20("0x8ac76a51cc950d9822d68b83fe1ad97b32cd580d") BSC_VAI = interface.IERC20("0x4bd17003473389a42daf6a0a729f6fdb328bbbd7") BSC_ETH = interface.IERC20("0x2170ed0880ac9a755fd29b2688956bd959f933f8") BSC_BTC = interface.IERC20("0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9c") BSC_BNB = interface.IERC20("0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c") TOKEN_PRICES = { "PancakeSwap": (PANCAKESWAP_ROUTER, [ ("ETH", BSC_ETH), ("BTC", BSC_BTC), ("BNB", BSC_BNB), ("DAI_BUSD", PANCAKE_DAI_BUSD), ("USDT_BUSD", PANCAKE_USDT_BUSD),
def USDT() -> interface.IERC20: return interface.IERC20( os.environ.get('USDT_ADDRESS', "0xdac17f958d2ee523a2206206994597c13d831ec7"))
from brownie import interface from functools import lru_cache SUSHISWAP_ROUTER = "0x1b02dA8Cb0d097eB8D57A175b88c7D8b47997506" ETH = interface.IERC20("0x82af49447d8a07e3bd95bd0d56f35241523fbab1") BTC = interface.IERC20("0x2f2a2543b76a4166549f7aab2e75bef0aefc5b0f") USDC = interface.IERC20("0xff970a61a04b1ca14834a43f5de4533ebddb5cc8") USDT = interface.IERC20("0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9") MIM = interface.IERC20("0xfea7a6a0b346362bf88a9e4a88416b77a57d6c2a") @lru_cache() def TOKEN_PRICES(): SUSHI_USDC_ETH = interface.UniswapPair( "0x905dfcd5649217c42684f23958568e533c711aa3") SUSHI_USDT_ETH = interface.UniswapPair( "0xcb0e5bfa72bbb4d16ab5aa0c60601c438f04b4ad") SUSHI_MIM_ETH = interface.UniswapPair( "0xb6dd51d5425861c808fd60827ab6cfbffe604959") return { "Sushi-Arbitrum": (SUSHISWAP_ROUTER, [ ("ETH", ETH), ("BTC", BTC), ("MIM", MIM), ("USDC_ETH", SUSHI_USDC_ETH), ("USDT_ETH", SUSHI_USDT_ETH), ("MIM_ETH", SUSHI_MIM_ETH), ]), }
def USDC() -> interface.IERC20: return interface.IERC20( os.environ.get('USDC_ADDRESS', "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"))
def test_bridge_basic(): renbtc = registry.tokens.renbtc wbtc = registry.tokens.wbtc badger = connect_badger(badger_config.prod_json) bridge = connect_bridge(badger, badger_config.prod_json) swap = connect_swap(badger_config.prod_json) _upgrade_bridge(badger, bridge) _upgrade_swap(badger, swap) _deploy_bridge_mocks(badger, bridge) router = swap.router # 3% slippage slippage = 0.03 amount = 1 * 10**8 # Test estimating slippage from a random account for wbtc <-> renbtc swaps. _assert_swap_slippage( router, renbtc, wbtc, amount, slippage, ) _assert_swap_slippage( router, wbtc, renbtc, amount, slippage, ) for accIdx in range(10, 12): account = accounts[accIdx] for i in range(0, 2): balanceBefore = interface.IERC20(wbtc).balanceOf(account) # Test mints bridge.adapter.mint( wbtc, slippage * 10**4, account.address, AddressZero, # No vault. amount, # Darknode args hash/sig optional since gateway is mocked. "", "", {"from": account}, ) assert interface.IERC20(wbtc).balanceOf(account) > balanceBefore # Test burns balance = interface.IERC20(wbtc).balanceOf(account) interface.IERC20(wbtc).approve(bridge.adapter, balance, {"from": account}) # Approve mock gateway for transfer of underlying token for "mock" burns. # NB: In the real world, burns don't require approvals as it's # just an internal update the the user's token balance. interface.IERC20(renbtc).approve( bridge.mocks.BTC.gateway, balance, {"from": bridge.adapter}, ) bridge.adapter.burn( wbtc, AddressZero, # No vault. slippage * 10**4, account.address, balance, {"from": account}, ) assert interface.IERC20(wbtc).balanceOf(account) == 0
def getToken0(pair) -> interface.IERC20: return interface.IERC20(pair.token0())
from brownie import interface from brownie.exceptions import ContractNotFound from datetime import datetime, timedelta from functools import lru_cache DAI = interface.IERC20("0x6b175474e89094c44da98b954eedeac495271d0f") WETH = interface.IERC20("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2") USDT = interface.IERC20("0xdac17f958d2ee523a2206206994597c13d831ec7") USDC = interface.IERC20("0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48") @lru_cache def getFactory(router): return interface.UniswapFactoryV2(router.factory()) @lru_cache def getToken0(pair): return interface.IERC20(pair.token0()) @lru_cache def getToken1(pair): return interface.IERC20(pair.token1()) @lru_cache def getPair(factory, token0, token1): return interface.UniswapPair(factory.getPair(token0, token1)) def getReserves(token, otherToken, factory): try: pair = getPair(factory, token, otherToken) except ContractNotFound: return 0
from brownie import interface QUICKSWAP_ROUTER = "0xa5E0829CaCEd8fFDD4De3c43696c57F7D7A678ff" USDC_WETH_STAKING = interface.StakingRewards("0x9732E1cC876d8D0B61389385fC1FC756920404fd") DAI_WETH_STAKING = interface.StakingRewards("0xDFc1b89b6184DfCC7371E3dd898377ECBFEf7058") USDC_maUSDC_STAKING = interface.StakingRewards("0x68910d18332fFDc1D11caEA4fE93C94Ccd540732") ETH_wBTC_STAKING = interface.StakingRewards("0x74aF83811468d7a51452128727AB14507B7DC57E") maUSDC_maTUSD_STAKING = interface.StakingRewards("0x5AE1e3Af79270e600D0e86609bB56B6c6CE23Ee8") maUSDC_maUSDT_STAKING = interface.StakingRewards("0x66aCCDc838F563D36D0695539c5A01E651eAAEC9") maUSDC_maDAI_STAKING = interface.StakingRewards("0x0A8E11C2C9B89285e810A206D391CE480dbA7562") MATIC_ETH = interface.IERC20("0x7ceb23fd6bc0add59e62ac25578270cff1b9f619") MATIC_BTC = interface.IERC20("0x1bfd67037b42cf73acf2047067bd4f2c47d9bfd6") MATIC_QUICK = interface.IERC20("0x831753dd7087cac61ab5644b308642cc1c33dc13") MATIC_MATIC = interface.IERC20("0x0d500b1d8e8ef31e21c99d1db9a6444d3adf1270") QUICK_ETH_USDC = interface.UniswapPair("0x853ee4b2a13f8a742d64c8f088be7ba2131f670d") QUICK_ETH_DAI = interface.UniswapPair("0x4a35582a710e1f4b2030a3f826da20bfb6703c09") TOKEN_PRICES = { "Quickswap": ( QUICKSWAP_ROUTER, [ ("ETH", MATIC_ETH), ("BTC", MATIC_BTC), ("QUICK", MATIC_QUICK), ("MATIC", MATIC_MATIC), ("ETH_USDC", QUICK_ETH_USDC), ("ETH_DAI", QUICK_ETH_DAI), ]
def erc20_by_address(self, address): return interface.IERC20(address)
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dfd = interface.IERC20Ex('0x20c36f062a31865bED8a5B1e512D9a1A20AA333A') dusd = interface.IERC20Ex('0x5BC25f649fc4e26069dDF4cF4010F9f706c23831') lp = interface.IERC20Ex('0xd8e9690eff99e21a2de25e0b148ffaf47f47c972') # pool is lp for balancer pool = interface.IBalancerPool( '0xd8e9690eff99e21a2de25e0b148ffaf47f47c972') crdfd = MockCErc20.deploy(dfd, {'from': admin}) crdusd = MockCErc20.deploy(dusd, {'from': admin}) werc20 = WERC20.deploy({'from': admin}) staking = accounts.at('0xf068236ecad5fabb9883bbb26a6445d6c7c9a924', force=True) wstaking = WStakingRewards.deploy(staking, lp, dfd, {'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dfd, dusd], [2**112 // 2 // 700, 2**112 * 2 // 700]) balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': alice}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wstaking], True, {'from': admin}) core_oracle.setRoute( [dfd, dusd, lp], [simple_oracle, simple_oracle, balancer_oracle], {'from': admin}, ) oracle.setOracles( [dfd, dusd, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) homora.addBank(dfd, crdfd, {'from': admin}) homora.addBank(dusd, crdusd, {'from': admin}) # setup initial funds to alice mint_tokens(dfd, alice) mint_tokens(dusd, alice) # check alice's funds print(f'Alice dusd balance {dusd.balanceOf(alice)}') print(f'Alice dfd balance {dfd.balanceOf(alice)}') # Steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) # set approval dfd.approve(homora, 2**256 - 1, {'from': alice}) dfd.approve(crdfd, 2**256 - 1, {'from': alice}) dusd.approve(homora, 2**256 - 1, {'from': alice}) dusd.approve(crdusd, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(staking, 2**256 - 1, {'from': bob}) balancer_spell = BalancerSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', {'from': admin}) # first time call to reduce gas balancer_spell.getPair(lp, {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = dfd.balanceOf(alice) prevBBal = dusd.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) prevARes = interface.IBalancerPool(lp).getBalance(dfd) prevBRes = interface.IBalancerPool(lp).getBalance(dusd) dfd_amt = 100 * 10**18 dusd_amt = 10**18 lp_amt = 0 borrow_dfd_amt = 0 borrow_dusd_amt = 0 # calculate slippage control total_dfd_amt = dfd_amt + borrow_dfd_amt total_dusd_amt = dusd_amt + borrow_dusd_amt dfd_weight = 0.58 dusd_weight = 0.42 ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \ (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1 lp_desired = lp_amt + int( interface.IERC20(lp).totalSupply() * ratio * 0.995) print('lp desired', lp_desired) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp, # lp token [ dfd_amt, # supply DFD dusd_amt, # supply DUSD lp_amt, # supply LP borrow_dfd_amt, # borrow DFD borrow_dusd_amt, # borrow DUSD 0, # borrow LP tokens lp_desired ], # LP desired wstaking), {'from': alice}) curABal = dfd.balanceOf(alice) curBBal = dusd.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) curARes = interface.IBalancerPool(lp).getBalance(dfd) curBRes = interface.IBalancerPool(lp).getBalance(dusd) print('spell lp balance', lp.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd) print('bank dfd dfdDebt', dfdDebt) print('bank dfd dfdShare', dfdShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('staking prev LP balance', prevLPBal_staking) print('staking cur LP balance', curLPBal_staking) print('prev dfd res', prevARes) print('cur dfd res', curARes) print('prev dusd res', prevBRes) print('cur dusd res', curBRes) # alice assert almostEqual(curABal - prevABal, -dfd_amt), 'incorrect DFD amt' assert almostEqual(curBBal - prevBBal, -dusd_amt), 'incorrect DUSD amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance' assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' assert dfdDebt == borrow_dfd_amt # check balance and pool reserves assert almostEqual( curABal - prevABal - borrow_dfd_amt, -(curARes - prevARes)), 'not all DFD tokens go to LP pool' assert almostEqual( curBBal - prevBBal - borrow_dusd_amt, -(curBRes - prevBRes)), 'not all DUSD tokens go to LP pool' _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevDfd = dfd.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob}) chain.sleep(20000) prevAliceDfdBalance = dfd.balanceOf(alice) print('Alice dfd balance', prevAliceDfdBalance) ##################################################################################### print( '=========================================================================' ) print('Case 2. add liquidity the second time') prevABal = dfd.balanceOf(alice) prevBBal = dusd.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) prevARes = interface.IBalancerPool(lp).getBalance(dfd) prevBRes = interface.IBalancerPool(lp).getBalance(dusd) dfd_amt = 100 * 10**18 dusd_amt = 10**18 lp_amt = 0 borrow_dfd_amt = 0 borrow_dusd_amt = 0 # calculate slippage control total_dfd_amt = dfd_amt + borrow_dfd_amt total_dusd_amt = dusd_amt + borrow_dusd_amt dfd_weight = 0.58 dusd_weight = 0.42 ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \ (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1 lp_desired = lp_amt + int( interface.IERC20(lp).totalSupply() * ratio * 0.995) print('lp desired', lp_desired) tx = homora.execute( 1, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp, # lp token [ dfd_amt, # supply DFD dusd_amt, # supply DUSD lp_amt, # supply LP borrow_dfd_amt, # borrow DFD borrow_dusd_amt, # borrow DUSD 0, # borrow LP tokens lp_desired ], # LP desired wstaking), {'from': alice}) curABal = dfd.balanceOf(alice) curBBal = dusd.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) curARes = interface.IBalancerPool(lp).getBalance(dfd) curBRes = interface.IBalancerPool(lp).getBalance(dusd) print('spell lp balance', lp.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd) print('bank dfd dfdDebt', dfdDebt) print('bank dfd dfdShare', dfdShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('staking prev LP balance', prevLPBal_staking) print('staking cur LP balance', curLPBal_staking) print('prev dfd res', prevARes) print('cur dfd res', curARes) print('prev dusd res', prevBRes) print('cur dusd res', curBRes) # alice assert almostEqual(curABal - prevABal, -dfd_amt), 'incorrect DFD amt' assert almostEqual(curBBal - prevBBal, -dusd_amt), 'incorrect DUSD amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance' assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' assert dfdDebt == borrow_dfd_amt # check balance and pool reserves assert almostEqual( curABal - prevABal - borrow_dfd_amt, -(curARes - prevARes)), 'not all DFD tokens go to LP pool' assert almostEqual( curBBal - prevBBal - borrow_dusd_amt, -(curBRes - prevBRes)), 'not all DUSD tokens go to LP pool' curAliceDfdBalance = dfd.balanceOf(alice) print('Alice dfd balance', curAliceDfdBalance) receivedDfd = curAliceDfdBalance - prevAliceDfdBalance + dfd_amt print('received dfd', receivedDfd) # check with staking directly tx = interface.IStakingRewards(staking).getReward({'from': bob}) receivedDfdFromStaking = dfd.balanceOf(bob) - prevDfd print('receivedDfdFromStaking', receivedDfdFromStaking) assert almostEqual(receivedDfd, receivedDfdFromStaking) return tx
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 main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] usdt = interface.IERC20Ex('0xdac17f958d2ee523a2206206994597c13d831ec7') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') lp = interface.IERC20Ex('0x06da0fd433C1A5d7a4faa01111c044910A184553') lp_usdc = interface.IERC20Ex('0x3041cbd36888becc7bbcbc0045e3b1f144466f5f') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') crusdc = interface.ICErc20('0x44fbebd2f576670a6c33f6fc0b00aa8c5753b322') sushi = interface.IERC20('0x6b3595068778dd592e39a122f4f5a5cf09c90fe2') # sushiswap router router = interface.IUniswapV2Router02( '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f') chef = accounts.at('0xc2edad668740f1aa35e4d8f227fb8e17dca888cd', force=True) wchef = WMasterChef.deploy(chef, {'from': admin}) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([usdt, weth, usdc], [2**112 // 700, 2**112, 2**112 // 700]) uniswap_oracle = UniswapV2Oracle.deploy(simple_oracle, {'from': admin}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wchef], True, {'from': admin}) core_oracle.setRoute( [usdt, weth, lp, usdc, lp_usdc], [ simple_oracle, simple_oracle, uniswap_oracle, simple_oracle, uniswap_oracle ], {'from': admin}, ) oracle.setOracles( [usdt, weth, lp, usdc, lp_usdc], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) homora.addBank(usdt, crusdt, {'from': admin}) homora.addBank(usdc, crusdc, {'from': admin}) # setup initial funds to alice mint_tokens(usdt, alice) mint_tokens(weth, alice) mint_tokens(usdc, alice) # check alice's funds print(f'Alice usdt balance {usdt.balanceOf(alice)}') print(f'Alice weth balance {weth.balanceOf(alice)}') # Steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) # set approval usdt.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(crusdt, 2**256 - 1, {'from': alice}) usdc.approve(homora, 2**256 - 1, {'from': alice}) usdc.approve(crusdc, 2**256 - 1, {'from': alice}) weth.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(chef, 2**256 - 1, {'from': bob}) sushiswap_spell = SushiswapSpellV1.deploy(homora, werc20, router, wchef, {'from': admin}) # first time call to reduce gas sushiswap_spell.getPair(weth, usdt, {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1. add liquidity first time') prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_chef = lp.balanceOf(chef) if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() usdt_amt = 10 * 10**6 weth_amt = 10**18 lp_amt = 0 borrow_usdt_amt = 0 borrow_weth_amt = 0 pid = 0 tx = homora.execute( 0, sushiswap_spell, sushiswap_spell.addLiquidityWMasterChef.encode_input( usdt, # token 0 weth, # token 1 [ usdt_amt, # supply USDT weth_amt, # supply WETH lp_amt, # supply LP borrow_usdt_amt, # borrow USDT borrow_weth_amt, # borrow WETH 0, # borrow LP tokens 0, # min USDT 0 ], # min WETH pid, ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_chef = lp.balanceOf(chef) if interface.IUniswapV2Pair(lp).token0() == usdt: curARes, curBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: curBRes, curARes, _ = interface.IUniswapV2Pair(lp).getReserves() print('spell lp balance', lp.balanceOf(sushiswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, totalDebt, totalShare = homora.getBankInfo(usdt) print('bank usdt totalDebt', totalDebt) print('bank usdt totalShare', totalShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('chef prev LP balance', prevLPBal_chef) print('chef cur LP balance', curLPBal_chef) print('prev usdt res', prevARes) print('cur usdt res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curABal - prevABal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert usdt.balanceOf(sushiswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(sushiswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(sushiswap_spell) == 0, 'non-zero spell LP balance' assert totalDebt == borrow_usdt_amt # check balance and pool reserves assert curABal - prevABal - borrow_usdt_amt == - \ (curARes - prevARes), 'not all USDT tokens go to LP pool' assert almostEqual( curBBal - prevBBal - borrow_weth_amt, -(curBRes - prevBRes)), 'not all WETH tokens go to LP pool' _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevSushi = sushi.balanceOf(bob) pid = 0 print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) tx = interface.IMasterChef(chef).deposit(pid, collSize, {'from': bob}) chain.sleep(20000) prevAliceSushiBalance = sushi.balanceOf(alice) print('Alice sushi balance', prevAliceSushiBalance) ##################################################################################### print( '=========================================================================' ) print('Case 2. add liquidity (failed tx desired)') usdc_amt = 10 * 10**6 weth_amt = 10**18 lp_amt = 0 borrow_usdc_amt = 0 borrow_weth_amt = 0 pid = 0 try: tx = homora.execute( 1, sushiswap_spell, sushiswap_spell.addLiquidityWMasterChef.encode_input( usdc, # token 0 weth, # token 1 [ usdc_amt, # supply USDC weth_amt, # supply WETH lp_amt, # supply LP borrow_usdc_amt, # borrow USDC borrow_weth_amt, # borrow WETH 0, # borrow LP tokens 0, # min USDC 0 ], # min WETH pid, ), {'from': alice}) assert False, 'tx not fail' except VirtualMachineError: pass ##################################################################################### print( '=========================================================================' ) print('Case 3. remove liquidity (failed tx desired)') lp_take_amt = collSize lp_want = 0 usdc_repay = 0 weth_repay = 0 try: tx = homora.execute( 1, sushiswap_spell, sushiswap_spell.removeLiquidityWMasterChef.encode_input( usdc, # token 0 weth, # token 1 [ lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet usdc_repay, # repay USDC weth_repay, # repay WETH 0, # repay LP tokens 0, # min USDC 0 ], # min WETH ), {'from': alice}) assert False, 'tx not failed' except VirtualMachineError: pass ##################################################################################### print( '=========================================================================' ) print('Case 4. remove liquidity') prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_chef = lp.balanceOf(chef) prevETHBal = alice.balance() if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() lp_take_amt = collSize lp_want = 0 usdt_repay = 0 weth_repay = 0 pid = 0 tx = homora.execute( 1, sushiswap_spell, sushiswap_spell.removeLiquidityWMasterChef.encode_input( usdt, # token 0 weth, # token 1 [ lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet usdt_repay, # repay USDT weth_repay, # repay WETH 0, # repay LP tokens 0, # min USDT 0 ], # min WETH ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_chef = lp.balanceOf(chef) curETHBal = alice.balance() if interface.IUniswapV2Pair(lp).token0() == usdt: curARes, curBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: curBRes, curARes, _ = interface.IUniswapV2Pair(lp).getReserves() print('spell lp balance', lp.balanceOf(sushiswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, totalDebt, totalShare = homora.getBankInfo(usdt) print('bank usdt totalDebt', totalDebt) print('bank usdt totalShare', totalShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('chef prev LP balance', prevLPBal_chef) print('chef cur LP balance', curLPBal_chef) print('prev usdt res', prevARes) print('cur usdt res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curBBal - prevBBal, 0), 'incorrect WETH amt' assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # chef assert almostEqual(curLPBal_chef - prevLPBal_chef, -lp_take_amt), 'incorrect chef LP amt' # spell assert usdt.balanceOf(sushiswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(sushiswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(sushiswap_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual( curABal - prevABal + usdt_repay, -(curARes - prevARes)), 'inconsistent USDT from withdraw' assert almostEqual(curBBal - prevBBal, 0), 'inconsistent WETH from withdraw' assert almostEqual(curETHBal - prevETHBal + weth_repay, -(curBRes - prevBRes)), 'inconsistent ETH from withdraw' curAliceSushiBalance = sushi.balanceOf(alice) print('Alice sushi balance', curAliceSushiBalance) receivedSushi = curAliceSushiBalance - prevAliceSushiBalance print('received sushi', receivedSushi) # check with staking directly pid = 0 tx = interface.IMasterChef(chef).withdraw(pid, collSize, {'from': bob}) receivedSushiFromStaking = sushi.balanceOf(bob) - prevSushi print('receivedSushiFromStaking', receivedSushiFromStaking) assert almostEqual(receivedSushi, receivedSushiFromStaking)
def main(): badger = connect_badger("deploy-final.json") test_user = accounts.at(decouple.config("TEST_ACCOUNT"), force=True) distribute_test_ether(test_user, Wei("20 ether")) distribute_from_whales(test_user, assets=["bBadger", "badger", "usdc"]) rest = get_active_rewards_schedule(badger) usdc = interface.IERC20(registry.tokens.usdc) usdc_per_badger = 40.37 * 0.75 usdc_total = 13386240 multi = GnosisSafe(badger.devMultisig) badger_total_scaled = usdc_total / usdc_per_badger badger_total = Wei(str(badger_total_scaled) + " ether") bBadger = badger.getSett("native.badger") ppfs = bBadger.getPricePerFullShare() bBadger_total = int(badger_total / ppfs * 10**18) badger_total = Wei(str(badger_total_scaled) + " ether") console.print({ "TRADE": "BASED", "usdc_per_badger": usdc_per_badger, "usdc_total": usdc_total, "badger_total_scaled": badger_total_scaled, "badger_total": badger_total, "ppfs": ppfs, "bBadger_total": str(bBadger_total), }) params = { "beneficiary": "0x3159b46a7829a0dbfa856888af768fe7146e7418", "duration": days(182), "usdcAmount": usdc_total * 10**6, "bBadgerAmount": bBadger_total, # "usdcAmount": 0, # "bBadgerAmount": 0, } console.print(params) # # Oxb1 Test beneficiary = accounts.at(params["beneficiary"], force=True) escrow = OtcEscrow.at("0x7163fB2fA38Ea3BBc1F8525F3d8D0417C0c9d903") # bBadger.transfer(badger.devMultisig, Wei("100000 ether"), {"from": test_user}) pre = get_token_balances( [usdc, bBadger], [test_user, escrow, badger.devMultisig, beneficiary]) pre.print() # assert usdc.balanceOf(params["beneficiary"]) >= params["usdcAmount"] # multi.execute(MultisigTxMetadata(description="Transfer to 0xb1"), { # "to": bBadger.address, # "data": bBadger.transfer.encode_input(escrow, bBadger_total + Wei("1000 ether")) # }) # assert usdc.allowance(beneficiary, escrow) >= params["usdcAmount"] # usdc.approve(escrow, params["usdcAmount"], {"from": beneficiary}) # tx = escrow.swap({"from": beneficiary}) tx = multi.execute(MultisigTxMetadata(description="Swap"), { "to": escrow.address, "data": escrow.swap.encode_input() }, print_output=False) chain.mine() print(tx.call_trace()) vesting = interface.ITokenTimelock( tx.events["VestingDeployed"][0]["vesting"]) console.print({ "token": vesting.token(), "beneficiary": vesting.beneficiary(), "releaseTime": to_utc_date(vesting.releaseTime()), }) post = get_token_balances( [usdc, bBadger], [test_user, escrow, badger.devMultisig, beneficiary]) diff_token_balances(pre, post) try: vesting.release({"from": test_user}) except: print("early vest failed!") chain.sleep(days(182)) chain.mine() # End vesting.release({"from": test_user}) post = get_token_balances( [usdc, bBadger], [test_user, escrow, badger.devMultisig, beneficiary]) diff_token_balances(pre, post) return escrow = OtcEscrow.deploy( params["beneficiary"], params["duration"], params["usdcAmount"], params["bBadgerAmount"], {"from": badger.deployer}, ) beneficiary = accounts.at(params["beneficiary"], force=True) usdc.transfer(beneficiary, params["usdcAmount"], {"from": test_user}) usdc.transfer(beneficiary, 1500000000000, {"from": test_user}) badger.token.transfer(badger.devMultisig, badger_total, {"from": test_user}) multi.execute( MultisigTxMetadata(description="Whitelist Multi"), { "to": bBadger.address, "data": bBadger.approveContractAccess.encode_input( badger.devMultisig), }, ) assert badger.token.balanceOf(badger.devMultisig) > Wei("100 ether") multi.execute( MultisigTxMetadata(description="Approve bBadger Contract"), { "to": badger.token.address, "data": badger.token.approve.encode_input(bBadger, badger_total), }, ) multi.execute( MultisigTxMetadata(description="Deposit"), { "to": bBadger.address, "data": bBadger.deposit.encode_input(badger_total) }, ) console.print( "bBadger.balanceOf(badger.devMultisig)", bBadger.balanceOf(badger.devMultisig), params["bBadgerAmount"], params["bBadgerAmount"] - bBadger.balanceOf(badger.devMultisig)) assert bBadger.balanceOf(badger.devMultisig) >= params["bBadgerAmount"] chain.mine() chain.sleep(14) chain.mine() multi.execute( MultisigTxMetadata(description="Transfer"), { "to": bBadger.address, "data": bBadger.transfer.encode_input(escrow, params["bBadgerAmount"]), }, ) assert bBadger.balanceOf(escrow) == params["bBadgerAmount"] multi.execute( MultisigTxMetadata(description="Revoke"), { "to": escrow.address, "data": escrow.revoke.encode_input() }, ) assert bBadger.balanceOf(escrow) == 0 assert bBadger.balanceOf(badger.devMultisig) >= params["bBadgerAmount"] print(bBadger.balanceOf(badger.devMultisig)) bBadger.transfer(escrow, params["bBadgerAmount"], {"from": test_user}) pre = get_token_balances( [usdc, bBadger], [test_user, escrow, badger.devMultisig, beneficiary]) console.print(pre) assert usdc.balanceOf(beneficiary) >= params["usdcAmount"] assert bBadger.balanceOf(escrow) == params["bBadgerAmount"] usdc.approve(escrow, params["usdcAmount"], {"from": beneficiary}) tx = escrow.swap({"from": beneficiary}) post = get_token_balances( [usdc, bBadger], [test_user, escrow, badger.devMultisig, beneficiary]) console.print(tx.events) post.print() diff_token_balances(pre, post) vesting = interface.ITokenTimelock( tx.events["VestingDeployed"][0]["vesting"]) console.print({ "token": vesting.token(), "beneficiary": vesting.beneficiary(), "releaseTime": to_utc_date(vesting.releaseTime()), }) chain.sleep(days(365)) chain.mine() vesting.release({"from": test_user})
def main(): admin = accounts[0] alice = accounts[1] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') # pool is lp for balancer pool = interface.IBalancerPool('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') crdai = interface.ICErc20('0x92b767185fb3b04f881e3ac8e5b0662a027a1d9f') werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([weth, dai], [5192296858534827628530496329220096, 8887571220661441971398610676149]) balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': alice}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) core_oracle.setRoute( [weth, dai, lp], [simple_oracle, simple_oracle, balancer_oracle], {'from': admin}, ) oracle.setOracles( [weth, dai, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) homora.addBank(dai, crdai, {'from': admin}) # setup initial funds to alice mint_tokens(dai, alice) mint_tokens(weth, alice) # check alice's funds print(f'Alice weth balance {weth.balanceOf(alice)}') print(f'Alice dai balance {dai.balanceOf(alice)}') # Steal some LP from the staking pool mint_tokens(lp, alice) # set approval dai.approve(homora, 2**256-1, {'from': alice}) dai.approve(crdai, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) lp.approve(homora, 2**256-1, {'from': alice}) balancer_spell = BalancerSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', {'from': admin}) # first time call to reduce gas balancer_spell.getPair(lp, {'from': admin}) ##################################################################################### print('=========================================================================') print('Case 1.') prevABal = dai.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) prevARes = interface.IBalancerPool(lp).getBalance(dai) prevBRes = interface.IBalancerPool(lp).getBalance(weth) dai_amt = 40000 * 10**18 weth_amt = 10 ** 18 lp_amt = 1 * 10**16 borrow_dai_amt = 0 borrow_weth_amt = 0 # calculate slippage control total_dai_amt = dai_amt + borrow_dai_amt total_weth_amt = weth_amt + borrow_weth_amt dai_weight = 0.2 weth_weight = 0.8 ratio = (((prevARes + total_dai_amt) / prevARes) ** dai_weight) * \ (((prevBRes + total_weth_amt) / prevBRes) ** weth_weight) - 1 lp_desired = lp_amt + int(interface.IERC20(lp).totalSupply() * ratio * 0.995) print('lp desired', lp_desired) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWERC20.encode_input( lp, # lp token [dai_amt, # supply DAI weth_amt, # supply WETH lp_amt, # supply LP borrow_dai_amt, # borrow DAI borrow_weth_amt, # borrow WETH 0, # borrow LP tokens lp_desired] # LP desired ), {'from': alice} ) curABal = dai.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) curARes = interface.IBalancerPool(lp).getBalance(dai) curBRes = interface.IBalancerPool(lp).getBalance(weth) print('spell lp balance', lp.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, daiDebt, daiShare = homora.getBankInfo(dai) print('bank dai daiDebt', daiDebt) print('bank dai daiShare', daiShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('werc20 prev LP balance', prevLPBal_werc20) print('werc20 cur LP balance', curLPBal_werc20) print('prev dai res', prevARes) print('cur dai res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curABal - prevABal, -dai_amt), 'incorrect DAI amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dai.balanceOf(balancer_spell) == 0, 'non-zero spell DAI balance' assert weth.balanceOf(balancer_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' assert daiDebt == borrow_dai_amt # check balance and pool reserves assert almostEqual(curABal - prevABal - borrow_dai_amt, - (curARes - prevARes)), 'not all DAI tokens go to LP pool' assert almostEqual(curBBal - prevBBal - borrow_weth_amt, - (curBRes - prevBRes)), 'not all WETH tokens go to LP pool' ##################################################################################### print('=========================================================================') print('Case 2.') # remove liquidity from the same position prevABal = dai.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) prevETHBal = alice.balance() prevARes = interface.IBalancerPool(lp).getBalance(dai) prevBRes = interface.IBalancerPool(lp).getBalance(weth) lp_take_amt = 2**256-1 # max lp_want = 1 * 10**15 dai_repay = 2**256-1 # max weth_repay = 0 real_dai_repay = homora.borrowBalanceStored(1, dai) _, _, _, real_lp_take_amt = homora.getPositionInfo(1) tx = homora.execute( 1, balancer_spell, balancer_spell.removeLiquidityWERC20.encode_input( lp, # LP token [lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet dai_repay, # repay DAI weth_repay, # repay WETH 0, # repay LP 0, # min DAI 0], # min WETH ), {'from': alice} ) # return tx curABal = dai.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) curETHBal = alice.balance() curARes = interface.IBalancerPool(lp).getBalance(dai) curBRes = interface.IBalancerPool(lp).getBalance(weth) print('spell lp balance', lp.balanceOf(balancer_spell)) print('spell dai balance', dai.balanceOf(balancer_spell)) print('spell weth balance', weth.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta ETH balance', curETHBal - prevETHBal) print('Alice delta LP balance', curLPBal - prevLPBal) print('remove liquidity gas', tx.gas_used) print('bank delta lp balance', curLPBal_bank - prevLPBal_bank) print('bank total lp balance', curLPBal_bank) _, _, _, daiDebt, daiShare = homora.getBankInfo(dai) print('bank dai totalDebt', daiDebt) print('bank dai totalShare', daiShare) print('LP want', lp_want) print('bank delta LP amount', curLPBal_bank - prevLPBal_bank) print('LP take amount', lp_take_amt) print('prev werc20 LP balance', prevLPBal_werc20) print('cur werc20 LP balance', curLPBal_werc20) print('real dai repay', real_dai_repay) # alice assert almostEqual(curBBal - prevBBal, 0), 'incorrect WETH amt' assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # werc20 assert almostEqual(curLPBal_werc20 - prevLPBal_werc20, - real_lp_take_amt), 'incorrect werc20 LP amt' # spell assert dai.balanceOf(balancer_spell) == 0, 'non-zero spell DAI balance' assert weth.balanceOf(balancer_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual(curABal - prevABal + real_dai_repay, - (curARes - prevARes)), 'inconsistent DAI from withdraw' assert almostEqual(curBBal - prevBBal, 0), 'inconsistent WETH from withdraw' assert almostEqual(curETHBal - prevETHBal + weth_repay, - (curBRes - prevBRes)), 'inconsistent ETH from withdraw' return tx