Skip to main content

Release over-reserved credit

GET 

/v1/actions/twyne/rebalance

Release the excess credit that interest accrual has left reserved on a position, lowering what the borrower pays.

Twyne is a credit-delegation layer over Aave V3 and Euler V2, not a lending market of its own: capital never leaves the external protocol. Credit-LPs deposit a receipt token they already hold (eWETH, or a Twyne wrapper around an aToken) into an intermediate credit vault; a borrower deploys a collateral vault — one contract per position — that RESERVES that credit, so the external market sees one ordinary borrower while the user's own collateral carries a much higher LTV (93.26 % → 98 %).

Three consequences shape this API:

  • A position is a contract, and there may be SEVERAL per user per market. Every op past the create takes an optional posId (the collateral vault address); omitted, it resolves the account's only vault and refuses when there is more than one. Discovery is factory.getCollateralVaults(borrower).
  • There is no per-market LTV. Each position carries its own twyneLiqLTV, chosen at deploy time inside a live BAND: extLiqLTV × externalLiqBuffer ≤ chosen ≤ maxTwyneLTVs. Both bounds move — governance ramps the ceiling, and for a PT market the floor drifts as the collateral ages — so they are read fresh on every call and returned as data.band.
  • The collateral is not all the borrower's. totalAssetsDepositedOrReserved − maxRelease() is what a withdraw can pay out; the rest is reserved Credit-LP capital.

Every borrower op is an evc.call through Twyne's OWN EVC 0xef39D649…, never Euler's canonical one. Liquidation is by INHERITANCE — the liquidator becomes the borrower and heals the position — so there is no seize-and-sell penalty auction.

rebalance() is PERMISSIONLESS — the transaction goes straight to the collateral vault, so a keeper may send it for someone else; operator names WHOSE position, not who must sign. The amount that will be released is returned as data.releasableCredit.

A position with nothing to release is refused before it becomes a transaction: the vault's canRebalance() REVERTS in that state, so the call would revert with no usable reason.

Plain-text reference — GET /v1/actions/twyne/rebalance

Parameters

ParameterInTypeRequiredDescription
chainIdquerystringyesChain id See the ChainId schema for the full set of supported chains.
lenderquerystringyesPer-market key See the LenderId schema for the full set of accepted values.
operatorquerystringyesThe position owner (NOT necessarily the sender — the op is permissionless)
posIdquerystringnoCollateral vault address. Optional when the account holds exactly one vault in this market

Response 200

FieldTypeDescription
successTrue
dataobjectInformational data (quotes, simulation results, etc.)
actionsobjectTransaction calldata and approvals. Null for quote-only responses (no account provided).
actions.transactionsobject[]Pre-trade setup transactions (e.g. e-mode switch, collateral enable). Execute these before the main swap. Empty when no setup is needed.
actions.transactions[].tostringTarget contract address
actions.transactions[].datastringEncoded calldata
actions.transactions[].valuestringETH value to send with the transaction
actions.transactions[].descriptionstringHuman-readable label. For alternatives, this is the aggregator name (e.g. "Paraswap"). For transactions, describes the setup action (e.g. "Switch e-mode to 1").
actions.alternativesobject[]DEX aggregator swap transactions sorted by best output (descending). Each entry's description is the aggregator name. The client should pick one to execute. Present on loop action endpoints.
actions.alternatives[].tostringTarget contract address
actions.alternatives[].datastringEncoded calldata
actions.alternatives[].valuestringETH value to send with the transaction
actions.alternatives[].descriptionstringHuman-readable label. For alternatives, this is the aggregator name (e.g. "Paraswap"). For transactions, describes the setup action (e.g. "Switch e-mode to 1").
actions.permissionsobject[]Approval/delegation transactions that must execute before both transactions and alternatives. Includes ERC20 allowances (targeting the composer contract) and lender borrow/withdrawal delegations (targeting the lending protocol contract directly). Filtered against on-chain state so only missing approvals are returned. Null when no approvals are needed.
actions.permissions[].tostringTarget contract address
actions.permissions[].datastringEncoded calldata
actions.permissions[].valuestringETH value
actions.permissions[].descriptionstringHuman-readable description of the approval (e.g. "Approve borrow for AAVE_V3", "Approve ERC20")
actions.permissions[].spenderstringERC-20 approve spender (x-chain permissions). Match it against the selected quote's approvalTarget — several bridges can share one spender, so do not match by description.

Example response

{
"success": true,
"data": {},
"actions": {
"transactions": [
{
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"alternatives": [
{
"to": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string"
}
],
"permissions": [
{
"to": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
"data": "0x617ba037000000000000000000000000c02aaa39b2",
"value": "0",
"description": "string",
"spender": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
}
]
}
}

Request

Responses

Rebalance transaction + releasableCredit