Contract state mutability is handled automatically based on how
self is used in the function parameters. Depending on which is used, the
#[near_bindgen] macro will generate the respective code to load/deserialize state for any function which uses
self and serialize/store state only for when
&mut self is used.
The following semantics are consistent for all public methods.
To access state immutably, where the existing state is not overwritten at the end of the transaction, you can use
self as a parameter. Both of these will generate the same code to load and deserialize the state into the structure and call the function, but the difference is that
&self will just pass a reference to this variable into the function where
self will move the variable into the function.
For more information about
self see this section in the Rust book.
Here are some examples of using each:
There is no simple guideline that works for every case, but here are some core reasons on when to use each:
Moving the owned value into the function can be useful if
self itself or its fields are moved within the function, as it will remove the need to
Copy the data.
This should be used when the contract state is only read or the function is re-used by other methods which do not have ownership of the variable. This can also be useful if the struct uses a lot of memory, to avoid moving a large amount of data into the function scope rather than just referencing it.
Some less common cases may intend to use read-only methods to return objects that are derived from modified objects stored in state. Below is a demonstration of this concept:
Mutable functions allow for loading the existing state, modifying it, then rewriting the modified state at the end of the function call. This should be used for any transaction which modifies the contract state. Note that the serialized contract data is stored in persistent storage under the key
An example of a mutable function is as follows:
These functions do not use
self at all, and will not read or write the contract state from storage. Using public pure functions will be very rare but can be useful if returning data embedded in the contract code or executing some static shared logic that doesn't depend on state.
Some examples of pure functions are as follows: