Skip to content

CurveTAREStrategy

ERC-4626-shaped MSV strategy. Single-sided USDC into TARE/USDC Curve StableSwap-NG LP — deepens PegKeeper liquidity; earns swap fees via virtual_price appreciation.

Source: khomdev-keep/src/strategies/CurveTAREStrategy.vy (Vyper 0.4.x)

Concept: Keep↔TARE symbiosis — MultiStrategyVault fallback strategy

Implementation overview

  • ValuationtotalAssets = lp_balance * get_virtual_price() / value_divisor (not spot withdraw quote)
  • Rewards — fees compound into virtual price; harvest() / sync() no-ops
  • APR — cached apr_bps for smart routing (admin-set, not on-chain realised)
  • Shares — internal accounting; only vault deposits/withdraws
  • Slippageslippage_bps floors add/remove liquidity via virtual price
flowchart LR
    MSV[MultiStrategyVault] --> CTS[CurveTAREStrategy]
    CTS -->|single-sided USDC| Pool[TARE/USDC Curve NG]
    Pool --> PK[PegKeeper liquidity]

Immutables

Name Role
asset USDC
vault Parent MSV
pool Curve NG pool (also LP token)
usdc_index / tare_index Coin indices
value_divisor 10**(36 - asset_decimals) for VP math

Roles

Role Powers
DEFAULT_ADMIN_ROLE APR, slippage, pause deposits, sweep stray tokens

Events

Event When
Deposit / Withdraw Vault capital flows
AprUpdated / SlippageUpdated / DepositsPaused Admin config

ERC-4626 views

totalAssets

CurveTAREStrategy.totalAssets() -> uint256

Strategy NAV from LP virtual price (manipulation-resistant).

Returns: uint256lp_balance * get_virtual_price() / value_divisor.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:147-148, _total_assets 363-368):

@external
@view
def totalAssets() -> uint256:
    return self._total_assets()

# lp * get_virtual_price() // value_divisor

Example:

nav = curve_tare.totalAssets()

Cross-links: convertToShares · MultiStrategyVault report

balanceOf

CurveTAREStrategy.balanceOf(account) -> uint256

Internal strategy shares for account.

Param Type Description
account address Share holder (MSV in practice)

Returns: uint256shares_held[account].

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:152-153):

@external
@view
def balanceOf(account: address) -> uint256:
    return self.shares_held[account]

Cross-links: totalSupply · convertToAssets

totalSupply

CurveTAREStrategy.totalSupply() -> uint256

Total strategy shares (vault position).

Returns: uint256total_shares.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:157-158):

@external
@view
def totalSupply() -> uint256:
    return self.total_shares

Cross-links: totalAssets · balanceOf

convertToAssets

CurveTAREStrategy.convertToAssets(shares) -> uint256

Shares → USDC quote (floor) at current virtual-price NAV.

Param Type Description
shares uint256 Strategy shares

Returns: uint256 — USDC value via total_shares / totalAssets ratio.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:162-163):

@external
@view
def convertToAssets(shares: uint256) -> uint256:
    return self._convert_to_assets(shares, False)

Cross-links: convertToShares · previewRedeem

convertToShares

CurveTAREStrategy.convertToShares(assets) -> uint256

USDC → shares quote (floor).

Param Type Description
assets uint256 USDC amount

Returns: uint256 — shares at current NAV.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:167-168):

@external
@view
def convertToShares(assets: uint256) -> uint256:
    return self._convert_to_shares(assets, False)

Cross-links: convertToAssets · previewDeposit

maxDeposit

CurveTAREStrategy.maxDeposit(receiver) -> uint256

Max USDC depositable (ERC-4626 view).

Param Type Description
receiver address Must be vault

Returns: uint2560 if paused or receiver != vault; else max_uint256.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:172-175):

@external
@view
def maxDeposit(receiver: address) -> uint256:
    if deposits_paused or receiver != vault:
        return 0
    return max_value(uint256)

Cross-links: deposit · maxMint

maxWithdraw

CurveTAREStrategy.maxWithdraw(owner) -> uint256

Max USDC withdrawable for owner.

Param Type Description
owner address Must be vault

Returns: uint256convertToAssets(shares_held[vault]); 0 if not vault.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:179-182):

