# Stake

**Overview**

In **Financial** contract there're op-codes `OP::SIMPLE_TRANSFER` and `OP::STAKE`. They're used to perform staking of TON in the contract, resulting in the creation of a corresponding amount of bmTON in exchange for the staked TON. The current pools of bmTON and TON are taken into account, allowing the calculation of the amount of bmTON to be created dynamically. If the operation is successful, the total supply of bmTON and TON is updated, and the newly minted bmTON jettons are sent to the user's wallet address.

* `OP::SIMPLE_TRANSFER`: Calls the mint function with a `query_id` of `0` and null for the `forward_payload`. It is a simple invocation that doesn’t pass any extra data aside from `msg_value` and `fwd_fee`.
* `OP::STAKE`: Calls the mint function with a `query_id` (provided in `in_msg_body`), a `forward_ton_amount` (specified TON amount to forward) and a `forward_payload` (optional cell for forwarding additional data). These parameters enable more complex interactions, such as sending additional data for use in staking-related functions.

When a user stakes a certain amount of TON, the number of bmTON jettons to be minted is determined based on the existing bmTON and TON pools.

The number of bmTON minted is calculated using the formula:

&#x20;`stake_jetton_amount = jetton_total_supply * stake_ton_amount / ton_total_supply`&#x20;

Where:

* `jetton_total_supply` is the total supply of bmTON before staking.
* `ton_total_supply` is the total amount of staked TON before the staking operation.
* `stake_ton_amount` is the amount of TON to be staked after subtracting any relevant fees (`int stake_ton_amount = msg_value - get_ton_amount_for_stake(forward_ton_amount, fwd_fee)`).

**TL-B scheme for stake message**

```
stake#4253c4d5 query_id:uint64 forward_ton_amount:Coins forward_payload:(Either Cell ^Cell) = InternalMsgBody;
```

**Steps to verify the result of the** **staking operation:**

To ensure the staking operation was executed correctly, follow these steps:

1. **Check the updated bmTON and TON pools:**

* Verify that the `jetton_total_supply` has increased by the `calculated stake_jetton_amount`.
* Ensure that the `ton_total_supply` has increased by `stake_ton_amount`.

2. **Confirm the transfer of bmTON:**

* The minted bmTON should be sent to the user’s jetton wallet address. Verify that the correct amount was transferred.
* The transaction should use the `OP::INTERNAL_TRANSFER`, and the `query_id` should match the identifier in the staking request.

**Validate any additional data transfers:**

* If the staking operation included forwarding any additional payload (`forward_payload`), ensure that it was correctly forwarded with the transfer.

**Common errors that may occur during processing `OP::STAKE` and `OP::SIMPLE_TRANSFER`**&#x20;

When performing operations in a smart contract, various errors can occur due to incorrect input, insufficient funds, or other issues. To handle these errors effectively, it’s important to understand what kind of errors might arise, how to catch them, and how to determine the underlying issue. Below is a detailed guide on common errors, how to detect them, and troubleshooting strategies.

1. `ERROR::INSUFFICIENT_MSG_VALUE`
   * **Cause**: This error occurs when the provided message value is less than the required amount to perform the operation. For example, the amount of TON sent may not be enough to cover the staking amount after subtracting fees.
   * **How to Detect**: Check if the contract throws this error when the condition `msg_value < required_amount` is true.
   * **Troubleshooting**: Ensure that the amount sent in the transaction is enough to cover the required fees and the intended operation. Recalculate the required amount based on the operation and include enough extra funds for transaction fees.
2. `ERROR::NOT_BASECHAIN`
   * **Cause**: This error happens when the message is sent from a non-basechain workchain (i.e., not workchain 0). The contract may be designed to only accept transactions from the main chain.
   * **How to Detect**: The contract checks if the sender’s workchain is not equal to 0 and throws this error if true.
   * **Troubleshooting**: Ensure that the transaction is being sent from the basechain (workchain = 0). Verify the sender address and ensure that it matches the expected workchain for the operation.

#### Example of sending stake message using pytoniq <a href="#user-content-example-of-sending-stake-message-using-pytoniq" id="user-content-example-of-sending-stake-message-using-pytoniq"></a>

So, to create a payload cell you need to provide the following params:

* `OP::STAKE` (`0x4253c4d5`) - The operation code indicating the type of operation. Represented by a 32-bit unsigned integer
* `query_id` - A unique identifier for the request, used for tracking the operation. It is a 64-bit unsigned integer that should be unique for each transaction.
* `forward_ton_amount` - The amount of TON to be forwarded in another message or included in the response. This amount is excluded from the staking calculation.
* `forward_payload` - An optional payload that can be included in the message to be forwarded. This data will be passed along with the forwarding message.

Or you can just send TON attached to the empty message to the **Financial** contract

**Let's write a simple code that builds payload cell and sends message to Financial:**

```
from pytoniq import WalletV4R2, LiteBalancer, begin_cell
import asyncio
mnemonics = ["your", "mnemonics", "here"]

async def main():
    provider = LiteBalancer.from_mainnet_config(1)
    await provider.start_up()

    OP_STAKE = 0x4253c4d5

    FINANCIAL_ADDRESS = "EQCSxGZPHqa3TtnODgMan8CEM0jf6HpY-uon_NMeFgjKqkEY"

    stake_msg = begin_cell()\
        .store_uint(OP_STAKE, 32)\
        .store_uint(123, 64)\   # example query_id, should be unique for each request
        .store_coins(int(0.01*1e9))\
    .end_cell()

    ton_to_stake = 100  # example value
    wallet = await WalletV4R2.from_mnemonic(provider=provider, mnemonics=mnemonics)
    await wallet.transfer(destination=FINANCIAL_ADDRESS,
                          amount=int(ton_to_stake*1e9),
                          body=stake_msg)

    await provider.close_all()

asyncio.run(main())

```


---

# 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://docs.bemo.fi/developers/bemo-v2/stake.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.
