def main(): admin = accounts[0] alice = accounts[1] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') eth_usdt = interface.IERC20Ex('0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852') eth_usdc = interface.IERC20Ex('0xb4e16d0168e52d35cacd2c6185b44281ec28c9dc') usdt_usdc = interface.IERC20Ex( '0x3041cbd36888becc7bbcbc0045e3b1f144466f5f') uni_pair = interface.IUniswapV2Pair( '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11') resA, resB, _ = uni_pair.getReserves() if uni_pair.token0() == weth: weth_price = resB * 10**18 // resA else: weth_price = resA * 10**18 // resB print('weth price', weth_price) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dai, usdt, usdc, weth], [ 2**112 * 10**18 // weth_price, 2**112 * 10**30 // weth_price, 2**112 * 10**30 // weth_price, 2**112 ]) uniswap_oracle = UniswapV2Oracle.deploy(simple_oracle, {'from': admin}) # expected ~100k * 2**112 print('ETH-USDT LP:', uniswap_oracle.getETHPx(eth_usdt)) # expected ~100k * 2**112 print('ETH-USDC LP:', uniswap_oracle.getETHPx(eth_usdc)) # expected ~3.8e9 * 2**112 print('USDT-USDC LP:', uniswap_oracle.getETHPx(usdt_usdc)) assert almostEqual( uniswap_oracle.getETHPx(eth_usdt), weth.balanceOf(eth_usdt) * 2 * 2**112 // eth_usdt.totalSupply()) assert almostEqual( uniswap_oracle.getETHPx(eth_usdc), weth.balanceOf(eth_usdc) * 2 * 2**112 // eth_usdc.totalSupply()) assert almostEqual( uniswap_oracle.getETHPx(usdt_usdc), usdt.balanceOf(usdt_usdc) * 2 * simple_oracle.getETHPx(usdt) // usdt_usdc.totalSupply())
def main(): admin = accounts[0] alice = accounts[1] weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') lp = interface.IERC20Ex('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') # pool is lp for balancer pool = interface.ICurvePool('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') werc20 = WERC20.deploy({'from': admin}) uni_pair = interface.IUniswapV2Pair( '0xa478c2975ab1ea89e8196811f51a7b7ade33eb11') resA, resB, _ = uni_pair.getReserves() if uni_pair.token0() == weth: weth_dai_price = resB * 10**18 // resA else: weth_dai_price = resA * 10**18 // resB print('weth dai price', weth_dai_price) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([weth, dai], [2**112, 2**112 * 10**18 // weth_dai_price]) balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': admin}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) oracle.setOracles( [weth, dai, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) core_oracle.setRoute( [weth, dai, lp], [simple_oracle, simple_oracle, balancer_oracle], {'from': admin}, ) ##################################################################################### print( '=========================================================================' ) print('Case 1.') lp_price = balancer_oracle.getETHPx(lp) dai_price = simple_oracle.getETHPx(dai) weth_price = simple_oracle.getETHPx(weth) print('lp price', lp_price) print('dai price', dai_price) print('weth price', weth_price) assert almostEqual( lp_price, weth.balanceOf(lp) * 5 // 4 * 2**112 // lp.totalSupply())
def main(): admin = accounts[0] alice = accounts[1] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') 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], [9011535487953795006625883219171279625142296, 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], 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) # 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}) uniswap_spell = UniswapV2SpellV1.deploy(homora, werc20, router, {'from': admin}) # first time call to reduce gas uniswap_spell.getPair(weth, usdt, {'from': admin}) # whitelist spell in bank homora.setWhitelistSpells([uniswap_spell], [True], {'from': admin}) # whitelist lp in spell uniswap_spell.setWhitelistLPTokens([lp], [True], {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() usdt_amt = 400 * 10**6 weth_amt = 10**18 lp_amt = 1 * 10**16 borrow_usdt_amt = 0 borrow_weth_amt = 0 tx = homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWERC20.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 ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) 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(uniswap_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('werc20 prev LP balance', prevLPBal_werc20) print('werc20 cur LP balance', curLPBal_werc20) 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(uniswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(uniswap_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.') # remove liquidity from the same position prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) 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 = 1 * 10**16 lp_want = 1 * 10**15 usdt_repay = 2**256 - 1 # max weth_repay = 0 real_usdt_repay = homora.borrowBalanceStored(1, usdt) tx = homora.execute( 1, uniswap_spell, uniswap_spell.removeLiquidityWERC20.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 0, # repay WETH 0, # repay LP 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_werc20 = lp.balanceOf(werc20) 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(uniswap_spell)) print('spell usdt balance', usdt.balanceOf(uniswap_spell)) print('spell weth balance', weth.balanceOf(uniswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) 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) _, _, _, totalDebt, totalShare = homora.getBankInfo(usdt) print('bank usdt totalDebt', totalDebt) print('bank usdt totalShare', totalShare) 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 usdt repay', real_usdt_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, -lp_take_amt), 'incorrect werc20 LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual( curABal - prevABal + real_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' return tx
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dpi = interface.IERC20Ex('0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') usdt = interface.IERC20Ex('0xdac17f958d2ee523a2206206994597c13d831ec7') lp = interface.IERC20Ex('0x4d5ef58aac27d99935e5b6b4a6778ff292059991') lp_usdt = interface.IERC20Ex('0x0d4a11d5eeaac28ec3f61d100daf4d40471f1852') crdpi = MockCErc20.deploy(dpi, {'from': admin}) crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') staking = accounts.at('0xB93b505Ed567982E2b6756177ddD23ab5745f309', force=True) index = interface.IERC20Ex( interface.IStakingRewardsEx(staking).rewardsToken()) wstaking = WStakingRewards.deploy(staking, lp, index, {'from': admin}) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dpi, weth, usdt], [2**112 * 100 // 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, wstaking], True, {'from': admin}) core_oracle.setRoute( [dpi, weth, lp, usdt, lp_usdt], [ simple_oracle, simple_oracle, uniswap_oracle, simple_oracle, uniswap_oracle ], {'from': admin}, ) oracle.setOracles( [dpi, weth, lp, usdt, lp_usdt], [ [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(dpi, crdpi, {'from': admin}) homora.addBank(usdt, crusdt, {'from': admin}) # setup initial funds to alice mint_tokens(dpi, alice) mint_tokens(weth, alice) mint_tokens(usdt, alice) mint_tokens(dpi, crdpi) # check alice's funds print(f'Alice dpi balance {dpi.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) mint_tokens(lp_usdt, alice) mint_tokens(lp_usdt, bob) # set approval dpi.approve(homora, 2**256 - 1, {'from': alice}) dpi.approve(crdpi, 2**256 - 1, {'from': alice}) weth.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(crusdt, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(staking, 2**256 - 1, {'from': bob}) uniswap_spell = UniswapV2SpellV1.deploy(homora, werc20, router, {'from': admin}) # first time call to reduce gas uniswap_spell.getPair(weth, dpi, {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1. add liquidity first time') prevABal = dpi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) if interface.IUniswapV2Pair(lp).token0() == dpi: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() dpi_amt = 10 * 10**18 weth_amt = 10**18 lp_amt = 0 borrow_dpi_amt = 10**18 borrow_weth_amt = 0 real_dpi_borrow_amt = borrow_dpi_amt tx = homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWStakingRewards.encode_input( dpi, # token 0 weth, # token 1 [ dpi_amt, # supply DPI weth_amt, # supply WETH lp_amt, # supply LP borrow_dpi_amt, # borrow DPI borrow_weth_amt, # borrow WETH 0, # borrow LP tokens 0, # min DPI 0 ], # min WETH wstaking, ), {'from': alice}) curABal = dpi.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) if interface.IUniswapV2Pair(lp).token0() == dpi: curARes, curBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: curBRes, curARes, _ = interface.IUniswapV2Pair(lp).getReserves() print('spell lp balance', lp.balanceOf(uniswap_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(dpi) print('bank dpi totalDebt', totalDebt) print('bank dpi totalShare', totalShare) 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 dpi res', prevARes) print('cur dpi res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curABal - prevABal, -dpi_amt), 'incorrect DPI amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dpi.balanceOf(uniswap_spell) == 0, 'non-zero spell DPI balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' assert totalDebt == borrow_dpi_amt # check balance and pool reserves assert curABal - prevABal - borrow_dpi_amt == - \ (curARes - prevARes), 'not all DPI tokens go to LP pool' assert 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 prevIndex = index.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob}) chain.sleep(20000) prevAliceIndexBalance = index.balanceOf(alice) print('Alice index balance', prevAliceIndexBalance) ##################################################################################### print( '=========================================================================' ) print('Case 2. add liquidity (failed tx desired)') usdt_amt = 10 * 10**6 weth_amt = 10**18 lp_amt = 0 borrow_usdt_amt = 0 borrow_weth_amt = 0 try: tx = homora.execute( 1, uniswap_spell, uniswap_spell.addLiquidityWStakingRewards.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 wstaking, ), {'from': alice}) except VirtualMachineError: pass ##################################################################################### print( '=========================================================================' ) print('Case 3. remove liquidity (failed tx desired)') lp_take_amt = collSize lp_want = 0 usdt_repay = 0 weth_repay = 0 try: tx = homora.execute( 1, uniswap_spell, uniswap_spell.removeLiquidityWStakingRewards.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 wstaking, ), {'from': alice}) except VirtualMachineError: pass ##################################################################################### print( '=========================================================================' ) print('Case 4. remove liquidity') prevABal = dpi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) prevETHBal = alice.balance() if interface.IUniswapV2Pair(lp).token0() == dpi: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() lp_take_amt = collSize lp_want = 0 dpi_repay = 2**256 - 1 weth_repay = 0 tx = homora.execute( 1, uniswap_spell, uniswap_spell.removeLiquidityWStakingRewards.encode_input( dpi, # token 0 weth, # token 1 [ lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet dpi_repay, # repay DPI weth_repay, # repay WETH 0, # repay LP tokens 0, # min DPI 0 ], # min WETH wstaking, ), {'from': alice}) curABal = dpi.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) curETHBal = alice.balance() if interface.IUniswapV2Pair(lp).token0() == dpi: curARes, curBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: curBRes, curARes, _ = interface.IUniswapV2Pair(lp).getReserves() print('spell lp balance', lp.balanceOf(uniswap_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(dpi) print('bank dpi totalDebt', totalDebt) print('bank dpi totalShare', totalShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('wstaking prev LP balance', prevLPBal_staking) print('wstaking cur LP balance', curLPBal_staking) print('prev dpi res', prevARes) print('cur dpi 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' # staking assert almostEqual(curLPBal_staking - prevLPBal_staking, -lp_take_amt), 'incorrect staking LP amt' # spell assert dpi.balanceOf(uniswap_spell) == 0, 'non-zero spell DPI balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual(curABal - prevABal + real_dpi_borrow_amt, -(curARes - prevARes)), 'inconsistent DPI from withdraw' assert almostEqual(curBBal - prevBBal, 0), 'inconsistent WETH from withdraw' assert almostEqual(curETHBal - prevETHBal + weth_repay, -(curBRes - prevBRes)), 'inconsistent ETH from withdraw' curAliceIndexBalance = index.balanceOf(alice) print('Alice index balance', curAliceIndexBalance) receivedIndex = curAliceIndexBalance - prevAliceIndexBalance print('received index', receivedIndex) # check with staking directly tx = interface.IStakingRewards(staking).getReward({'from': bob}) receivedIndexFromStaking = index.balanceOf(bob) - prevIndex print('receivedIndexFromStaking', receivedIndexFromStaking) assert almostEqual(receivedIndex, receivedIndexFromStaking)
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dpi = interface.IERC20Ex('0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x4d5ef58aac27d99935e5b6b4a6778ff292059991') crdpi = MockCErc20.deploy(dpi, {'from': admin}) router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') staking = accounts.at('0xB93b505Ed567982E2b6756177ddD23ab5745f309', force=True) index = interface.IERC20Ex(interface.IStakingRewardsEx(staking).rewardsToken()) wstaking = WStakingRewards.deploy(staking, lp, index, {'from': admin}) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dpi, weth], [2**112 * 100 // 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, wstaking], True, {'from': admin}) core_oracle.setRoute( [dpi, weth, lp], [simple_oracle, simple_oracle, uniswap_oracle], {'from': admin}, ) oracle.setOracles( [dpi, 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(dpi, crdpi, {'from': admin}) # setup initial funds to alice mint_tokens(dpi, alice) mint_tokens(weth, alice) mint_tokens(dpi, crdpi) # check alice's funds print(f'Alice dpi balance {dpi.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 dpi.approve(homora, 2**256-1, {'from': alice}) dpi.approve(crdpi, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) lp.approve(homora, 2**256-1, {'from': alice}) lp.approve(staking, 2**256-1, {'from': bob}) uniswap_spell = UniswapV2SpellV1.deploy( homora, werc20, router, {'from': admin}) # first time call to reduce gas uniswap_spell.getPair(weth, dpi, {'from': admin}) # whitelist spell in bank homora.setWhitelistSpells([uniswap_spell], [True], {'from': admin}) # whitelist token in bank homora.setWhitelistTokens([dpi], [True], {'from': admin}) # whitelist lp in spell uniswap_spell.setWhitelistLPTokens([lp], [True], {'from': admin}) ##################################################################################### print('=========================================================================') print('Case 1. add liquidity') prevABal = dpi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_staking = lp.balanceOf(staking) if interface.IUniswapV2Pair(lp).token0() == dpi: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() dpi_amt = 10 * 10**18 weth_amt = 10**18 lp_amt = 0 borrow_dpi_amt = 10**18 borrow_weth_amt = 0 tx = homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWStakingRewards.encode_input( dpi, # token 0 weth, # token 1 [dpi_amt, # supply DPI weth_amt, # supply WETH lp_amt, # supply LP borrow_dpi_amt, # borrow DPI borrow_weth_amt, # borrow WETH 0, # borrow LP tokens 0, # min DPI 0], # min WETH wstaking, ), {'from': alice} ) curABal = dpi.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_staking = lp.balanceOf(staking) if interface.IUniswapV2Pair(lp).token0() == dpi: curARes, curBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: curBRes, curARes, _ = interface.IUniswapV2Pair(lp).getReserves() print('spell lp balance', lp.balanceOf(uniswap_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(dpi) print('bank dpi totalDebt', totalDebt) print('bank dpi totalShare', totalShare) 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 dpi res', prevARes) print('cur dpi res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curABal - prevABal, -dpi_amt), 'incorrect DPI amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dpi.balanceOf(uniswap_spell) == 0, 'non-zero spell DPI balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' assert totalDebt == borrow_dpi_amt # check balance and pool reserves assert curABal - prevABal - borrow_dpi_amt == - \ (curARes - prevARes), 'not all DPI tokens go to LP pool' assert curBBal - prevBBal - borrow_weth_amt == - \ (curBRes - prevBRes), 'not all WETH tokens go to LP pool' # ##################################################################################### print('=========================================================================') print('Case 2. harvest first time') prevIndexBalance = index.balanceOf(alice) print('Alice INDEX balance before harvest', prevIndexBalance) _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevIndex = index.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob}) chain.sleep(20000) tx = homora.execute( 1, uniswap_spell, uniswap_spell.harvestWStakingRewards.encode_input(wstaking), {'from': alice} ) print('tx gas used', tx.gas_used) curIndexBalance = index.balanceOf(alice) print('Alice INDEX balance after harvest', curIndexBalance) receivedIndex = curIndexBalance - prevIndexBalance # check with staking directly tx = interface.IStakingRewards(staking).getReward({'from': bob}) receivedIndexFromStaking = index.balanceOf(bob) - prevIndex print('receivedIndexFromStaking', receivedIndexFromStaking) assert almostEqual(receivedIndex, receivedIndexFromStaking) # ##################################################################################### print('=========================================================================') print('Case 3. harvest second time') prevIndexBalance = index.balanceOf(alice) print('Alice INDEX balance before harvest', prevIndexBalance) prevIndex = index.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) chain.sleep(20000) tx = homora.execute( 1, uniswap_spell, uniswap_spell.harvestWStakingRewards.encode_input(wstaking), {'from': alice} ) print('tx gas used', tx.gas_used) curIndexBalance = index.balanceOf(alice) print('Alice INDEX balance after harvest', curIndexBalance) receivedIndex = curIndexBalance - prevIndexBalance # check with staking directly tx = interface.IStakingRewards(staking).getReward({'from': bob}) receivedIndexFromStaking = index.balanceOf(bob) - prevIndex print('receivedIndexFromStaking', receivedIndexFromStaking) assert almostEqual(receivedIndex, receivedIndexFromStaking)
def main(): admin = accounts[0] alice = accounts[1] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') lp = interface.IERC20Ex('0x3041cbd36888becc7bbcbc0045e3b1f144466f5f') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') crusdc = interface.ICErc20('0x44fbebd2f576670a6c33f6fc0b00aa8c5753b322') router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([usdt, usdc], [ 8343331721347310729683379470025550036595362, 8344470555541464992529317899641128796042472 ]) uniswap_oracle = UniswapV2Oracle.deploy(simple_oracle, {'from': admin}) oracle = ProxyOracle.deploy({'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) oracle.setOracles( [ '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', # USDC '0x3041cbd36888becc7bbcbc0045e3b1f144466f5f', # USDT-USDC ], [ [simple_oracle, 10000, 10000, 10000], [simple_oracle, 10000, 10000, 10000], [uniswap_oracle, 10000, 10000, 10000], ], {'from': admin}, ) # initialize homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) # add bank homora.addBank(usdt, crusdt, {'from': admin}) homora.addBank(usdc, crusdc, {'from': admin}) # setup initial funds 10^6 USDT + 10^6 USDC to alice setup_transfer( usdt, accounts.at('0xbe0eb53f46cd790cd13851d5eff43d12404d33e8', force=True), alice, 10**6 * 10**6) setup_transfer( usdc, accounts.at('0xa191e578a6736167326d05c119ce0c90849e84b7', force=True), alice, 10**6 * 10**6) # setup initial funds 10^6 USDT + 10^6 USDC to homora bank setup_transfer( usdt, accounts.at('0xbe0eb53f46cd790cd13851d5eff43d12404d33e8', force=True), homora, 10**6 * 10**6) setup_transfer( usdc, accounts.at('0x397ff1542f962076d0bfe58ea045ffa2d347aca0', force=True), homora, 10**6 * 10**6) # check alice's funds print(f'Alice usdt balance {usdt.balanceOf(alice)}') print(f'Alice usdc balance {usdc.balanceOf(alice)}') # steal some LP from the staking pool lp.transfer( alice, 1 * 10**8, { 'from': accounts.at('0x85af1678527f63eb6492ab158ed5d2a94b8732c0', force=True) }) # 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}) lp.approve(homora, 2**256 - 1, {'from': alice}) uniswap_spell = UniswapV2SpellV1.deploy(homora, werc20, router, {'from': admin}) # first time call to reduce gas uniswap_spell.getPair(usdt, usdc, {'from': admin}) ##################################################################################### # add liquidity print( '=========================================================================' ) print('Case 1.') prevABal = usdt.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() usdt_amt = 40000 * 10**6 usdc_amt = 50000 * 10**6 lp_amt = 1 * 10**7 borrow_usdt_amt = 1000 * 10**6 borrow_usdc_amt = 200 * 10**6 tx = homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidity.encode_input( usdt, # token 0 usdc, # token 1 [ usdt_amt, # supply USDT usdc_amt, # supply USDC lp_amt, # supply LP borrow_usdt_amt, # borrow USDT borrow_usdc_amt, # borrow USDC 0, # borrow 0 LP tokens 0, # min USDT 0 ], # min USDC ), {'from': alice}) position_id = tx.return_value print('position_id', position_id) curABal = usdt.balanceOf(alice) curBBal = usdc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) 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(uniswap_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) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank usdt debt', usdtDebt) print('bank usdt debt share', usdtDebtShare) print('bank usdc debt', usdcDebt) print('bank usdc debt share', usdcDebtShare) 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 usdt res', prevARes) print('cur usdt res', curARes) print('prev usdc res', prevBRes) print('cur usdc res', curBRes) # alice assert almostEqual(curABal - prevABal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curBBal - prevBBal, -usdc_amt), 'incorrect USDC amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert usdc.balanceOf(uniswap_spell) == 0, 'non-zero spell USDC balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' assert usdtDebt == borrow_usdt_amt assert usdcDebt == borrow_usdc_amt # check balance and pool reserves assert curABal - prevABal - borrow_usdt_amt == - \ (curARes - prevARes), 'not all USDT tokens go to LP pool' assert curBBal - prevBBal - borrow_usdc_amt == - \ (curBRes - prevBRes), 'not all USDC tokens go to LP pool' ##################################################################################### # add liquidity to the same position print( '=========================================================================' ) print('Case 2.') prevABal = usdt.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() usdt_amt = 20000 * 10**6 usdc_amt = 30000 * 10**6 lp_amt = 1 * 10**7 borrow_usdt_amt = 1000 * 10**6 borrow_usdc_amt = 200 * 10**6 tx = homora.execute( 1, uniswap_spell, uniswap_spell.addLiquidity.encode_input( usdt, # token 0 usdc, # token 1 [ usdt_amt, # supply USDT usdc_amt, # supply USDC lp_amt, # supply LP borrow_usdt_amt, # borrow USDT borrow_usdc_amt, # borrow USDC 0, # borrow LP 0, # min USDT 0 ], # min USDC ), {'from': alice}) position_id = tx.return_value print('position_id', position_id) curABal = usdt.balanceOf(alice) curBBal = usdc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) 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(uniswap_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) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank usdt debt', usdtDebt) print('bank usdt debt share', usdtDebtShare) print('bank usdc debt', usdcDebt) print('bank usdc debt share', usdcDebtShare) 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 usdt res', prevARes) print('cur usdt res', curARes) print('prev usdc res', prevBRes) print('cur usdc res', curBRes) # assert position_id assert position_id == 1 # position doesn't increase # alice assert almostEqual(curABal - prevABal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curBBal - prevBBal, -usdc_amt), 'incorrect USDC amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert usdc.balanceOf(uniswap_spell) == 0, 'non-zero spell USDC balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # borrow same amount twice (with small interest accrued) assert usdtDebt >= borrow_usdt_amt * 2 # borrow same amount twice (with small interest accrued) assert usdcDebt >= borrow_usdc_amt * 2 # check balance and pool reserves assert curABal - prevABal - borrow_usdt_amt == - \ (curARes - prevARes), 'not all USDT tokens go to LP pool' assert curBBal - prevBBal - borrow_usdc_amt == - \ (curBRes - prevBRes), 'not all USDC tokens go to LP pool' ##################################################################################### # remove half liquidity from the same position print( '=========================================================================' ) print('Case 3.') prevABal = usdt.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) _, _, _, collSize = homora.getPositionInfo(position_id) lp_take_amt = collSize // 2 lp_want = 1 * 10**5 usdt_repay = MAX_INT usdc_repay = MAX_INT tx = homora.execute( position_id, uniswap_spell, uniswap_spell.removeLiquidity.encode_input( usdt, # token 0 usdc, # token 1 [ lp_take_amt, # take out LP lp_want, # withdraw LP to wallet usdt_repay, # repay USDT usdc_repay, # repay USDC 0, # repay LP 0, # min USDT 0 ], # min USDC ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = usdc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) print('spell lp balance', lp.balanceOf(uniswap_spell)) print('spell usdt balance', usdt.balanceOf(uniswap_spell)) print('spell usdc balance', usdc.balanceOf(uniswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) 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) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank usdt totalDebt', usdtDebt) print('bank usdt totalShare', usdtDebtShare) print('bank usdc totalDebt', usdcDebt) print('bank usdc totalShare', usdcDebtShare) 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('coll size', collSize) # alice assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # werc20 assert almostEqual(curLPBal_werc20 - prevLPBal_werc20, -lp_take_amt), 'incorrect werc20 LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert usdc.balanceOf(uniswap_spell) == 0, 'non-zero spell USDC balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # debt assert usdtDebt == 0, 'usdtDebt should be 0' assert usdcDebt == 0, 'usdcDebt should be 0' ##################################################################################### # remove remaining liquidity from the same position print( '=========================================================================' ) print('Case 4.') prevABal = usdt.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) _, _, _, collSize = homora.getPositionInfo(position_id) lp_take_amt = MAX_INT lp_want = 1 * 10**5 usdt_repay = MAX_INT usdc_repay = MAX_INT tx = homora.execute( position_id, uniswap_spell, uniswap_spell.removeLiquidity.encode_input( usdt, # token 0 usdc, # token 1 [ lp_take_amt, # take out LP lp_want, # withdraw LP to wallet usdt_repay, # repay USDT usdc_repay, # repay USDC 0, # repay LP 0, # min USDT 0 ], # min USDC ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = usdc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) print('spell lp balance', lp.balanceOf(uniswap_spell)) print('spell usdt balance', usdt.balanceOf(uniswap_spell)) print('spell usdc balance', usdc.balanceOf(uniswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) 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) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank usdt totalDebt', usdtDebt) print('bank usdt totalShare', usdtDebtShare) print('bank usdc totalDebt', usdcDebt) print('bank usdc totalShare', usdcDebtShare) 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('coll size', collSize) # alice assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # werc20 assert almostEqual(curLPBal_werc20 - prevLPBal_werc20, -collSize), 'incorrect werc20 LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert usdc.balanceOf(uniswap_spell) == 0, 'non-zero spell USDC balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # debt assert usdtDebt == 0, 'usdtDebt should be 0' assert usdcDebt == 0, 'usdcDebt should be 0' ##################################################################################### # add liquidity without borrowing (1x) print( '=========================================================================' ) print('Case 5.') prevABal = usdt.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) usdt_amt = 2000 * 10**6 # 2000 USDT usdc_amt = 3000 * 10**6 # 3000 USDC lp_amt = 0 borrow_usdt_amt = 0 borrow_usdc_amt = 0 prevBBal = usdc.balanceOf(alice) tx = homora.execute( 1, uniswap_spell, uniswap_spell.addLiquidity.encode_input( usdt, # token 0 usdc, # token 1 [ usdt_amt, # supply USDT usdc_amt, # supply USDC lp_amt, # supply LP borrow_usdt_amt, # borrow USDT borrow_usdc_amt, # borrow USDC 0, # borrow LP 0, # min USDT 0 ], # min USDC ), {'from': alice}) position_id = tx.return_value print('position_id', position_id) curABal = usdt.balanceOf(alice) curBBal = usdc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) print('spell lp balance', lp.balanceOf(uniswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta lp balance', curLPBal - prevLPBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank usdt totalDebt', usdtDebt) print('bank usdt totalShare', usdtDebtShare) print('bank usdc totalDebt', usdcDebt) print('bank usdc totalShare', usdcDebtShare) 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) # alice assert almostEqual(curABal - prevABal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curBBal - prevBBal, -usdc_amt), 'incorrect USDC amt' assert almostEqual(curLPBal - prevLPBal, -lp_amt), 'incorrect LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert usdc.balanceOf(uniswap_spell) == 0, 'non-zero spell USDC balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # debt assert usdtDebt == borrow_usdt_amt assert usdcDebt == borrow_usdc_amt ##################################################################################### # remove all liquidity from the same position print( '=========================================================================' ) print('Case 6.') prevABal = usdt.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) _, _, _, collSize = homora.getPositionInfo(position_id) lp_take_amt = MAX_INT # max lp_want = 0 usdt_repay = 0 # max usdc_repay = 0 # max tx = homora.execute( position_id, uniswap_spell, uniswap_spell.removeLiquidity.encode_input( usdt, usdc, [ lp_take_amt, # take out LP lp_want, # withdraw LP to wallet usdt_repay, # repay USDT usdc_repay, # repay USDC 0, # repay LP 0, # min USDT 0 ], # min USDC ), {'from': alice}) curABal = usdt.balanceOf(alice) curBBal = usdc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) print('spell lp balance', lp.balanceOf(uniswap_spell)) print('spell usdt balance', usdt.balanceOf(uniswap_spell)) print('spell usdc balance', usdc.balanceOf(uniswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) 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) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank usdt totalDebt', usdtDebt) print('bank usdt totalShare', usdtDebtShare) print('bank usdc totalDebt', usdcDebt) print('bank usdc totalShare', usdcDebtShare) 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('coll size', collSize) # alice assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # werc20 assert almostEqual(curLPBal_werc20 - prevLPBal_werc20, -collSize), 'incorrect werc20 LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert usdc.balanceOf(uniswap_spell) == 0, 'non-zero spell USDC balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # debt assert usdtDebt == 0, 'usdtDebt should be 0' assert usdcDebt == 0, 'usdcDebt should be 0' return tx
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(): admin = accounts[0] alice = accounts[1] alpha = interface.IERC20Ex('0xa1faa113cbe53436df28ff0aee54275c13b40975') ibethv2 = SafeBoxETH.at('0xeEa3311250FE4c3268F8E684f7C87A82fF183Ec1') mint_tokens(alpha, alice) mint_tokens(alpha, admin) ibethv2.deposit({'from': alice, 'value': '100000 ether'}) ibethv2.deposit({'from': admin, 'value': '100000 ether'}) pair = interface.IUniswapV2Pair( '0xf79a07cd3488BBaFB86dF1bAd09a6168D935c017') # sushi router router = interface.IUniswapV2Router02( '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f') ibethv2_router = IbETHRouterV2.deploy(alpha, ibethv2, router, {'from': admin}) alpha.approve(ibethv2_router, 2**256 - 1, {'from': alice}) ibethv2.approve(ibethv2_router, 2**256 - 1, {'from': alice}) pair.approve(ibethv2_router, 2**256 - 1, {'from': alice}) ####################################################################### # setup liquidity first time init_alpha_amt = 1000 * 10**alpha.decimals() init_ibethv2_amt = 1 * 10**ibethv2.decimals() ibethv2.transfer(pair, init_ibethv2_amt, {'from': admin}) alpha.transfer(pair, init_alpha_amt, {'from': admin}) pair.mint(admin, {'from': admin}) prevIbethv2Bal = ibethv2.balanceOf(admin) ibethv2.deposit({'from': admin, 'value': '1 ether'}) curIbethv2Bal = ibethv2.balanceOf(admin) ibethv2_eth_rate = 10**18 / (curIbethv2Bal - prevIbethv2Bal) print('conversion rate', ibethv2_eth_rate) print('init ibethv2 amt', init_ibethv2_amt * ibethv2_eth_rate) print('deposited', 10**18, 'ether') print('received', curIbethv2Bal - prevIbethv2Bal, 'ibethv2') ######################################################################## # check state vars print('=======================================') print('Case. check state vars') assert ibethv2_router.alpha() == alpha assert ibethv2_router.ibETHv2() == ibethv2 assert ibethv2_router.lpToken() == pair assert ibethv2_router.router() == router ####################################################################### # test swap exact ETH to ALPHA print('===========================================') print('Case. test swap exact eth to alpha') eth_amt = 10**12 prevETHBal = alice.balance() prevAlphaBal = alpha.balanceOf(alice) ibethv2_router.swapExactETHToAlpha(0, alice, 2**256 - 1, { 'from': alice, 'value': eth_amt, 'gas_price': 0 }) curETHBal = alice.balance() curAlphaBal = alpha.balanceOf(alice) print('∆ alpha', curAlphaBal - prevAlphaBal) print( 'calc alpha', eth_amt * (init_alpha_amt / init_ibethv2_amt) / ibethv2_eth_rate * 0.997) assert curETHBal - prevETHBal == -eth_amt, 'incorrect ETH amount' assert almostEqual( curAlphaBal - prevAlphaBal, eth_amt * (init_alpha_amt / init_ibethv2_amt) / ibethv2_eth_rate * 0.997), 'incorrect alpha amount' ####################################################################### # test swap exact ALPHA to ETH print('=========================================') print('Case. swap exact alpha to eth') alpha_amt = 10**18 prevETHBal = alice.balance() prevAlphaBal = alpha.balanceOf(alice) ibethv2_router.swapExactAlphaToETH(alpha_amt, 0, alice, 2**256 - 1, { 'from': alice, 'gas_price': 0 }) curETHBal = alice.balance() curAlphaBal = alpha.balanceOf(alice) print('∆ eth', curETHBal - prevETHBal) print( 'calc eth', alpha_amt / (init_alpha_amt / init_ibethv2_amt) * ibethv2_eth_rate * 0.997) assert almostEqual( curETHBal - prevETHBal, alpha_amt / (init_alpha_amt / init_ibethv2_amt) * ibethv2_eth_rate * 0.997), 'incorrect ETH amount' assert almostEqual(curAlphaBal - prevAlphaBal, -alpha_amt), 'incorrect alpha amount' ####################################################################### # test add liquidity eth alpha optimal print('=========================================') print('Case. test add liquidity eth alpha optimal') alpha_amt = 100000 * 10**18 eth_amt = 1000 * 10**18 prevETHBal = alice.balance() prevAlphaBal = alpha.balanceOf(alice) prevLPBal = pair.balanceOf(alice) prevLPSupply = pair.totalSupply() r0, r1, _ = pair.getReserves() ibethv2_router.addLiquidityETHAlphaOptimal(alpha_amt, 0, alice, 2**256 - 1, { 'from': alice, 'value': eth_amt, 'gas_price': 0 }) curETHBal = alice.balance() curAlphaBal = alpha.balanceOf(alice) curLPBal = pair.balanceOf(alice) new_r0, new_r1, _ = pair.getReserves() expected_lp = (sqrt((new_r0 * new_r1) / (r0 * r1)) - 1) * prevLPSupply print('prev total lp supply', prevLPSupply) print('prev reserves', r0, r1) print('cur reserves', new_r0, new_r1) print('∆ lp', curLPBal - prevLPBal) print('calc lp', expected_lp) assert almostEqual(new_r0, r0 + alpha_amt), 'incorrect r0 new amt' assert almostEqual(new_r1, r1 + eth_amt / ibethv2_eth_rate), 'incorrect r1 new amt' assert curETHBal - prevETHBal == -eth_amt, 'incorrect ETH add' assert curAlphaBal - prevAlphaBal == -alpha_amt, 'incorrect Alpha add' assert almostEqual(curLPBal - prevLPBal, expected_lp), 'incorrect LP received' # ########################################################################### # # test add liquidity ibethv2 alpha optimal print('=========================================') print('Case. test add liquidity ibethv2 alpha optimal') alpha_amt = 1000000 * 10**18 ibethv2_amt = 1000 * 10**5 prevETHBal = alice.balance() prevIbethv2Bal = ibethv2.balanceOf(alice) prevAlphaBal = alpha.balanceOf(alice) prevLPBal = pair.balanceOf(alice) prevLPSupply = pair.totalSupply() r0, r1, _ = pair.getReserves() ibethv2_router.addLiquidityIbETHv2AlphaOptimal(ibethv2_amt, alpha_amt, 0, alice, 2**256 - 1, { 'from': alice, 'gas_price': 0 }) curETHBal = alice.balance() curAlphaBal = alpha.balanceOf(alice) curIbethv2Bal = ibethv2.balanceOf(alice) curLPBal = pair.balanceOf(alice) new_r0, new_r1, _ = pair.getReserves() expected_lp = (sqrt((new_r0 * new_r1) / (r0 * r1)) - 1) * prevLPSupply print('prev total lp supply', prevLPSupply) print('prev reserves', r0, r1) print('cur reserves', new_r0, new_r1) print('∆ lp', curLPBal - prevLPBal) print('calc lp', expected_lp) assert almostEqual(new_r0, r0 + alpha_amt), 'incorrect r0 new amt' assert almostEqual(new_r1, r1 + ibethv2_amt), 'incorrect r1 new amt' assert curIbethv2Bal - prevIbethv2Bal == -ibethv2_amt, 'incorrect ibethv2 add' assert curAlphaBal - prevAlphaBal == -alpha_amt, 'incorrect Alpha add' assert almostEqual(curLPBal - prevLPBal, expected_lp), 'incorrect LP received' ############################################################################### # test remove liquidity eth alpha print('===========================================') print('Case. test remove liquidity eth alpha') lp_amt = pair.balanceOf(alice) // 3 prevETHBal = alice.balance() prevIbethv2Bal = ibethv2.balanceOf(alice) prevAlphaBal = alpha.balanceOf(alice) prevLPBal = pair.balanceOf(alice) prevLPSupply = pair.totalSupply() r0, r1, _ = pair.getReserves() # token0 = alpha ibethv2_router.removeLiquidityETHAlpha(lp_amt, 0, 0, alice, 2**256 - 1, {'from': alice}) curETHBal = alice.balance() curAlphaBal = alpha.balanceOf(alice) curIbethv2Bal = ibethv2.balanceOf(alice) curLPBal = pair.balanceOf(alice) print('∆ alpha', curAlphaBal - prevAlphaBal) print('∆ ibethv2', curIbethv2Bal - prevIbethv2Bal) assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP withdraw' assert almostEqual(curAlphaBal - prevAlphaBal, lp_amt / prevLPSupply * r0), 'incorrect alpha withdraw amount' assert almostEqual(curETHBal - prevETHBal, lp_amt / prevLPSupply * r1 * ibethv2_eth_rate), 'incorrect eth withraw amount' ################################################################################## # test remove liquidity alpha only print('===============================================') print('Case. test remove liquidity alpha only') lp_amt = pair.balanceOf(alice) // 10**3 prevETHBal = alice.balance() prevIbethv2Bal = ibethv2.balanceOf(alice) prevAlphaBal = alpha.balanceOf(alice) prevLPBal = pair.balanceOf(alice) prevLPSupply = pair.totalSupply() r0, r1, _ = pair.getReserves() # token0 = alpha ibethv2_router.removeLiquidityAlphaOnly(lp_amt, 0, alice, 2**256 - 1, {'from': alice}) curETHBal = alice.balance() curAlphaBal = alpha.balanceOf(alice) curIbethv2Bal = ibethv2.balanceOf(alice) curLPBal = pair.balanceOf(alice) assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP withdraw' assert almostEqual(curAlphaBal - prevAlphaBal, lp_amt / prevLPSupply * r0 * 2), 'incorrect alpha withdraw amount'
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(), })
def main(): admin = accounts[0] alice = accounts[1] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx( [usdt, weth], [9011535487953795006625883219171279625142296, 2**112]) uniswap_oracle = UniswapV2Oracle.deploy(simple_oracle, {'from': admin}) oracle = ProxyOracle.deploy({'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) oracle.setOracles( [ '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', # WETH '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852', # USDT-WETH ], [ [simple_oracle, 10000, 10000, 10000], [simple_oracle, 10000, 10000, 10000], [uniswap_oracle, 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 10^5 USDT + 10^4 WETH to alice setup_transfer( usdt, accounts.at('0xbe0eb53f46cd790cd13851d5eff43d12404d33e8', force=True), alice, 10**5 * 10**6) setup_transfer( weth, accounts.at('0x397ff1542f962076d0bfe58ea045ffa2d347aca0', force=True), alice, 10**4 * 10**18) # setup initial funds 10^6 USDT + 10^5 WETH to homora bank setup_transfer( usdt, accounts.at('0xbe0eb53f46cd790cd13851d5eff43d12404d33e8', force=True), homora, 10**6 * 10**6) setup_transfer( weth, accounts.at('0x397ff1542f962076d0bfe58ea045ffa2d347aca0', force=True), homora, 10**4 * 10**18) # 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 lp.transfer( alice, 1 * 10**17, { 'from': accounts.at('0x767ecb395def19ab8d1b2fcc89b3ddfbed28fd6b', force=True) }) lp.transfer( homora, 2 * 10**17, { 'from': accounts.at('0x767ecb395def19ab8d1b2fcc89b3ddfbed28fd6b', force=True) }) # 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}) uniswap_spell = UniswapV2SpellV1.deploy(homora, werc20, router, {'from': admin}) # first time call to reduce gas uniswap_spell.getPair(weth, usdt, {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) if interface.IUniswapV2Pair(lp).token0() == usdt: prevARes, prevBRes, _ = interface.IUniswapV2Pair(lp).getReserves() else: prevBRes, prevARes, _ = interface.IUniswapV2Pair(lp).getReserves() usdt_amt = 400 * 10**6 weth_amt = 10**18 eth_amt = 10**18 lp_amt = 1 * 10**16 borrow_usdt_amt = 1000 * 10**6 borrow_weth_amt = 0 tx = homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidity.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 ), { 'from': alice, 'value': eth_amt }) position_id = tx.return_value print('position_id', position_id) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) 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(uniswap_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('werc20 prev LP balance', prevLPBal_werc20) print('werc20 cur LP balance', curLPBal_werc20) # alice assert almostEqual(curABal - prevABal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert almostEqual(curETHBal - prevETHBal, -eth_amt), 'incorrect ETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert uniswap_spell.balance() == 0, 'non-zero spell ETH balance' assert lp.balanceOf(uniswap_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 curBBal - prevBBal - borrow_weth_amt - eth_amt == - \ (curBRes - prevBRes), 'not all WETH tokens go to LP pool' ##################################################################################### print( '=========================================================================' ) print('Case 2.') # remove liquidity from the same position prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) 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 = 1 * 10**16 lp_want = 1 * 10**15 usdt_repay = 2**256 - 1 # max weth_repay = 0 real_usdt_repay = homora.borrowBalanceStored(position_id, usdt) tx = homora.execute( position_id, uniswap_spell, uniswap_spell.removeLiquidity.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 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_werc20 = lp.balanceOf(werc20) 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(uniswap_spell)) print('spell usdt balance', usdt.balanceOf(uniswap_spell)) print('spell weth balance', weth.balanceOf(uniswap_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) 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) _, _, _, totalDebt, totalShare = homora.getBankInfo(usdt) print('bank usdt totalDebt', totalDebt) print('bank usdt totalShare', totalShare) 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) # 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, -lp_take_amt), 'incorrect werc20 LP amt' # spell assert usdt.balanceOf(uniswap_spell) == 0, 'non-zero spell USDT balance' assert weth.balanceOf(uniswap_spell) == 0, 'non-zero spell WETH balance' assert uniswap_spell.balance() == 0, 'non-zero spell ETH balance' assert lp.balanceOf(uniswap_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual( curABal - prevABal + real_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' return tx