Exemple #1
0
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)
Exemple #2
0
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)
Exemple #3
0
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)
Exemple #4
0
def main():
    admin = accounts[0]

    alice = accounts[1]
    bob = accounts[2]
    dfd = interface.IERC20Ex('0x20c36f062a31865bED8a5B1e512D9a1A20AA333A')
    dusd = interface.IERC20Ex('0x5BC25f649fc4e26069dDF4cF4010F9f706c23831')

    lp = interface.IERC20Ex('0xd8e9690eff99e21a2de25e0b148ffaf47f47c972')
    # pool is lp for balancer
    pool = interface.IBalancerPool(
        '0xd8e9690eff99e21a2de25e0b148ffaf47f47c972')

    crdfd = MockCErc20.deploy(dfd, {'from': admin})
    crdusd = MockCErc20.deploy(dusd, {'from': admin})

    werc20 = WERC20.deploy({'from': admin})

    staking = accounts.at('0xf068236ecad5fabb9883bbb26a6445d6c7c9a924',
                          force=True)

    wstaking = WStakingRewards.deploy(staking, lp, dfd, {'from': admin})

    simple_oracle = SimpleOracle.deploy({'from': admin})
    simple_oracle.setETHPx([dfd, dusd],
                           [2**112 // 2 // 700, 2**112 * 2 // 700])

    balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': alice})

    core_oracle = CoreOracle.deploy({'from': admin})
    oracle = ProxyOracle.deploy(core_oracle, {'from': admin})
    oracle.setWhitelistERC1155([werc20, wstaking], True, {'from': admin})
    core_oracle.setRoute(
        [dfd, dusd, lp],
        [simple_oracle, simple_oracle, balancer_oracle],
        {'from': admin},
    )
    oracle.setOracles(
        [dfd, dusd, lp],
        [
            [10000, 10000, 10000],
            [10000, 10000, 10000],
            [10000, 10000, 10000],
        ],
        {'from': admin},
    )

    homora = HomoraBank.deploy({'from': admin})
    homora.initialize(oracle, 1000, {'from': admin})  # 10% fee
    setup_bank_hack(homora)
    homora.addBank(dfd, crdfd, {'from': admin})
    homora.addBank(dusd, crdusd, {'from': admin})

    # setup initial funds to alice
    mint_tokens(dfd, alice)
    mint_tokens(dusd, alice)

    # check alice's funds
    print(f'Alice dusd balance {dusd.balanceOf(alice)}')
    print(f'Alice dfd balance {dfd.balanceOf(alice)}')

    # Steal some LP from the staking pool
    mint_tokens(lp, alice)
    mint_tokens(lp, bob)

    # set approval
    dfd.approve(homora, 2**256 - 1, {'from': alice})
    dfd.approve(crdfd, 2**256 - 1, {'from': alice})
    dusd.approve(homora, 2**256 - 1, {'from': alice})
    dusd.approve(crdusd, 2**256 - 1, {'from': alice})
    lp.approve(homora, 2**256 - 1, {'from': alice})
    lp.approve(staking, 2**256 - 1, {'from': bob})

    balancer_spell = BalancerSpellV1.deploy(
        homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
        {'from': admin})
    # first time call to reduce gas
    balancer_spell.getPair(lp, {'from': admin})

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 1.')

    prevABal = dfd.balanceOf(alice)
    prevBBal = dusd.balanceOf(alice)
    prevLPBal = lp.balanceOf(alice)
    prevLPBal_bank = lp.balanceOf(homora)
    prevLPBal_staking = lp.balanceOf(staking)

    prevARes = interface.IBalancerPool(lp).getBalance(dfd)
    prevBRes = interface.IBalancerPool(lp).getBalance(dusd)

    dfd_amt = 100 * 10**18
    dusd_amt = 10**18
    lp_amt = 0
    borrow_dfd_amt = 0
    borrow_dusd_amt = 0

    # calculate slippage control
    total_dfd_amt = dfd_amt + borrow_dfd_amt
    total_dusd_amt = dusd_amt + borrow_dusd_amt
    dfd_weight = 0.58
    dusd_weight = 0.42

    ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \
        (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1
    lp_desired = lp_amt + int(
        interface.IERC20(lp).totalSupply() * ratio * 0.995)
    print('lp desired', lp_desired)

    tx = homora.execute(
        0,
        balancer_spell,
        balancer_spell.addLiquidityWStakingRewards.encode_input(
            lp,  # lp token
            [
                dfd_amt,  # supply DFD
                dusd_amt,  # supply DUSD
                lp_amt,  # supply LP
                borrow_dfd_amt,  # borrow DFD
                borrow_dusd_amt,  # borrow DUSD
                0,  # borrow LP tokens
                lp_desired
            ],  # LP desired
            wstaking),
        {'from': alice})

    curABal = dfd.balanceOf(alice)
    curBBal = dusd.balanceOf(alice)
    curLPBal = lp.balanceOf(alice)
    curLPBal_bank = lp.balanceOf(homora)
    curLPBal_staking = lp.balanceOf(staking)

    curARes = interface.IBalancerPool(lp).getBalance(dfd)
    curBRes = interface.IBalancerPool(lp).getBalance(dusd)

    print('spell lp balance', lp.balanceOf(balancer_spell))
    print('Alice delta A balance', curABal - prevABal)
    print('Alice delta B balance', curBBal - prevBBal)
    print('add liquidity gas', tx.gas_used)
    print('bank lp balance', curLPBal_bank)

    _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd)
    print('bank dfd dfdDebt', dfdDebt)
    print('bank dfd dfdShare', dfdShare)

    print('bank prev LP balance', prevLPBal_bank)
    print('bank cur LP balance', curLPBal_bank)

    print('staking prev LP balance', prevLPBal_staking)
    print('staking cur LP balance', curLPBal_staking)

    print('prev dfd res', prevARes)
    print('cur dfd res', curARes)

    print('prev dusd res', prevBRes)
    print('cur dusd res', curBRes)

    # alice
    assert almostEqual(curABal - prevABal, -dfd_amt), 'incorrect DFD amt'
    assert almostEqual(curBBal - prevBBal, -dusd_amt), 'incorrect DUSD amt'
    assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt'

    # spell
    assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance'
    assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance'
    assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance'
    assert dfdDebt == borrow_dfd_amt

    # check balance and pool reserves
    assert almostEqual(
        curABal - prevABal - borrow_dfd_amt,
        -(curARes - prevARes)), 'not all DFD tokens go to LP pool'
    assert almostEqual(
        curBBal - prevBBal - borrow_dusd_amt,
        -(curBRes - prevBRes)), 'not all DUSD tokens go to LP pool'

    _, _, collId, collSize = homora.getPositionInfo(1)
    print('collSize', collSize)

    # staking directly
    prevDfd = dfd.balanceOf(bob)
    print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob))
    tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob})

    chain.sleep(20000)

    prevAliceDfdBalance = dfd.balanceOf(alice)
    print('Alice dfd balance', prevAliceDfdBalance)

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 2. add liquidity the second time')

    prevABal = dfd.balanceOf(alice)
    prevBBal = dusd.balanceOf(alice)
    prevLPBal = lp.balanceOf(alice)
    prevLPBal_bank = lp.balanceOf(homora)
    prevLPBal_staking = lp.balanceOf(staking)

    prevARes = interface.IBalancerPool(lp).getBalance(dfd)
    prevBRes = interface.IBalancerPool(lp).getBalance(dusd)

    dfd_amt = 100 * 10**18
    dusd_amt = 10**18
    lp_amt = 0
    borrow_dfd_amt = 0
    borrow_dusd_amt = 0

    # calculate slippage control
    total_dfd_amt = dfd_amt + borrow_dfd_amt
    total_dusd_amt = dusd_amt + borrow_dusd_amt
    dfd_weight = 0.58
    dusd_weight = 0.42

    ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \
        (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1
    lp_desired = lp_amt + int(
        interface.IERC20(lp).totalSupply() * ratio * 0.995)
    print('lp desired', lp_desired)

    tx = homora.execute(
        1,
        balancer_spell,
        balancer_spell.addLiquidityWStakingRewards.encode_input(
            lp,  # lp token
            [
                dfd_amt,  # supply DFD
                dusd_amt,  # supply DUSD
                lp_amt,  # supply LP
                borrow_dfd_amt,  # borrow DFD
                borrow_dusd_amt,  # borrow DUSD
                0,  # borrow LP tokens
                lp_desired
            ],  # LP desired
            wstaking),
        {'from': alice})

    curABal = dfd.balanceOf(alice)
    curBBal = dusd.balanceOf(alice)
    curLPBal = lp.balanceOf(alice)
    curLPBal_bank = lp.balanceOf(homora)
    curLPBal_staking = lp.balanceOf(staking)

    curARes = interface.IBalancerPool(lp).getBalance(dfd)
    curBRes = interface.IBalancerPool(lp).getBalance(dusd)

    print('spell lp balance', lp.balanceOf(balancer_spell))
    print('Alice delta A balance', curABal - prevABal)
    print('Alice delta B balance', curBBal - prevBBal)
    print('add liquidity gas', tx.gas_used)
    print('bank lp balance', curLPBal_bank)

    _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd)
    print('bank dfd dfdDebt', dfdDebt)
    print('bank dfd dfdShare', dfdShare)

    print('bank prev LP balance', prevLPBal_bank)
    print('bank cur LP balance', curLPBal_bank)

    print('staking prev LP balance', prevLPBal_staking)
    print('staking cur LP balance', curLPBal_staking)

    print('prev dfd res', prevARes)
    print('cur dfd res', curARes)

    print('prev dusd res', prevBRes)
    print('cur dusd res', curBRes)

    # alice
    assert almostEqual(curABal - prevABal, -dfd_amt), 'incorrect DFD amt'
    assert almostEqual(curBBal - prevBBal, -dusd_amt), 'incorrect DUSD amt'
    assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt'

    # spell
    assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance'
    assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance'
    assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance'
    assert dfdDebt == borrow_dfd_amt

    # check balance and pool reserves
    assert almostEqual(
        curABal - prevABal - borrow_dfd_amt,
        -(curARes - prevARes)), 'not all DFD tokens go to LP pool'
    assert almostEqual(
        curBBal - prevBBal - borrow_dusd_amt,
        -(curBRes - prevBRes)), 'not all DUSD tokens go to LP pool'

    curAliceDfdBalance = dfd.balanceOf(alice)
    print('Alice dfd balance', curAliceDfdBalance)
    receivedDfd = curAliceDfdBalance - prevAliceDfdBalance + dfd_amt
    print('received dfd', receivedDfd)

    # check with staking directly
    tx = interface.IStakingRewards(staking).getReward({'from': bob})
    receivedDfdFromStaking = dfd.balanceOf(bob) - prevDfd
    print('receivedDfdFromStaking', receivedDfdFromStaking)
    assert almostEqual(receivedDfd, receivedDfdFromStaking)

    return tx
