Skip to content
This repository has been archived by the owner on Jul 14, 2020. It is now read-only.

Latest commit

 

History

History
393 lines (275 loc) · 12.8 KB

RFC-007-SWAP-Basic-Ether.adoc

File metadata and controls

393 lines (275 loc) · 12.8 KB

Ether Basic HTLC Atomic Swap

Note
RFC-Number: 007
Status: Draft
+ Created on: 2019-03-12

1. Description

This RFC defines how to execute a RFC003 SWAP where one of the ledgers is Ethereum and the associated asset is the native Ether asset.

For definitions of the Ethereum ledger and Ether asset see RFC006.

To fulfil the requirements of RFC003 this RFC defines:

  • The identity to be used when negotiating a SWAP on the Ethereum ledger.

  • How to construct a Hash Time Lock Contract (HTLC) to lock the Ether asset on the Ethereum blockchain.

  • How to deploy, redeem and refund the HTLC during the execution phase of RFC003.

2. The Ethereum Identity

RFC003 requires ledgers have an identity type specified to negotiate a SWAP.

The identity to be used on Ethereum is the Ethereum address as defined in equation 284 of the Ethereum Yellowpaper: the right most 160-bits (20 bytes) of the Keccak-256 hash of the corresponding ECDSA public key.

An ethereum address MUST be encoded as this 20 byte hex string prefixed by 0x (as is standard in the Ethereum ecosystem). Furthermore, implementations MUST also accept EIP50 mixed case addresses and MAY verify the checksum.

This RFC extends the registry with the following entry in the identity table:

Ledger Identity Name Description

Ethereum

address

An Ethereum Address

Note that since contract addresses and user addresses are indistinguishable, a contract address could be used as an identity. RFCs that use the Ethereum identity defined here should explain the impact (if any) this has on the protocol.

3. Hash Time Lock Contract

3.1. Hash Functions

This RFC specifies SHA-256 as the only value the hash_function parameter to comit-rfc-003 may take if Ethereum is used as a ledger. This may be expanded in subsequent RFCs.

3.2. Parameters

The parameters for the Ether HTLC follow RFC003 and are described concretely in the following table:

Variable Description

asset

The quantity of wei

secret_hash

The hash of the secret (32 bytes for SHA-256)

redeem_identity

The address of the redeeming party

refund_identity

The address of the refunding party

expiry

The absolute UNIX timestamp in seconds after which the HTLC can be refunded

3.3. Contract

This RFC defines a single disposable contract as the HTLC. It uses the selfdestruct EVM opcode to release the funds to the intended party.

This approach was chosen over a stateful contract written in solidity so that the contract can be precisely defined, verified and updated.

The redeem_identity and refund_identity are hard coded into the contract. If called with the correct secret as the calldata it will transfer all the Ether to the redeem_identity using selfdestruct. If called without any calldata after the expiry it will transfer all the Ether to the refund_identity using selfdestruct.

The contract never checks the caller so the redeem and refund transactions can be sent by anyone. The funds will only ever be transferred to the redeem_identity or the refund_identity. No special considerations need to be made when either identity is a contract address as they simply receive funds.

The contract is compiled from the following EVM assembly:

{
    // Load received secret size
    calldatasize

    // Check if secret is zero length
    iszero

    // If secret is zero length, jump to branch that checks if expiry time has been reached
    check_expiry
    jumpi

    // Load expected secret size
    32

    // Load received secret size
    calldatasize

    // Compare secret size
    eq
    iszero

    // If passed secret is wrong size, jump to exit contract
    invalid_secret
    jumpi

    // Load secret into memory
    calldatacopy(0, 0, 32)

    // Hash secret with SHA-256 (pre-compiled contract 0x02)
    call(72, 0x02, 0, 0, 32, 33, 32)

    // Placeholder for correct secret hash
    <secret_hash>

    // Load hashed secret from memory
    mload(33)

    // Compare hashed secret with existing one
    eq

    // Combine `eq` result with `call` result
    and

    // Jump to redeem if hashes match
    redeem
    jumpi

    // Continue to invalid secret if no match
invalid_secret:
    // return "invalidSecret" = 0x696e76616c69645365637265740000000000000000000000000000000000000000
    mstore(0, "invalidSecret")
    revert(0, 32)

check_expiry:
    // Timestamp of the current block in seconds since the epoch
    timestamp

    // Placeholder for refund timestamp
    <expiry>

    // Compare refund timestamp with current timestamp
    lt

    // Jump to refund if time is expired
    refund
    jumpi

    // return "too early" = 0x746f6f4561726c79000000000000000000000000000000000000000000000000
    mstore(0, "tooEarly")
    revert(0, 32)


redeem:
    // log ascii to hex of "redeemed"
    // 0x72656465656d6564000000000000000000000000000000000000000000000000
    log1(0, 32, "redeemed")
    selfdestruct(<redeem_identity>)

refund:
    // log ascii to hex of "refunded"
    // 0x726566756e646564000000000000000000000000000000000000000000000000
    log1(0, 0, "refunded")
    selfdestruct(<refund_identity>)
}

The following is the contract deployment code template encoded as hex which will deploy the above contract when the placeholder values are replaced with the parameters.

61012861000f6000396101286000f3361561007957602036141561004f57602060006000376020602160206000600060026048f17f100000000000000000000000000000000000000000000000000000000000000160215114166100ae575b7f696e76616c69645365637265740000000000000000000000000000000000000060005260206000fd5b426320000002106100eb577f746f6f4561726c7900000000000000000000000000000000000000000000000060005260206000fd5b7f72656465656d656400000000000000000000000000000000000000000000000060206000a1733000000000000000000000000000000000000003ff5b7f726566756e64656400000000000000000000000000000000000000000000000060006000a1734000000000000000000000000000000000000004ff

To compile the contract code replace the placeholder values with the HTLC parameters at the following offsets:

Name Byte Range Length (bytes)

secret_hash

53..85

32

refund_timestamp

139..143

4

redeem_address

229..249

20

refund_address

290..310

20

The contract emits two logs:

Topic keccack256(Topic) Data Emitted When

ascii to hex of redeemed

0x72656465656d6564000000000000000000000000000000000000000000000000

secret

The contract is redeemed

ascii to hex of refunded

0x726566756e646564000000000000000000000000000000000000000000000000

-

The contract is refunded

The contract returns two different error values for the failure cases:

Description bytes Emitted When

ascii to hex of invalidSecret

0x696e76616c69645365637265740000000000000000000000000000000000000000

Attempt to redeem with an invalid secret

ascii to hex of tooEarly

0x746f6f4561726c79000000000000000000000000000000000000000000000000

Attempt to refund too early

Implementations SHOULD use the following gas limits on the transactions related to the contract:

Transaction recommended gas limit

Deployment

121,800

Redeem

100,000

Refund

100,000

4. Execution Phase

The following section describes how both parties should interact with the Ethereum blockchain during the RFC003 execution phase.

4.1. Deployment

At the start of the deployment stage, both parties compile the contract code as described in the previous section. We will call this value contract_code.

To deploy the Ether HTLC, the funder must deploy the contract_code. They SHOULD do this by sending a contract deployment transaction to the relevant Ethereum blockchain with:

  • contract_code as the data of the transaction

  • The quantity of wei specified in the Ether Asset header as the value of the transaction

The funder SHOULD NOT do this through another contract, i.e. by executing the CREATE opcode.

To be notified of the deployment event, both parties MAY watch the blockchain for a transaction with the contract_code as the data. Upon observing the deployment transaction, both parties SHOULD record the address the contract was deployed to (referred to as contract_address from now on).

4.2. Redeem

Before redeeming, the redeemer SHOULD wait until the deployment transaction has enough confirmation such that they consider it permanent.

To redeem the HTLC, the redeemer SHOULD send a transaction to the contract_address with the data of the transaction set to the secret.

