Custom instructions
The Flare Smart Accounts allow XRPL users to make custom function calls on Flare through instructions sent on XRPL.
In this guide we will look at how the custom instructions can be developed using a mock version of the MasterAccountController
contract.
In a typical workflow the users sends instructions as memo data on XRPL. Those then have to be verified by the FDC on the Flare chain. That process requires waiting, which is less than ideal in a development environment.
For that reason, a mock version of the MasterAccountController
contract has been deployed.
It implements two additional functions:
createFundPersonalAccount
executeCustomInstructionDevelopment
The createFundPersonalAccount
function creates a new PersonalAccount
for the user.
It accepts as its argument a string _xrplAddress
, which represents and address on XRPL.
The string is then concatenated with the msg.sender
value;
the PersonalAccount
is created for this address.
Thus, a developer can create multiple XRPL "addresses". This allows them to more easily test the interactions between different personal accounts. The "address" is combined with their Flare address, so that they can give meaningful names to their "addresses" without a danger of multiple developers' addresses crashing.
The createFundPersonalAccount
function is a payable function.
And funds sent with the transaction are deposited to the newly created personal account.
That way, the personal account can interact with payable functions from the get-go.
The executeCustomInstructionDevelopment
function sidesteps the XRP transaction and the FDC Payment
verification process.
It allows developers to send an array of custom instructions to the MasterAccountController
contract directly.
The two parameters this function takes are the _xrplAddress
string, and an array of IMasterAccountController.CustomInstruction
structs.
It first concatenates the input string with the msg.sender
value, the same way the createFundPersonalAccount
function does.
Then, it retrieves the PersonalAccount
representing that address, and calls its custom
function with the array of custom instructions it received as input.
A simple example
We will now use the Flare Smart Accounts CLI to interact with a simple contract.
The contract Foo
has a single payable function bar
.
The bar
function accepts a uint256
value as input, and add the fee paid with the transaction to a mapping.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;
contract Foo {
mapping(uint256 => uint256) public map;
function bar(uint256 a) public payable {
map[a] = map[a] + msg.value;
}
}
We want to send 1 FLR
to the contract, and save it under number 42
.
The address of the Foo
contract is 0x296432C15504Ed465fAce11E54Ce4aac50cCd8A3
.
Using an online ABI-encoding tool, we get that the following hash for the bar
function, with 42
as input: 0x0423a132000000000000000000000000000000000000000000000000000000000000002a
.
There are two ways we can go about developing the custom instructions. We will start with an approach, which is what the production code would take. Afterwards, we will use the the mock functions to speed up the development.
Normal approach
Before we can execute the above instructions we need to top up the smart account that will perform the function call. We run the following command, which fails because our account lacks funds on Flare. It is necessary to send some instructions, because that is what creates an account for us in the first place.
./smart_accounts.py bridge custom -a "0x296432C15504Ed465fAce11E54Ce4aac50cCd8A3" -v 1 -d "0423a132000000000000000000000000000000000000000000000000000000000000002a"
We then need to retrieve the smart account address.
./smart_accounts personal-account --from-env print
With the address, we can go to the Flare faucet and request C2FLR for the smart account address. We can also do this through the CLI.
./smart_accounts personal-account --from-env faucet
Afterwards, we can run the following command again. This time, it works.
./smart_accounts.py bridge custom -a "0x296432C15504Ed465fAce11E54Ce4aac50cCd8A3" -v 1 -d "0423a132000000000000000000000000000000000000000000000000000000000000002a"
Mocking
We can speed up the process, as well as simplify it, by using the Flare Smart Accounts CLI. First, we need to create a mock account, which we do with the command. This will only work if our Flare address has sufficient funds.
./smart_accounts mock-create-fund --seed "mockAccount" --value 1
Here we arbitrarily chose the name mockAccount
as the account address.
Behind the scenes, the string mockAccount
will be concatenated with our Flare address.
Then, we execute the custom instructions.
We use the string mockAccount
as the seed.
./smart_accounts.py debug mock-custom -s "mockAccount" -a "0x296432C15504Ed465fAce11E54Ce4aac50cCd8A3" -v 1 -d "0423a132000000000000000000000000000000000000000000000000000000000000002a"