This example demonstrates the usage of purse
s to transfer motes inside a contract.
Each account on the network has its own default purse (the main_purse
). Creation of new purses inside contracts and session code is possible, and the creating context has full access to the purse by default. Access to purses can be limited by stripping READ|ADD|WRITE
bytes from the URef
that holds the purse.
It is important to note that not every purse action is available from any context.
transfer_from_purse_to_purse
is only possible when the caller has access rights to both purses. Namely WRITE
and READ
access to the purse they are transferring from, and ADD
access to the purse they are trying to transfer to.
An important example is the main_purse
of accounts. You can only withdraw from the main_purse
in the session context of the owning account, and WRITE
byte is removed automatically when you transfer a URef
to the main_purse
from the owners session.
If you want to use transfer_from_purse_to_account
on the other hand, you need only have access rights to the purse you transfer from, and will only transfer to the target account's main_purse
.
In short, you can only put motes into a purse you have ADD
access on, and you can only withdraw from a purse that has READ
and WRITE
.
You can also not give out WRITE
access to your main_purse
to other contexts.
You also cannot just "reconstruct" a URef that holds a purse from its bytes in a different contract.
You also cannot store purses in contract dictionaries, as such a purse when used will revert with a ForgedReference
error.
This means that a purse stored in a dictionary will become unusable, and as such you should not do this.
Calling the deposit endpoint requires a purse
as a parameter, as such you need separate logic which could be either session code or another smart contract, that creates a purse, transfers motes into it, and calls the endpoint with it.
- | Name | Type |
---|---|---|
param | amount | CLType::U512 |
param | purse | CLType::URef |
param | recipient | CLType::Key::Account |
return | - | - |
Purses can be withdrawn from if there are READ and WRITE bytes on the associated URef
. When you transfer to your account, the transfer ends up in your main_purse. When depositing there is no need to take the extra step of fetching the main_purse.
Since collecting is done by transfering motes from the purse contained in the contract straight into the callers account, the only parameter is an Option<U512>
argument called amount
.
- | Name | Type |
---|---|---|
param | amount | CLType::U512 |
return | - | - |
- transfer from caller accounts purse to an account (can only be done in session code):
let recipient: AccountHash = runtime::get_named_arg("recipient");
let amount: U512 = runtime::get_named_arg("amount");
let main_purse = account::get_main_purse();
system::transfer_from_purse_to_account(main_purse, recipient, amount, None)
.unwrap_or_revert();
- transfer from account to a purse inside contract (can only be done in session code):
let main_purse = account::get_main_purse();
let amount: U512 = runtime::get_named_arg("amount");
let local_purse = system::create_purse();
system::transfer_from_purse_to_purse(main_purse, local_purse, amount, None)
.unwrap_or_revert();
- get purse the balance of any purse that gets passed in as parameter, that has READ access byte:
let main_purse = account::get_main_purse();
system::get_purse_balance(main_purse);
- get caller account balance:
system::get_balance();
- create purse for in-contract use:
system::create_purse()
-
admin
- private key:
[1u8;32]
- account addr:
ef4687f74d465826239bab05c4e1bdd2223dd8c201b96f361f775125e624ef70
- purse_addr:
486e322928be0239e1ee99888cdca5be4e84cbce32b276903718c63fa84cc392
- private key:
-
participant_dos
- private key:
[2u8;32]
- account addr:
a6f341ee3d5124163c75a93364df7556b1763313554d3abf4bedc8206d94c1b2
- purse_addr:
d124a145ff53378cfff7970ca163b2acee77570c6c6852fc717de5067c325db6
- private key:
-
participant_tres
- private key:
[3u8;32]
- account addr:
67e7554760e6a57150ca567bdf38cc46ed178b5e688842ede7b854e8eabe5d80
- purse_addr:
3742e6011967754e97d28b35be8d915159db7b05370f802e79c9d4507f075e04
- private key:
This example has been tested with rustc 1.60.0-nightly (75d9a0ae2 2022-02-16)