|
| 1 | +--- |
| 2 | +title: "Reserve coins" |
| 3 | +--- |
| 4 | + |
| 5 | +_Reserving coins_ is one of actions that a smart contract can perform during the [action phase](/foundations/phases#action-phase). In TVM it is implemented via the [`RAWRESERVE`](/tvm/instructions#fb02-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_. |
| 6 | + |
| 7 | +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. |
| 8 | + |
| 9 | +## Modes |
| 10 | + |
| 11 | +The `mode` parameter is a bitmask that specifies how a reserved amount is calculated. The resulting mode value can have the following base modes: |
| 12 | + |
| 13 | +| Mode value | Convenient name | Description | |
| 14 | +| ---------: | :----------------- | ------------------------------------------------------- | |
| 15 | +| `0` | `ReserveExact` | Reserves exactly the specified `amount` of nanotoncoin. | |
| 16 | +| `1` | `ReserveAllExcept` | Reserves all but the specified `amount` of nanotoncoin. | |
| 17 | +| `2` | `ReserveAtMost` | Reserves at most the specified `amount` of nanotoncoin. | |
| 18 | + |
| 19 | +Additionally, the resulting `mode` can have the following optional flags added: |
| 20 | + |
| 21 | +| Flag value | Convenient name | Description | |
| 22 | +| ---------: | :-------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | |
| 23 | +| `+4` | `ReserveAddOriginalBalance` | Increases the `amount` by the original balance (i.e. without incoming message value) of the current account before the compute phase. | |
| 24 | +| `+8` | `ReserveInvertSign` | Negates the `amount` value before performing the reservation. | |
| 25 | +| `+16` | `ReserveBounceIfActionFail` | Bounces the transaction if the reservation fails. | |
| 26 | + |
| 27 | +## Behavior |
| 28 | + |
| 29 | +Notation: |
| 30 | + |
| 31 | +- `amount` – the amount of Toncoin passed to the `RAWRESERVE` instruction. |
| 32 | +- `mode` – the integer mode passed to the `RAWRESERVE` instruction. |
| 33 | +- `original_balance`: |
| 34 | + - 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 $0$; |
| 35 | + - otherwise, `original_balance` equals account's balance before the compute phase minus incoming message value. |
| 36 | +- `remaining_balance` – account's balance before the reservation action. |
| 37 | +- `reserve` – the final amount to be reserved. |
| 38 | + |
| 39 | +The algorithm is as follows: |
| 40 | + |
| 41 | +1. Check that `mode` has flag `ReserveBounceIfActionFail`: |
| 42 | + - if so, then in case of any failure the action phase will be interrupted and the bounce phase will be initiated; |
| 43 | + - if not, then in case of any failure the reservation action will be skipped. |
| 44 | +1. Set `reserve` to `amount`. |
| 45 | +1. Check that `mode` has flag `ReserveAddOriginalBalance`: |
| 46 | + 1. If so, then check that `mode` has flag `ReserveInvertSign`: |
| 47 | + - if so, then set `reserve` to `original_balance - reserve`; |
| 48 | + - otherwise, increase `reserve` by `original_balance`. |
| 49 | + 1. Otherwise, if `mode` has flag `ReserveInvertSign`, throw the error "invalid reserve mode". |
| 50 | +1. Check that `mode` has flag `ReserveAtMost`: |
| 51 | + - if so, then set `reserve` to `min(reserve, remaining_balance)`. |
| 52 | +1. Check that `mode` has flag `ReserveAllExcept`: |
| 53 | + - if so, then set `reserve` to `remaining_balance - reserve`. |
| 54 | +1. Set `remaining_balance` to `remaining_balance - reserve`. |
| 55 | + |
| 56 | +If there were no errors, then the reservation action was successful, and the subsequent actions can spend only at most the new `remaining_balance`. |
| 57 | + |
| 58 | +For example, suppose that: |
| 59 | + |
| 60 | +- `amount` = `0.1` Ton; |
| 61 | +- `mode` = `1 + 4 + 8` (`ReserveAllExcept`, `ReserveAddOriginalBalance`, `ReserveInvertSign`); |
| 62 | +- `original_balance` = `2` Ton; |
| 63 | +- `remaining_balance` = `3` Ton. |
| 64 | + |
| 65 | +Then the reservation proceeds as follows: |
| 66 | + |
| 67 | +1. `mode` has flag `ReserveBounceIfActionFail`? No. |
| 68 | +1. `reserve` = `0.1` Ton. |
| 69 | +1. `mode` has flag `ReserveAddOriginalBalance`? Yes. |
| 70 | + - `mode` has flag `ReserveInvertSign`? Yes. |
| 71 | + - Thus, `reserve` = `original_balance - reserve` = `2 - 0.1` = `1.9` Ton. |
| 72 | +1. `mode` has flag `ReserveAtMost`? No. |
| 73 | +1. `mode` has flag `ReserveAllExcept`? Yes. |
| 74 | + - Thus, `reserve` = `remaining_balance - reserve` = `3 - 1.9` = `1.1` Ton. |
| 75 | +1. `remaining_balance` = `remaining_balance - reserve` = `3 - 1.1` = `1.9` Ton. |
| 76 | + |
| 77 | +## Errors |
| 78 | + |
| 79 | +The following errors can occur during the reservation flow: |
| 80 | + |
| 81 | +- If the `mode` bitmask has more then first five ones positive bits, then the error [`34`](https://beta-docs.ton.org/tvm/exit-codes#34%3A-invalid-or-unsupported-action) is thrown. |
| 82 | +- If `mode` has flag `8` but not flag `4`, then the the error [`34`](https://beta-docs.ton.org/tvm/exit-codes#34%3A-invalid-or-unsupported-action) is thrown. |
| 83 | +- If after step 3, `reserve` is negative, then the the error [`34`](https://beta-docs.ton.org/tvm/exit-codes#34%3A-invalid-or-unsupported-action) is thrown. |
| 84 | +- Passing a negative `amount` also results in the same error. |
| 85 | +- If after step 4, `reserve` is greater than `remaining_balance`, then the error [`37`](https://beta-docs.ton.org/tvm/exit-codes#37%3A-not-enough-toncoin) ("Not enough Toncoin") is thrown. |
| 86 | +- Some problems with unpacking the reserve action cell. |
| 87 | +- A problem related to extra-currency. |
| 88 | + |
| 89 | +If the action had flag `16`, then in case of any of the above errors a [bounce message](/foundations/messages/bounce) is sent back to a sender. |
0 commit comments