Example #1
0
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
Example #2
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
Example #3
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
Example #4
0
    print(f'sending from {fro} {amt} {asset.name()} to {to}')
    asset.transfer(to, amt, {'from': fro})


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})