diff --git a/tips/TIP-0051/tip-0051.md b/tips/TIP-0051/tip-0051.md new file mode 100644 index 000000000..1d3fbf4d0 --- /dev/null +++ b/tips/TIP-0051/tip-0051.md @@ -0,0 +1,141 @@ +--- +tip: 51 +title: ISC request Output metadata encoding +description: describes the encoding to send request outputs to an ISC chain +author: Jorge Silva (@jorgemmsilva) +status: Draft +type: Standards +layer: L2 Smart Contracts +created: 2023-09-27 +requires: None +replaces: None +--- + +## Summary + +This document describes the encoding of an ISC request to be included in a request output Metadata feature. + +## Motivation + +In order to interact with ISC chains using L1 output requests, the metadata for a request must be specified in the Metadata feature of the created output. + +## Specification + +(LE stands for Little Endian, BE stands for Big Endian.) + +### Request Metadata + +Encoding of the request metadata follows the following structure, in strict order: + +| Description | Type | Encoding | +| ---------------- | ---------------- | ---------------------------------------------------------------------------------- | +| SenderContract | ContractIdentity | [custom](./###ContractIdentity) | +| TargetContract | HName (uint32) | LE encoding uint32 (4 bytes) | +| TargetEntryPoint | HName (uint32) | LE encoding uint32 (4 bytes) | +| GasBudget | uint64 | LE encoding uint64 (8 bytes) - Value +1
(1 must be encoded as 2, 3 as 4 ,etc) | +| Params | Dictionary | [custom](./###Dictionary) | +| Allowance | Assets | [custom](./###Assets) | + + +### Hname + +The hnames can be calculated from: Blake2B Hash of an UTF-encoded string, then taking the initial 4 bytes as a LE encoded uint32: + +```go +Blake2B("accounts") // yields 0x3c4b5e02..... +``` + +### ContractIdentity + +Is used to identify a contract on a given chain (for the time being, contracts can only be of type `EVM` or `ISC`). + +When sending requests from non-chain identities (regular user wallet), the `ContractIdentity` should always be `null`. + +There are 3 types of `ContractIdentity`: + +- `null` - encoded as a single Kind `0` byte +- `EVM` - encoded as a Kind byte `1`, followed by the EVM address (20 bytes) +- `ISC` - encoded as a kind byte `2`, followed by an uint32 LE encoding (4 bytes) + +### Dictionary + +A dictionary is a set of Key/Value pairs. +Must be encoded in the following way: + +- Length Prefix (number of kv pairs) using [Optimized Size Encode](https://github.com/iotaledger/wasp/blob/c362291b053f70c9b14a16961dd74b3b4176bba5/packages/util/rwutil/convert.go#L108-L137) +- Each kv pair: [ + - `Key` bytes, prefixed with size in [Optimized Size Encode](https://github.com/iotaledger/wasp/blob/c362291b053f70c9b14a16961dd74b3b4176bba5/packages/util/rwutil/convert.go#L108-L137) + - \+ `Value` bytes prefixed with size in [Optimized Size Encode](https://github.com/iotaledger/wasp/blob/c362291b053f70c9b14a16961dd74b3b4176bba5/packages/util/rwutil/convert.go#L108-L137)] + +### Assets + +The Assets encoding starts with a bitmask: + +```go +hasBaseTokens = 0x80 +hasNativeTokens = 0x40 +hasNFTs = 0x20 +``` + +followed by the 3 optional parts, in strict order: + +- Base Tokens - uint64 - LE encoding +- Native Tokens: + - length prefix (number of different tokens - uint16 LE encoding) + - \+ each [TokenID (38 bytes) + amount ([uint256 special encoding](./###Uint256))] +- NFTs + - length prefix (number of NFTs - uint16 LE encoding) + - \+ the bytes off all the NFTIDs (32 bytes each) + +### Uint256 + +Uint256 values are encoded using BE and unused bytes removed. Must prefixed by the length of the encoded bytes using the [Optimized Size Encode](https://github.com/iotaledger/wasp/blob/c362291b053f70c9b14a16961dd74b3b4176bba5/packages/util/rwutil/convert.go#L108-L137). + +## Example + +Follows an example of a deposit from L1 to an EVM address on a target chain: + +```go +{ + SenderContract: nil, + TargetContract: 1011572226 ( = 0x3c4b5e02), + EntryPoint: 603251617 ( = 0x23f4e3a1), + GasBudget: 10000, + Params: [ + { k: "a", v: EthereumAgentID( + address: 0xE913CAc59E0bA840039aDD645D5df83C294CC230, + chainID: 0xe14c3499349cb8d2fd771e09829883e4ecfae02e6b09c9b6a0fb3c7504b4e2f4) + }, + ], + Allowance: { + BaseTokens:0, + NativeTokens:[ + { + ID: 0x08e14c3499349cb8d2fd771e09829883e4ecfae02e6b09c9b6a0fb3c7504b4e2f40100000000, + Amount: 50 + } + ], + NFTs: [], + }, +} +``` + +The `TargetContract` is `"accounts"` and `TargetEntrypoint` is `"transferAllowanceTo"`. + +The `EthereumAgentID` is encoded as: kind byte of value 3 + chainID bytes + ethereumAddress bytes. + +results in the following metadata: + +```hex +0x00025e4b3ca1e3f423914e0101613503e14c3499349cb8d2fd771e09829883e4ecfae02e6b09c9b6a0fb3c7504b4e2f4e913cac59e0ba840039add645d5df83c294cc230400108e14c3499349cb8d2fd771e09829883e4ecfae02e6b09c9b6a0fb3c7504b4e2f401000000000132 +``` + +## Libraries + +The Wasp repo already provides function to Encode/Decode request metadata (in Go). + +A javascript library should be produced to be re-used across client applications. + +## Copyright + +Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).