Exemple #5
0
def main():
    admin = accounts[0]

    alice = accounts[1]
    bob = accounts[2]
    dfd = interface.IERC20Ex('0x20c36f062a31865bED8a5B1e512D9a1A20AA333A')
    dusd = interface.IERC20Ex('0x5BC25f649fc4e26069dDF4cF4010F9f706c23831')
    weth = interface.IERC20Ex('0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2')
    dai = interface.IERC20Ex('0x6B175474E89094C44Da98b954EedeAC495271d0F')

    lp = interface.IERC20Ex('0xd8e9690eff99e21a2de25e0b148ffaf47f47c972')

    # pool is lp for balancer
    pool = interface.IBalancerPool(
        '0xd8e9690eff99e21a2de25e0b148ffaf47f47c972')
    lp_dai = interface.IERC20Ex('0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a')
    pool_dai = interface.IBalancerPool(
        '0x8b6e6e7b5b3801fed2cafd4b22b8a16c2f2db21a')

    crdfd = MockCErc20.deploy(dfd, {'from': admin})
    crdusd = MockCErc20.deploy(dusd, {'from': admin})
    crdai = MockCErc20.deploy(dai, {'from': admin})
    crweth = MockCErc20.deploy(weth, {'from': admin})

    werc20 = WERC20.deploy({'from': admin})

    staking = accounts.at('0xf068236ecad5fabb9883bbb26a6445d6c7c9a924',
                          force=True)

    wstaking = WStakingRewards.deploy(staking, lp, dfd, {'from': admin})

    simple_oracle = SimpleOracle.deploy({'from': admin})
    simple_oracle.setETHPx([dfd, dusd],
                           [2**112 // 2 // 700, 2**112 * 2 // 700])

    balancer_oracle = BalancerPairOracle.deploy(simple_oracle, {'from': alice})

    core_oracle = CoreOracle.deploy({'from': admin})
    oracle = ProxyOracle.deploy(core_oracle, {'from': admin})
    oracle.setWhitelistERC1155([werc20, wstaking], True, {'from': admin})
    core_oracle.setRoute(
        [dfd, dusd, lp],
        [simple_oracle, simple_oracle, balancer_oracle],
        {'from': admin},
    )
    oracle.setOracles(
        [dfd, dusd, lp],
        [
            [10000, 10000, 10000],
            [10000, 10000, 10000],
            [10000, 10000, 10000],
        ],
        {'from': admin},
    )

    homora = HomoraBank.deploy({'from': admin})
    homora.initialize(oracle, 1000, {'from': admin})  # 10% fee
    setup_bank_hack(homora)
    homora.addBank(dfd, crdfd, {'from': admin})
    homora.addBank(dusd, crdusd, {'from': admin})

    # setup initial funds to alice
    mint_tokens(dfd, alice)
    mint_tokens(dusd, alice)

    mint_tokens(weth, alice)
    mint_tokens(dai, alice)

    mint_tokens(dfd, crdfd)

    # check alice's funds
    print(f'Alice dusd balance {dusd.balanceOf(alice)}')
    print(f'Alice dfd balance {dfd.balanceOf(alice)}')

    # Steal some LP from the staking pool
    mint_tokens(lp, alice)
    mint_tokens(lp, bob)

    # set approval
    dfd.approve(homora, 2**256 - 1, {'from': alice})
    dfd.approve(crdfd, 2**256 - 1, {'from': alice})
    dusd.approve(homora, 2**256 - 1, {'from': alice})
    dusd.approve(crdusd, 2**256 - 1, {'from': alice})
    dai.approve(homora, 2**256 - 1, {'from': alice})
    dai.approve(crdai, 2**256 - 1, {'from': alice})
    weth.approve(homora, 2**256 - 1, {'from': alice})
    weth.approve(crweth, 2**256 - 1, {'from': alice})

    lp.approve(homora, 2**256 - 1, {'from': alice})
    lp.approve(staking, 2**256 - 1, {'from': bob})

    balancer_spell = BalancerSpellV1.deploy(
        homora, werc20, '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2',
        {'from': admin})
    # first time call to reduce gas
    balancer_spell.getPair(lp, {'from': admin})

    # whitelist spell in bank
    homora.setWhitelistSpells([balancer_spell], [True], {'from': admin})

    # whitelist token in bank
    homora.setWhitelistTokens([dfd], [True], {'from': admin})

    # whitelist lp in spell
    balancer_spell.setWhitelistLPTokens([lp, lp_dai], [True, True],
                                        {'from': admin})

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 1.')

    prevABal = dfd.balanceOf(alice)
    prevBBal = dusd.balanceOf(alice)
    prevLPBal = lp.balanceOf(alice)
    prevLPBal_bank = lp.balanceOf(homora)
    prevLPBal_staking = lp.balanceOf(staking)

    prevARes = interface.IBalancerPool(lp).getBalance(dfd)
    prevBRes = interface.IBalancerPool(lp).getBalance(dusd)

    dfd_amt = 100 * 10**18
    dusd_amt = 10**18
    lp_amt = 0
    borrow_dfd_amt = 10**18
    borrow_dusd_amt = 0

    # calculate slippage control
    total_dfd_amt = dfd_amt + borrow_dfd_amt
    total_dusd_amt = dusd_amt + borrow_dusd_amt
    dfd_weight = 0.58
    dusd_weight = 0.42

    ratio = (((prevARes + total_dfd_amt) / prevARes) ** dfd_weight) * \
        (((prevBRes + total_dusd_amt) / prevBRes) ** dusd_weight) - 1
    lp_desired = lp_amt + int(
        interface.IERC20(lp).totalSupply() * ratio * 0.995)
    print('lp desired', lp_desired)

    tx = homora.execute(
        0,
        balancer_spell,
        balancer_spell.addLiquidityWStakingRewards.encode_input(
            lp,  # lp token
            [
                dfd_amt,  # supply DFD
                dusd_amt,  # supply DUSD
                lp_amt,  # supply LP
                borrow_dfd_amt,  # borrow DFD
                borrow_dusd_amt,  # borrow DUSD
                0,  # borrow LP tokens
                lp_desired
            ],  # LP desired
            wstaking),
        {'from': alice})

    curABal = dfd.balanceOf(alice)
    curBBal = dusd.balanceOf(alice)
    curLPBal = lp.balanceOf(alice)
    curLPBal_bank = lp.balanceOf(homora)
    curLPBal_staking = lp.balanceOf(staking)

    curARes = interface.IBalancerPool(lp).getBalance(dfd)
    curBRes = interface.IBalancerPool(lp).getBalance(dusd)

    print('spell lp balance', lp.balanceOf(balancer_spell))
    print('Alice delta A balance', curABal - prevABal)
    print('Alice delta B balance', curBBal - prevBBal)
    print('add liquidity gas', tx.gas_used)
    print('bank lp balance', curLPBal_bank)

    _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd)
    print('bank dfd dfdDebt', dfdDebt)
    print('bank dfd dfdShare', dfdShare)

    print('bank prev LP balance', prevLPBal_bank)
    print('bank cur LP balance', curLPBal_bank)

    print('staking prev LP balance', prevLPBal_staking)
    print('staking cur LP balance', curLPBal_staking)

    print('prev dfd res', prevARes)
    print('cur dfd res', curARes)

    print('prev dusd res', prevBRes)
    print('cur dusd res', curBRes)

    # alice
    assert almostEqual(curABal - prevABal, -dfd_amt), 'incorrect DFD amt'
    assert almostEqual(curBBal - prevBBal, -dusd_amt), 'incorrect DUSD amt'
    assert curLPBal - prevLPBal == -lp_amt, 'incorrect LP amt'

    # spell
    assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance'
    assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance'
    assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance'
    assert dfdDebt == borrow_dfd_amt

    # check balance and pool reserves
    assert almostEqual(
        curABal - prevABal - borrow_dfd_amt,
        -(curARes - prevARes)), 'not all DFD tokens go to LP pool'
    assert almostEqual(
        curBBal - prevBBal - borrow_dusd_amt,
        -(curBRes - prevBRes)), 'not all DUSD tokens go to LP pool'

    _, _, collId, collSize = homora.getPositionInfo(1)
    print('collSize', collSize)

    # staking directly
    prevDfd = dfd.balanceOf(bob)
    print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob))
    tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob})

    chain.sleep(20000)

    prevAliceDfdBalance = dfd.balanceOf(alice)
    print('Alice dfd balance', prevAliceDfdBalance)

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 2. add liquidity (failed tx desired)')

    weth_amt = 100 * 10**18
    dai_amt = 10**18
    lp_amt = 0
    borrow_weth_amt = 0
    borrow_dai_amt = 0

    # calculate slippage control
    total_weth_amt = weth_amt + borrow_weth_amt
    total_dai_amt = dai_amt + borrow_dai_amt
    dfd_weight = 0.8
    dusd_weight = 0.2

    ratio = (((prevARes + total_weth_amt) / prevARes) ** dfd_weight) * \
        (((prevBRes + total_dai_amt) / prevBRes) ** dusd_weight) - 1
    lp_desired = lp_amt + int(
        interface.IERC20(lp).totalSupply() * ratio * 0.995)
    lp_desired = 0
    print('lp desired', lp_desired)

    try:
        tx = homora.execute(
            1,
            balancer_spell,
            balancer_spell.addLiquidityWStakingRewards.encode_input(
                lp_dai,  # lp token
                [
                    weth_amt,  # supply DFD
                    dai_amt,  # supply DUSD
                    lp_amt,  # supply LP
                    borrow_weth_amt,  # borrow DFD
                    borrow_dai_amt,  # borrow DUSD
                    0,  # borrow LP tokens
                    lp_desired
                ],  # LP desired
                wstaking),
            {'from': alice})
        assert False, 'tx should fail'
    except VirtualMachineError:
        pass

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 3. remove liquidity (failed tx desired)')

    lp_take_amt = 2**256 - 1  # max
    lp_want = 0
    weth_repay = 2**256 - 1  # max
    dai_repay = 2**256 - 1  # max

    real_weth_repay = homora.borrowBalanceStored(1, dfd)
    _, _, _, real_lp_take_amt = homora.getPositionInfo(1)

    expected_withdraw_dfd = collSize * prevARes // interface.IBalancerPool(
        lp).totalSupply()
    print('expected withdraw DFD', expected_withdraw_dfd)

    try:
        tx = homora.execute(
            1,
            balancer_spell,
            balancer_spell.removeLiquidityWStakingRewards.encode_input(
                lp_dai,  # LP token
                [
                    lp_take_amt,  # take out LP tokens
                    lp_want,  # withdraw LP tokens to wallet
                    weth_repay,  # repay DFD
                    dai_repay,  # repay DUSD
                    0,  # repay LP
                    0,  # min DFD
                    0
                ],  # min DUSD
                wstaking),
            {'from': alice})
        assert False, 'tx should fail'
    except VirtualMachineError:
        pass

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 4. remove liquidity')

    # remove liquidity from the same position
    prevABal = dfd.balanceOf(alice)
    prevBBal = dusd.balanceOf(alice)
    prevETHBal = alice.balance()
    prevLPBal = lp.balanceOf(alice)
    prevLPBal_bank = lp.balanceOf(homora)
    prevLPBal_staking = lp.balanceOf(staking)
    prevETHBal = alice.balance()
    prevCrdfdBal = lp.balanceOf(crdfd)

    prevARes = interface.IBalancerPool(lp).getBalance(dfd)
    prevBRes = interface.IBalancerPool(lp).getBalance(dusd)

    lp_take_amt = 2**256 - 1  # max
    lp_want = 0
    dfd_repay = 2**256 - 1  # max
    dusd_repay = 0

    real_dfd_repay = homora.borrowBalanceStored(1, dfd)
    _, _, _, real_lp_take_amt = homora.getPositionInfo(1)

    expected_withdraw_dfd = collSize * prevARes // interface.IBalancerPool(
        lp).totalSupply()
    print('expected withdraw DFD', expected_withdraw_dfd)

    tx = homora.execute(
        1,
        balancer_spell,
        balancer_spell.removeLiquidityWStakingRewards.encode_input(
            lp,  # LP token
            [
                lp_take_amt,  # take out LP tokens
                lp_want,  # withdraw LP tokens to wallet
                dfd_repay,  # repay DFD
                dusd_repay,  # repay DUSD
                0,  # repay LP
                0,  # min DFD
                0
            ],  # min DUSD
            wstaking),
        {'from': alice})

    curABal = dfd.balanceOf(alice)
    curBBal = dusd.balanceOf(alice)
    curETHBal = alice.balance()
    curLPBal = lp.balanceOf(alice)
    curLPBal_bank = lp.balanceOf(homora)
    curLPBal_staking = lp.balanceOf(staking)
    curETHBal = alice.balance()
    curCrdfdBal = lp.balanceOf(crdfd)

    curARes = interface.IBalancerPool(lp).getBalance(dfd)
    curBRes = interface.IBalancerPool(lp).getBalance(dusd)

    print('spell lp balance', lp.balanceOf(balancer_spell))
    print('spell dfd balance', dfd.balanceOf(balancer_spell))
    print('spell dusd balance', dusd.balanceOf(balancer_spell))
    print('Alice delta A balance', curABal - prevABal)
    print('Alice delta B balance', curBBal - prevBBal)
    print('Alice delta ETH balance', curETHBal - prevETHBal)
    print('Alice delta LP balance', curLPBal - prevLPBal)
    print('remove liquidity gas', tx.gas_used)
    print('bank delta lp balance', curLPBal_bank - prevLPBal_bank)
    print('bank total lp balance', curLPBal_bank)

    _, _, _, dfdDebt, dfdShare = homora.getBankInfo(dfd)
    print('bank dfd totalDebt', dfdDebt)
    print('bank dfd totalShare', dfdShare)

    print('LP want', lp_want)

    print('bank delta LP amount', curLPBal_bank - prevLPBal_bank)
    print('LP take amount', lp_take_amt)

    print('prev staking LP balance', prevLPBal_staking)
    print('cur staking LP balance', curLPBal_staking)

    print('real dfd repay', real_dfd_repay)

    print('curCrdfdBal', curCrdfdBal)
    print('delta crdfd', curCrdfdBal - prevCrdfdBal)

    print('A res delta', prevARes - curARes)
    print('B res delta', prevBRes - curBRes)

    # alice
    assert almostEqual(curLPBal - prevLPBal, lp_want), 'incorrect LP amt'

    # staking
    assert almostEqual(curLPBal_staking - prevLPBal_staking,
                       -real_lp_take_amt), 'incorrect staking LP amt'

    # spell
    assert dfd.balanceOf(balancer_spell) == 0, 'non-zero spell DFD balance'
    assert dusd.balanceOf(balancer_spell) == 0, 'non-zero spell DUSD balance'
    assert lp.balanceOf(balancer_spell) == 0, 'non-zero spell LP balance'

    # check balance and pool reserves
    assert almostEqual(curABal - prevABal + real_dfd_repay,
                       -(curARes - prevARes)), 'inconsistent DFD from withdraw'
    assert almostEqual(
        curBBal - prevBBal + dusd_repay,
        -(curBRes - prevBRes)), 'inconsistent DUSD from withdraw'

    curAliceDfdBalance = dfd.balanceOf(alice)
    print('Alice dfd balance', curAliceDfdBalance)
    receivedDfd = curAliceDfdBalance - prevAliceDfdBalance + real_dfd_repay - (
        prevARes - curARes)
    print('received dfd', receivedDfd)

    # check with staking directly
    tx = interface.IStakingRewards(staking).getReward({'from': bob})
    receivedDfdFromStaking = dfd.balanceOf(bob) - prevDfd
    print('receivedDfdFromStaking', receivedDfdFromStaking)
    assert almostEqual(receivedDfd, receivedDfdFromStaking)

    #####################################################################################
    print(
        '========================================================================='
    )
    print('Case 5. add & remove all LP')

    lp_amt = 10 * 10**18

    prevLPBal = lp.balanceOf(alice)

    tx = homora.execute(
        0,
        balancer_spell,
        balancer_spell.addLiquidityWStakingRewards.encode_input(
            lp,  # lp token
            [
                0,  # supply DAI
                0,  # supply WETH
                lp_amt,  # supply LP
                0,  # borrow DAI
                0,  # borrow WETH
                0,  # borrow LP tokens
                0
            ],  # LP desired
            wstaking),
        {'from': alice})

    tx = homora.execute(
        2,
        balancer_spell,
        balancer_spell.removeLiquidityWStakingRewards.encode_input(
            lp,  # LP token
            [
                2**256 - 1,  # take out LP tokens
                lp_amt,  # withdraw LP tokens to wallet
                0,  # repay DAI
                0,  # repay WETH
                0,  # repay LP
                0,  # min DAI
                0
            ],  # min WETH
            wstaking),
        {'from': alice})

    curLPBal = lp.balanceOf(alice)

    assert prevLPBal == curLPBal, 'incorrect LP Balance'

    return tx
Exemple #6
0
# #####################################################################################

print(
    '========================================================================='
)
print('Case 2. harvest first time')

prevDfdBalance = dfd.balanceOf(alice)
print('Alice DFD balance before harvest', prevDfdBalance)
_, _, collId, collSize = homora.getPositionInfo(1)
print('collSize', collSize)

# staking directly
prevDfd = dfd.balanceOf(bob)
print('bob lp balance', interface.IERC20Ex(lp).balanceOf(bob))
tx = interface.IStakingRewards(staking).stake(collSize, {'from': bob})

chain.sleep(20000)

tx = homora.execute(
    1, balancer_spell,
    balancer_spell.harvestWStakingRewards.encode_input(wstaking),
    {'from': alice})

print('tx gas used', tx.gas_used)

curDfdBalance = dfd.balanceOf(alice)
print('Alice DFD balance after harvest', curDfdBalance)
receivedDfd = curDfdBalance - prevDfdBalance

# check with staking directly