---
# System prepended metadata

title: Alpha Homora contract documentation

---

# Alpha Homora contract documentation

Alpha Homora is a decentralize leverage yield farming product. We allow users to lever up their yield farming position by borrowing external liquidity from the lending protocol.

Users can open leveraged positions, add more liquidity, harvest their positions, and remove their liquidity.

# Alpha Homora Components

Alpha Homora product is mainly composed of 5 components

1. Homora Bank Contract
    - is the main contract where stores user's positions and  tracks the borrowing tokens.
2. Homora Wrapper Contracts 
    - handle the farming process (i.e. deposit into Masterchef contract).
3. Homora Spell Contracts 
    - interact with DEX and the wrapper contract to open/add/remove/close users' positions.
4. Homora Oracle Contracts
    - Identify position values and token price
5. Homora SafeBox Contracts
    - allow users to lend tokens and earn lending interest (interest rate is reflected from how much user borrow the token).

# Interact with Alpha Homora Product

Farming on different DEX protocols uses different spell contracts. To interact with HomoraBank, you need to know which DEX protocol to farm (i.e. Uniswap, Sushiswap or Curve) and correctly map with the spell contract.

![](https://i.imgur.com/cizves9.png)

See all contract addresses and download abi file [ABI](https://drive.google.com/drive/folders/1bAYYGEeVfkNoq9dzaDqzqy2-ZprxUHB6?usp=sharing)

| Description            | Contract Address                           | ABI |
| ---------------------- |:------------------------------------------ |:--- |
| HomoraBank             | 0xba5eBAf3fc1Fcca67147050Bf80462393814E54B |     |
| SushiswapSpellV1       | 0xdc9c7a2bae15dd89271ae5701a6f4db147baa44c |     |
| UniswapV2SpellV1       | 0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14 |     |
| CurveSpellV1           | 0x8b947D8448CFFb89EF07A6922b74fBAbac219795 |     |
| WMasterChef            | 0xA2caEa05fF7B98f10Ad5ddc837F15905f33FEb60 |     |
| WLiquidityGauge        | 0xf1F32C8EEb06046d3cc3157B8F9f72B09D84ee5b |     |
| WStakingRewards(INDEX) | 0x011535FD795fD28c749363E080662D62fBB456a7 |     |
| IMasterChef            | -                                          |     |
| IStakingRewards        | -                                          |     |


Available pools https://api.homora.alphaventuredao.io/v2/1/pools

### Steps
- Choose a spell that you want to farm


| Chain    | Protocol  | Spell            | Address                                    |
| -------- |:--------- |:---------------- |:------------------------------------------ |
| Ethereum | Uniswap   | UniswapV2SpellV1 | 0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14 |
|          | Sushiswap | SushiswapSpellV1 | 0xdc9c7a2bae15dd89271ae5701a6f4db147baa44c |
|          | Curve     | CurveSpellV1     | 0x8b947D8448CFFb89EF07A6922b74fBAbac219795 |

- Choose an action you want to interact with HomoraBank
For example, you want to integrate with Sushiswap leverage farm, you choose SushiswapSpellV1 and then decide which action/function you want to interact to HomoraBank from the list [here](#SushiswapSpellV1).
- For yield farming, you need to add more additional argument to function (i.e. pool id for Sushiswap, wrapped staking contract for UniswapV2, gauge id for Curve). You will see how to find it in the examples below

> Scenario: User opens new position to farm DEI-WETH LP on UniswapV2 with staking contract
> - choose spell -> UniswapV2SpellV1
> - choose action -> addLiquidityWStakingRewards

The followings are example of how to interact with the product.

## Example [actions](#SushiswapSpellV1) for Sushiswap leverage farm
- To find available leverage pools for Sushiswap, visit https://api.homora.alphaventuredao.io/v2/1/pools and then filter only pool that `exchange.name` is Sushiswap.
### Yield Farming: Assume a user farms on Masterchef of Sushiswap 

1. open position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = SushiswapSpellV1.at("0xdc9c7a2bae15dd89271ae5701a6f4db147baa44c") # spell
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount_lp = # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1
pid = 20 # pool id
bank.execute(
    0, # (0 is reserved for opening new position)
    spell, 
    spell.addLiquidityWMasterChef.encode_input(
        token0,  # token 0
        token1,  # token 1
        [
            amount0,  # supply token0
            amount1,  # supply token1
            amount_lp,  # supply LP
            amount0_borrow,  # borrow token0
            amount1_borrow,  # borrow token1
            0,  # borrow LP tokens (always 0 since LP for borrowing is disabled)
            0,  # min token0
            0,  # min token1
        ],
        pid, # pool id to farm on MasterChef
    ), # data
    {"from": user},
)
```

2. increase position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = SushiswapSpellV1.at("0xdc9c7a2bae15dd89271ae5701a6f4db147baa44c")
pos_id = 123 # position to increase
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount_lp = 0 # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1
pid = 20 # pool id
bank.execute(
    pos_id, # position id
    spell, # spell
    spell.addLiquidityWMasterChef.encode_input(
        token0,  # token 0
        token1,  # token 1
        [
            amount0,  # supply token0
            amount1,  # supply token1
            amount_lp,  # supply LP
            amount0_borrow,  # borrow token0
            amount1_borrow,  # borrow token1
            0,  # borrow LP tokens (always 0 since LP for borrowing is disabled)
            0,  # min token0
            0,  # min token1
        ],
        pid, # pool id to farm on MasterChef
    ), # data
    {"from": user},
)
```

3. reduce position (and repay debt if any)
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = SushiswapSpellV1.at("0xdc9c7a2bae15dd89271ae5701a6f4db147baa44c")
pos_id = 123 # position to increase
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amt_a_repay = 100000 # amtARepay
amt_b_repay = 200000 # amtBRepay

# fetch remaining collateral amount in the position
_, _, _, coll_amt = bank.getPositionInfo(pos_id)
debt_tokens, debt_amts = bank.getPositionDebts(pos_id)


remove_wmasterchef_amt = coll_amt
remove_lp_amt = coll_amt
bank.execute(
    pos_id,
    spell,
    spell.removeLiquidityWMasterChef.encode_input(
        token0, # token0
        token1, # token1
        [
            remove_wmasterchef_amt, # amtLPTake
            remove_lp_amt, # amtLPWithdraw
            amt_a_repay, # amtARepay
            amt_b_repay, # amtBRepay
            0, # amtLPRepay
            0, # amtAMin
            0  # amtBMin
        ],
    ),
    {"from": user},
)
```

4. harvest rewards
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = SushiswapSpellV1.at("0xdc9c7a2bae15dd89271ae5701a6f4db147baa44c")
pos_id = 123
bank.execute(
    pos_id,
    spell,
    spell.harvestWMasterChef.encode_input(),
    {"from": user},
)
```
5. get pending rewards
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
pos_id = 10 # position id to calculate pending rewards

_, coll_token_addr, coll_id, coll_amt = bank.getPositionInfo(pos_id)

# for sushiswap, choose wmasterchef contract
wrapper = WMasterChef.at(coll_token_addr)

# use interface contract from MasterChef
chef = interface.IMasterChef(wrapper.chef())

# find start token per share
pid, start_token_per_share = wrapper.decodeId(coll_id)

# find current token per share
_, _, _, end_token_per_share = chef.poolInfo(pid)
acc_token_per_share_precision = 12  # depend on staking contract implementation

# calculate pending rewards
pending_rewards = (
    coll_amt
    * (end_token_per_share - start_token_per_share)
    // 10 ** (acc_token_per_share_precision)
)
```

## Example [actions](#UniswapV2SpellV1) for UniswapV2 leverage farm

- To find available leverage pools for UniswapV2, visit https://api.homora.alphaventuredao.io/v2/1/pools and then filter only pool that `exchange.name` is Uniswap V2.

### Liquidity Providing: Assume a user adds liquidity to Uniswap pool without staking rewards 

1. open position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14") # spell
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount_lp = # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1

bank.execute(
    0, # (0 is reserved for opening new position)
    spell, 
    spell.addLiquidityWERC20.encode_input(
        token0,  # token 0
        token1,  # token 1
        [
            amount0,  # supply token0
            amount1,  # supply token1
            amount_lp,  # supply LP
            amount0_borrow,  # borrow token0
            amount1_borrow,  # borrow token1
            0,  # borrow LP tokens (always 0 since LP for borrowing is disabled)
            0,  # min token0
            0,  # min token1
        ],
    ), # data
    {"from": user},
)
```

2. increase position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14")
pos_id = 123 # position to increase
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount_lp = 0 # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1
bank.execute(
    pos_id, # position id
    spell, # spell
    spell.addLiquidityWERC20.encode_input(
        token0,  # token 0
        token1,  # token 1
        [
            amount0,  # supply token0
            amount1,  # supply token1
            amount_lp,  # supply LP
            amount0_borrow,  # borrow token0
            amount1_borrow,  # borrow token1
            0,  # borrow LP tokens (always 0 since LP for borrowing is disabled)
            0,  # min token0
            0,  # min token1
        ],
    ), # data
    {"from": user},
)
```

3. reduce position (and repay debt if any)
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14")
pos_id = 123 # position to increase
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amt_a_repay = 100000 # amtARepay
amt_b_repay = 200000 # amtBRepay

# fetch remaining collateral amount in the position
_, _, _, coll_amt = bank.getPositionInfo(pos_id)
debt_tokens, debt_amts = bank.getPositionDebts(pos_id)

remove_lp_amt = coll_amt
bank.execute(
    pos_id,
    spell,
    spell.removeLiquidityWERC20.encode_input(
        token0, # token0
        token1, # token1
        [
            remove_lp_amt, # amtLPTake
            remove_lp_amt, # amtLPWithdraw
            amt_a_repay, # amtARepay
            amt_b_repay, # amtBRepay
            0, # amtLPRepay
            0, # amtAMin
            0  # amtBMin
        ],
    ),
    {"from": user},
)
```
### Yield Farming: Assume a user adds liquidity to Uniswap pool with staking rewards 

- Find wrapped staking contract whose underlying token address matches LP address that you want to farm
- Currently there is only one pool that allows user to use wstaking contract for UniswapV2


| Farm     | WStakingRewards address                    | Underlying token address                   |
| -------- |:------------------------------------------ |:------------------------------------------ |
| DPI-WETH | 0x011535FD795fD28c749363E080662D62fBB456a7 | 0x4d5ef58aAc27d99935E5b6B4A6778ff292059991 |

1. open position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14") # spell
wstaking = WStakingRewards.at("0x011535FD795fD28c749363E080662D62fBB456a7")

# please make sure that received LP address after providing token0 and token1 
# is the same as underlying token address from wrapped staking contract
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount_lp = # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1

bank.execute(
    0, # (0 is reserved for opening new position)
    spell, 
    spell.addLiquidityWStakingRewards.encode_input(
        token0,  # token 0
        token1,  # token 1
        [
            amount0,  # supply token0
            amount1,  # supply token1
            amount_lp,  # supply LP
            amount0_borrow,  # borrow token0
            amount1_borrow,  # borrow token1
            0,  # borrow LP tokens (always 0 since LP for borrowing is disabled)
            0,  # min token0
            0,  # min token1
        ],
        wstaking
    ), # data
    {"from": user},
)
```

2. increase position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14")
wstaking = WStakingRewards.at("0x011535FD795fD28c749363E080662D62fBB456a7")
pos_id = 123 # position to increase

# please make sure that received LP address after providing token0 and token1 
# is the same as underlying token address from wrapped staking contract
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount_lp = 0 # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1
bank.execute(
    pos_id, # position id
    spell, # spell
    spell.addLiquidityWStakingRewards.encode_input(
        token0,  # token 0
        token1,  # token 1
        [
            amount0,  # supply token0
            amount1,  # supply token1
            amount_lp,  # supply LP
            amount0_borrow,  # borrow token0
            amount1_borrow,  # borrow token1
            0,  # borrow LP tokens (always 0 since LP for borrowing is disabled)
            0,  # min token0
            0,  # min token1
        ],
        wstaking
    ), # data
    {"from": user},
)
```

3. reduce position (and repay debt if any)
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14")
wstaking = WStakingRewards.at("0x011535FD795fD28c749363E080662D62fBB456a7")
pos_id = 123 # position to increase
token0 = "0x.." # token 0
token1 = "0x.." # token 1
amt_a_repay = 100000 # amtARepay
amt_b_repay = 200000 # amtBRepay

# fetch remaining collateral amount in the position
_, _, _, coll_amt = bank.getPositionInfo(pos_id)
remove_wstaking_amt = coll_amt
remove_lp_amt = coll_amt
bank.execute(
    pos_id,
    spell,
    spell.removeLiquidityWStakingRewards.encode_input(
        token0, # token0
        token1, # token1
        [
            remove_wstaking_amt, # amtLPTake
            remove_lp_amt, # amtLPWithdraw
            amt_a_repay, # amtARepay
            amt_b_repay, # amtBRepay
            0, # amtLPRepay
            0, # amtAMin
            0  # amtBMin
        ],
        wstaking,
    ),
    {"from": user},
)
```
4. harvest rewards
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = UniswapV2SpellV1.at("0x00b1a4e7f217380a7c9e6c12f327ac4a1d9b6a14")
wstaking = WStakingRewards.at("0x011535FD795fD28c749363E080662D62fBB456a7")
pos_id = 123
bank.execute(
    pos_id,
    spell,
    spell.harvestWStakingRewards.encode_input(wstaking),
    {"from": user},
)
```

5. get pending rewards
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
pos_id = 454

_, coll_token_addr, coll_id, coll_amt = bank.getPositionInfo(pos_id)

# for uniswapV2, use wstaking contract
wrapper = WStakingRewards.at(coll_token_addr)
staking = interface.IStakingRewards(wrapper.staking())

# find start token per share
# NOTE: for wstaking contract, coll_id is reward token per share
start_token_per_share = coll_id

# find current token per share
end_token_per_share = staking.rewardPerToken()
acc_token_per_share_precision = 18  # depend on staking contract implementation

pending_rewards = (
    coll_amt
    * (end_token_per_share - start_token_per_share)
    // 10 ** (acc_token_per_share_precision)
)
```

## Example [actions](#CurveSpellV1) for Curve leverage farm
### Yield Farming: Assume a user adds liquidity to Curve pool with gauge 

| Farm   | pool id | gauge id | WLiquidity                                 |
| ------ |:------- |:-------- | ------------------------------------------ |
| 3-pool | 0       | 0        | 0xf1f32c8eeb06046d3cc3157b8f9f72b09d84ee5b |

- To find available leverage pools for Curve, visit https://api.homora.alphaventuredao.io/v2/1/pools and then filter only pool that `wTokenType` is WLiquidityGauge. To find all tokens (token0, token1, ...) in that pool, you can see through `tokens` key 

1. open position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = CurveSpellV1.at("0x8b947D8448CFFb89EF07A6922b74fBAbac219795") # spell

lp = "0x6c3f90f043a72fa612cbac8115ee7e52bde6e490"
# token0 = "0x6b175474e89094c44da98b954eedeac495271d0f"
# token1 = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
# token2 = "0xdac17f958d2ee523a2206206994597c13d831ec7"
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount2 = 10000 # supply token2
amount_lp = 0 # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1
amount2_borrow = 10000 # borrow token2
min_lp_mint = 0 # min LP mint
pid = 0 # pool id
gid = 0 # gauge id

bank.execute(
    0,
    spell,
    spell.addLiquidity3.encode_input(
        lp,  # LP
        [amount0, amount1, amount2],  # supply tokens
        amount_lp,  # supply LP
        [amount0_borrow, amount1_borrow, amount2_borrow],  # borrow tokens
        0,  # borrow LP (always 0 since LP for borrowing is disabled)
        min_lp_mint,  # min LP mint
        pid,
        gid,
    ),
    {"from": user},
)
```

2. increase position
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = CurveSpellV1.at("0x8b947D8448CFFb89EF07A6922b74fBAbac219795") # spell

pos_id = 100
lp = "0x6c3f90f043a72fa612cbac8115ee7e52bde6e490"
# token0 = "0x6b175474e89094c44da98b954eedeac495271d0f"
# token1 = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
# token2 = "0xdac17f958d2ee523a2206206994597c13d831ec7"
amount0 = 10000 # supply token0
amount1 = 10000 # supply token1
amount2 = 10000 # supply token2
amount_lp = 0 # supply LP
amount0_borrow = 10000 # borrow token0
amount1_borrow = 10000 # borrow token1
amount2_borrow = 10000 # borrow token2
min_lp_mint = 0 # min LP mint
pid = 0 # pool id
gid = 0 # gauge id

bank.execute(
    pos_id,
    spell,
    spell.addLiquidity3.encode_input(
        lp,  # LP
        [amount0, amount1, amount2],  # supply tokens
        amount_lp,  # supply LP
        [amount0_borrow, amount1_borrow, amount2_borrow],  # borrow tokens
        0,  # borrow LP (always 0 since LP for borrowing is disabled)
        min_lp_mint,  # min LP mint
        pid,
        gid,
    ),
    {"from": user},
)
```

3. reduce position (and repay debt if any)
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = CurveSpellV1.at("0x8b947D8448CFFb89EF07A6922b74fBAbac219795") # spell

pos_id = 100
lp = "0x6c3f90f043a72fa612cbac8115ee7e52bde6e490"
# token0 = "0x6b175474e89094c44da98b954eedeac495271d0f"
# token1 = "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
# token2 = "0xdac17f958d2ee523a2206206994597c13d831ec7"

# fetch remaining collateral amount in the position
_, _, _, coll_amt = bank.getPositionInfo(pos_id)
debt_tokens, debt_amts = bank.getPositionDebts(pos_id)


lp_take_amt = coll_amt # LP amount to take out
lp_want = coll_amt // 2 # LP amount to withdraw to wallet

amount_lp = 0 # supply LP
repay_token0 = 10000 # repay token0
repay_token1 = 10000 # repay token1
repay_token2 = 10000 # repay token2
lp_repay = 0
min_amt0 = 0 # min amount token0
min_amt1 = 0 # min amount token1
min_amt2 = 0 # min amount token2

bank.execute(
    pos_id,
    spell,
    curve_spell.removeLiquidity3.encode_input(
        lp,  # LP token
        lp_take_amt,  # LP amount to take out
        lp_want,  # LP amount to withdraw to wallet
        [repay_token0, repay_token1, repay_token2],  # repay amounts
        lp_repay,  # repay LP amount
        [min_amt0, min_amt1, min_amt2],  # min amounts
    ),
    {"from": user},
)
```
4. harvest rewards
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
spell = CurveSpellV1.at("0x8b947D8448CFFb89EF07A6922b74fBAbac219795") # spell
pos_id = 123
bank.execute(
    pos_id, spell, spell.harvest.encode_input(), {"from": user}
)
```

5. get pending rewards
```python=
bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
pos_id = 1570
pid = 0
gid = 0

_, coll_token_addr, coll_id, coll_amt = bank.getPositionInfo(pos_id)

# for curve, use wrapped liquidity gauge contract
wrapper = WLiquidityGauge.at(coll_token_addr)

# find start token per share
_, _, start_token_per_share = wrapper.decodeId(coll_id)

# find current token per share
_, end_token_per_share = wrapper.gauges(pid, gid)
acc_token_per_share_precision = 18  # depend on staking contract implementation

pending_rewards = (
    coll_amt
    * (end_token_per_share - start_token_per_share)
    // 10 ** (acc_token_per_share_precision)
)
```


# HomoraBank

## Execute

This function passes the bytes data to the given spell address and execute on that contract. In order to correctly encode bytes data, you may need to know function abis on the target spell.


| action                                | function        |
| ------------------------------------- |:--------------- |
| open new position / increase position | addLiquidity    |
| decrease position / close postiion    | removeLiquidity |
| harvest rewards                       | harvest         |

```solidity
function execute(
    uint positionId,
    address spell,
    bytes memory data
) external payable lock onlyEOAEx returns (uint) 
```
- `positionId`: The position id to execute the action, or zero for new position.
- `spell`: The spell contract address which is an agent to handle user's tokens
- `data`: The encoded function and its arguments which Homora bank will call to
- `RETURN`: The position id of execution (new position id for new position)


## Query function

### borrowBalanceStored
Return the borrow balance for given position and token without triggering interest accrual.
```solidity=
function borrowBalanceStored(uint positionId, address token) public view override returns (uint)
```
- `positionId`: The position to query for borrow balance.
- `token`: The token to query for borrow balance.

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> token = "0x.."
> position_id = 10
> debt = bank.borrowBalanceStored(position_id, token)


### borrowBalanceCurrent
Trigger interest accrual and return the current borrow balance.
```solidity=
function borrowBalanceCurrent(uint positionId, address token) public view override returns (uint)
```
- `positionId`: The position to query for borrow balance.
- `token`: The token to query for borrow balance.

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> token = "0x.."
> position_id = 10
> debt = bank.borrowBalanceCurrent(position_id, token)
> ```

### getBankInfo
Return bank information for the given token.
```solidity=
function getBankInfo(address token)
    external
    view
    override
    returns (
      bool isListed,
      address cToken,
      uint reserve,
      uint totalDebt,
      uint totalShare
    )
```
- `token`: The token address to query for bank information.
- `isListed`: The flag whether this market exists.
- `cToken`:  The CToken to draw liquidity from.
- `reserve`:  The reserve portion allocated to Homora protocol.
- `totalDebt`: The last recorded total debt since last action.
- `totalShare`: The total debt share count across all open positions.

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> token = "0x.."
> is_listed, c_token_addr, reserve, total_debt, total_share = bank.getBankInfo(token)
> ```

### getPositionInfo
Return position information for the given position id.
```solidity=
function getPositionInfo(uint positionId)
    public
    view
    override
    returns (
      address owner,
      address collToken,
      uint collId,
      uint collateralSize
    )
```
- `positionId`:  The position id to query for position information.
- `owner`:  The owner of this position.
- `collToken`: The ERC1155 token used as collateral for this position.
- `collId`: The token id used as collateral.
- `collateralSize`: The size of collateral token for this position.

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> position_id = 1
> owner, coll_token_addr, coll_id, coll_size = bank.getPositionInfo(position_id)
> ```

### getPositionDebtShareOf
Return the debt share of the given bank token for the given position id.
```solidity=
function getPositionDebtShareOf(uint positionId, address token) external view returns (uint)
```
- `positionId`: position id to get debt of
- `token`: ERC20 debt token to query

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> token = "0x.."
> position_id = 1
> debt_share = bank.getPositionDebtShareOf(position_id, token)
> ```

### getPositionDebts
Return the list of all debts for the given position id.
```solidity=
function getPositionDebts(uint positionId)
    external
    view
    returns (address[] memory tokens, uint[] memory debts)
```
- `positionId`: The position id to get debts of
- `tokens`: The list of all token addresses
- `debts`: The list of all debts (the list is same order as `tokens`)

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> token = "0x.."
> position_id = 1
> debt_tokens, debt_amts = bank.getPositionDebts(position_id)
> ```


### getCollateralETHValue
Return the total collateral value of the given position in ETH.
```solidity=
function getCollateralETHValue(uint positionId) public view returns (uint)
```
- `positionId`: The position ID to query for the collateral value.

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> position_id = 1
> coll_in_eth = bank.getCollateralETHValue(position_id)
> ```

### getBorrowETHValue
Return the total borrow value of the given position in ETH.
```solidity=
function getBorrowETHValue(uint positionId) public view returns (uint)
```
- `positionId`: The position ID to query for the borrow value.

> Example
> ```solidity=
> bank = HomoraBank.at("0xba5eBAf3fc1Fcca67147050Bf80462393814E54B")
> position_id = 1
> borrow_in_eth = bank.getBorrowETHValue(position_id)
> ```

# Spell
To use spell functionality, you cannot call following functions directly so you must encode function and its input as `data` and execute it through HomoraBank contract [example here](#Execute)

```solidity=
struct Amounts {
    uint amtAUser; // Supplied tokenA amount
    uint amtBUser; // Supplied tokenB amount
    uint amtLPUser; // Supplied LP token amount
    uint amtABorrow; // Borrow tokenA amounthttps://hackmd.io/MauBEDLlSdaMrYslhAln4Q?both#
    uint amtBBorrow; // Borrow tokenB amount
    uint amtLPBorrow; // Borrow LP token amount
    uint amtAMin; // Desired tokenA amount (slippage control)
    uint amtBMin; // Desired tokenB amount (slippage control)
}

struct RepayAmounts {
    uint amtLPTake; // Take out LP token amount (from Homora)
    uint amtLPWithdraw; // Withdraw LP token amount (back to caller)
    uint amtARepay; // Repay tokenA amount
    uint amtBRepay; // Repay tokenB amount
    uint amtLPRepay; // Repay LP token amount
    uint amtAMin; // Desired tokenA amount
    uint amtBMin; // Desired tokenB amount
}
```

## Ethereum
### UniswapV2SpellV1

| Leverage mode       | action                   | function                       |
| ------------------- | ------------------------ |:------------------------------ |
| Liquidity Providing | open / increase position | addLiquidityWERC20             |
| Liquidity Providing | reduce / close position  | removeLiquidityWERC20          |
| Yield Farming       | open / increase position | addLiquidityWStakingRewards    |
| Yield Farming       | reduce / close position  | removeLiquidityWStakingRewards |
| Yield Farming       | harvest                  | harvestWStakingRewards         |

#### addLiquidityWERC20
Add liquidity to Uniswap pool, with no staking rewards (use WERC20 wrapper) 
```solidity=
function addLiquidityWERC20(
    address tokenA,
    address tokenB,
    Amounts calldata amt
  ) external payable
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to supply, borrow, and get.


#### addLiquidityWStakingRewards
Add liquidity to Uniswap pool, with staking rewards
```solidity=
function addLiquidityWStakingRewards(
    address tokenA,
    address tokenB,
    Amounts calldata amt,
    address wstaking
  ) external payable 
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to supply, borrow, and get.
- `wstaking`: Wrapped staking contract address

#### removeLiquidityWERC20
Remove liquidity from Uniswap pool, with no staking rewards (use WERC20 wrapper)
```solidity=
function removeLiquidityWERC20(
    address tokenA,
    address tokenB,
    RepayAmounts calldata amt
  ) external
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to take out, withdraw, repay, and get.

#### removeLiquidityWStakingRewards
Remove liquidity from Uniswap pool, from staking rewards
```solidity=
function removeLiquidityWStakingRewards(
    address tokenA,
    address tokenB,
    RepayAmounts calldata amt,
    address wstaking
) external
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to take out, withdraw, repay, and get.
- `wstaking`: Wrapped staking contract address

#### harvestWStakingRewards
Harvest staking reward tokens to in-exec position's owner
```solidity=
function harvestWStakingRewards(address wstaking) external
```
### SushiswapSpellV1

| Leverage mode | action                   | function                   |
| ------------- | ------------------------ |:-------------------------- |
| Yield Farming | open / increase position | addLiquidityWMasterChef    |
| Yield Farming | reduce / close position  | removeLiquidityWMasterChef |
| Yield Farming | harvest                  | harvestWMasterChef         |

#### addLiquidityWMasterChef
Add liquidity to TraderJoe pool, with staking to masterChef
```solidity=
function addLiquidityWMasterChef(
    address tokenA,
    address tokenB,
    Amounts calldata amt,
    uint pid
) external payable
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to supply, borrow, and get.
- `pid`: Pool id


#### removeLiquidityWMasterChef
Remove liquidity from TraderJoe pool, from masterChef staking
```solidity=
function removeLiquidityWMasterChef(
    address tokenA,
    address tokenB,
    RepayAmounts calldata amt
) external
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to take out, withdraw, repay, and get.

#### harvestWMasterChef
Harvest Joe reward tokens to in-exec position's owner
```solidity=
function harvestWMasterChef() external
```
### CurveSpellV1

| Leverage mode | action                   | function        |
| ------------- | ------------------------ |:--------------- |
| Yield Farming | open / increase position | addLiquidity    |
| Yield Farming | reduce / close position  | removeLiquidity |
| Yield Farming | harvest                  | harvest         |

#### addLiquidity2
Add liquidity to Curve pool with 2 underlying tokens, with staking to Curve gauge
```solidity=
function addLiquidity2(
    address lp,
    uint[2] calldata amtsUser,
    uint amtLPUser,
    uint[2] calldata amtsBorrow,
    uint amtLPBorrow,
    uint minLPMint,
    uint pid,
    uint gid
  ) external
```
- `lp`: LP token for the pool
- `amtsUser`: Supplied underlying token amounts
- `amtLPUser`: Supplied LP token amount
- `amtsBorrow`: Borrow underlying token amounts
- `amtLPBorrow`: Borrow LP token amount
- `minLPMint`: Desired LP token amount (slippage control)
- `pid`: Curve pool id for the pool
- `gid`: Curve gauge id for the pool

#### addLiquidity3
Add liquidity to Curve pool with 3 underlying tokens, with staking to Curve gauge
```solidity=
function addLiquidity3(
    address lp,
    uint[3] calldata amtsUser,
    uint amtLPUser,
    uint[3] calldata amtsBorrow,
    uint amtLPBorrow,
    uint minLPMint,
    uint pid,
    uint gid
  ) external
```
- `lp`: LP token for the pool
- `amtsUser`: Supplied underlying token amounts
- `amtLPUser`: Supplied LP token amount
- `amtsBorrow`: Borrow underlying token amounts
- `amtLPBorrow`: Borrow LP token amount
- `minLPMint`: Desired LP token amount (slippage control)
- `pid`: Curve pool id for the pool
- `gid`: Curve gauge id for the pool


#### addLiquidity4
Add liquidity to Curve pool with 4 underlying tokens, with staking to Curve gauge
```solidity=
function addLiquidity4(
    address lp,
    uint[4] calldata amtsUser,
    uint amtLPUser,
    uint[4] calldata amtsBorrow,
    uint amtLPBorrow,
    uint minLPMint,
    uint pid,
    uint gid
  ) external
```
- `lp`: LP token for the pool
- `amtsUser`: Supplied underlying token amounts
- `amtLPUser`: Supplied LP token amount
- `amtsBorrow`: Borrow underlying token amounts
- `amtLPBorrow`: Borrow LP token amount
- `minLPMint`: Desired LP token amount (slippage control)
- `pid`: Curve pool id for the pool
- `gid`: Curve gauge id for the pool

#### removeLiquidity2
Remove liquidity from Curve pool with 2 underlying tokens
```solidity=
function removeLiquidity2(
    address lp,
    uint amtLPTake,
    uint amtLPWithdraw,
    uint[2] calldata amtsRepay,
    uint amtLPRepay,
    uint[2] calldata amtsMin
  ) external
```
- `lp`: LP token for the pool
- `amtLPTake`: Take out LP token amount (from Homora)
- `amtLPWithdraw`: Withdraw LP token amount (back to caller)
- `amtsRepay`: Repay underlying token amounts
- `amtLPRepay`: Repay LP token amount
- `amtsMin`: Desired underlying token amounts (slippage control)

#### removeLiquidity3
Remove liquidity from Curve pool with 3 underlying tokens
```solidity=
function removeLiquidity3(
    address lp,
    uint amtLPTake,
    uint amtLPWithdraw,
    uint[3] calldata amtsRepay,
    uint amtLPRepay,
    uint[3] calldata amtsMin
  ) external
```
- `lp`: LP token for the pool
- `amtLPTake`: Take out LP token amount (from Homora)
- `amtLPWithdraw`: Withdraw LP token amount (back to caller)
- `amtsRepay`: Repay underlying token amounts
- `amtLPRepay`: Repay LP token amount
- `amtsMin`: Desired underlying token amounts (slippage control)

#### removeLiquidity4
Remove liquidity from Curve pool with 4 underlying tokens
```solidity=
function removeLiquidity4(
    address lp,
    uint amtLPTake,
    uint amtLPWithdraw,
    uint[4] calldata amtsRepay,
    uint amtLPRepay,
    uint[4] calldata amtsMin
  ) external
```
- `lp`: LP token for the pool
- `amtLPTake`: Take out LP token amount (from Homora)
- `amtLPWithdraw`: Withdraw LP token amount (back to caller)
- `amtsRepay`: Repay underlying token amounts
- `amtLPRepay`: Repay LP token amount
- `amtsMin`: Desired underlying token amounts (slippage control)

#### harvest
Harvest CRV reward tokens to in-exec position's owner
```solidity=
function harvest() external 
```


##########################

## Avalanche
### TraderJoeSpellV2


#### addLiquidityWMasterChef
Add liquidity to TraderJoe pool, with staking to masterChef
```solidity=
function addLiquidityWMasterChef(
    address tokenA,
    address tokenB,
    Amounts calldata amt,
    uint pid
) external payable
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to supply, borrow, and get.
- `pid`: Pool id


#### removeLiquidityWMasterChef
Remove liquidity from TraderJoe pool, from masterChef staking
```solidity=
function removeLiquidityWMasterChef(
    address tokenA,
    address tokenB,
    RepayAmounts calldata amt
) external
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to take out, withdraw, repay, and get.

#### harvestWMasterChef
Harvest Joe reward tokens to in-exec position's owner
```solidity=
function harvestWMasterChef() external
```

### PangolinSpell

#### addLiquidityWMiniChef
Add liquidity to Pangolin pool, with staking to miniChef
```solidity=
function addLiquidityWMiniChef(
    address tokenA,
    address tokenB,
    Amounts calldata amt,
    uint pid
  ) external payable
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to supply, borrow, and get.
- `pid`: Pool id


#### removeLiquidityWMiniChef
Remove liquidity from Pangolin pool, from miniChef staking
```solidity=
function removeLiquidityWMiniChef(
    address tokenA,
    address tokenB,
    RepayAmounts calldata amt
  ) external
```
- `tokenA`: Token A for the pair
- `tokenB`: Token B for the pair
- `amt`: Amounts of tokens to take out, withdraw, repay, and get.

#### harvestWMiniChefRewards
Harvest staking reward tokens to in-exec position's owner
```solidity=
function harvestWMiniChefRewards() external
```

# FAQ