Skip to main content
Reserving coins is one of actions that a smart contract can perform during the action phase. In TVM it is implemented via the RAWRESERVE instruction that takes from the stack an amount of Toncoin (in nanotoncoins) to reserve and an integer mode specifying a way of the reservation. The reservation action is queued to the output action list of a smart contract, which contains other actions such as message sends. The RAWRESERVE instruction is equivalent to creating an outbound message carrying the specified amount of nanotoncoin to oneself. But unlike regular sending of a message, the reservation action does not create a new message and does not incur any forward fees. Its primary goal is to limit the amount of Toncoin that can be spent by subsequent actions.

Modes

The mode parameter is a bitmask that specifies how a reserved amount is calculated. The resulting mode value can have the following base modes:
Mode valueConvenient nameDescription
0ReserveExactReserves exactly the specified amount of nanotoncoin.
1ReserveAllExceptReserves all but the specified amount of nanotoncoin.
2ReserveAtMostReserves at most the specified amount of nanotoncoin.
Additionally, the resulting mode can have the following optional flags added:
Flag valueConvenient nameDescription
+4ReserveAddOriginalBalanceIncreases the amount by the original balance (i.e. without incoming message value) of the current account before the compute phase.
+8ReserveInvertSignNegates the amount value before performing the reservation.
+16ReserveBounceIfActionFailBounces the transaction if the reservation fails.

Behavior

Notation:
  • amount – the amount of Toncoin passed to the RAWRESERVE instruction.
  • mode – the integer mode passed to the RAWRESERVE instruction.
  • original_balance:
    • if after the storage phase, account’s balance is less than the value of incoming message with bounce flag set to false, then original_balance is set to 00;
    • otherwise, original_balance equals account’s balance before the compute phase minus incoming message value.
  • remaining_balance – account’s balance before the reservation action.
  • reserve – the final amount to be reserved.
The algorithm is as follows:
  1. Check that mode has flag ReserveBounceIfActionFail:
    • if so, then in case of any failure the action phase will be interrupted and the bounce phase will be initiated;
    • if not, then in case of any failure the reservation action will be skipped.
  2. Set reserve to amount.
  3. Check that mode has flag ReserveAddOriginalBalance:
    1. If so, then check that mode has flag ReserveInvertSign:
      • if so, then set reserve to original_balance - reserve;
      • otherwise, increase reserve by original_balance.
    2. Otherwise, if mode has flag ReserveInvertSign, throw the error “invalid reserve mode”.
  4. Check that mode has flag ReserveAtMost:
    • if so, then set reserve to min(reserve, remaining_balance).
  5. Check that mode has flag ReserveAllExcept:
    • if so, then set reserve to remaining_balance - reserve.
  6. Set remaining_balance to remaining_balance - reserve.
If there were no errors, then the reservation action was successful, and the subsequent actions can spend only at most the new remaining_balance. For example, suppose that:
  • amount = 0.1 Ton;
  • mode = 1 + 4 + 8 (ReserveAllExcept, ReserveAddOriginalBalance, ReserveInvertSign);
  • original_balance = 2 Ton;
  • remaining_balance = 3 Ton.
Then the reservation proceeds as follows:
  1. mode has flag ReserveBounceIfActionFail? No.
  2. reserve = 0.1 Ton.
  3. mode has flag ReserveAddOriginalBalance? Yes.
    • mode has flag ReserveInvertSign? Yes.
    • Thus, reserve = original_balance - reserve = 2 - 0.1 = 1.9 Ton.
  4. mode has flag ReserveAtMost? No.
  5. mode has flag ReserveAllExcept? Yes.
    • Thus, reserve = remaining_balance - reserve = 3 - 1.9 = 1.1 Ton.
  6. remaining_balance = remaining_balance - reserve = 3 - 1.1 = 1.9 Ton.

Errors

The following errors can occur during the reservation flow:
  • If the mode bitmask has more then first five ones positive bits, then the error 34 is thrown.
  • If mode has flag 8 but not flag 4, then the the error 34 is thrown.
  • If after step 3, reserve is negative, then the the error 34 is thrown.
  • Passing a negative amount also results in the same error.
  • If after step 4, reserve is greater than remaining_balance, then the error 37 (“Not enough Toncoin”) is thrown.
  • Some problems with unpacking the reserve action cell.
  • A problem related to extra-currency.
If the action had flag 16, then in case of any of the above errors a bounce message is sent back to a sender.