An RLP encoded set with the following items:
- Block number, 4 bytes
- Transaction number in block, 4 bytes
- Output number in transaction, 1 byte
- "Amount" field, 32 bytes, that is more a data field, usually used for an amount of the output referenced by previous field, but has special meaning for "Deposit" transactions
An RLP encoded set with the following items:
- Output number in transaction, 1 byte
- Receiver's Ethereum address, 20 bytes
- "Amount" field, 32 bytes
An RLP encoded set with the following items:
- Transaction type, 1 byte
- An array (list) of Inputs, maximum 2 items
- An array (list) of Outputs, maximum 3 items. One of the outputs is an explicit output to an address of Plasma operator.
An RLP encoded set with the following items:
- Transaction, as described above
- Recoverable EC of the transaction sender:
- V value, 1 byte, expected values 27, 28
- R value, 32 bytes
- S value, 32 bytes
From this signature Plasma operator deduces a sender, checks that the sender is an owner of UTXOs referenced by inputs. Signature is based on EthereumPersonalHash(RLPEncode(Transaction)). Transaction should be well-formed, sum of inputs equal to sum of the outputs, etc
- Block number, 4 bytes, used in the main chain to double check proper ordering
- Number of transactions in block, 4 bytes, purely informational
- Parent hash, 32 bytes, hash of the previous block, hashes the full header
- Merkle root of the transactions tree, 32 bytes
- V value, 1 byte, expected values 27, 28
- R value, 32 bytes
- S value, 32 bytes
Signature is based on EthereumPersonalHash(block number || number of transactions || previous hash || merkle root), where || means concatenation. Values V, R, S are then concatenated to the header.
- Block header, as described above, 137 bytes
- RLP encoded array (list) of signed transactions, as described above
While some fields can be excessive, such block header can be submitted by anyone to the main Ethereum chain when block is available, but for some reason not sent to the smart contract. Transaction numbering is done by the operator, it should be monotonically increasing without spaces and number of transactions in header should (although this is not necessary for the functionality) match the number of transactions in the Merkle tree and the full block.
- Other transactions structure with nested RLP fields
- Deposit transactions are declarative: new block with 1 transaction is not created automatically (although can be easily changed), but deposit record is created and can be withdrawn back to user if Plasma operator doesn't provide transaction of appropriate structure (referencing this deposit, having proper owner and amount).
- Anyone(!) can send a header of the block to the main chain, so if block is assembled and available, but not yet pushed to the main chain, anyone can send a header on behalf of Plasma operator.
All basic challenges and potential "cheats" for operator or user should be now covered
- Block header uploads
- should accept one properly signed header
- should NOT accept same header twice
- should accept two headers in right sequence
- should accept two headers in right sequence in the same transaction
- should NOT accept two headers in wrong sequence
- should NOT accept invalidly signed block header
- should NOT accept invalidly signed block header in sequence in one transaction
- should property update two weeks old block number
- should check block hashes match in addition to block numbers in sequence
- Deposits
- should emit deposit event
- should allow deposit withdraw process
- should respond to deposit withdraw challenge
- should allow successful deposit withdraw
- should require bond for deposit withdraw start
- should stop Plasma on duplicate funding transaction
- should stop Plasma on funding without deposit
- should update total deposited amount for all tests above
- should update amount pending exit for all tests above
- Exits (normal process)
- should start withdraw with proper proof
- should not allow non-owner of transaction to start a withdraw of UTXO
- should respond to withdraw challenge
- should allow successful withdraw
- should require bond for withdraw start
- should return bond on successful withdraw
- should update amount pending withdraw for all tests above
- should update total amount deposited for all tests above
- should allow offer for buyout
- should allow accepting a buyout offer
- should allow returning funds for expired offer
- Limbo exits (when Plasma is stopped)
- should allow to start a limbo exit
- should require a collateral for each input
- should allow to join a limbo exit
- should maintain priority in the queue
- should give the same priority for blocks that are older than 2 weeks
- should respond to exit prevention challenge
- should allow successful exit
- should update amount pending withdraw for all tests above
- should update total amount deposited for all tests above
- Challenges
- Invalid transaction in block (unrealisable)
- should NOT stop on valid transaction (not malformed) in block
- Transaction in block references the future
- Two transactions have the same number in block
- Transaction is malformed (balance breaking)
- Double spend
- Spend without owner signature
- UTXO amount is not equal to input amount
- UTXO was successfully withdrawn and than spent in Plasma
git submodule init
git submodule update --recursive
Everyone is welcome to spot mistakes in the logic of this contract as number of provided functions is substantial. If you find a potential error or security loophole (one that would allow Plasma operator or user to break the normal operation and not being caught) - please open an issue.
Alex Vlasov, @shamatar, alex.m.vlasov@gmail.com
Make optimizations for reduced gas costs for most of the functions.
All source code and information in this repository is available under the Apache License 2.0 license.