def main(): deployer = accounts.at('0xB593d82d53e2c187dc49673709a6E9f806cdC835', force=True) # deployer = accounts.load('gh') # deploy safeboxes safebox_eth = SafeBoxETH.deploy( '0x41c84c0e2EE0b740Cf0d31F63f3B6F627DC6b393', 'Interest Bearing Ether v2', 'ibETHv2', {'from': deployer}) safebox_dai = SafeBox.deploy('0x8e595470Ed749b85C6F7669de83EAe304C2ec68F', 'Interest Bearing Dai Stablecoin v2', 'ibDAIv2', {'from': deployer}) safebox_usdt = SafeBox.deploy('0x48759F220ED983dB51fA7A8C0D2AAb8f3ce4166a', 'Interest Bearing Tether USD v2', 'ibUSDTv2', {'from': deployer}) safebox_usdc = SafeBox.deploy('0x76Eb2FE28b36B3ee97F3Adae0C69606eeDB2A37c', 'Interest Bearing USD Coin v2', 'ibUSDCv2', {'from': deployer}) safebox_yfi = SafeBox.deploy('0xFa3472f7319477c9bFEcdD66E4B948569E7621b9', 'Interest Bearing yearn.finance v2', 'ibYFIv2', {'from': deployer}) # add banks usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') usdc = interface.IERC20Ex('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48') yfi = interface.IERC20Ex('0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e') cyusdt = '0x48759F220ED983dB51fA7A8C0D2AAb8f3ce4166a' cyusdc = '0x76Eb2FE28b36B3ee97F3Adae0C69606eeDB2A37c' cyyfi = '0xFa3472f7319477c9bFEcdD66E4B948569E7621b9' bank = HomoraBank.at('0x5f5Cd91070960D13ee549C9CC47e7a4Cd00457bb') bank.addBank(usdt, cyusdt, {'from': deployer}) bank.addBank(usdc, cyusdc, {'from': deployer})
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dfd = interface.IERC20Ex('0x20c36f062a31865bED8a5B1e512D9a1A20AA333A') dusd = interface.IERC20Ex('0x5BC25f649fc4e26069dDF4cF4010F9f706c23831')
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}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx( [weth, dai], [5192296858534827628530496329220096, 8887571220661441971398610676149]) balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': admin}) oracle = ProxyOracle.deploy({'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) oracle.setOracles( [ '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', # WETH '0x6B175474E89094C44Da98b954EedeAC495271d0F', # DAI '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490', # lp ], [ [simple_oracle, 10000, 10000, 10000], [simple_oracle, 10000, 10000, 10000], [balancer_oracle, 10000, 10000, 10000], ], {'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 test_bank(token, bank): alice = accounts[1] uniswap_spell = UniswapV2SpellV1.at( '0xc671B7251a789de0835a2fa33c83c8D4afB39092') mint_tokens(token, alice) token.approve(bank, 2**256 - 1, {'from': alice}) weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') amt = 100 * 10**(token.decimals() - 4) borrow_amt = 1 * 10**(token.decimals() - 4) prevTokenAlice = token.balanceOf(alice) bank.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWERC20.encode_input( token, weth, [amt, 0, 0, borrow_amt, 10**10, 0, 0, 0]), {'from': alice}) curTokenAlice = token.balanceOf(alice) assert almostEqual(curTokenAlice - prevTokenAlice, -amt), 'incorrect input amt'
def main(): deployer = accounts.at('0xB593d82d53e2c187dc49673709a6E9f806cdC835', force=True) # deployer = accounts.load('gh') werc20 = WERC20.at('0xe28D9dF7718b0b5Ba69E01073fE82254a9eD2F98') wmas = WMasterChef.at('0x373ae78a14577682591E088F2E78EF1417612c68') wliq = WLiquidityGauge.at('0xfdB4f97953150e47C8606758C13e70b5a789a7ec') wsindex = WStakingRewards.at('0x713df2DDDA9C7d7bDa98A9f8fCd82c06c50fbd90') wsperp = WStakingRewards.at('0xC4635854480ffF80F742645da0310e9e59795c63') uni_kp3r_oracle = ERC20KP3ROracle.at( '0x8E2A3777AB22e1c5f6d1fF2BcC6C4aA6aB1DeA14') sushi_kp3r_oracle = ERC20KP3ROracle.at( '0xC331687FD71bb1D7f2e237091F8888dDcaD50C9a') core_oracle = CoreOracle.at('0x1E5BDdd0cDF8839d6b27b34927869eF0AD7bf692') uni_oracle = UniswapV2Oracle.at( '0x910aD02D355c2966e8dD8E32C890cD50DB29C3B9') bal_oracle = BalancerPairOracle.at( '0x8F93B0AA2643bf74ab38d6a5910fA82D2da02134') crv_oracle = CurveOracle.at('0x04DE0E42B3b0483248deafE86C4F5428613b76Ff') proxy_oracle = ProxyOracle.at('0x43c425fB2b00a991A51b18c217D749E393bF1AB2') # pair token with oracle from .tokens import Tokens # re-set oracles oracle_params = [ # lp tokens [Tokens.bal_perp_usdc, [14886, 6718, 10250]], ] token_list_2, param_list = zip(*oracle_params) proxy_oracle.setOracles(token_list_2, param_list, {'from': deployer}) proxy_oracle.unsetOracles([Tokens.bal_dai_weth], {'from': deployer}) print('DONE') ########################################################### # test spells (UNCOMMENT TO TEST) for token in [ Tokens.weth, Tokens.dai, Tokens.usdc, Tokens.usdt, Tokens.dpi, Tokens.yfi, Tokens.snx, Tokens.susd ]: token = interface.IERC20Ex(token) deposit_safebox(token) bank = HomoraBank.at('0x5f5Cd91070960D13ee549C9CC47e7a4Cd00457bb') uniswap_spell = UniswapV2SpellV1.at( '0xc671B7251a789de0835a2fa33c83c8D4afB39092') sushiswap_spell = SushiswapSpellV1.at( '0x21Fa95485f4571A3a0d0c396561cF4D8D13D445d') balancer_spell = BalancerSpellV1.at( '0x15B79c184A6a8E19a4CA1F637081270343E4D15D') curve_spell = CurveSpellV1.at('0x42C750024E02816eE32EB2eB4DA79ff5BF343D30')
def main(): deployer = accounts.at('0xB593d82d53e2c187dc49673709a6E9f806cdC835', force=True) # deployer = accounts.load('gh') yfi = interface.IERC20Ex('0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e') cyyfi = '0xFa3472f7319477c9bFEcdD66E4B948569E7621b9' bank = HomoraBank.at('0x5f5Cd91070960D13ee549C9CC47e7a4Cd00457bb') bank.addBank(yfi, cyyfi, {'from': deployer})
def main(): deployer = accounts.at('0xB593d82d53e2c187dc49673709a6E9f806cdC835', force=True) # deployer = accounts.load('gh') snx = interface.IERC20Ex('0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F') susd = interface.IERC20Ex('0x57Ab1ec28D129707052df4dF418D58a2D46d5f51') cysnx = interface.IERC20Ex('0x12A9cC33A980DAa74E00cc2d1A0E74C57A93d12C') cysusd = interface.IERC20Ex('0x4e3a36A633f63aee0aB57b5054EC78867CB3C0b8') # add safeboxes safebox_snx = SafeBox.deploy( cysnx, 'Interest Bearing Synthetix Network Token v2', 'ibSNXv2', {'from': deployer}) safebox_susd = SafeBox.deploy(cysusd, 'Interest Bearing Synth sUSD v2', 'ibsUSDv2', {'from': deployer}) # add banks bank = HomoraBank.at('0x5f5Cd91070960D13ee549C9CC47e7a4Cd00457bb') bank.addBank(snx, cysnx, {'from': deployer}) bank.addBank(susd, cysusd, {'from': deployer})
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] 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') simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dai, usdt, usdc, weth], [ 9060553589188986552095106856227, 9002288773315920458132820329673073223442669, 9011535487953795006625883219171279625142296, 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] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') lp = interface.IERC20Ex('0x3041cbd36888becc7bbcbc0045e3b1f144466f5f') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') crusdc = interface.ICErc20('0x44fbebd2f576670a6c33f6fc0b00aa8c5753b322') 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, usdc], [ 8343331721347310729683379470025550036595362, 8344470555541464992529317899641128796042472 ]) 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, usdc, lp], [simple_oracle, simple_oracle, uniswap_oracle], {'from': admin}, ) oracle.setOracles( [usdt, usdc, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [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 to alice mint_tokens(usdt, alice) mint_tokens(usdc, alice) # 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 mint_tokens(lp, alice) # 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}) ##################################################################################### 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) usdt_amt = 40000 * 10**6 # 40000 USDT usdc_amt = 50000 * 10**6 # 50000 USDC lp_amt = 1 * 10**7 borrow_usdt_amt = 1000 * 10**6 # 1000 USDT borrow_usdc_amt = 200 * 10**6 # 200 USDC tx = homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWERC20.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 tokens 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('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 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 ##################################################################################### print( '=========================================================================' ) print('Case 2.') # remove liquidity from the same position 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(1) lp_take_amt = 2**256 - 1 # max lp_want = 1 * 10**5 usdt_repay = 2**256 - 1 # max usdc_repay = 2**256 - 1 # max tx = homora.execute( 1, uniswap_spell, uniswap_spell.removeLiquidityWERC20.encode_input( usdt, # token 0 usdc, # token 1 [ lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens 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] 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] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') lp = interface.IERC20Ex('0x6c3f90f043a72fa612cbac8115ee7e52bde6e490') pool = interface.ICurvePool('0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7') registry = interface.ICurveRegistry( '0x7d86446ddb609ed0f5f8684acf30380a356b2b4c') crdai = interface.ICErc20('0x92B767185fB3B04F881e3aC8e5B0662a027A1D9f') crusdc = interface.ICErc20('0x44fbebd2f576670a6c33f6fc0b00aa8c5753b322') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dai, usdt, usdc], [ 9060553589188986552095106856227, 9002288773315920458132820329673073223442669, 9011535487953795006625883219171279625142296 ]) curve_oracle = CurveOracle.deploy(simple_oracle, registry, {'from': admin}) curve_oracle.registerPool(lp) # update pool info oracle = ProxyOracle.deploy({'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) oracle.setOracles( [ '0x6B175474E89094C44Da98b954EedeAC495271d0F', # DAI '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48', # USDC '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '0x6c3f90f043a72fa612cbac8115ee7e52bde6e490', # lp ], [ [simple_oracle, 10000, 10000, 10000], [simple_oracle, 10000, 10000, 10000], [simple_oracle, 10000, 10000, 10000], [curve_oracle, 10000, 10000, 10000], ], {'from': admin}, ) ##################################################################################### print( '=========================================================================' ) print('Case 1.') print('pool virtual price', pool.get_virtual_price()) lp_price = curve_oracle.getETHPx(lp) dai_price = simple_oracle.getETHPx(dai) usdt_price = simple_oracle.getETHPx(usdt) usdc_price = simple_oracle.getETHPx(usdc) print('lp price', lp_price) print('dai price', dai_price) print('usdt price', usdt_price) print('usdc price', usdc_price) # min price is from USDT assert almostEqual( 9002288773315920458132820329673073223442669 * pool.get_virtual_price() * 10**6 // 10**18 // 10**18, lp_price)
def main(): admin = accounts[0] alice = accounts[1] perp = interface.IERC20Ex('0xbC396689893D065F41bc2C6EcbeE5e0085233447') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') bpt = interface.IERC20Ex( '0xf54025af2dc86809be1153c1f20d77adb7e8ecf4') # perp-usdc staking = accounts.at( '0xb9840a4a8a671f79de3df3b812feeb38047ce552', force=True) wstaking = WStakingRewards.deploy(staking, bpt, perp, {'from': admin}) perp.approve(staking, 2**256-1, {'from': alice}) usdc.approve(staking, 2**256-1, {'from': alice}) bpt.approve(staking, 2**256-1, {'from': alice}) perp.approve(wstaking, 2**256-1, {'from': alice}) usdc.approve(wstaking, 2**256-1, {'from': alice}) bpt.approve(wstaking, 2**256-1, {'from': alice}) # setup initial funds 10^6 USDT + 10^6 USDC + 10^6 WETH to alice setup_transfer(perp, accounts.at('0xc49f76a596d6200e4f08f8931d15b69dd1f8033e', force=True), alice, 10**18) setup_transfer(usdc, accounts.at('0xa191e578a6736167326d05c119ce0c90849e84b7', force=True), alice, 10**6 * 10**6) setup_transfer(bpt, accounts.at('0x5e4b407eb1253527628bab875525aaec0099ffc5', force=True), alice, 10**2 * 10**18) ###################################################################### # check getUnderlying print('===========================================================') print('Case 1.') underlying = wstaking.getUnderlying(0) assert underlying == bpt ###################################################################### # check mint & burn print('===========================================================') print('Case 2.') amt = 10**2 * 10**18 prevBPTBalance = bpt.balanceOf(alice) tx = wstaking.mint(amt, {'from': alice}) curBPTBalance = bpt.balanceOf(alice) stRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() token_id = tx.return_value print('alice bpt balance', curBPTBalance) assert curBPTBalance - prevBPTBalance == -amt chain.sleep(5000) prevPerpBalance = perp.balanceOf(alice) prevBPTBalance = bpt.balanceOf(alice) tx = wstaking.burn(token_id, amt, {'from': alice}) curBPTBalance = bpt.balanceOf(alice) curPerpBalance = perp.balanceOf(alice) enRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() print('alice bpt balance', curBPTBalance) print('alice perp balance', curPerpBalance) assert curBPTBalance - prevBPTBalance == amt print('perp gained', curPerpBalance - prevPerpBalance) print('perp calculated reward', (enRewardPerToken - stRewardPerToken) * amt // (10**18)) assert almostEqual(curPerpBalance - prevPerpBalance, (enRewardPerToken - stRewardPerToken) * amt // (10**18)) # check perp gained with directly staking (using large chain sleep time) prevReward = perp.balanceOf(alice) tx = interface.IStakingRewards(staking).stake(amt, {'from': alice}) chain.sleep(5000) tx = interface.IStakingRewards(staking).withdraw(amt, {'from': alice}) tx = interface.IStakingRewards(staking).getReward({'from': alice}) curReward = perp.balanceOf(alice) print('perp gained from directly staking', curReward - prevReward) assert almostEqual(curPerpBalance - prevPerpBalance, curReward - prevReward) ###################################################################### # check mint & burn max_int print('===========================================================') print('Case 3.') amt = 10**2 * 10**18 prevBPTBalance = bpt.balanceOf(alice) tx = wstaking.mint(amt, {'from': alice}) curBPTBalance = bpt.balanceOf(alice) stRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() token_id = tx.return_value print('alice bpt balance', curBPTBalance) assert curBPTBalance - prevBPTBalance == -amt chain.sleep(5000) prevPerpBalance = perp.balanceOf(alice) prevBPTBalance = bpt.balanceOf(alice) tx = wstaking.burn(token_id, 2**256-1, {'from': alice}) curBPTBalance = bpt.balanceOf(alice) curPerpBalance = perp.balanceOf(alice) enRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() print('alice bpt balance', curBPTBalance) print('alice perp balance', curPerpBalance) assert curBPTBalance - prevBPTBalance == amt print('perp gained', curPerpBalance - prevPerpBalance) print('perp calculated reward', (enRewardPerToken - stRewardPerToken) * amt // (10**18)) assert almostEqual(curPerpBalance - prevPerpBalance, (enRewardPerToken - stRewardPerToken) * amt // (10**18)) # check perp gained with directly staking (using large chain sleep time) prevReward = perp.balanceOf(alice) tx = interface.IStakingRewards(staking).stake(amt, {'from': alice}) chain.sleep(5000) tx = interface.IStakingRewards(staking).withdraw(amt, {'from': alice}) tx = interface.IStakingRewards(staking).getReward({'from': alice}) curReward = perp.balanceOf(alice) print('perp gained from directly staking', curReward - prevReward) assert almostEqual(curPerpBalance - prevPerpBalance, curReward - prevReward) ###################################################################### # check mint & burn (try more than available--revert, half, then remaining) print('===========================================================') print('Case 4.') amt = 10**2 * 10**18 prevBPTBalance = bpt.balanceOf(alice) tx = wstaking.mint(amt, {'from': alice}) curBPTBalance = bpt.balanceOf(alice) stRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() token_id = tx.return_value print('alice bpt balance', curBPTBalance) assert curBPTBalance - prevBPTBalance == -amt try: tx = wstaking.burn(token_id, amt + 1, {'from': alice}) assert tx.status == 0 except: pass chain.sleep(5000) prevPerpBalance = perp.balanceOf(alice) prevBPTBalance = bpt.balanceOf(alice) tx = wstaking.burn(token_id, amt // 2, {'from': alice}) interRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() chain.sleep(5000) tx = wstaking.burn(token_id, 2**256-1, {'from': alice}) curBPTBalance = bpt.balanceOf(alice) curPerpBalance = perp.balanceOf(alice) enRewardPerToken = interface.IStakingRewards(staking).rewardPerToken() print('perp gained', curPerpBalance - prevPerpBalance) print('perp calc reward', (interRewardPerToken - stRewardPerToken) * (amt // 2) // (10**18) + (enRewardPerToken - stRewardPerToken) * (amt - amt//2) // (10**18)) assert almostEqual(curPerpBalance - prevPerpBalance, (interRewardPerToken - stRewardPerToken) * (amt // 2) // (10**18) + (enRewardPerToken - stRewardPerToken) * (amt - amt//2) // (10**18)) # check perp gained with directly staking (using large chain sleep time) prevReward = perp.balanceOf(alice) tx = interface.IStakingRewards(staking).stake(amt, {'from': alice}) chain.sleep(5000) tx = interface.IStakingRewards(staking).withdraw(amt//2, {'from': alice}) chain.sleep(5000) tx = interface.IStakingRewards(staking).withdraw( amt-amt//2, {'from': alice}) tx = interface.IStakingRewards(staking).getReward({'from': alice}) curReward = perp.balanceOf(alice) print('perp gained from wstaking', curPerpBalance - prevPerpBalance) print('perp gained from directly staking', curReward - prevReward) assert almostEqual(curPerpBalance - prevPerpBalance, curReward - prevReward)
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] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') lpusdt = interface.IERC20Ex('0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') erc20_oracle = ERC20KP3ROracle.deploy(KP3R_ADDRESS, {'from': admin}) lp_oracle = UniswapV2LPKP3ROracle.deploy(KP3R_ADDRESS, {'from': admin}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) core_oracle.setRoute( [ '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852', # USDT-ETH ], [erc20_oracle, lp_oracle], {'from': admin}, ) oracle.setOracles( [ '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852', # USDT-ETH ], [ [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}) # lpusdt.approve(homora, 2**256-1, {'from': alice}) # Steal some LP from the staking pool lpusdt.transfer( alice, 1 * 10**17, { 'from': accounts.at('0x6C3e4cb2E96B01F4b866965A91ed4437839A121a', force=True) }) household_spell = HouseHoldSpell.deploy(homora, WETH_ADDRESS, {'from': admin}) tx = homora.execute( 0, # position id household_spell, household_spell.putCollateral.encode_input( '0x0d4a11d5EEaaC28EC3F61d100daF4d40471f1852', # USDT '0.00001 ether', # valued at approximately $600 ), {'from': alice}, ) print('put collateral gas', tx.gas_used) position_id = tx.return_value print(homora.getCollateralETHValue(position_id), homora.getBorrowETHValue(position_id)) tx = homora.execute( position_id, # position id household_spell, household_spell.borrow.encode_input( '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '500000000', # $500 ), {'from': alice}, ) print('bal', usdt.balanceOf(alice)) print('put collateral gas', tx.gas_used) _, _, _, totalDebt, totalShare = homora.getBankInfo(usdt) print('bank usdt totalDebt', totalDebt) print('bank usdt totalShare', totalShare) usdt.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(crusdt, 2**256 - 1, {'from': accounts.at(homora, force=True)}) tx = homora.execute( position_id, # position id household_spell, household_spell.repay.encode_input( '0xdAC17F958D2ee523a2206206994597C13D831ec7', # USDT '300000000', # $300 ), {'from': alice}, ) print('bal', usdt.balanceOf(alice)) print('repay gas', tx.gas_used)
def main(): admin = accounts[0] alice = accounts[1] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') # pool is lp for balancer pool = interface.IBalancerPool('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') crdai = interface.ICErc20('0x92b767185fb3b04f881e3ac8e5b0662a027a1d9f') werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([weth, dai], [5192296858534827628530496329220096, 8887571220661441971398610676149]) balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': alice}) core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20], True, {'from': admin}) core_oracle.setRoute( [weth, dai, lp], [simple_oracle, simple_oracle, balancer_oracle], {'from': admin}, ) oracle.setOracles( [weth, dai, lp], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) homora = HomoraBank.deploy({'from': admin}) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) homora.addBank(dai, crdai, {'from': admin}) # setup initial funds to alice mint_tokens(dai, alice) mint_tokens(weth, alice) # check alice's funds print(f'Alice weth balance {weth.balanceOf(alice)}') print(f'Alice dai balance {dai.balanceOf(alice)}') # Steal some LP from the staking pool mint_tokens(lp, alice) # set approval dai.approve(homora, 2**256-1, {'from': alice}) dai.approve(crdai, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) lp.approve(homora, 2**256-1, {'from': alice}) balancer_spell = BalancerSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', {'from': admin}) # first time call to reduce gas balancer_spell.getPair(lp, {'from': admin}) ##################################################################################### print('=========================================================================') print('Case 1.') prevABal = dai.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) prevARes = interface.IBalancerPool(lp).getBalance(dai) prevBRes = interface.IBalancerPool(lp).getBalance(weth) dai_amt = 40000 * 10**18 weth_amt = 10 ** 18 lp_amt = 1 * 10**16 borrow_dai_amt = 0 borrow_weth_amt = 0 # calculate slippage control total_dai_amt = dai_amt + borrow_dai_amt total_weth_amt = weth_amt + borrow_weth_amt dai_weight = 0.2 weth_weight = 0.8 ratio = (((prevARes + total_dai_amt) / prevARes) ** dai_weight) * \ (((prevBRes + total_weth_amt) / prevBRes) ** weth_weight) - 1 lp_desired = lp_amt + int(interface.IERC20(lp).totalSupply() * ratio * 0.995) print('lp desired', lp_desired) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWERC20.encode_input( lp, # lp token [dai_amt, # supply DAI weth_amt, # supply WETH lp_amt, # supply LP borrow_dai_amt, # borrow DAI borrow_weth_amt, # borrow WETH 0, # borrow LP tokens lp_desired] # LP desired ), {'from': alice} ) curABal = dai.balanceOf(alice) curBBal = weth.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) curARes = interface.IBalancerPool(lp).getBalance(dai) curBRes = interface.IBalancerPool(lp).getBalance(weth) print('spell lp balance', lp.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, daiDebt, daiShare = homora.getBankInfo(dai) print('bank dai daiDebt', daiDebt) print('bank dai daiShare', daiShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('werc20 prev LP balance', prevLPBal_werc20) print('werc20 cur LP balance', curLPBal_werc20) print('prev dai res', prevARes) print('cur dai res', curARes) print('prev weth res', prevBRes) print('cur weth res', curBRes) # alice assert almostEqual(curABal - prevABal, -dai_amt), 'incorrect DAI amt' assert almostEqual(curBBal - prevBBal, -weth_amt), 'incorrect WETH amt' assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt' # spell assert dai.balanceOf(balancer_spell) == 0, 'non-zero spell DAI balance' assert weth.balanceOf(balancer_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' assert daiDebt == borrow_dai_amt # check balance and pool reserves assert almostEqual(curABal - prevABal - borrow_dai_amt, - (curARes - prevARes)), 'not all DAI tokens go to LP pool' assert almostEqual(curBBal - prevBBal - borrow_weth_amt, - (curBRes - prevBRes)), 'not all WETH tokens go to LP pool' ##################################################################################### print('=========================================================================') print('Case 2.') # remove liquidity from the same position prevABal = dai.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_werc20 = lp.balanceOf(werc20) prevETHBal = alice.balance() prevARes = interface.IBalancerPool(lp).getBalance(dai) prevBRes = interface.IBalancerPool(lp).getBalance(weth) lp_take_amt = 2**256-1 # max lp_want = 1 * 10**15 dai_repay = 2**256-1 # max weth_repay = 0 real_dai_repay = homora.borrowBalanceStored(1, dai) _, _, _, real_lp_take_amt = homora.getPositionInfo(1) tx = homora.execute( 1, balancer_spell, balancer_spell.removeLiquidityWERC20.encode_input( lp, # LP token [lp_take_amt, # take out LP tokens lp_want, # withdraw LP tokens to wallet dai_repay, # repay DAI weth_repay, # repay WETH 0, # repay LP 0, # min DAI 0], # min WETH ), {'from': alice} ) # return tx curABal = dai.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_werc20 = lp.balanceOf(werc20) curETHBal = alice.balance() curARes = interface.IBalancerPool(lp).getBalance(dai) curBRes = interface.IBalancerPool(lp).getBalance(weth) print('spell lp balance', lp.balanceOf(balancer_spell)) print('spell dai balance', dai.balanceOf(balancer_spell)) print('spell weth balance', weth.balanceOf(balancer_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta ETH balance', curETHBal - prevETHBal) print('Alice delta LP balance', curLPBal - prevLPBal) print('remove liquidity gas', tx.gas_used) print('bank delta lp balance', curLPBal_bank - prevLPBal_bank) print('bank total lp balance', curLPBal_bank) _, _, _, daiDebt, daiShare = homora.getBankInfo(dai) print('bank dai totalDebt', daiDebt) print('bank dai totalShare', daiShare) print('LP want', lp_want) print('bank delta LP amount', curLPBal_bank - prevLPBal_bank) print('LP take amount', lp_take_amt) print('prev werc20 LP balance', prevLPBal_werc20) print('cur werc20 LP balance', curLPBal_werc20) print('real dai repay', real_dai_repay) # alice assert almostEqual(curBBal - prevBBal, 0), 'incorrect WETH amt' assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # werc20 assert almostEqual(curLPBal_werc20 - prevLPBal_werc20, - real_lp_take_amt), 'incorrect werc20 LP amt' # spell assert dai.balanceOf(balancer_spell) == 0, 'non-zero spell DAI balance' assert weth.balanceOf(balancer_spell) == 0, 'non-zero spell WETH balance' assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance' # check balance and pool reserves assert almostEqual(curABal - prevABal + real_dai_repay, - (curARes - prevARes)), 'inconsistent DAI from withdraw' assert almostEqual(curBBal - prevBBal, 0), 'inconsistent WETH from withdraw' assert almostEqual(curETHBal - prevETHBal + weth_repay, - (curBRes - prevBRes)), 'inconsistent ETH from withdraw' return tx
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 test_uniswap_spell_wstaking(uniswap_spell, homora, wstaking, oracle): alice = accounts[0] dpi = interface.IERC20Ex('0x1494ca1f11d487c2bbe4543e90080aeba4ba3c2b') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') index = interface.IERC20Ex('0x0954906da0bf32d5479e25f46056d22f08464cab') mint_tokens(dpi, alice) mint_tokens(weth, alice) dpi.approve(homora, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) prevABal = dpi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() initABal = prevABal initBBal = prevBBal initETHBal = prevETHBal print('prev A bal', prevABal) print('prev B bal', prevBBal) # open a position homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWStakingRewards.encode_input( dpi, weth, [10**18, 10**18, 0, 0, 5 * 10**17, 0, 0, 0], wstaking ), {'from': alice} ) curABal = dpi.balanceOf(alice) curBBal = weth.balanceOf(alice) print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) prevABal = dpi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() position_id = homora.nextPositionId() # close the position homora.execute( position_id - 1, uniswap_spell, uniswap_spell.removeLiquidityWStakingRewards.encode_input( dpi, weth, [2**256-1, 0, 0, 2**256-1, 0, 0, 0], wstaking ), {'from': alice} ) curABal = dpi.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() finalABal = curABal finalBBal = curBBal finalETHBal = curETHBal tokenAPrice = oracle.getETHPx(dpi) tokenBPrice = oracle.getETHPx(weth) tokenETHPrice = oracle.getETHPx('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta ETH Bal', curETHBal - prevETHBal) print('token A price', tokenAPrice) print('token B price', tokenBPrice) print('token ETH price', tokenETHPrice) print('index reward', index.balanceOf(alice)) assert almostEqual(tokenAPrice * initABal + tokenBPrice * initBBal + tokenETHPrice * initETHBal, tokenAPrice * finalABal + tokenBPrice * finalBBal + tokenETHPrice * finalETHBal), 'too much value lost' assert index.balanceOf(alice) > 0, 'should get some INDEX reward'
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') adai = interface.IERC20Ex('0x028171bCA77440897B824Ca71D1c56caC55b68A3') ausdc = interface.IERC20Ex('0xBcca60bB61934080951369a648Fb03DF4F96263C') ausdt = interface.IERC20Ex('0x3Ed3B47Dd13EC9a98b44e6204A523E766B225811') lp = interface.IERC20Ex('0x6c3f90f043a72fa612cbac8115ee7e52bde6e490') pool = interface.ICurvePool('0xbEbc44782C7dB0a1A60Cb6fe97d0b483032FF1C7') lp_aave = interface.IERC20Ex('0xFd2a8fA60Abd58Efe3EeE34dd494cD491dC14900') pool_aave = interface.ICurvePool( '0xDeBF20617708857ebe4F679508E7b7863a8A8EeE') registry = interface.ICurveRegistry( '0x7d86446ddb609ed0f5f8684acf30380a356b2b4c') crdai = interface.ICErc20('0x92B767185fB3B04F881e3aC8e5B0662a027A1D9f') crusdc = interface.ICErc20('0x44fbebd2f576670a6c33f6fc0b00aa8c5753b322') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') cradai = MockCErc20.deploy(adai, {'from': admin}) crausdc = MockCErc20.deploy(ausdc, {'from': admin}) crausdt = MockCErc20.deploy(ausdt, {'from': admin}) gauge = accounts.at('0xbFcF63294aD7105dEa65aA58F8AE5BE2D9d0952A', force=True) wgauge = WLiquidityGauge.deploy( registry, '0xD533a949740bb3306d119CC777fa900bA034cd52', {'from': admin}) crv = interface.IERC20Ex(wgauge.crv()) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx([dai, usdt, usdc, adai, ausdc, ausdt], [ 2**112 // 700, 2**112 // 700, 2**112 // 700, 2**112 // 700, 2**112 // 700, 2**112 // 700 ]) curve_oracle = CurveOracle.deploy(simple_oracle, registry, {'from': admin}) curve_oracle.registerPool(lp) # update pool info curve_oracle.registerPool(lp_aave) # update pool info core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wgauge], True, {'from': admin}) core_oracle.setRoute( [dai, usdc, usdt, lp, adai, ausdc, ausdt, lp_aave], [ simple_oracle, simple_oracle, simple_oracle, curve_oracle, simple_oracle, simple_oracle, simple_oracle, curve_oracle ], {'from': admin}, ) oracle.setOracles( [dai, usdc, usdt, lp, adai, ausdc, ausdt, lp_aave], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) # initialize homora = HomoraBank.deploy({'from': admin}) print('donator ether', accounts[5].balance()) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) # add bank homora.addBank(dai, crdai, {'from': admin}) homora.addBank(usdc, crusdc, {'from': admin}) homora.addBank(usdt, crusdt, {'from': admin}) homora.addBank(adai, cradai, {'from': admin}) homora.addBank(ausdc, crausdc, {'from': admin}) homora.addBank(ausdt, crausdt, {'from': admin}) # setup initial funds 10^6 USDT + 10^6 USDC + 10^6 DAI to alice mint_tokens( dai, alice, ) mint_tokens(usdc, alice) mint_tokens(usdt, alice) mint_tokens(adai, alice) mint_tokens(ausdc, alice) mint_tokens(ausdt, alice) # check alice's funds print(f'Alice dai balance {dai.balanceOf(alice)}') print(f'Alice usdc balance {usdc.balanceOf(alice)}') print(f'Alice usdt balance {usdt.balanceOf(alice)}') print(f'Alice adai balance {adai.balanceOf(alice)}') print(f'Alice ausdc balance {ausdc.balanceOf(alice)}') print(f'Alice ausdt balance {ausdt.balanceOf(alice)}') # steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) mint_tokens(lp_aave, alice) # set approval dai.approve(homora, 2**256 - 1, {'from': alice}) dai.approve(crdai, 2**256 - 1, {'from': alice}) usdc.approve(homora, 2**256 - 1, {'from': alice}) usdc.approve(crusdc, 2**256 - 1, {'from': alice}) usdt.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(crusdt, 2**256 - 1, {'from': alice}) adai.approve(homora, 2**256 - 1, {'from': alice}) adai.approve(cradai, 2**256 - 1, {'from': alice}) ausdc.approve(homora, 2**256 - 1, {'from': alice}) ausdc.approve(crausdc, 2**256 - 1, {'from': alice}) ausdt.approve(homora, 2**256 - 1, {'from': alice}) ausdt.approve(crausdt, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(gauge, 2**256 - 1, {'from': bob}) lp_aave.approve(homora, 2**256 - 1, {'from': alice}) curve_spell = CurveSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', wgauge, {'from': admin}) # register gauge wgauge.registerGauge(0, 0) wgauge.registerGauge(25, 0) # set up pools curve_spell.getPool(lp) curve_spell.getPool(lp_aave) # first time call to reduce gas curve_spell.ensureApproveN(lp, 3, {'from': admin}) curve_spell.ensureApproveN(lp_aave, 3, {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = dai.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevCBal = usdt.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_gauge = lp.balanceOf(gauge) dai_amt = 200 * 10**18 usdc_amt = 500 * 10**6 usdt_amt = 400 * 10**6 lp_amt = 1 * 10**18 borrow_dai_amt = 0 borrow_usdc_amt = 20 * 10**6 borrow_usdt_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 0 gid = 0 tx = homora.execute( 0, curve_spell, curve_spell.addLiquidity3.encode_input( lp, # LP [dai_amt, usdc_amt, usdt_amt], # supply tokens lp_amt, # supply LP [borrow_dai_amt, borrow_usdc_amt, borrow_usdt_amt ], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) curABal = dai.balanceOf(alice) curBBal = usdc.balanceOf(alice) curCBal = usdt.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_gauge = lp.balanceOf(gauge) print('spell lp balance', lp.balanceOf(curve_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta C balance', curCBal - prevCBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, daiDebt, daiDebtShare = homora.getBankInfo(dai) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, lpDebt, usdcDebtShare = homora.getBankInfo(usdc) print('bank dai totalDebt', daiDebt) print('bank dai totalShare', daiDebtShare) 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('gauge prev LP balance', prevLPBal_gauge) print('gauge cur LP balance', curLPBal_gauge) # alice assert almostEqual(curABal - prevABal, -dai_amt), 'incorrect DAI amt' assert almostEqual(curBBal - prevBBal, -usdc_amt), 'incorrect USDC amt' assert almostEqual(curCBal - prevCBal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curLPBal - prevLPBal, -lp_amt), 'incorrect LP amt' # spell assert dai.balanceOf(curve_spell) == 0, 'non-zero spell DAI balance' assert usdc.balanceOf(curve_spell) == 0, 'non-zero spell USDC balance' assert usdt.balanceOf(curve_spell) == 0, 'non-zero spell USDT balance' assert lp.balanceOf(curve_spell) == 0, 'non-zero spell LP balance' # debt assert daiDebt == borrow_dai_amt assert usdcDebt == borrow_usdc_amt assert usdtDebt == borrow_usdt_amt _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevCrv = crv.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) pid, gid = 0, 0 gauge, _ = wgauge.gauges(pid, gid) tx = interface.ILiquidityGauge(gauge).deposit(collSize, {'from': bob}) chain.sleep(20000) prevAliceCrvBalance = crv.balanceOf(alice) print('Alice crv balance', prevAliceCrvBalance) # ##################################################################################### print( '=========================================================================' ) print('Case 2. add liquidity (failed tx desired)') adai_amt = 200 * 10**18 ausdc_amt = 500 * 10**6 ausdt_amt = 400 * 10**6 lp_amt = 0 borrow_adai_amt = 0 borrow_ausdc_amt = 0 borrow_ausdt_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 0 gid = 0 try: tx = homora.execute( 1, curve_spell, curve_spell.addLiquidity3.encode_input( lp_aave, # LP_aave [adai_amt, ausdc_amt, ausdt_amt], # supply tokens lp_amt, # supply LP [borrow_adai_amt, borrow_ausdc_amt, borrow_ausdt_amt ], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) assert False, 'tx should fail' except VirtualMachineError: pass # ##################################################################################### print( '=========================================================================' ) print('Case 3. add liquidity (failed tx desired)') adai_amt = 200 * 10**18 ausdc_amt = 500 * 10**6 ausdt_amt = 400 * 10**6 lp_amt = 0 borrow_adai_amt = 0 borrow_ausdc_amt = 0 borrow_ausdt_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 25 gid = 0 try: tx = homora.execute( 1, curve_spell, curve_spell.addLiquidity3.encode_input( lp_aave, # LP_aave [adai_amt, ausdc_amt, ausdt_amt], # supply tokens lp_amt, # supply LP [borrow_adai_amt, borrow_ausdc_amt, borrow_ausdt_amt ], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) assert False, 'tx should fail' except VirtualMachineError: pass # ##################################################################################### print( '=========================================================================' ) print('Case 4. remove liquidity (failed tx desired)') lp_take_amt = 2**256 - 1 # max lp_want = 1 * 10**17 adai_repay = 2**256 - 1 # max ausdc_repay = 2**256 - 1 # max ausdt_repay = 2**256 - 1 # max lp_repay = 0 try: tx = homora.execute( 1, curve_spell, curve_spell.removeLiquidity3.encode_input( lp_aave, # LP_aave token lp_take_amt, # LP amount to take out lp_want, # LP amount to withdraw to wallet [adai_repay, ausdc_repay, ausdt_repay], # repay amounts lp_repay, # repay LP amount [0, 0, 0] # min amounts ), {'from': alice}) assert False, 'tx should revert' except VirtualMachineError: pass # ##################################################################################### print( '=========================================================================' ) print('Case 5. remove liqudiity') # remove liquidity from the same position prevABal = dai.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevCBal = usdt.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_gauge = lp.balanceOf(gauge) _, _, _, collSize = homora.getPositionInfo(1) lp_take_amt = 2**256 - 1 # max lp_want = 1 * 10**17 dai_repay = 2**256 - 1 # max usdc_repay = 2**256 - 1 # max usdt_repay = 2**256 - 1 # max lp_repay = 0 tx = homora.execute( 1, curve_spell, curve_spell.removeLiquidity3.encode_input( lp, # LP token lp_take_amt, # LP amount to take out lp_want, # LP amount to withdraw to wallet [dai_repay, usdc_repay, usdt_repay], # repay amounts lp_repay, # repay LP amount [0, 0, 0] # min amounts ), {'from': alice}) curABal = dai.balanceOf(alice) curBBal = usdc.balanceOf(alice) curCBal = usdt.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_gauge = lp.balanceOf(gauge) print('spell lp balance', lp.balanceOf(curve_spell)) print('spell dai balance', dai.balanceOf(curve_spell)) print('spell usdc balance', usdc.balanceOf(curve_spell)) print('spell usdt balance', usdt.balanceOf(curve_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta C balance', curCBal - prevCBal) print('Alice delta LP balance', curLPBal - prevLPBal) print('remove liquidity gas', tx.gas_used) print('bank delta lp balance', curLPBal_bank - prevLPBal_bank) print('bank total lp balance', curLPBal_bank) _, _, _, daiDebt, daiDebtShare = homora.getBankInfo(dai) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) print('bank dai totalDebt', daiDebt) print('bank dai totalDebt', daiDebt) print('bank usdc totalShare', usdcDebtShare) print('bank usdc totalShare', usdcDebtShare) print('bank usdt totalDebt', usdtDebt) print('bank usdt totalShare', usdtDebtShare) print('LP want', lp_want) print('bank delta LP amount', curLPBal_bank - prevLPBal_bank) print('LP take amount', lp_take_amt) print('prev gauge LP balance', prevLPBal_gauge) print('cur gauge LP balance', curLPBal_gauge) print('coll size', collSize) # alice assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # gauge assert almostEqual(curLPBal_gauge - prevLPBal_gauge, -collSize), 'incorrect gauge LP amt' # spell assert dai.balanceOf(curve_spell) == 0, 'non-zero spell DAI balance' assert usdc.balanceOf(curve_spell) == 0, 'non-zero spell USDC balance' assert usdt.balanceOf(curve_spell) == 0, 'non-zero spell USDT balance' assert lp.balanceOf(curve_spell) == 0, 'non-zero spell LP balance' # debt assert usdcDebt == 0, 'usdcDebt should be 0' assert daiDebt == 0, 'daiDebt should be 0' assert usdtDebt == 0, 'usdtDebt should be 0' curAliceCrvBalance = crv.balanceOf(alice) print('Alice crv balance', curAliceCrvBalance) receivedCrv = curAliceCrvBalance - prevAliceCrvBalance print('received crv', receivedCrv) # check with staking directly minter = interface.ILiquidityGaugeMinter( interface.ILiquidityGauge(gauge).minter()) print('minter', minter) tx = minter.mint(gauge, {'from': bob}) print('tx status', tx.status) tx = interface.ILiquidityGauge(gauge).withdraw(collSize, {'from': bob}) receivedCrvFromGauge = crv.balanceOf(bob) - prevCrv print('receivedCrvFromGauge', receivedCrvFromGauge) assert almostEqual(receivedCrv, receivedCrvFromGauge) return tx
def test_uniswap_spell(uniswap_spell, homora, oracle): alice = accounts[0] yfi = interface.IERC20Ex('0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') mint_tokens(yfi, alice) mint_tokens(weth, alice) yfi.approve(homora, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) prevABal = yfi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() initABal = prevABal initBBal = prevBBal initETHBal = prevETHBal print('prev A bal', prevABal) print('prev B bal', prevBBal) # open a position homora.execute( 0, uniswap_spell, uniswap_spell.addLiquidityWERC20.encode_input( yfi, weth, [10 * 10**18, 10 * 10**18, 0, 0, 10**18, 0, 0, 0], ), {'from': alice} ) curABal = yfi.balanceOf(alice) curBBal = weth.balanceOf(alice) print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) prevABal = yfi.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() position_id = homora.nextPositionId() # close the position homora.execute( position_id - 1, uniswap_spell, uniswap_spell.removeLiquidityWERC20.encode_input( yfi, weth, [2**256-1, 0, 0, 2**256-1, 0, 0, 0], ), {'from': alice} ) curABal = yfi.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() finalABal = curABal finalBBal = curBBal finalETHBal = curETHBal tokenAPrice = oracle.getETHPx(yfi) tokenBPrice = oracle.getETHPx(weth) tokenETHPrice = oracle.getETHPx('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta ETH Bal', curETHBal - prevETHBal) print('token A price', tokenAPrice) print('token B price', tokenBPrice) print('token ETH price', tokenETHPrice) assert almostEqual(tokenAPrice * initABal + tokenBPrice * initBBal + tokenETHPrice * initETHBal, tokenAPrice * finalABal + tokenBPrice * finalBBal + tokenETHPrice * finalETHBal), 'too much value lost'
def main(): admin = accounts[0] alice = accounts[1] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') sushi = interface.IERC20Ex('0x6b3595068778dd592e39a122f4f5a5cf09c90fe2') lpusdt = interface.IERC20Ex( '0x06da0fd433c1a5d7a4faa01111c044910a184553') # pid 0 lpusdc = interface.IERC20Ex( '0x397ff1542f962076d0bfe58ea045ffa2d347aca0') # pid 1 chef = accounts.at('0xc2edad668740f1aa35e4d8f227fb8e17dca888cd', force=True) wchef = WMasterChef.deploy(chef, {'from': admin}) # set approval usdt.approve(wchef, 2**256 - 1, {'from': alice}) usdc.approve(wchef, 2**256 - 1, {'from': alice}) weth.approve(wchef, 2**256 - 1, {'from': alice}) lpusdt.approve(wchef, 2**256 - 1, {'from': alice}) lpusdc.approve(wchef, 2**256 - 1, {'from': alice}) lpusdt.approve(chef, 2**256 - 1, {'from': alice}) lpusdc.approve(chef, 2**256 - 1, {'from': alice}) # setup initial funds to alice mint_tokens(usdt, alice) mint_tokens(usdc, alice) mint_tokens(weth, alice) mint_tokens(lpusdt, alice) mint_tokens(lpusdc, alice) ###################################################################### # Check encoding and decoding ids print( '######################################################################' ) print('Case 1.') pid = 10 sushiPerShare = 210 encoded_id = wchef.encodeId(pid, sushiPerShare) print('encoded id', encoded_id) assert (encoded_id >> 240) == pid assert (encoded_id & ((1 << 240) - 1)) == sushiPerShare d_pid, d_sushiPerShare = wchef.decodeId(encoded_id) print('decoded pid', d_pid) print('decoded sushiPerShare', d_sushiPerShare) assert d_pid == pid assert d_sushiPerShare == sushiPerShare ###################################################################### # check getUnderlyingToken pid = 10 sushiPerShare = 210 id_num = wchef.encodeId(pid, sushiPerShare) lpToken = wchef.getUnderlyingToken(id_num) print('lpToken', lpToken) assert lpToken == '0xCb2286d9471cc185281c4f763d34A962ED212962' ###################################################################### # check mint & burn print( '######################################################################' ) print('Case 2.') pid = 0 amt = 10**10 print('alice lpusdt balance', lpusdt.balanceOf(alice)) # mint tx = wchef.mint(pid, amt, {'from': alice}) encoded_id = tx.return_value print('tx status', tx.status) print('encoded id', encoded_id) _, _, _, prevAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('prevAccSushiPerShare', prevAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) assert tx.status == 1 assert wchef.balanceOf(alice, encoded_id) == amt # burn exact prevSushiBalance = sushi.balanceOf(alice) tx = wchef.burn(encoded_id, amt, {'from': alice}) _, _, _, newAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('tx status', tx.status) print('newAccSushiPerShare', newAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) print('alice sushi balance', sushi.balanceOf(alice)) receivedSushi = sushi.balanceOf(alice) - prevSushiBalance assert tx.status == 1 assert wchef.balanceOf(alice, encoded_id) == 0 # remove all assert almostEqual(receivedSushi, (newAccSushiPerShare - prevAccSushiPerShare) * amt // 10**12) # check reward same as staking directly prevSushi = sushi.balanceOf(alice) print('alice lpusdt balance', interface.IERC20Ex(lpusdt).balanceOf(alice)) tx = interface.IMasterChef(chef).deposit(pid, amt, {'from': alice}) tx = interface.IMasterChef(chef).withdraw(pid, amt, {'from': alice}) receivedSushiFromChef = sushi.balanceOf(alice) - prevSushi print('receivedSushiFromChef', receivedSushiFromChef) assert almostEqual(receivedSushi, receivedSushiFromChef) ###################################################################### # check mint & burn max_int print( '######################################################################' ) print('Case 3.') pid = 0 amt = 10**10 print('alice lpusdt balance', lpusdt.balanceOf(alice)) # mint tx = wchef.mint(pid, amt, {'from': alice}) encoded_id = tx.return_value print('tx status', tx.status) print('encoded id', encoded_id) _, _, _, prevAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('prevAccSushiPerShare', prevAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) assert tx.status == 1 assert wchef.balanceOf(alice, encoded_id) == amt # burn all prevSushiBalance = sushi.balanceOf(alice) tx = wchef.burn(encoded_id, 2**256 - 1, {'from': alice}) _, _, _, newAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('tx status', tx.status) print('newAccSushiPerShare', newAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) print('alice sushi balance', sushi.balanceOf(alice)) receivedSushi = sushi.balanceOf(alice) - prevSushiBalance assert tx.status == 1 assert wchef.balanceOf(alice, encoded_id) == 0 # remove all assert almostEqual( sushi.balanceOf(alice) - prevSushiBalance, (newAccSushiPerShare - prevAccSushiPerShare) * amt // 10**12) # check reward same as staking directly prevSushi = sushi.balanceOf(alice) print('alice lpusdt balance', interface.IERC20Ex(lpusdt).balanceOf(alice)) tx = interface.IMasterChef(chef).deposit(pid, amt, {'from': alice}) tx = interface.IMasterChef(chef).withdraw(pid, amt, {'from': alice}) receivedSushiFromChef = sushi.balanceOf(alice) - prevSushi print('receivedSushiFromChef', receivedSushiFromChef) assert almostEqual(receivedSushi, receivedSushiFromChef) ###################################################################### # check mint & burn (try more than available--revert, half, then remaining) print( '######################################################################' ) print('Case 4.') pid = 0 amt = 10**10 print('alice lpusdt balance', lpusdt.balanceOf(alice)) # mint startSushiBalance = sushi.balanceOf(alice) tx = wchef.mint(pid, amt, {'from': alice}) encoded_id = tx.return_value print('encoded id', encoded_id) _, _, _, prevAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('accSushiPerShare', prevAccSushiPerShare) assert tx.status == 1 assert wchef.balanceOf(alice, encoded_id) == amt # burn too much (expected failed) prevSushiBalance = sushi.balanceOf(alice) _, _, _, prevAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) try: tx = wchef.burn(encoded_id, amt + 1, {'from': alice}) assert tx.status == 0 except: pass _, _, _, newAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('accSushiPerShare', newAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) print('alice sushi balance', sushi.balanceOf(alice)) assert prevSushiBalance == sushi.balanceOf(alice) assert wchef.balanceOf(alice, encoded_id) == amt # burn half prevSushiBalance = sushi.balanceOf(alice) _, _, _, prevAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) tx = wchef.burn(encoded_id, amt // 2, {'from': alice}) _, _, _, newAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('accSushiPerShare', newAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) print('alice sushi balance', sushi.balanceOf(alice)) assert tx.status == 1 assert almostEqual( sushi.balanceOf(alice) - prevSushiBalance, (newAccSushiPerShare - prevAccSushiPerShare) * amt // 2 // 10**12) assert almostEqual(wchef.balanceOf(alice, encoded_id), amt - amt // 2) # burn remaining prevSushiBalance = sushi.balanceOf(alice) tx = wchef.burn(encoded_id, 2**256 - 1, {'from': alice}) _, _, _, newAccSushiPerShare = interface.IMasterChef(chef).poolInfo(0) print('accSushiPerShare', newAccSushiPerShare) print('alice wlpusdt balance', wchef.balanceOf(alice, encoded_id)) print('alice sushi balance', sushi.balanceOf(alice)) receivedSushi = sushi.balanceOf(alice) - prevSushiBalance assert tx.status == 1 assert almostEqual( sushi.balanceOf(alice) - prevSushiBalance, (newAccSushiPerShare - prevAccSushiPerShare) * amt // 2 // 10**12) assert wchef.balanceOf(alice, encoded_id) == 0 # check reward same as staking directly prevSushi = sushi.balanceOf(alice) print('alice lpusdt balance', interface.IERC20Ex(lpusdt).balanceOf(alice)) tx = interface.IMasterChef(chef).deposit(pid, amt, {'from': alice}) # stake all tx = interface.IMasterChef(chef).withdraw(pid, amt // 2, {'from': alice}) # redeem half tx = interface.IMasterChef(chef).withdraw( pid, amt - amt // 2, {'from': alice}) # redeem remaining receivedSushiFromChef = sushi.balanceOf(alice) - prevSushi print('receivedSushiFromChef', receivedSushiFromChef) assert almostEqual(receivedSushi, receivedSushiFromChef)
def test_sushiswap_spell_wmasterchef(sushiswap_spell, homora, oracle): alice = accounts[0] usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') sushi = interface.IERC20Ex('0x6b3595068778dd592e39a122f4f5a5cf09c90fe2') mint_tokens(usdt, alice) mint_tokens(weth, alice) usdt.approve(homora, 0, {'from': alice}) usdt.approve(homora, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() initABal = prevABal initBBal = prevBBal initETHBal = prevETHBal print('prev A bal', prevABal) print('prev B bal', prevBBal) homora.execute( 0, sushiswap_spell, sushiswap_spell.addLiquidityWMasterChef.encode_input( usdt, # token 0 weth, # token 1 [10 * 10**6, # supply USDT 10 * 10**18, # supply WETH 0, # supply LP 0, # borrow USDT 10**18, # borrow WETH 0, # borrow LP tokens 0, # min USDT 0], # min WETH 0 ), {'from': alice} ) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) prevABal = usdt.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() position_id = homora.nextPositionId() homora.execute( position_id - 1, sushiswap_spell, sushiswap_spell.removeLiquidityWMasterChef.encode_input( usdt, # token 0 weth, # token 1 [2**256-1, # take out LP tokens 0, # withdraw LP tokens to wallet 0, # repay USDT 2**256-1, # repay WETH 0, # repay LP 0, # min USDT 0], # min WETH ), {'from': alice} ) curABal = usdt.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() finalABal = curABal finalBBal = curBBal finalETHBal = curETHBal tokenAPrice = oracle.getETHPx(usdt) tokenBPrice = oracle.getETHPx(weth) tokenETHPrice = oracle.getETHPx('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta ETH Bal', curETHBal - prevETHBal) print('token A price', tokenAPrice) print('token B price', tokenBPrice) print('token ETH price', tokenETHPrice) print('sushi reward', sushi.balanceOf(alice)) assert almostEqual(tokenAPrice * initABal + tokenBPrice * initBBal + tokenETHPrice * initETHBal, tokenAPrice * finalABal + tokenBPrice * finalBBal + tokenETHPrice * finalETHBal), 'too much value lost' assert sushi.balanceOf(alice) > 0, 'should get some sushi reward'
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 test_balancer_spell(balancer_spell, homora, oracle): alice = accounts[0] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2') lp = interface.IERC20Ex('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a') mint_tokens(dai, alice) mint_tokens(weth, alice) dai.approve(homora, 2**256-1, {'from': alice}) weth.approve(homora, 2**256-1, {'from': alice}) prevABal = dai.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() initABal = prevABal initBBal = prevBBal initETHBal = prevETHBal print('prev A bal', prevABal) print('prev B bal', prevBBal) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWERC20.encode_input( lp, # lp token [10 * 10**18, # supply DAI 10 * 10**18, # supply WETH 0, # supply LP 1 * 10**18, # borrow DAI 1 * 10**18, # borrow WETH 0, # borrow LP tokens 0] # LP desired ), {'from': alice} ) curABal = dai.balanceOf(alice) curBBal = weth.balanceOf(alice) print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) prevABal = dai.balanceOf(alice) prevBBal = weth.balanceOf(alice) prevETHBal = alice.balance() position_id = homora.nextPositionId() tx = homora.execute( position_id - 1, balancer_spell, balancer_spell.removeLiquidityWERC20.encode_input( lp, # LP token [2**256-1, # take out LP tokens 0, # withdraw LP tokens to wallet 2**256-1, # repay DAI 2**256-1, # repay WETH 0, # repay LP 0, # min DAI 0], # min WETH ), {'from': alice} ) curABal = dai.balanceOf(alice) curBBal = weth.balanceOf(alice) curETHBal = alice.balance() finalABal = curABal finalBBal = curBBal finalETHBal = curETHBal tokenAPrice = oracle.getETHPx(dai) tokenBPrice = oracle.getETHPx(weth) tokenETHPrice = oracle.getETHPx('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta ETH Bal', curETHBal - prevETHBal) print('token A price', tokenAPrice) print('token B price', tokenBPrice) print('token ETH price', tokenETHPrice) assert almostEqual(tokenAPrice * initABal + tokenBPrice * initBBal + tokenETHPrice * initETHBal, tokenAPrice * finalABal + tokenBPrice * finalBBal + tokenETHPrice * finalETHBal), 'too much value lost'
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') susd = interface.IERC20Ex('0x57ab1ec28d129707052df4df418d58a2d46d5f51') ydai = interface.IERC20Ex('0xC2cB1040220768554cf699b0d863A3cd4324ce32') yusdc = interface.IERC20Ex('0x26EA744E5B887E5205727f55dFBE8685e3b21951') yusdt = interface.IERC20Ex('0xE6354ed5bC4b393a5Aad09f21c46E101e692d447') ybusd = interface.IERC20Ex('0x04bC0Ab673d88aE9dbC9DA2380cB6B79C4BCa9aE') lp = interface.IERC20Ex('0xC25a3A3b969415c80451098fa907EC722572917F') pool = interface.ICurvePool('0xA5407eAE9Ba41422680e2e00537571bcC53efBfD') lp_busd = interface.IERC20Ex('0x3B3Ac5386837Dc563660FB6a0937DFAa5924333B') pool_busd = interface.ICurvePool( '0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27') registry = interface.ICurveRegistry( '0x7d86446ddb609ed0f5f8684acf30380a356b2b4c') crdai = interface.ICErc20('0x92B767185fB3B04F881e3aC8e5B0662a027A1D9f') crusdc = interface.ICErc20('0x44fbebd2f576670a6c33f6fc0b00aa8c5753b322') crusdt = interface.ICErc20('0x797AAB1ce7c01eB727ab980762bA88e7133d2157') crsusd = MockCErc20.deploy(susd, {'from': admin}) crydai = MockCErc20.deploy(ydai, {'from': admin}) cryusdc = MockCErc20.deploy(yusdc, {'from': admin}) cryusdt = MockCErc20.deploy(yusdt, {'from': admin}) crybusd = MockCErc20.deploy(ybusd, {'from': admin}) gauge = accounts.at('0xA90996896660DEcC6E997655E065b23788857849', force=True) wgauge = WLiquidityGauge.deploy( registry, '0xD533a949740bb3306d119CC777fa900bA034cd52', {'from': admin}) crv = interface.IERC20Ex(wgauge.crv()) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx( [dai, usdt, usdc, susd, ydai, yusdc, yusdt, ybusd], [ 2**112 // 700, 2**112 * 10**12 // 700, 2**112 * 10**12 // 700, 2**112 // 700, 2**112 // 700, 2**112 * 10**12 // 700, 2**112 * 10**12 // 700, 2**112 // 700 ]) curve_oracle = CurveOracle.deploy(simple_oracle, registry, {'from': admin}) curve_oracle.registerPool(lp) # update pool info curve_oracle.registerPool(lp_busd) # update pool info core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wgauge], True, {'from': admin}) core_oracle.setRoute( [ dai, usdc, usdt, susd, lp, ydai, yusdc, yusdt, ybusd, lp_busd, ], [ simple_oracle, simple_oracle, simple_oracle, simple_oracle, curve_oracle, simple_oracle, simple_oracle, simple_oracle, simple_oracle, curve_oracle ], {'from': admin}, ) oracle.setOracles( [dai, usdc, usdt, susd, lp, ydai, yusdc, yusdt, ybusd, lp_busd], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], ], {'from': admin}, ) # initialize homora = HomoraBank.deploy({'from': admin}) print('donator ether', accounts[5].balance()) homora.initialize(oracle, 1000, {'from': admin}) # 10% fee setup_bank_hack(homora) # add bank homora.addBank(dai, crdai, {'from': admin}) homora.addBank(usdc, crusdc, {'from': admin}) homora.addBank(usdt, crusdt, {'from': admin}) homora.addBank(susd, crsusd, {'from': admin}) homora.addBank(ydai, crydai, {'from': admin}) homora.addBank(yusdc, cryusdc, {'from': admin}) homora.addBank(yusdt, cryusdt, {'from': admin}) homora.addBank(ybusd, crybusd, {'from': admin}) # setup initial funds to alice mint_tokens( dai, alice, ) mint_tokens(usdc, alice) mint_tokens(usdt, alice) mint_tokens(susd, alice) mint_tokens(ydai, alice) mint_tokens(yusdc, alice) mint_tokens(yusdt, alice) mint_tokens(ybusd, alice) # check alice's funds print(f'Alice dai balance {dai.balanceOf(alice)}') print(f'Alice usdc balance {usdc.balanceOf(alice)}') print(f'Alice usdt balance {usdt.balanceOf(alice)}') print(f'Alice susd balance {susd.balanceOf(alice)}') print(f'Alice ydai balance {ydai.balanceOf(alice)}') print(f'Alice yusdc balance {yusdc.balanceOf(alice)}') print(f'Alice yusdt balance {yusdt.balanceOf(alice)}') print(f'Alice ybusd balance {ybusd.balanceOf(alice)}') # steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) mint_tokens(lp_busd, alice) # set approval dai.approve(homora, 2**256 - 1, {'from': alice}) dai.approve(crdai, 2**256 - 1, {'from': alice}) usdc.approve(homora, 2**256 - 1, {'from': alice}) usdc.approve(crusdc, 2**256 - 1, {'from': alice}) usdt.approve(homora, 2**256 - 1, {'from': alice}) usdt.approve(crusdt, 2**256 - 1, {'from': alice}) susd.approve(homora, 2**256 - 1, {'from': alice}) susd.approve(crsusd, 2**256 - 1, {'from': alice}) ydai.approve(homora, 2**256 - 1, {'from': alice}) ydai.approve(crydai, 2**256 - 1, {'from': alice}) yusdc.approve(homora, 2**256 - 1, {'from': alice}) yusdc.approve(cryusdc, 2**256 - 1, {'from': alice}) yusdt.approve(homora, 2**256 - 1, {'from': alice}) yusdt.approve(cryusdt, 2**256 - 1, {'from': alice}) ybusd.approve(homora, 2**256 - 1, {'from': alice}) ybusd.approve(crybusd, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(gauge, 2**256 - 1, {'from': bob}) lp_busd.approve(homora, 2**256 - 1, {'from': alice}) curve_spell = CurveSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', wgauge, {'from': admin}) # register gauge wgauge.registerGauge(12, 0) wgauge.registerGauge(1, 0) # set up pools curve_spell.getPool(lp) curve_spell.getPool(lp_busd) # first time call to reduce gas curve_spell.ensureApproveN(lp, 4, {'from': admin}) curve_spell.ensureApproveN(lp_busd, 4, {'from': admin}) # whitelist spell in bank homora.setWhitelistSpells([curve_spell], [True], {'from': admin}) # whitelist token in bank homora.setWhitelistTokens([dai, usdt, usdc, susd], [True, True, True, True], {'from': admin}) # whitelist lp in spell curve_spell.setWhitelistLPTokens([lp], [True], {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = dai.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevCBal = usdt.balanceOf(alice) prevDBal = susd.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_gauge = lp.balanceOf(gauge) dai_amt = 200 * 10**18 usdc_amt = 1000 * 10**6 usdt_amt = 1000 * 10**6 susd_amt = 1000 * 10**18 lp_amt = 0 borrow_dai_amt = 10 * 10**18 borrow_usdc_amt = 10**6 borrow_usdt_amt = 0 borrow_susd_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 12 gid = 0 tx = homora.execute( 0, curve_spell, curve_spell.addLiquidity4.encode_input( lp, # LP [dai_amt, usdc_amt, usdt_amt, susd_amt], # supply tokens lp_amt, # supply LP [ borrow_dai_amt, borrow_usdc_amt, borrow_usdt_amt, borrow_susd_amt ], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) curABal = dai.balanceOf(alice) curBBal = usdc.balanceOf(alice) curCBal = usdt.balanceOf(alice) curDBal = susd.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_gauge = lp.balanceOf(gauge) print('spell lp balance', lp.balanceOf(curve_spell)) print('Alice delta A balance', curABal - prevABal) print('Alice delta B balance', curBBal - prevBBal) print('Alice delta C balance', curCBal - prevCBal) print('add liquidity gas', tx.gas_used) print('bank lp balance', curLPBal_bank) _, _, _, daiDebt, daiDebtShare = homora.getBankInfo(dai) _, _, _, usdcDebt, usdcDebtShare = homora.getBankInfo(usdc) _, _, _, usdtDebt, usdtDebtShare = homora.getBankInfo(usdt) _, _, _, susdDebt, susdDebtShare = homora.getBankInfo(susd) print('bank dai totalDebt', daiDebt) print('bank dai totalShare', daiDebtShare) print('bank usdt totalDebt', usdtDebt) print('bank usdt totalShare', usdtDebtShare) print('bank usdc totalDebt', usdcDebt) print('bank usdc totalShare', usdcDebtShare) print('bank susd totalDebt', susdDebt) print('bank susd totalShare', susdDebtShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('gauge prev LP balance', prevLPBal_gauge) print('gauge cur LP balance', curLPBal_gauge) # alice assert almostEqual(curABal - prevABal, -dai_amt), 'incorrect DAI amt' assert almostEqual(curBBal - prevBBal, -usdc_amt), 'incorrect USDC amt' assert almostEqual(curCBal - prevCBal, -usdt_amt), 'incorrect USDT amt' assert almostEqual(curDBal - prevDBal, -susd_amt), 'incorrect SUSD amt' assert almostEqual(curLPBal - prevLPBal, -lp_amt), 'incorrect LP amt' # spell assert dai.balanceOf(curve_spell) == 0, 'non-zero spell DAI balance' assert usdc.balanceOf(curve_spell) == 0, 'non-zero spell USDC balance' assert usdt.balanceOf(curve_spell) == 0, 'non-zero spell USDT balance' assert susd.balanceOf(curve_spell) == 0, 'non-zero spell SUSD balance' assert lp.balanceOf(curve_spell) == 0, 'non-zero spell LP balance' # debt assert daiDebt == borrow_dai_amt assert usdcDebt == borrow_usdc_amt assert usdtDebt == borrow_usdt_amt assert susdDebt == borrow_susd_amt # ##################################################################################### print( '=========================================================================' ) print('Case 2. harvest first time') prevCRVBalance = crv.balanceOf(alice) print('Alice CRV balance before harvest', prevCRVBalance) _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevCrv = crv.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) pid, gid = 12, 0 gauge, _ = wgauge.gauges(pid, gid) tx = interface.ILiquidityGauge(gauge).deposit(collSize, {'from': bob}) chain.sleep(20000) tx = homora.execute(1, curve_spell, curve_spell.harvest.encode_input(), {'from': alice}) print('tx gas used', tx.gas_used) curCRVBalance = crv.balanceOf(alice) print('Alice CRV balance after harvest', curCRVBalance) receivedCrv = curCRVBalance - prevCRVBalance # check with staking directly minter = interface.ILiquidityGaugeMinter( interface.ILiquidityGauge(gauge).minter()) print('minter', minter) tx = minter.mint(gauge, {'from': bob}) print('tx status', tx.status) tx = interface.ILiquidityGauge(gauge).withdraw(collSize, {'from': bob}) receivedCrvFromGauge = crv.balanceOf(bob) - prevCrv print('receivedCrvFromGauge', receivedCrvFromGauge) assert almostEqual(receivedCrv, receivedCrvFromGauge) # ##################################################################################### print( '=========================================================================' ) print('Case 3. harvest second time') prevCRVBalance = crv.balanceOf(alice) print('Alice CRV balance before harvest', prevCRVBalance) _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevCrv = crv.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) pid, gid = 12, 0 gauge, _ = wgauge.gauges(pid, gid) tx = interface.ILiquidityGauge(gauge).deposit(collSize, {'from': bob}) chain.sleep(20000) tx = homora.execute(1, curve_spell, curve_spell.harvest.encode_input(), {'from': alice}) print('tx gas used', tx.gas_used) curCRVBalance = crv.balanceOf(alice) print('Alice CRV balance after harvest', curCRVBalance) receivedCrv = curCRVBalance - prevCRVBalance # check with staking directly minter = interface.ILiquidityGaugeMinter( interface.ILiquidityGauge(gauge).minter()) print('minter', minter) tx = minter.mint(gauge, {'from': bob}) print('tx status', tx.status) tx = interface.ILiquidityGauge(gauge).withdraw(collSize, {'from': bob}) receivedCrvFromGauge = crv.balanceOf(bob) - prevCrv print('receivedCrvFromGauge', receivedCrvFromGauge) assert almostEqual(receivedCrv, receivedCrvFromGauge) return tx
def test_balancer_spell_wstaking(balancer_spell, homora, wstaking, oracle): alice = accounts[0] perp = interface.IERC20Ex('0xbC396689893D065F41bc2C6EcbeE5e0085233447') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') lp = interface.IERC20Ex('0xf54025af2dc86809be1153c1f20d77adb7e8ecf4') mint_tokens(perp, alice) mint_tokens(usdc, alice) perp.approve(homora, 2**256-1, {'from': alice}) usdc.approve(homora, 2**256-1, {'from': alice}) prevABal = perp.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevETHBal = alice.balance() initABal = prevABal initBBal = prevBBal initETHBal = prevETHBal print('prev A bal', prevABal) print('prev B bal', prevBBal) tx = homora.execute( 0, balancer_spell, balancer_spell.addLiquidityWStakingRewards.encode_input( lp, # lp token [10**18, # supply PERP 2 * 10**6, # supply USDC 0, # supply LP 0, # borrow PERP 0, # borrow USDC 0, # borrow LP tokens 0], # LP desired wstaking, ), {'from': alice} ) curABal = perp.balanceOf(alice) curBBal = usdc.balanceOf(alice) print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) prevABal = perp.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevETHBal = alice.balance() position_id = homora.nextPositionId() tx = homora.execute( position_id - 1, balancer_spell, balancer_spell.removeLiquidityWStakingRewards.encode_input( lp, # LP token [2**256-1, # take out LP tokens 0, # withdraw LP tokens to wallet 0, # repay PERP 0, # repay USDC 0, # repay LP 0, # min PERP 0], # min USDC wstaking, ), {'from': alice} ) curABal = perp.balanceOf(alice) curBBal = usdc.balanceOf(alice) curETHBal = alice.balance() finalABal = curABal finalBBal = curBBal finalETHBal = curETHBal tokenAPrice = oracle.getETHPx(perp) tokenBPrice = oracle.getETHPx(usdc) tokenETHPrice = oracle.getETHPx('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta ETH Bal', curETHBal - prevETHBal) print('token A price', tokenAPrice) print('token B price', tokenBPrice) print('token ETH price', tokenETHPrice) assert almostEqual(tokenAPrice * initABal + tokenBPrice * initBBal + tokenETHPrice * initETHBal, tokenAPrice * finalABal + tokenBPrice * finalBBal + tokenETHPrice * finalETHBal), 'too much value lost'
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] renbtc = interface.IERC20Ex('0xeb4c2781e4eba804ce9a9803c67d0893436bb27d') wbtc = interface.IERC20Ex('0x2260fac5e5542a773aa44fbcfedf7c193bc2c599') eurs = interface.IERC20Ex('0xdB25f211AB05b1c97D595516F45794528a807ad8') seur = interface.IERC20Ex('0xD71eCFF9342A5Ced620049e616c5035F1dB98620') lp = interface.IERC20Ex('0x49849C98ae39Fff122806C06791Fa73784FB3675') pool = interface.ICurvePool('0x93054188d876f558f4a66B2EF1d97d16eDf0895B') lp_eurs = interface.IERC20Ex('0x194eBd173F6cDacE046C53eACcE9B953F28411d1') pool_eurs = interface.ICurvePool( '0x0Ce6a5fF5217e38315f87032CF90686C96627CAA') registry = interface.ICurveRegistry( '0x7d86446ddb609ed0f5f8684acf30380a356b2b4c') crrenbtc = MockCErc20.deploy(renbtc, {'from': admin}) crwbtc = MockCErc20.deploy(wbtc, {'from': admin}) creurs = MockCErc20.deploy(eurs, {'from': admin}) crseur = MockCErc20.deploy(seur, {'from': admin}) gauge = accounts.at('0xB1F2cdeC61db658F091671F5f199635aEF202CAC', force=True) wgauge = WLiquidityGauge.deploy( registry, '0xD533a949740bb3306d119CC777fa900bA034cd52', {'from': admin}) crv = interface.IERC20Ex(wgauge.crv()) werc20 = WERC20.deploy({'from': admin}) simple_oracle = SimpleOracle.deploy({'from': admin}) simple_oracle.setETHPx( [renbtc, wbtc, eurs, seur], [2**112 * 30, 2**112 * 30, 2**112 // 700, 2**112 // 700]) curve_oracle = CurveOracle.deploy(simple_oracle, registry, {'from': admin}) curve_oracle.registerPool(lp) # update pool info curve_oracle.registerPool(lp_eurs) # update pool info core_oracle = CoreOracle.deploy({'from': admin}) oracle = ProxyOracle.deploy(core_oracle, {'from': admin}) oracle.setWhitelistERC1155([werc20, wgauge], True, {'from': admin}) core_oracle.setRoute( [renbtc, wbtc, lp, eurs, seur, lp_eurs], [ simple_oracle, simple_oracle, curve_oracle, simple_oracle, simple_oracle, curve_oracle ], {'from': admin}, ) oracle.setOracles( [renbtc, wbtc, lp, eurs, seur, lp_eurs], [ [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [10000, 10000, 10000], [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(renbtc, crrenbtc, {'from': admin}) homora.addBank(wbtc, crwbtc, {'from': admin}) homora.addBank(eurs, creurs, {'from': admin}) homora.addBank(seur, crseur, {'from': admin}) # setup initial funds to alice mint_tokens(renbtc, alice) mint_tokens(wbtc, alice) mint_tokens(eurs, alice) mint_tokens(seur, alice) mint_tokens(wbtc, crwbtc) # check alice's funds print(f'Alice renbtc balance {renbtc.balanceOf(alice)}') print(f'Alice wbtc balance {wbtc.balanceOf(alice)}') print(f'Alice eurs balance {eurs.balanceOf(alice)}') print(f'Alice seur balance {seur.balanceOf(alice)}') # steal some LP from the staking pool mint_tokens(lp, alice) mint_tokens(lp, bob) mint_tokens(lp_eurs, alice) # set approval renbtc.approve(homora, 2**256 - 1, {'from': alice}) renbtc.approve(crrenbtc, 2**256 - 1, {'from': alice}) wbtc.approve(homora, 2**256 - 1, {'from': alice}) wbtc.approve(crwbtc, 2**256 - 1, {'from': alice}) eurs.approve(homora, 2**256 - 1, {'from': alice}) eurs.approve(creurs, 2**256 - 1, {'from': alice}) seur.approve(homora, 2**256 - 1, {'from': alice}) seur.approve(crseur, 2**256 - 1, {'from': alice}) lp.approve(homora, 2**256 - 1, {'from': alice}) lp.approve(gauge, 2**256 - 1, {'from': bob}) lp_eurs.approve(homora, 2**256 - 1, {'from': alice}) curve_spell = CurveSpellV1.deploy( homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', wgauge, {'from': admin}) # register gauge wgauge.registerGauge(9, 0) wgauge.registerGauge(23, 0) # set up pools curve_spell.getPool(lp) curve_spell.getPool(lp_eurs) # first time call to reduce gas curve_spell.ensureApproveN(lp, 2, {'from': admin}) curve_spell.ensureApproveN(lp_eurs, 2, {'from': admin}) # whitelist spell in bank homora.setWhitelistSpells([curve_spell], [True], {'from': admin}) # whitelist lp in spell curve_spell.setWhitelistLPTokens([lp, lp_eurs], [True, True], {'from': admin}) ##################################################################################### print( '=========================================================================' ) print('Case 1.') prevABal = renbtc.balanceOf(alice) prevBBal = wbtc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_gauge = lp.balanceOf(gauge) renbtc_amt = 1 * 10**7 wbtc_amt = 1 * 10**7 lp_amt = 10**13 borrow_renbtc_amt = 0 borrow_wbtc_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 9 gid = 0 tx = homora.execute( 0, curve_spell, curve_spell.addLiquidity2.encode_input( lp, # LP [renbtc_amt, wbtc_amt], # supply tokens lp_amt, # supply LP [borrow_renbtc_amt, borrow_wbtc_amt], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) curABal = renbtc.balanceOf(alice) curBBal = wbtc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_gauge = lp.balanceOf(gauge) print('spell lp balance', lp.balanceOf(curve_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) _, _, _, renbtcDebt, renbtcDebtShare = homora.getBankInfo(renbtc) _, _, _, wbtcDebt, wbtcDebtShare = homora.getBankInfo(wbtc) print('bank renbtc totalDebt', renbtcDebt) print('bank renbtc totalShare', renbtcDebtShare) print('bank wbtc totalDebt', wbtcDebt) print('bank wbtc totalShare', wbtcDebtShare) print('bank prev LP balance', prevLPBal_bank) print('bank cur LP balance', curLPBal_bank) print('gauge prev LP balance', prevLPBal_gauge) print('gauge cur LP balance', curLPBal_gauge) # alice assert almostEqual(curABal - prevABal, -renbtc_amt), 'incorrect renbtc amt' assert almostEqual(curBBal - prevBBal, -wbtc_amt), 'incorrect wbtc amt' assert almostEqual(curLPBal - prevLPBal, -lp_amt), 'incorrect LP amt' # spell assert renbtc.balanceOf(curve_spell) == 0, 'non-zero spell renbtc balance' assert wbtc.balanceOf(curve_spell) == 0, 'non-zero spell wbtc balance' assert lp.balanceOf(curve_spell) == 0, 'non-zero spell LP balance' # debt assert renbtcDebt == borrow_renbtc_amt assert wbtcDebt == borrow_wbtc_amt _, _, collId, collSize = homora.getPositionInfo(1) print('collSize', collSize) # staking directly prevCrv = crv.balanceOf(bob) print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob)) pid, gid = 9, 0 gauge, _ = wgauge.gauges(pid, gid) print('gauge address', gauge) tx = interface.ILiquidityGauge(gauge).deposit(collSize, {'from': bob}) chain.sleep(20000) prevAliceCrvBalance = crv.balanceOf(alice) print('Alice crv balance', prevAliceCrvBalance) # ##################################################################################### print( '=========================================================================' ) print('Case 2. add liquidity (failed tx desired)') eurs_amt = 1 * 10**3 seur_amt = 1 * 10**3 lp_amt = 0 borrow_eurs_amt = 0 borrow_seur_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 9 gid = 0 try: tx = homora.execute( 1, curve_spell, curve_spell.addLiquidity2.encode_input( lp_eurs, # lp_eurs [eurs_amt, seur_amt], # supply tokens lp_amt, # supply LP [borrow_eurs_amt, borrow_seur_amt], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) assert False, 'tx should fail' except VirtualMachineError: pass # ##################################################################################### print( '=========================================================================' ) print('Case 3. add liquidity (failed tx desired)') eurs_amt = 1 * 10**3 seur_amt = 1 * 10**3 lp_amt = 0 borrow_eurs_amt = 0 borrow_seur_amt = 0 borrow_lp_amt = 0 minLPMint = 0 pid = 23 gid = 0 try: tx = homora.execute( 1, curve_spell, curve_spell.addLiquidity2.encode_input( lp_eurs, # lp_eurs [eurs_amt, seur_amt], # supply tokens lp_amt, # supply LP [borrow_eurs_amt, borrow_seur_amt], # borrow tokens borrow_lp_amt, # borrow LP minLPMint, # min LP mint pid, gid), {'from': alice}) assert False, 'tx should fail' except VirtualMachineError: pass # ##################################################################################### print( '=========================================================================' ) print('Case 4. remove liquidity (failed tx desired)') lp_take_amt = 2**256 - 1 # max lp_want = 1 * 10**17 eurs_repay = 2**256 - 1 # max seur_repay = 2**256 - 1 # max lp_repay = 0 try: tx = homora.execute( 1, curve_spell, curve_spell.removeLiquidity2.encode_input( lp_eurs, # lp_eurs token lp_take_amt, # LP amount to take out lp_want, # LP amount to withdraw to wallet [eurs_repay, seur_repay], # repay amounts lp_repay, # repay LP amount [0, 0] # min amounts ), {'from': alice}) assert False, 'tx should revert' except VirtualMachineError: pass # ##################################################################################### print( '=========================================================================' ) print('Case 5. remove liquidity') # remove liquidity from the same position prevABal = renbtc.balanceOf(alice) prevBBal = wbtc.balanceOf(alice) prevLPBal = lp.balanceOf(alice) prevLPBal_bank = lp.balanceOf(homora) prevLPBal_gauge = lp.balanceOf(gauge) _, _, _, collSize = homora.getPositionInfo(1) lp_take_amt = 2**256 - 1 # max lp_want = 1 * 10**12 renbtc_repay = 2**256 - 1 # max wbtc_repay = 2**256 - 1 # max lp_repay = 0 tx = homora.execute( 1, curve_spell, curve_spell.removeLiquidity2.encode_input( lp, # LP token lp_take_amt, # LP amount to take out lp_want, # LP amount to withdraw to wallet [renbtc_repay, wbtc_repay], # repay amounts lp_repay, # repay LP amount [0, 0] # min amounts ), {'from': alice}) curABal = renbtc.balanceOf(alice) curBBal = wbtc.balanceOf(alice) curLPBal = lp.balanceOf(alice) curLPBal_bank = lp.balanceOf(homora) curLPBal_gauge = lp.balanceOf(gauge) print('spell lp balance', lp.balanceOf(curve_spell)) print('spell renbtc balance', renbtc.balanceOf(curve_spell)) print('spell wbtc balance', wbtc.balanceOf(curve_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) _, _, _, renbtcDebt, renbtcDebtShare = homora.getBankInfo(renbtc) _, _, _, wbtcDebt, wbtcDebtShare = homora.getBankInfo(wbtc) print('bank renbtc totalDebt', renbtcDebt) print('bank renbtc totalDebt', renbtcDebt) print('bank wbtc totalShare', wbtcDebtShare) print('bank wbtc totalShare', wbtcDebtShare) print('LP want', lp_want) print('bank delta LP amount', curLPBal_bank - prevLPBal_bank) print('LP take amount', lp_take_amt) print('prev gauge LP balance', prevLPBal_gauge) print('cur gauge LP balance', curLPBal_gauge) print('coll size', collSize) # alice assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt' # gauge assert almostEqual(curLPBal_gauge - prevLPBal_gauge, -collSize), 'incorrect gauge LP amt' # spell assert renbtc.balanceOf(curve_spell) == 0, 'non-zero spell renbtc balance' assert wbtc.balanceOf(curve_spell) == 0, 'non-zero spell wbtc balance' assert lp.balanceOf(curve_spell) == 0, 'non-zero spell LP balance' # debt assert wbtcDebt == 0, 'wbtcDebt should be 0' assert renbtcDebt == 0, 'renbtcDebt should be 0' curAliceCrvBalance = crv.balanceOf(alice) print('Alice crv balance', curAliceCrvBalance) receivedCrv = curAliceCrvBalance - prevAliceCrvBalance print('received crv', receivedCrv) # check with staking directly minter = interface.ILiquidityGaugeMinter( interface.ILiquidityGauge(gauge).minter()) print('minter', minter) tx = minter.mint(gauge, {'from': bob}) print('tx status', tx.status) tx = interface.ILiquidityGauge(gauge).withdraw(collSize, {'from': bob}) receivedCrvFromGauge = crv.balanceOf(bob) - prevCrv print('receivedCrvFromGauge', receivedCrvFromGauge) assert almostEqual(receivedCrv, receivedCrvFromGauge) return tx
def test_curve_spell_wgauge(curve_spell, homora, oracle): alice = accounts[0] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') usdc = interface.IERC20Ex('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48') usdt = interface.IERC20Ex('0xdAC17F958D2ee523a2206206994597C13D831ec7') lp = interface.IERC20Ex('0x6c3f90f043a72fa612cbac8115ee7e52bde6e490') mint_tokens(dai, alice) mint_tokens(usdc, alice) mint_tokens(usdt, alice) dai.approve(homora, 2**256-1, {'from': alice}) usdc.approve(homora, 2**256-1, {'from': alice}) usdt.approve(homora, 0, {'from': alice}) usdt.approve(homora, 2**256-1, {'from': alice}) prevABal = dai.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevCBal = usdt.balanceOf(alice) prevETHBal = alice.balance() initABal = prevABal initBBal = prevBBal initCBal = prevCBal initETHBal = prevETHBal print('prev A bal', prevABal) print('prev B bal', prevBBal) print('prev C bal', prevCBal) tx = homora.execute( 0, curve_spell, curve_spell.addLiquidity3.encode_input( lp, # LP [10**18, 10**6, 10**6], # supply tokens 0, # supply LP [10**18, 0, 0], # borrow tokens 0, # borrow LP 0, # min LP mint 0, # pid 0 # gid ), {'from': alice} ) curABal = dai.balanceOf(alice) curBBal = usdc.balanceOf(alice) curCBal = usdt.balanceOf(alice) print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta C Bal', curCBal - prevCBal) prevABal = dai.balanceOf(alice) prevBBal = usdc.balanceOf(alice) prevETHBal = alice.balance() position_id = homora.nextPositionId() tx = homora.execute( position_id - 1, curve_spell, curve_spell.removeLiquidity3.encode_input( lp, # LP token 2**256-1, # LP amount to take out 0, # LP amount to withdraw to wallet [2**256-1, 0, 0], # repay amounts 0, # repay LP amount [0, 0, 0] # min amounts ), {'from': alice} ) curABal = dai.balanceOf(alice) curBBal = usdc.balanceOf(alice) curCBal = usdt.balanceOf(alice) curETHBal = alice.balance() finalABal = curABal finalBBal = curBBal finalCBal = curCBal finalETHBal = curETHBal tokenAPrice = oracle.getETHPx(dai) tokenBPrice = oracle.getETHPx(usdc) tokenCPrice = oracle.getETHPx(usdt) tokenETHPrice = oracle.getETHPx('0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE') print('alice delta A Bal', curABal - prevABal) print('alice delta B Bal', curBBal - prevBBal) print('alice delta C Bal', curCBal - prevCBal) print('alice delta ETH Bal', curETHBal - prevETHBal) print('token A price', tokenAPrice) print('token B price', tokenBPrice) print('token C price', tokenCPrice) print('token ETH price', tokenETHPrice) assert almostEqual(tokenAPrice * initABal + tokenBPrice * initBBal + tokenCPrice * initCBal + tokenETHPrice * initETHBal, tokenAPrice * finalABal + tokenBPrice * finalBBal + tokenCPrice * finalCBal + tokenETHPrice * finalETHBal), 'too much value lost'
def main(): admin = accounts[0] alice = accounts[1] bob = accounts[2] dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F') cydai = interface.IERC20Ex('0x8e595470ed749b85c6f7669de83eae304c2ec68f') homora = HomoraBank.deploy({'from': admin}) safebox = SafeBox.deploy(cydai, 'Yearn Wrapped DAI', 'cyDAI', {'from': admin}) # set up funds to alice mint_tokens(dai, alice) mint_tokens(dai, bob) # approve dai dai.approve(safebox, 2**256 - 1, {'from': alice}) dai.approve(safebox, 2**256 - 1, {'from': bob}) ################################################################# # deposit print('====================================') print('Case 1. deposit') prevDAIAlice = dai.balanceOf(alice) prevDAIBob = dai.balanceOf(bob) prevIBDAIAlice = safebox.balanceOf(alice) prevIBDAIBob = safebox.balanceOf(bob) alice_amt = 10**18 bob_amt = 10**18 safebox.deposit(alice_amt, {'from': alice}) chain.mine(20) safebox.deposit(bob_amt, {'from': bob}) curDAIAlice = dai.balanceOf(alice) curDAIBob = dai.balanceOf(bob) curIBDAIAlice = safebox.balanceOf(alice) curIBDAIBob = safebox.balanceOf(bob) print('∆ dai alice', curDAIAlice - prevDAIAlice) print('∆ dai bob', curDAIBob - prevDAIBob) print('∆ ibDAI bal alice', curIBDAIAlice - prevIBDAIAlice) print('∆ ibDAI bal bob', curIBDAIBob - prevIBDAIBob) print('calculated ibDAI alice', alice_amt * 10**18 // cydai.exchangeRateStored()) print('calculated ibDAI bob', bob_amt * 10**18 // cydai.exchangeRateStored()) assert curDAIAlice - prevDAIAlice == -alice_amt, 'incorrect alice amount' assert curDAIBob - prevDAIBob == -bob_amt, 'incorrect bob amount' assert almostEqual(curIBDAIAlice - prevIBDAIAlice, alice_amt * 10**18 // cydai.exchangeRateStored()) assert almostEqual(curIBDAIBob - prevIBDAIBob, bob_amt * 10**18 // cydai.exchangeRateStored()) chain.mine(200) ################################################################# # alice withdraws 1/3 & 2/3. bob withdraws all. print('====================================') print('Case 2. withdraw') alice_withdraw_1 = safebox.balanceOf(alice) // 3 alice_withdraw_2 = safebox.balanceOf(alice) - alice_withdraw_1 bob_withdraw = safebox.balanceOf(bob) prevDAIAlice = dai.balanceOf(alice) prevDAIBob = dai.balanceOf(bob) prevIBDAIAlice = safebox.balanceOf(alice) prevIBDAIBob = safebox.balanceOf(bob) safebox.withdraw(alice_withdraw_1, {'from': alice}) chain.mine(20) safebox.withdraw(bob_withdraw, {'from': bob}) curDAIAlice = dai.balanceOf(alice) curDAIBob = dai.balanceOf(bob) curIBDAIAlice = safebox.balanceOf(alice) curIBDAIBob = safebox.balanceOf(bob) print('∆ dai alice', curDAIAlice - prevDAIAlice) print('∆ dai bob', curDAIBob - prevDAIBob) print('∆ ibDAI bal alice', curIBDAIAlice - prevIBDAIAlice) print('∆ ibDAI bal bob', curIBDAIBob - prevIBDAIBob) assert almostEqual(curDAIAlice - prevDAIAlice, alice_amt // 3), 'incorrect alice withdraw dai amount' assert almostEqual(curDAIBob - prevDAIBob, bob_amt), 'incorrect bob withdraw dai amount' assert curIBDAIAlice - prevIBDAIAlice == -alice_withdraw_1, 'incorrect alice ∆ibDAI' assert curIBDAIBob - prevIBDAIBob == -bob_withdraw, 'incorrect bob ∆ibDAI' chain.mine(20) prevDAIAlice = dai.balanceOf(alice) prevIBDAIAlice = safebox.balanceOf(alice) safebox.withdraw(alice_withdraw_2, {'from': alice}) curDAIAlice = dai.balanceOf(alice) curIBDAIAlice = safebox.balanceOf(alice) print('∆ dai alice', curDAIAlice - prevDAIAlice) print('∆ dai bob', curDAIBob - prevDAIBob) print('∆ ibDAI bal alice', curIBDAIAlice - prevIBDAIAlice) print('∆ ibDAI bal bob', curIBDAIBob - prevIBDAIBob) assert almostEqual(curDAIAlice - prevDAIAlice, alice_amt * 2 // 3), 'incorrect alice second withdraw dai amount' assert curIBDAIAlice - prevIBDAIAlice == -alice_withdraw_2, 'incorrect alice second ∆ibDAI '
def mint_tokens(token, to, amount=None): if amount is None: # default is 1M tokens amount = 10**12 * 10**token.decimals() if token == USDT: owner = token.owner() token.issue(amount, {'from': owner}) token.transfer(to, amount, {'from': owner}) elif token == USDC: master_minter = token.masterMinter() token.configureMinter(master_minter, 2**256 - 1, {'from': master_minter}) token.mint(to, amount, {'from': master_minter}) elif token == DAI: auth = '0x9759a6ac90977b93b58547b4a71c78317f391a28' token.mint(to, amount, {'from': auth}) elif token == AUSDT: pool = '0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9' token.mint(to, amount, 10**18, {'from': pool}) elif token == AUSDC: pool = '0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9' token.mint(to, amount, 10**18, {'from': pool}) elif token == ADAI: pool = '0x7d2768de32b0b80b7a3454c06bdac94a69ddc7a9' token.mint(to, amount, 10**18, {'from': pool}) elif token == WETH: token.deposit({'from': to, 'value': amount}) elif token == SUSD: target = interface.IERC20Ex(token.target()) contract_issuer = target.resolverAddressesRequired()[2] resolver = interface.IERC20Ex(target.resolver()) resolver_target = interface.IERC20Ex(resolver.target()) issuer = resolver_target.repository(contract_issuer) target.issue(to, amount, {'from': issuer}) elif token == HUSD: issuer = '0xc2fbf9b9084e92f9649ca4cec9043daac9092539' token.issue(to, amount, {'from': issuer}) elif token == BUSD: supply_controller = token.supplyController() token.increaseSupply(amount, {'from': supply_controller}) token.transfer(to, amount, {'from': supply_controller}) elif token == YDAI: mint_tokens(interface.IERC20Ex(DAI), to, amount) interface.IERC20Ex(DAI).approve(token, 0, {'from': to}) interface.IERC20Ex(DAI).approve(token, 2**256 - 1, {'from': to}) token.deposit(amount, {'from': to}) elif token == YUSDT: mint_tokens(interface.IERC20Ex(USDT), to, amount) interface.IERC20Ex(USDT).approve(token, 0, {'from': to}) interface.IERC20Ex(USDT).approve(token, 2**256 - 1, {'from': to}) token.deposit(amount, {'from': to}) elif token == YBUSD: mint_tokens(interface.IERC20Ex(BUSD), to, amount) interface.IERC20Ex(BUSD).approve(token, 0, {'from': to}) interface.IERC20Ex(BUSD).approve(token, 2**256 - 1, {'from': to}) token.deposit(amount, {'from': to}) elif token == YUSDC: mint_tokens(interface.IERC20Ex(USDC), to, amount) interface.IERC20Ex(USDC).approve(token, 0, {'from': to}) interface.IERC20Ex(USDC).approve(token, 2**256 - 1, {'from': to}) token.deposit(amount, {'from': to}) elif token == DPI: module = token.getModules()[0] token.mint(to, amount, {'from': module}) elif token == WBTC: owner = token.owner() token.mint(to, amount, {'from': owner}) elif token == RENBTC: owner = token.owner() token.mint(to, amount, {'from': owner}) elif token == PERP: owner = token.owner() token.addMinter(owner, {'from': owner}) token.mint(to, amount, {'from': owner}) elif token == DFD: gov = token.governance() token.mint(to, amount, {'from': gov}) elif token == DUSD: core = token.core() token.mint(to, amount, {'from': core}) elif token == EURS: owner = '0x2EbBbc541E8f8F24386FA319c79CedA0579f1Efb' token.createTokens(amount, {'from': owner}) token.transfer(to, amount, {'from': owner}) elif token == SEUR: target = interface.IERC20Ex(token.target()) contract_issuer = target.resolverAddressesRequired()[2] resolver = interface.IERC20Ex(target.resolver()) resolver_target = interface.IERC20Ex(resolver.target()) issuer = resolver_target.repository(contract_issuer) target.issue(to, amount, {'from': issuer}) elif token == YFI: governor = token.governance() token.addMinter(to, {'from': governor}) token.mint(to, amount, {'from': to}) elif is_uni_lp(token): router = interface.IUniswapV2Router02( '0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D') # Uniswap LP token token0 = interface.IERC20Ex(token.token0()) token1 = interface.IERC20Ex(token.token1()) # mint underlying amount0 = 10**12 * 10**token0.decimals() amount1 = 10**12 * 10**token1.decimals() mint_tokens(token0, to, amount0) mint_tokens(token1, to, amount1) # approve router token0.approve(router, 0, {'from': to}) token0.approve(router, 2**256 - 1, {'from': to}) token1.approve(router, 0, {'from': to}) token1.approve(router, 2**256 - 1, {'from': to}) # add liquidity interface.IUniswapV2Router02(router).addLiquidity( token0, token1, amount0, amount1, 0, 0, to, chain.time() + 1200, {'from': to}) elif is_sushi_lp(token): router = interface.IUniswapV2Router02( '0xd9e1ce17f2641f24ae83637ab66a2cca9c378b9f') # Sushiswap LP token token0 = interface.IERC20Ex(token.token0()) token1 = interface.IERC20Ex(token.token1()) # mint underlying amount0 = 10**12 * 10**token0.decimals() amount1 = 10**12 * 10**token1.decimals() mint_tokens(token0, to, amount0) mint_tokens(token1, to, amount1) # approve router token0.approve(router, 0, {'from': to}) token0.approve(router, 2**256 - 1, {'from': to}) token1.approve(router, 0, {'from': to}) token1.approve(router, 2**256 - 1, {'from': to}) # add liquidity interface.IUniswapV2Router02(router).addLiquidity( token0, token1, amount0, amount1, 0, 0, to, chain.time() + 1200, {'from': to}) elif is_bal_lp(token): # Balancer LP token tokens = token.getFinalTokens() max_amts = [] amt_desired = 10**100 for _token in tokens: _token = interface.IERC20Ex(_token) amt = 10**12 * 10**_token.decimals() mint_tokens(_token, to, amt) _token.approve(token, 0, {'from': to}) _token.approve(token, 2**256 - 1, {'from': to}) max_amts.append(amt) amt_desired = min( amt_desired, amt * token.totalSupply() // token.getBalance(_token)) token.joinPool(amt_desired * 9 // 10, max_amts, {'from': to}) elif is_crv_lp(token): # Curve LP token registry = interface.ICurveRegistry( '0x7d86446ddb609ed0f5f8684acf30380a356b2b4c') pool = registry.get_pool_from_lp_token(token) tokens = registry.get_coins(pool) amts = [] for _token in tokens: if _token == '0x0000000000000000000000000000000000000000': continue _token = interface.IERC20Ex(_token) amt = 10**6 * 10**_token.decimals() prevBal = _token.balanceOf(to) mint_tokens(_token, to, amt) curBal = _token.balanceOf(to) amts.append(curBal - prevBal) interface.IERC20Ex(_token).approve(pool, 0, {'from': to}) interface.IERC20Ex(_token).approve(pool, 2**256 - 1, {'from': to}) desc = f'uint[{len(amts)}],uint' print('adding liquidity to curve') print(amts) interface.ICurvePool(pool).add_liquidity[desc](amts, 0, {'from': to}) else: raise Exception('unsupported token')