On-chain games on StarkNet will require frequent transactions. With a typical wallet the user has to approve every transaction in the UI of his wallet. This results in the user frequently leaving the game to open his wallet, approve the transaction, before he can return to the game and resume playing. This is a terrible user experience and one of the main friction point for on-chain gaming.
Instead, what users want is to connect their wallet at the beginning of a play and stay in the game until the end of the session. All this without giving custody of their wallet and with the guarantee that only game related transactions can be executed during the session.
Thanks to account abstraction we can create this ideal experience by using session keys. A session key
is a temporary key created and managed by the game which is authorised to execute transactions directly on the user’s account contract under certain conditions. These conditions can be e.g.:
All conditions must be enforced on-chain.
We note that on StarkNet the main cost of a transaction comes from state changes that must be propagated to L1. The best implementation of session keys should thus minimise the amount of data that must be stored on-chain.
The ArgentAccount
contract will support the addition of plugins. A plugin is a separate contract that can extend the functionalities of the account. It exposes the following interface:
@contract_interface
namespace IPlugin:
# Method to call for validation
func validate(
plugin_data_len: felt,
plugin_data: felt*,
call_array_len: felt,
call_array: CallArray*,
calldata_len: felt,
calldata: felt*
):
end
# Method to call for execution
func execute(
plugin_data_len: felt,
plugin_data: felt*,
call_array_len: felt,
call_array: CallArray*,
calldata_len: felt,
calldata: felt*
):
end
end
For any transaction the caller can instruct the account to execute a multi-call with a given plugin provided that the plugin has been registered in the account. During validation and execution the account will delegate the execution to the plugin by calling the validate
and execute
methods respectively. The methods must be called with a delgate_call
to comply to the limitations of the validation phase, and to make sure the calling contract of the calls is always the account (i.e. msg.sende = account
in Solidity).
To instruct the account to use a plugin the caller must prepend the multi-call to execute with a first call identifying the plugin to use. Some additional raw data can be optionally passed to the methods of the plugin.
A multi-call with plugin as the form:
multicall = [Call0, Call1, Call2, Call3]
where