# MarginTrading.sol

## How to Interact with a Margin Account directly

Below, you will find the functions needed to interact with a margin account. In most cases, you will need to know the margin account ID, which is a unique number assigned to each created margin account. To understand how to obtain this number, please refer to this page.

### How To Deposit Collateral (UDSC, WBTC, ETH)

To borrow funds from the liquidity pools, users must provide collateral tokens (USDC, WBTC, or ETH). We use Chainlink price feeds to calculate the value of your collateral in USDC.

```solidity
    function provideERC20(uint marginAccountID, address token, uint amount) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        marginAccount.provideERC20(marginAccountID, msg.sender, token, amount);

        emit ProvideERC20(marginAccountID, msg.sender, token, amount);
    }
```

### How to Deposit American-style options (Hegic Option Position)

```solidity
    function provideERC721(uint marginAccountID, address token, uint collateralTokenID) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        require(modularSwapRouter.checkValidityERC721(token, BASE_TOKEN, collateralTokenID), "token id is not valid");
        marginAccount.provideERC721(marginAccountID, msg.sender, token, collateralTokenID);

        emit ProvideERC721(marginAccountID, msg.sender, token, collateralTokenID);
    }
```

### How To Withdraw Collateral (USDC, WBTC, ETH)

When withdrawing collateral from a margin account, the following criteria must be met:

* `portfolioRatio > yellowCoeff`

The `yellowCoeff` may change, so to get the actual number, please check beginning of this contract

```solidity
    uint public yellowCoeff = 1.10 * 1e5; 
```

```solidity
    function withdrawERC20(uint marginAccountID, address token, uint amount) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        require(marginAccount.checkERC20Amount(marginAccountID, token, amount), "Insufficient token balance for withdrawal");
        uint marginAccountValue = calculateMarginAccountValue(marginAccountID);

        uint withdrawSizeInBaseToken = modularSwapRouter.calculatePositionValue(token, BASE_TOKEN, amount);
        marginAccountValue -= withdrawSizeInBaseToken;
        uint debtWithAccruedInterest = calculateDebtWithAccruedInterest(marginAccountID);
        uint portfolioRatio = _calculatePortfolioRatio(marginAccountValue, debtWithAccruedInterest);
        require(portfolioRatio > yellowCoeff, "portfolioRatio is too low");
        marginAccount.withdrawERC20(marginAccountID, token, amount, msg.sender);

        emit WithdrawERC20(marginAccountID, msg.sender, token, amount);
    }
```

### How to Withdraw American-style option (Hegic Option Position)

```solidity
    function withdrawERC721(uint marginAccountID, address token, uint value) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        require(marginAccount.checkERC721Value(marginAccountID, token, value), "The ERC721 token you are attempting to withdraw is not available for withdrawal");

        uint marginAccountValue = calculateMarginAccountValue(marginAccountID);

        uint withdrawSizeInBaseToken = modularSwapRouter.calculateAmountOutERC721(token, BASE_TOKEN, value);
        marginAccountValue -= withdrawSizeInBaseToken;

        uint debtWithAccruedInterest = calculateDebtWithAccruedInterest(marginAccountID);
        uint portfolioRatio = _calculatePortfolioRatio(marginAccountValue, debtWithAccruedInterest);

        require(portfolioRatio > yellowCoeff, "portfolioRatio is too low");

        marginAccount.withdrawERC721(marginAccountID, token, value, msg.sender);

        emit WithdrawERC721(marginAccountID, msg.sender, token, value);
    }
```

### How to Borrow (USDC, WBTC, ETH)

