> For the complete documentation index, see [llms.txt](https://docs.curvance.com/app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.curvance.com/app/developer-docs/quick-start-guides/plugin-integration/list-of-delegable-actions.md).

# List of Delegable Actions

Once a user has approved your contract as a delegate on a Curvance contract via `setDelegateApproval`, your application can perform that contract's delegated actions on their behalf. This page enumerates the plugin-delegated entrypoints that call `_checkDelegate`, plus the permissionless or PositionManager-only `*For` functions that are easy to confuse with plugin delegation.

***

### How the delegation check works

Not every `*For` function is plugin-delegated. The plugin-delegated entrypoints are the paths that call `_checkDelegate(userOrOwner, msg.sender)`, and the checked parameter name varies by contract: `receiver`, `owner`, `account`, `recipient`, or `user`. If the caller is not approved for that account on the contract being called, `_checkDelegate` reverts with `PluginDelegable__Unauthorized()`.

Delegation approval is stored on each contract that inherits `PluginDelegable`. Approving a delegate on one cToken does not approve it on another cToken or on a PositionManager. The current approval index comes from the Central Registry, so `centralRegistry.incrementApprovalIndex()` mass-revokes prior delegate approvals across `PluginDelegable` contracts.

***

### Delegable actions on each cToken

The cToken-level delegated actions below are implemented in `BaseCToken`, which inherits `PluginDelegable`; they are available on cToken implementations that inherit `BaseCToken`. Debt actions are implemented in `BorrowableCToken`. Do not infer borrowability from a market name or from "collateral" versus "debt" wording. Check `marketManager.debtCaps(cToken)`: zero means borrow attempts revert, while a nonzero cap means the market can carry debt up to that cap.

#### Collateral management

| Function                 | Signature                                           | Source               |
| ------------------------ | --------------------------------------------------- | -------------------- |
| `depositAsCollateralFor` | `(uint256 assets, address receiver)`                | `BaseCToken.sol:262` |
| `postCollateralFor`      | `(uint256 shares, address owner)`                   | `BaseCToken.sol:338` |
| `removeCollateralFor`    | `(uint256 shares, address owner)`                   | `BaseCToken.sol:363` |
| `redeemCollateralFor`    | `(uint256 shares, address receiver, address owner)` | `BaseCToken.sol:313` |

* `depositAsCollateralFor`: pull the caller's underlying, mint shares to `receiver`, and post them as collateral for `receiver` in one call.
* `postCollateralFor`: mark existing shares owned by `owner` as collateral.
* `removeCollateralFor`: unpost collateral for `owner`, leaving the shares as plain lending liquidity.
* `redeemCollateralFor`: redeem `owner`'s posted collateral shares to underlying and send the assets to `receiver`. This path forces the redeemed shares to come out of `owner`'s posted collateral. `redeemFor` does not force collateral removal; it uses idle shares first and removes posted collateral only if the redeemed share amount exceeds the owner's idle share balance.

#### Share redemption

| Function    | Signature                                           | Source               |
| ----------- | --------------------------------------------------- | -------------------- |
| `redeemFor` | `(uint256 shares, address receiver, address owner)` | `BaseCToken.sol:595` |

`redeemFor` burns `owner`'s shares and sends the resulting underlying to `receiver`. Delegation substitutes for the ERC20 share allowance that plain `redeem` requires when `msg.sender != owner`.

**There is no `withdrawFor`.** If your integration needs to pull a specific amount of underlying on behalf of a user, compute shares with `previewWithdraw(assets)` first, then call `redeemFor(shares, receiver, owner)`.

#### Debt management (BorrowableCToken only)

| Function    | Signature                                           | Source                     | Delegation-gated?                                |
| ----------- | --------------------------------------------------- | -------------------------- | ------------------------------------------------ |
| `borrowFor` | `(uint256 assets, address receiver, address owner)` | `BorrowableCToken.sol:194` | Yes. Checks `_checkDelegate(owner, msg.sender)`. |
| `repayFor`  | `(uint256 assets, address owner)`                   | `BorrowableCToken.sol:292` | **No** (permissionless)                          |

* `borrowFor`: take on new debt for `owner` and deliver the borrowed underlying to `receiver`. It requires prior delegation on the borrowed cToken, and the borrow still must pass the market's borrow checks, including the debt cap and account liquidity checks.
* `repayFor`: pull underlying from `msg.sender` and apply it against `owner`'s debt. It does not check delegation, so another account can repay a borrower's debt, but the caller still needs underlying token allowance and balance. Repayment also checks that `owner` has an active debt position, that the minimum hold period has passed, and that any remaining partial debt does not fall below `MIN_LOAN_SIZE`.

***

### Delegable actions on each PositionManager

Every Curvance PositionManager inherits `BasePositionManager` (which in turn inherits `PluginDelegable`). The following leverage actions are delegation-gated on the PositionManager itself, not on the cTokens.

| Function        | Signature                                                      | Source                        |
| --------------- | -------------------------------------------------------------- | ----------------------------- |
| `leverageFor`   | `(LeverageAction action, address account, uint256 slippage)`   | `BasePositionManager.sol:249` |
| `deleverageFor` | `(DeleverageAction action, address account, uint256 slippage)` | `BasePositionManager.sol:314` |

* `leverageFor`: borrow against `account`'s market liquidity, swap the borrowed asset into the collateral asset, and deposit it back as collateral.
* `deleverageFor`: redeem `account`'s collateral, swap it into the debt asset, and repay their debt.

{% hint style="info" %}
**Heads up:** `leverageFor` and `deleverageFor` require delegation on the PositionManager itself. A pure bundled PositionManager leverage or deleverage call does not require the user to delegate on the underlying cTokens. Internally, `leverageFor` calls `borrowForPositionManager`, which is authorized by `marketManager.isPositionManager(msg.sender)`, not by cToken plugin delegation. `deleverageFor` calls `withdrawByPositionManager`, which is also PositionManager-only, and then uses `repayFor`, which is permissionless.

Separate cToken calls before or after the bundled PositionManager action require approval on the specific cToken being called. For example, a delegated `redeemFor` on the collateral cToken needs collateral cToken delegation, and a delegated `borrowFor` on the debt cToken needs debt cToken delegation.
{% endhint %}

***

### Common calling pattern

All `*For` functions that take an `owner` or `account` parameter require the caller to be a pre-approved delegate of that owner on the specific contract being called:

```js
const userAddress = await user.getAddress();
const delegateAddress = await platform.getAddress();

// Add approvals only on contracts your platform will call directly.
// These approvals must be sent by the user.
const collateralApprovalTx = await collateralCToken
  .connect(user)
  .setDelegateApproval(delegateAddress, true);
await collateralApprovalTx.wait();

const positionManagerApprovalTx = await positionManager
  .connect(user)
  .setDelegateApproval(delegateAddress, true);
await positionManagerApprovalTx.wait();

// The platform can now invoke delegated calls on those contracts.
const redeemTx = await collateralCToken
  .connect(platform)
  .redeemFor(shares, delegateAddress, userAddress);
await redeemTx.wait();

const leverageTx = await positionManager
  .connect(platform)
  .leverageFor(action, userAddress, slippage);
await leverageTx.wait();
```

See [Plugin Integration](/app/developer-docs/quick-start-guides/plugin-integration.md) for the setup flow, per-contract verification via `isDelegate`, and revocation (both per-contract and global via `incrementApprovalIndex`).

***