@external
@view
def maxWithdraw(owner: address) -> uint256:
    if owner != vault:
        return 0
    return self._convert_to_assets(self.shares_held[owner], False)

Cross-links: withdraw · maxRedeem

previewDeposit

CurveTAREStrategy.previewDeposit(assets) -> uint256

Simulate deposit — shares minted (floor).

Param Type Description
assets uint256 USDC in

Returns: uint256 — expected shares (= convertToShares).

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:186-187):

@external
@view
def previewDeposit(assets: uint256) -> uint256:
    return self._convert_to_shares(assets, False)

Cross-links: deposit · convertToShares

previewWithdraw

CurveTAREStrategy.previewWithdraw(assets) -> uint256

Simulate withdraw — shares burned (ceil).

Param Type Description
assets uint256 USDC out

Returns: uint256 — shares required.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:191-192):

@external
@view
def previewWithdraw(assets: uint256) -> uint256:
    return self._convert_to_shares(assets, True)

Cross-links: withdraw · previewRedeem

previewRedeem

CurveTAREStrategy.previewRedeem(shares) -> uint256

Simulate redeem — USDC out (floor).

Param Type Description
shares uint256 Shares to burn

Returns: uint256 — expected USDC (= convertToAssets).

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:196-197):

@external
@view
def previewRedeem(shares: uint256) -> uint256:
    return self._convert_to_assets(shares, False)

Cross-links: redeem · convertToAssets

maxMint

CurveTAREStrategy.maxMint(receiver) -> uint256

Max shares mintable (vault-only).

Param Type Description
receiver address Must be vault

Returns: uint256 — same gates as maxDeposit.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:201-204):

@external
@view
def maxMint(receiver: address) -> uint256:
    if deposits_paused or receiver != vault:
        return 0
    return max_value(uint256)

Cross-links: mint · maxDeposit

maxRedeem

CurveTAREStrategy.maxRedeem(owner) -> uint256

Max shares redeemable by owner.

Param Type Description
owner address Must be vault

Returns: uint256 — full shares_held[owner]; 0 if not vault.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:208-211):

@external
@view
def maxRedeem(owner: address) -> uint256:
    if owner != vault:
        return 0
    return self.shares_held[owner]

Cross-links: redeem · maxWithdraw

IStrategy hooks

getApr

CurveTAREStrategy.getApr() -> uint256

Cached APR signal for MSV smart routing (admin-set; fees accrue via LP virtual price, not this field).

Returns: uint256apr_bps.

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:219-220):

@external
@view
def getApr() -> uint256:
    return self.apr_bps

Cross-links: set_apr_bps · Rebalancer compute_smart_targets

harvest

CurveTAREStrategy.harvest() -> uint256

No-op. Swap fees compound into LP get_virtual_price() — nothing to claim separately.

Returns: uint256 — always 0.

Access: Any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:223-225):

@external
def harvest() -> uint256:
    return 0

Cross-links: totalAssets · MultiStrategyVault report

sync

CurveTAREStrategy.sync()

No-op. NAV reads get_virtual_price() live on every totalAssets call.

Access: Any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:228-230):

@external
def sync():
    pass

Cross-links: totalAssets · harvest

deployAvailable

CurveTAREStrategy.deployAvailable(amount) -> uint256

Fallback deploy capacity — accepts full amount (vault max_debt is the real cap).

Param Type Description
amount uint256 Requested USDC deployment

Returns: uint256 — always max_uint256 (unlike CoilMaker's idle-based cap).

Access: view, any caller.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:239-244):

@external
@view
def deployAvailable(amount: uint256) -> uint256:
    return max_value(uint256)

Cross-links: MultiStrategyVault allocateCapital · CoilMakerStrategy deployAvailable

ERC-4626 writes

deposit

CurveTAREStrategy.deposit(assets, receiver) -> uint256

Vault deposits USDC; strategy single-sided adds to Curve LP; mints internal shares.

Param Type Description
assets uint256 USDC amount
receiver address Must be vault

Returns: uint256 — shares minted.

Returns / state: Pulls USDC from vault → _add_liquidity with slippage floor from virtual price.

Access: vault only. nonreentrant. Reverts if deposits_paused.

Events: Deposit.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:253-267):

