Alert Source Discuss
⚠️ Draft Standards Track: ERC

ERC-7573: Conditional-upon-Transfer-Decryption for DvP

A Protocol for Secure Delivery-versus-Payment across two Blockchains

Authors Christian Fries (@cfries), Peter Kohl-Landgraf (@pekola)
Created 2023-12-05
Discussion Link https://ethereum-magicians.org/t/erc-7573-conditional-upon-transfer-decryption-for-delivery-versus-payment/17232

Abstract

The interfaces in this proposal model a functional transaction scheme to establish a secure delivery-versus-payment across two blockchains, where a) no intermediary is required and b) one of the two chains can securely interact with a stateless “decryption oracle”. Here, delivery-versus-payment refers to the exchange of, e.g., an asset against a payment; however, the concept is generic to make a transfer of one token on one chain (e.g., the payment) conditional to the successful transfer of another token on another chain (e.g., the asset).

The scheme is realized by two smart contracts, one on each chain. One smart contract implements the ILockingContract interface on one chain (e.g. the “asset chain”), and another smart contract implements the IDecryptionContract interface on the other chain (e.g., the “payment chain”). The smart contract implementing ILockingContract locks a token (e.g., the asset) on its chain until a key is presented to encrypt to one of two given values. The smart contract implementing IDecryptionContract, decrypts one of two keys (via the decryption oracle) conditional to the success or failure of the token transfer (e.g., the payment). A stateless decryption oracle is attached to the chain running IDecryptionContract for the decryption.

Motivation

Within the domain of financial transactions and distributed ledger technology (DLT), the Hash-Linked Contract (HLC) concept has been recognized as valuable and has been thoroughly investigated. The concept may help to solve the challenge of delivery-versus-payment (DvP), especially in cases where the asset chain and payment system (which may be a chain, too) are separated. A prominent application of smart contracts realizing a secure DvP is that of buying an asset, where the asset is managed on one chain (the asset chain), but the payments are executed on another chain (the payment chain). Proposed solutions are based on an API-based interaction mechanism which bridges the communication between a so-called asset chain and a corresponding payment system or requires complex and problematic time-locks.1

Here, we propose a protocol that facilitates secure delivery-versus-payment with less overhead, especially with a stateless oracle.2

Specification

Methods

Smart Contract on the chain that performs the locking (e.g. the asset chain)

The following methods specify the functionality of the smart contract implementing the locking. For further information, please also look at the interface documentation ILockingContract.sol.

Initiation of Transfer: inceptTransfer
function inceptTransfer(bytes32 id, int amount, address from, string memory keyEncryptedSeller) external;

Called from the buyer of the token to initiate token transfer. Emits a TransferIncepted event. The parameter id is an identifier of the trade. The parameter from is the address of the seller (the address of the buyer is msg.sender). The parameter keyEncryptedSeller is an encryption of the key that can be used by the seller to (re-)claim the token. See below on “encryption”.

Initiation of Transfer: confirmTransfer
function confirmTransfer(bytes32 id, int amount, address to, string memory keyEncryptedBuyer) external;

Called from the seller of the token to confirm token transfer. Emits a TransferConfirmed event. The parameter id is an identifier of the trade. The parameter to is the address of the buyer (the address of the seller is msg.sender). The parameter keyEncryptedBuyer is an encryption of the key that can be used by the buyer to claim the token.

If the trade specification, that is, the quadruppel (id, amount, from, to), in a call to confirmTransfer matches that of a previous call to inceptTransfer, and the balance is sufficient, the corresponding amount of tokens is locked (transferred from from to the smart contract) and TransferConfirmed is emitted.

Transfer: transferWithKey
function transferWithKey(bytes32 id, string memory key) external;

Called from either the buyer or the seller of the token of the trade with id id.

If the method is called from the buyer (to) and the encryption of key matches keyEncryptedBuyer, then the locked tokens are transferred to the buyer (to). This emits TokenClaimed.

If the method is called from the seller (from) and the encryption of key matches keyEncryptedSeller, then the locked tokens are transferred (back) to the seller (to). This emits TokenReclaimed.

Summary

The interface ILockingContract:

interface ILockingContract {
    event TransferIncepted(bytes32 id, int amount, address from, address to, string keyEncryptedSeller);
    event TransferConfirmed(bytes32 id, int amount, address from, address to, string keyEncryptedBuyer);
    event TokenClaimed(bytes32 id, string key);
    event TokenReclaimed(bytes32 id, string key);

    function inceptTransfer(bytes32 id, int amount, address from, string memory keyEncryptedSeller) external;
    function confirmTransfer(bytes32 id, int amount, address to, string memory keyEncryptedBuyer) external;
    function transferWithKey(bytes32 id, string memory key) external;
}

Smart Contract on the other chain that performs the conditional decryption (e.g. the payment chain)

The following methods specify the functionality of the smart contract implementing the conditional decryption. For further information, please also look at the interface documentation IDecryptionContract.sol.