```solidity
    function borrow(uint marginAccountID, address token, uint amount) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        require(marginAccount.checkLiquidityPool(token), "Token is not supported");
        uint amountInBaseToken = modularSwapRouter.calculatePositionValue(token, BASE_TOKEN, amount);
        uint marginAccountValue = calculateMarginAccountValue(marginAccountID);
        uint debtWithAccruedInterest = calculateDebtWithAccruedInterest(marginAccountID);
        uint marginAccountRatio = _calculatePortfolioRatio(marginAccountValue + amountInBaseToken, debtWithAccruedInterest + amountInBaseToken);
        require(marginAccountRatio >= yellowCoeff, "Cannot borrow more; margin account ratio is too high"); 

        marginAccount.borrow(marginAccountID, token, amount);

        emit Borrow(marginAccountID, msg.sender, token, amount);
    }
```

### How to Repay&#x20;

```solidity
   function repay(uint marginAccountID, address token, uint amount) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        marginAccount.repay(marginAccountID, token, amount);

        emit Repay(marginAccountID, msg.sender, token, amount);
    }
```

### How to swap tokens

When a trader makes a swap, it is routed through Uniswap v3.

```solidity
    function swap(uint marginAccountID, address tokenIn, address tokenOut, uint amountIn, uint amountOutMinimum) external nonReentrant onlyApprovedOrOwner(marginAccountID) {
        uint marginAccountValue = calculateMarginAccountValue(marginAccountID);
        uint debtWithAccruedInterest = calculateDebtWithAccruedInterest(marginAccountID);
        uint marginAccountRatio = _calculatePortfolioRatio(marginAccountValue, debtWithAccruedInterest);
        require(marginAccountRatio >= redCoeff, "Cannot swap"); 
        emit Swap(marginAccountID, swapID, tokenIn, tokenOut, amountIn);

        marginAccount.swap(marginAccountID, swapID, tokenIn, tokenOut, amountIn, amountOutMinimum);

        swapID++;
    }
```

### How to exercise American-style option (Hegic Option Position)

```solidity
    function exercise(uint marginAccountID, address token, uint collateralTokenID) external nonReentrant onlyApprovedOrOwner(marginAccountID)  {
        require(marginAccount.checkERC721Value(marginAccountID, token, collateralTokenID), "You are not allowed to execute this ERC721 token");

        marginAccount.exercise(marginAccountID, token, BASE_TOKEN, collateralTokenID, msg.sender);

        emit Exercise(marginAccountID, token, BASE_TOKEN, collateralTokenID);
    }
```

### How to get the current margin account value in USDC

```solidity
    function calculateMarginAccountValue(uint marginAccountID) public returns (uint marginAccountValue) {
        (
            IModularSwapRouter.ERC20PositionInfo[] memory erc20Params, 
            IModularSwapRouter.ERC721PositionInfo[] memory erc721Params
        ) = prepareTokensParams(marginAccountID, BASE_TOKEN);
        marginAccountValue = modularSwapRouter.calculateTotalPositionValue(erc20Params,erc721Params);
    }
```

### How to get the current debt across all liquidity pools in USDC (borrowed amount + interest to be paid)

```solidity
    function calculateDebtWithAccruedInterest(uint marginAccountID) public returns (uint debtSizeInUSDC) {
        (
            IModularSwapRouter.ERC20PositionInfo[] memory erc20Params, 
            IModularSwapRouter.ERC721PositionInfo[] memory erc721Params
        ) = prepareTokensParamsByDebt(marginAccountID, BASE_TOKEN);
        debtSizeInUSDC += modularSwapRouter.calculateTotalPositionValue(erc20Params, erc721Params);
    }
```

### How to get the current margin ratio

```solidity
    function getMarginAccountRatio(uint marginAccountID) public returns(uint) {
        uint marginAccountValue = calculateMarginAccountValue(marginAccountID);
        uint debtWithAccruedInterest = calculateDebtWithAccruedInterest(marginAccountID);
        return _calculatePortfolioRatio(marginAccountValue, debtWithAccruedInterest);
    }
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sharwa.gitbook.io/sharwa-docs/for-devs/margin-account/core-contracts/margintrading.sol.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
