Problem:

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.

Solution:

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.

Implementation:

Support for plugins

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