To be notified of the redeem event, both parties SHOULD watch the blockchain for contract_address emitting the Redeemed() log. If Ethereum is the beta_ledger (see RFC003), then the funder MUST watch for such a log, extract the secret from the transaction receipt and continue the protocol. In this case, Bob MUST NOT watch for a transaction sent to contract_address with the secret as data. This would be insufficient, because he would miss learning the secret if the contract is redeemed by a call from another contract (rather than from a transaction).

4.3. Refund

To refund the HTLC, the funder MUST send a transaction to contract_address with empty data in a block with timestamp greater than expiry.

To be notified of the refund event, both parties SHOULD watch the blockchain for contract_address emitting the Refunded() log.

4.4. Failure

A transaction to the HTLC will fail in two cases:

  1. If redeem was attempted with an invalid secret: the contract will return invalidSecret in bytes (0x696e76616c69645365637265740000000000000000000000000000000000000000)

  2. If refund was attempted too early: the contract will return tooEarly in bytes (0x746f6f4561726c79000000000000000000000000000000000000000000000000)

5. Registry extension

This RFC extends the registry with an identity definition for the Ethereum ledger:

Ledger Identity Name Encoding Description

Ethereum

address

0x prefixed address

An Ethereum Address

Examples/Test vectors

1. RFC003 SWAP REQUEST

The following shows an RFC003 SWAP REQUEST where the alpha_ledger is Ethereum, the alpha_asset is 1 Ether (with …​ being used where the value is only relevant for the beta_ledger).

{
  "type": "SWAP",
  "headers": {
    "alpha_ledger": {
      "value": "ethereum",
      "parameters": { "network": "mainnet" }
    },
    "beta_ledger": {...},
    "alpha_asset": {
      "value": "ether",
      "parameters": { "quantity": "1000000000000000000" }
    },
    "beta_asset": {...},
    "protocol": {
        "value" : "comit-rfc-003",
        "parameters" : { "hash_function" : "SHA-256" }
    }
  },
  "body": {
    "aplha_ledger_refund_identity": "0x0f59e9e105be01d5e2206792a267406f255c5ea5",
    "alpha_expiry": 1552263040,
    "secret_hash" : "ac5a18da6431ed256965b873ef49dc15a70a0a66e2d28d0c226b5db040123727",
    "beta_ledger_redeem_identity" : "...",
    "beta_expiry" : ...
  },
}

Note, the pre-image of secret_hash is 51a488e06e9c69c555b8ad5e2c4629bb3135b96accd1f23451af75e06d3aee9c.

2. RFC003 SWAP RESPONSE

A valid RESPONSE to the above REQUEST could look like:

{
  "status" : "OK00",
  "body": {
     "alpha_ledger_redeem_identity": "0x53fd2cac865d3aa1ad6fbdebaa00802c94239fba",
     "beta_ledger_refund_identity": "..."
  }
}

3. HTLC

The above REQUEST and RESPONSE results in the following parameters to the HTLC:

Parameter value

redeem_identity

0x53fd2cac865d3aa1ad6fbdebaa00802c94239fba

redund_identity

0x0f59e9e105be01d5e2206792a267406f255c5ea5

secret_hash

ac5a18da6431ed256965b873ef49dc15a70a0a66e2d28d0c226b5db040123727

expiry

1552263040

Which should compile to the following contract_code:

61012861000f6000396101286000f3361561007957602036141561004f57602060006000376020602160206000600060026048f17fac5a18da6431ed256965b873ef49dc15a70a0a66e2d28d0c226b5db04012372760215114166100ae575b7f696e76616c69645365637265740000000000000000000000000000000000000060005260206000fd5b42635c85a780106100eb577f746f6f4561726c7900000000000000000000000000000000000000000000000060005260206000fd5b7f72656465656d656400000000000000000000000000000000000000000000000060206000a17353fd2cac865d3aa1ad6fbdebaa00802c94239fbaff5b7f726566756e64656400000000000000000000000000000000000000000000000060006000a1730f59e9e105be01d5e2206792a267406f255c5ea5ff