---
# System prepended metadata

title: K Hack

---


### Problem

If Hyperdrive simply adjusts bond liquidity proportional to the liquidity being added we run into issues with price discovery and sandwich attacks. If someone adds liquidity at an irrationally high interest rate, it inflates the bond reserves so much that the rate can't be arbed back. Additionally, this creates an opportunity for a long-range sandwich attack. To mitigate this, we implement the following initialize routine.

### Zeta and Bond Reserves for Initialization
\begin{align}
&\text{We want to solve for } y \text{ and } \zeta \text{ using the following systems of equations:} \\
&\quad(1) \quad c z - c \zeta + p y = c z \\
&\quad(2) \quad p =\left( \frac{\mu z - \mu \zeta}{y} \right)^{t_s}\\
&\text{where } c  z \text{ is the amount of base the pool is initialized with. Combining (1) and (2) we have:} \\
&\quad(3) \quad \zeta = z - \frac{1}{\mu}p^{\frac{1}{t_s}}y\\
&\text{Combining (1) and (3) gives us:} \\
&\quad c z - c (z - \frac{1}{\mu}p^{\frac{1}{t_s}}y) + py = c z \\
&\text{this simplifies to: }\\
&\quad(4) \quad  y = \frac{cz}{\frac{c}{\mu}p^{\frac{1}{t_s}}+p}\\
\end{align}


### Visualization of `The Fix`

<iframe src="https://www.desmos.com/calculator/adshhzmwpj?embed" width="1024" height="768" style="border: 1px solid #ccc" frameborder=0></iframe>

### Test Code

```
    function test_example() external {
        IHyperdrive.PoolConfig memory config = testConfig(
            0.05e18,
            POSITION_DURATION
        );
        config.fees.curve = 0.001e18;
        config.fees.flat = 0.0005e18;
        deploy(alice, config);
        uint256 apr = 0.05e18;
        uint256 contribution = 100_000_000e18;
        uint256 lpShares = initialize(alice, apr, contribution);

        // Celine opens a large short.
        uint256 shortAmount = hyperdrive.calculateMaxShort();
        (, uint256 shortPaid) = openShort(celine, shortAmount);
        console.log(
            "spot rate = %s",
            hyperdrive.calculateSpotAPR().toString(18)
        );

        // Celine adds liquidity.
        uint256 celineLpShares = addLiquidity(celine, 100_000_000e18);

        // Celine opens a large long.
        uint256 basePaid = hyperdrive.calculateMaxLong();
        (uint256 maturityTime, uint256 bondAmount) = openLong(
            celine,
            hyperdrive.calculateMaxLong()
        );

        // The term advances. Alice removes her liquidity.
        advanceTime(POSITION_DURATION, 0.05e18);

        // Remove liquidity.
        (uint256 baseProceeds, uint256 withdrawalShares) = removeLiquidity(
            alice,
            lpShares
        );
        console.log("alice contribution     = %s", contribution.toString(18));
        console.log("alice baseProceeds     = %s", baseProceeds.toString(18));
        console.log(
            "alice withdrawalShares = %s",
            withdrawalShares.toString(18)
        );

        // Celine closes her long and removes liquidity.
        uint256 shortProceeds = closeShort(celine, maturityTime, shortAmount);
        uint256 longProceeds = closeLong(celine, maturityTime, bondAmount);
        (baseProceeds, withdrawalShares) = removeLiquidity(
            celine,
            celineLpShares
        );
        console.log(
            "celine paid           = %s",
            (100_000_000e18 + basePaid + shortPaid).toString(18)
        );
        console.log(
            "celine proceeds       = %s",
            (baseProceeds + longProceeds + shortProceeds).toString(18)
        );
    }
```