@external
@nonreentrant
def deposit(assets, receiver) -> uint256:
    self._only_vault()
    shares = self._convert_to_shares(assets, False)
    self._add_liquidity(assets)
    total_shares += shares; shares_held[receiver] += shares
    return shares

Cross-links: previewDeposit · withdraw

mint

CurveTAREStrategy.mint(shares, receiver) -> uint256

Mint exact shares; vault pays ceil-rounded USDC into Curve LP.

Param Type Description
shares uint256 Target shares
receiver address Must be vault

Returns: uint256 — USDC pulled from vault.

Access: vault only. Same gates as deposit.

Events: Deposit.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:271-284):

@external
@nonreentrant
def mint(shares, receiver) -> uint256:
    assets = self._convert_to_assets(shares, True)
    self._add_liquidity(assets)
    total_shares += shares; shares_held[receiver] += shares
    return assets

Cross-links: deposit · maxMint

withdraw

CurveTAREStrategy.withdraw(assets, receiver, owner) -> uint256

Burn shares; remove USDC liquidity from Curve pool to receiver.

Param Type Description
assets uint256 Target USDC
receiver address Payout address
owner address Must be vault

Returns: uint256 — shares burned.

Access: vault only. nonreentrant. Full exit if requested shares ≥ held.

Events: Withdraw.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:288-306):

@external
@nonreentrant
def withdraw(assets, receiver, owner) -> uint256:
    # burn shares; _remove_liquidity(assets_eff, receiver, full)
    return shares

Cross-links: redeem · previewWithdraw

redeem

CurveTAREStrategy.redeem(shares, receiver, owner) -> uint256

Burn exact shares; remove USDC from Curve LP to receiver.

Param Type Description
shares uint256 Shares to burn
receiver address USDC recipient
owner address Must be vault

Returns: uint256 — USDC paid (got from _remove_liquidity).

Access: vault only. nonreentrant.

Events: Withdraw (logs actual USDC got).

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:310-322):

@external
@nonreentrant
def redeem(shares, receiver, owner) -> uint256:
    assets_eff = self._convert_to_assets(shares, False)
    got = self._remove_liquidity(assets_eff, receiver, full)
    return got

Cross-links: withdraw · previewRedeem

Admin

set_apr_bps

CurveTAREStrategy.set_apr_bps(new_bps)

Update cached APR for smart routing.

Param Type Description
new_bps uint256 APR bps (≤ MAX_APR_BPS = 5000)

Access: DEFAULT_ADMIN_ROLE only.

Events: AprUpdated(new_bps).

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:329-333):

@external
def set_apr_bps(new_bps: uint256):
    access_control._check_role(DEFAULT_ADMIN_ROLE, msg.sender)
    self.apr_bps = new_bps

Cross-links: getApr

set_slippage_bps

CurveTAREStrategy.set_slippage_bps(new_bps)

Slippage tolerance for add/remove liquidity vs virtual price.

Param Type Description
new_bps uint256 Slippage bps (≤ MAX_SLIPPAGE_BPS = 1000)

Access: DEFAULT_ADMIN_ROLE only.

Events: SlippageUpdated(new_bps).

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:336-340):

@external
def set_slippage_bps(new_bps: uint256):
    access_control._check_role(DEFAULT_ADMIN_ROLE, msg.sender)
    self.slippage_bps = new_bps

Cross-links: deposit · withdraw

set_deposits_paused

CurveTAREStrategy.set_deposits_paused(state)

Pause/resume vault deposits. Withdrawals always allowed.

Param Type Description
state bool True = pause deposits

Access: DEFAULT_ADMIN_ROLE only.

Events: DepositsPaused(state).

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:343-346):

@external
def set_deposits_paused(state: bool):
    access_control._check_role(DEFAULT_ADMIN_ROLE, msg.sender)
    self.deposits_paused = state

Cross-links: deposit · maxDeposit

sweep

CurveTAREStrategy.sweep(token, to)

Recover stray ERC-20 (not USDC or pool LP token).

Param Type Description
token address Token to sweep
to address Recipient

Access: DEFAULT_ADMIN_ROLE only. Cannot sweep asset or pool.

Source (khomdev-keep/src/strategies/CurveTAREStrategy.vy:349-355):

@external
def sweep(token: address, to: address):
    assert token != asset and token != pool
    IERC20(token).transfer(to, IERC20(token).balanceOf(self))