Initiation of Transfer: inceptTransfer
function inceptTransfer(bytes32 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;

Called from the receiver of the amount to initiate payment transfer. Emits a PaymentTransferIncepted. The parameter id is an identifier of the trade. The parameter from is the address of the sender of the payment (the address of the receiver is msg.sender). The parameter keyEncryptedSuccess is an encryption of the key and will be decrypted if the transfer is successful in a call to transferAndDecrypt. The parameter keyEncryptedFailure is an encryption of the key and will be decrypted if the transfer fails in a call to transferAndDecrypt or if cancelAndDecryptis successful.

Transfer: transferAndDecrypt
function transferAndDecrypt(bytes32 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;

Called from the sender of the amount to initiate completion of the payment transfer. Emits a TransferKeyRequested and TransferKeyReleased with keys depending on completion success. The parameter id is an identifier of the trade. The parameter to is the address of the receiver of the payment (the sender of the payment (from) is implicitly the msg.sender). The parameter keyEncryptedSuccess is an encryption of the key and will be decrypted if the transfer is successful. The parameter keyEncryptedFailure is an encryption of the key and will be decrypted if the transfer failed.

The method will not decrypt any key and not perfrom a transfer of a payment if the values (id, amount, from to, keyEncryptedSuccess, keyEncryptedFailure) do not match a previous call to inceptTransfer.

Cancelation of Transfer: cancelAndDecrypt
function cancelAndDecrypt(bytes32 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;

Called from the receiver of the amount to cancel payment transfer (cancels the incept transfer).

The method must be called from the caller of a previous call to inceptTransfer with the exact same arguments and cancels this specific transfer.

Summary

The interface IDecryptionContract:

interface IDecryptionContract {
    event TransferIncepted(bytes32 id, int amount, address from, address to, string keyEncryptedSuccess, string keyEncryptedFailure);
    event TransferKeyRequested(bytes32 id, string encryptedKey);
    event TransferKeyReleased(bytes32 id, bool success, string key);

    function inceptTransfer(bytes32 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
    function transferAndDecrypt(bytes32 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
    function cancelAndDecrypt(bytes32 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
}

Encryption and Decryption

The linkage of the two smart contract relies on use of a key and encryptedKey. The implementation is free to support several encryption methods for as long as the decryption oracle supports it.

The encryption is performed with the public key of the decryption oracle, which is known to both parties.

It is implicitly assumed that the two parties may check that the strings keyEncryptedBuyer and keyEncryptedSeller are in a valid format.

Sequence diagram of delivery versus payment

The interplay of the two smart contracts is summarized in the following sequence diagram:

sequence diagram

Rationale

The protocol tries to be parsimonious. The transfer is associated with a (preferable unique) id possibly generated by some additional interaction of the trading parties.

The key and the encryptedKey arguments are strings to allow the flexible use of different encryption schemes. The decryption/encryption scheme should be inferable from the contents of the encryptedKey.

Security Considerations

No known security issues up to now.

Copyright and related rights waived via CC0.

    {
      "type": "article",
      "id": 1,
      "author": [
        {
          "family": "La Rocca",
          "given": "Rosario"
        },
        {
          "family": "Mancini",
          "given": "Riccardo"
        },
        {
          "family": "Benedetti",
          "given": "Marco"
        },
        {
          "family": "Caruso",
          "given": "Matteo"
        },
        {
          "family": "Cossu",
          "given": "Stefano"
        },
        {
          "family": "Galano",
          "given": "Giuseppe"
        },
        {
          "family": "Mancini",
          "given": "Simone"
        },
        {
          "family": "Marcelli",
          "given": "Gabriele"
        },
        {
          "family": "Martella",
          "given": "Piero"
        },
        {
          "family": "Nardelli",
          "given": "Matteo"
        },
        {
          "family": "Oliviero",
          "given": "Ciro"
        }
      ],
      "DOI": "10.2139/ssrn.4386904",
      "title": "Integrating DLTs with Market Infrastructures: Analysis and Proof-of-Concept for Secure DvP between TIPS and DLT Platforms",
      "original-date": {
        "date-parts": [
          [2022, 7, 19]
        ]
      },
      "URL": "http://dx.doi.org/10.2139/ssrn.4386904"
    }
    {
      "type": "article",
      "id": 2,
      "author": [
        {
          "family": "Fries",
          "given": "Christian"
        },
        {
          "family": "Kohl-Landgraf",
          "given": "Peter"
        }
      ],
      "DOI": "10.2139/ssrn.4628811",
      "title": "A Proposal for a Lean and Functional Delivery versus Payment across two Blockchains",
      "original-date": {
        "date-parts": [
          [2023, 11, 9]
        ]
      },
      "URL": "http://dx.doi.org/10.2139/ssrn.4628811"
    }

Citation

Please cite this document as:

Christian Fries (@cfries), Peter Kohl-Landgraf (@pekola), "ERC-7573: Conditional-upon-Transfer-Decryption for DvP [DRAFT]," Ethereum Improvement Proposals, no. 7573, December 2023. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-7573.