Self describing selector to simplify wallets data parsing

Here I present a proposal to enable wallets to trustlessly parse and decode data coming as inputs of smart contract functions.

Let be foo(amount, token, merklePath), where foo is a smart contract method, amount is a Uint, token is an address, merklePath is an array of bytes
Today, StarkNet defines function selector as keccak_250(foo), with foo being the method name.

The suggestion is to define the selector as the -keccak_250(amount,uint,true,token,address,true,merklePath,array[bytes],false), where each variable is defined by a triplet [variableName, variableType, variableToDisplayToUser]

The purpose is to provide a secure way to pass to wallets the method description. This selection creation could be generated by the compiler. Notice that this change is backward compatible as the compiler is not enforced at the StarkNet level.

1 Like

I see an improvement by adding a version element at the start of the selector

The suggestion is to define the selector as the - keccak_250(version,amount,uint,true,token,address,true,merklePath,array[bytes],false), where each variable is defined by a triplet [variableName, variableType, variableToDisplayToUser] and version is a uint

Is it a good idea to have a variableToDisplayToUser field which means dapp can control what the user sees on his wallet? Probably safer to display all the inputs by default.

Also, I think having some form of structure in the input fields would make it less prone to errors. For example if we remove variableToDisplayToUser then the selctor of foo could be computed as keccak_250(amount:uint,token:address,merklePath:array[bytes])

As a user calls a contract, it trusts it. The only reason to have data displayed or not is just indicative and to help wallets (such that they don’t display endless merkle path for instance.)
The wallet can decide to respect the convention or discard it

1 Like

Some comments (please bear with me if there are any starknet specific details that I might be missing… just point me to the relevant docs)

  • If I understand correctly, this would be signing the hash of arguments ONLY, however, the contract address or chain id is not included or signed. This could result in replay attacks, etc. Is this supposed to be included in some kind of envelope? When is the envelope signed?

  • The “variableToDisplayToUser” can be useful to optionally decide if this info should be shown or not. In HW wallets if can be used to determine if this field is only shown to experts. I would probably use a full byte for full extensibility.

  • Being the smart contracts quite generic, there is a risk that number formatting (decimal point, etc) may not be very clear or correct. Having more specific types would be useful. A table of types would be important.

  • I know a second stage would be to define the serialization details for this list of arguments. Is RLP planned or it is possible to use something like CBOR instead?

1 Like

New version:
The suggestion is to define the selector as the - keccak_250(version,foo(amount,uint,true,token,address,true,merklePath,array[bytes],false)) , where each variable is defined by a triplet [variableName, variableType, variableToDisplayToUser]

1 Like

@guthl, there’s no reason to verify (open the hash) the format in the StarkNet OS, right?
It’s between the compiler and the wallet: Assuming the user verifies the contract he’s interacting with (which they anyway should), and that the contract was compiled with a compiler that follows this standard, the wallets will be able to show the arguments to the user (there’s no need to trust the ABI information).

(If we do want to verify the format in the OS (I don’t see why we would), then it can’t be keccak, it should be a STARK friendly hash (e.g., pedersen))

I want to suggest another alternative:
Have the (keccak) hash of the JSON ABI part of the address computation of the contract in the deployment process. This way the wallet can verify that it has the right ABI and it will be able to show the correct fields to the user. WDYT?

  • If I understand correctly, this would be signing the hash of arguments ONLY, however, the contract address or chain id is not included or signed. This could result in replay attacks, etc. Is this supposed to be included in some kind of envelope? When is the envelope signed?

If I understand @guthl’s proposal correctly, the point is only to remove the required trust from the ABI. The contract address will need to be verified by the user (maybe there’s something we can do there as well?) and the chain ID is on the wallet anyway so no need for special treatment.

  • The “variableToDisplayToUser” can be useful to optionally decide if this info should be shown or not. In HW wallets if can be used to determine if this field is only shown to experts. I would probably use a full byte for full extensibility.

So to expend on this suggestion, we can consider adding a default value to less frequently used fields?

  • Being the smart contracts quite generic, there is a risk that number formatting (decimal point, etc) may not be very clear or correct. Having more specific types would be useful. A table of types would be important.

Right, if we go with this proposal, we’ll have to make it very explicit.

1 Like