Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TIP 51 - ISC request metadata #155

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
141 changes: 141 additions & 0 deletions tips/TIP-0051/tip-0051.md
Original file line number Diff line number Diff line change
@@ -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) <[email protected]>
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 <br/>(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
- `ISC` - encoded as a kind byte `1`, followed by an uint32 LE encoding (4 bytes)
- `EVM` - encoded as a Kind byte `2`, followed by the EVM address (20 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/).
Loading