diff --git a/plasma_framework/contracts/src/transactions/FungibleTokenOutputModel.sol b/plasma_framework/contracts/src/transactions/FungibleTokenOutputModel.sol index b2e31b1cc..e46ca7389 100644 --- a/plasma_framework/contracts/src/transactions/FungibleTokenOutputModel.sol +++ b/plasma_framework/contracts/src/transactions/FungibleTokenOutputModel.sol @@ -19,7 +19,7 @@ library FungibleTokenOutputModel { /** * @notice Given a GenericTransaction.Output, decodes the `data` field. - * The data field is an RLP list that must satisy the following conditions: + * The data field is an RLP list that must satisfy the following conditions: * - It must have 3 elements: [`outputGuard`, `token`, `amount`] * - `outputGuard` is a 20 byte long array * - `token` is a 20 byte long array @@ -59,4 +59,4 @@ library FungibleTokenOutputModel { require(outputIndex < transaction.outputs.length, "Output index out of bounds"); return decodeOutput(transaction.outputs[outputIndex]); } -} \ No newline at end of file +} diff --git a/plasma_framework/docs/design/payment-game-implementation-v1.md b/plasma_framework/docs/design/payment-game-implementation-v1.md index 08153994b..e000bd945 100644 --- a/plasma_framework/docs/design/payment-game-implementation-v1.md +++ b/plasma_framework/docs/design/payment-game-implementation-v1.md @@ -13,6 +13,7 @@ struct Transaction { uint256 txType; bytes32[] inputs; Output[] outputs; + uint256 txData; bytes32 metaData; } @@ -28,9 +29,10 @@ struct Output { 1. `txType` is a unique number that represents the type of transaction. Each transaction type has only one exit game contract associated with it. 1. The `inputs` field is an array of `bytes32` representing the `utxoPos` as the output identifier. There are a maximum four inputs allowed. An input can not be `0x0` if it is specified `inputs` list. 1. The `outputs` field is an array of `Output` struct representing payment output information. There are a maximum of four outputs allowed. -1. `metaData` field is a `bytes32` field that can be used to add extra data to the transaction. It should contain `0x0` if the transaction does not have extra data. +2. `txData` is unused and must be `0`. +3. `metaData` field is a `bytes32` field that can be used to add extra data to the transaction. It should contain `0x0` if the transaction does not have extra data. -Output has four elements that fulfil the current `GenericTransaction.Output`: +Output has four elements that fulfil the current `FungibleTokenOutputModel.Output`: 1. `outputType` represents the type of output. Each transaction type is tied to one or more output types. In Payment transaction V1, there is only one output type. The output type is used to decide, eg. which spending condition to use. Also, output type is bound to the input type. Currently the only output type that requires the spending tx's input to be using `utxoPos`. Potentially there can be output type deciding to be pointed by `outputId` instead in the future. 1. `outputGuard` is the field that represents the authentication data of the output. Its value must always be the same as the `owner` address of the output in the first version of Payment Transaction. For instance, if the output belongs to Alice, then the value of `outputGuard` equals Alice's address. 1. `token` is the ERC20 token contract address that represents the transferred asset. For `ETH`, it uses `address(0)`. diff --git a/plasma_framework/docs/design/tx-types-dependencies.md b/plasma_framework/docs/design/tx-types-dependencies.md index 377ba83eb..acfeb7ca5 100644 --- a/plasma_framework/docs/design/tx-types-dependencies.md +++ b/plasma_framework/docs/design/tx-types-dependencies.md @@ -36,6 +36,8 @@ Aside from the dependency of the path that a tx type can be spent, there are als txType: uint256 inputs: [bytes32], outputs: [struct], + txData: undefined, + metaData: bytes32 } ``` @@ -45,26 +47,37 @@ The second field `inputs` is a list of pointers that link to other outputs in pr The third field `outputs` is a list of `Output` structs that are further described in the below paragraph. -A transaction can have more fields than the three described above. Just the first three fields should follow this format. +`txData` is undefined and left up to concrete transaction types to use if required. Note that `txData` can be a list, so it can be extended as uch as necessary. -#### Output Format +`metaData` is 32 bytes long. +#### Generic Output Format +A Generic output only defines the outputType and leaves the outputData to be defined by the concrete transactions. ``` { outputType: uint256, + outputData: struct +} +``` + +#### Payment OutputData Format + +``` +{ outputGuard: bytes20, token: address, amount: uint256, } ``` -The first field of the output is a `uint256` that holds the info of `outputType`. Second field is the `outputGuard` field that would hold `owner` related information. Third field is `token`, which is the `address` that represents the `ERC20` token. The Fourth field is `amount`, a `uint256` that holds the value of amount of an output. +- The `outputGuard` field holds `owner` related information. +- The `token` field is the `address` that represents the `ERC20` token. +- The `amount` field is a `uint256` that holds the value of amount of an output. #### Current Payment Exit Game Implementation Current implementation of Payment Exit Game assumes all transactions of inputs and outputs would follow the format. Under this assumption and restriction, one can add new tx types as input or output to current Payment Exit Game implementation without the need to re-write it. -We actually realize that current format of `GenericTransaction` has some limitation on adding feature. For example, if we want to add non fungible token support (ERC721 tokens), this data structure would be looking awkward to hold the information. Luckily, it is possible for us to change the format with new a Exit Game implementation design. However, it would mean an extra round of implementation and code audit. - Previous discussions: - https://github.com/omisego/plasma-contracts/issues/236#issuecomment-546798910 - https://github.com/omisego/plasma-contracts/issues/282#issuecomment-535429760 +- https://github.com/omisego/plasma-contracts/pull/502 diff --git a/plasma_framework/docs/integration-docs/integration-doc.md b/plasma_framework/docs/integration-docs/integration-doc.md index 3d92c1b1a..acefe3d9e 100644 --- a/plasma_framework/docs/integration-docs/integration-doc.md +++ b/plasma_framework/docs/integration-docs/integration-doc.md @@ -69,42 +69,106 @@ ALD introduces the concepts of transaction type, and transcation output type. Ea -## Transaction format -Transactions follow the [Generic Transaction format](https://docs.google.com/document/d/1ETAO5ZUO7S_A8sXUK5cyAN6yMMotRDbJphAa2hPJIyU/edit). +## Generic transaction format +All Transactions follow the same basic format [GenericTransaction](../contracts/GenericTransaction.md) and can be extended. +GenericTransaction is based on [Wire Transaction format](https://docs.google.com/document/d/1ETAO5ZUO7S_A8sXUK5cyAN6yMMotRDbJphAa2hPJIyU/edit) but has diverged somewhat from the original design. -Briefly, this is: +A GenericTransaction is: ``` -transaction::= transactionType [input] [output] metadata [witness] +transaction::= txType [input] [output] txData metaData [witness] ``` Where ``` -transactionType::= uint256 +txType ::= uint256 input ::= outputId | outputPosition outputId ::= hash of the transaction that produced the output concatenated with the outputIndex outputPosition ::= 32 byte string that is (blockNumber * BLOCK_OFFSET + txIndex * TX_OFFSET + outputIndex) -output ::= outputType outputGuard token amount +output ::= outputType outputData outputType ::= uint256 -outputGuard ::= bytes20 -token ::= address -amount ::= uint256 +outputData ::= undefined, to be defined by concrete transaction types +txData ::= undefined, to be defined by concrete transaction types +metaData ::= bytes32 witness ::= bytes ``` - > ***Note**: Currently, the PlasmaFramework contract only partially follows the proposed Generic Transaction format; output type is implemented as `outputType outputGuard token amount` instead of `outputType outputGuard token vaultId standardSpecificData confirmAddress`.* - -The current implementation supports only the following transaction types: `Payment` and `DEX` +The current implementation supports only the `Payment` transaction type. Support for additional transaction types, such as ERC721, is reserved for future development. +## Payment transaction format +Payment transactions are used to transfer fungible tokens, such as ETH and ERC20 tokens. A Payment transaction's output is as described in [FungibleTokenOutputModel](../contracts/FungibleTokenOutputModel.md) + +### Payment transaction RLP encoding +A Payment transaction must be RLP encoded as follows: +``` +[txType, inputs, outputs, txData, metaData] +txType ::= uint256 +inputs ::= [input] +input ::= bytes32 +outputs ::= [output] +output ::= [outputType, outputData] +outputType ::= uint256 +outputData ::= [outputGuard, token, amount] +outputGuard ::= bytes20 +token ::= bytes20 +amount ::= uint256 +txData ::= uint256 (must be 0) +metadata ::= bytes32 +``` + +Example transaction with two inputs and two outputs: +``` +[ + 1, + [ + "0x0000000000000000000011111111111111100001", + "0x0000000000000000000011111111111111100002", + ], + [ + [ + 1, + [ + "0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef", + "0x0000000000000000000000000000000000000000", + 100 + ] + ], + [ + 1, + [ + "0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef", + "0x0000000000000000000000000000000000000000", + 900 + ] + ] + ], + 0, + "0x0000000000000000000000000000000000000000000000000000000000000000" +] +``` +Note that: + +1. `txType` must not be `0` +2. `inputs` must be a list +3. `input` must be padded to 32 bytes long +4. A null `input` (`"0x0...000"`) is invalid +5. `outputs` must be a list +6. `outputType` must not be `0` +7. `outputData` must be a list containing 3 items +8. `outputData.outputGuard` must be 20 bytes long +9. A null `outputData.outputGuard` (`"0x0...000"`) is invalid +10. An `outputData.amount` of `0` is invalid +11. `txData` is unused and must be set to `0` +12. `metadata` must be padded to 32 bytes long ## Deposit transactions Deposit transactions are special transactions that have no inputs. The transaction inputs should be encoded as an empty array. Deposit transactions are created by the vault contracts, and do not need to be explicitly submitted. -## EIP-712 signing +## Payment transction EIP-712 signing The **witness** field of a transaction contains the data that proves its inputs can be spent. For a standard payment transaction, this data is the signatures of the owners of the inputs. Transactions are signed using the [EIP-712](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md) method. The EIP-712 typed data structure is as follows: @@ -129,6 +193,7 @@ The EIP-712 typed data structure is as follows: { name: 'output1', type: 'Output' }, { name: 'output2', type: 'Output' }, { name: 'output3', type: 'Output' }, + { name: 'txData', type: 'uint256' }, { name: 'metadata', type: 'bytes32' } ], Input: [