Skip to content

Commit 3101e11

Browse files
authored
Update ERC-7573: ERC-7573 decryption oracle contracts and n-dvp documentation / fix (0.6.0)
Merged by EIP-Bot.
1 parent a7921b2 commit 3101e11

File tree

9 files changed

+337
-43
lines changed

9 files changed

+337
-43
lines changed

ERCS/erc-7573.md

Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ One smart contract implements the `ILockingContract` interface on one chain (e.g
2424
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.
2525
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.
2626

27+
In addtion there are to interface that standardize the communication with external decryption oracle(s).
28+
29+
The interface`IDecryptionOracle.sol` is implemented by a decryption oracle proxy contract.
30+
The interface `IDecryptionOracleCallback.sol` has to be implemented by a callback receiving the decrypted key.
31+
2732
## Motivation
2833

2934
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.
@@ -47,7 +52,7 @@ documentation [`ILockingContract.sol`](../assets/eip-7573/contracts/ILockingCont
4752
##### Initiation of Transfer: `inceptTransfer`
4853

4954
```solidity
50-
function inceptTransfer(uint256 id, int amount, address from, string keyHashedSeller, string memory keyEncryptedSeller) external;
55+
function inceptTransfer(uint256 id, int amount, address from, bytes keyHashedSeller, bytes memory keyEncryptedSeller) external;
5156
```
5257

5358
Called from the buyer of the token to initiate token transfer. Emits a `TransferIncepted` event.
@@ -59,7 +64,7 @@ It is possible to implement the protocol in a way where the hashing method agree
5964
##### Initiation of Transfer: `confirmTransfer`
6065

6166
```solidity
62-
function confirmTransfer(uint256 id, int amount, address to, string keyHashedBuyer, string memory keyEncryptedBuyer) external;
67+
function confirmTransfer(uint256 id, int amount, address to, bytes keyHashedBuyer, bytes memory keyEncryptedBuyer) external;
6368
```
6469

6570
Called from the seller of the token to confirm token transfer. Emits a `TransferConfirmed` event.
@@ -75,7 +80,7 @@ of tokens is locked (transferred from `from` to the smart contract) and `Transfe
7580
##### Transfer: `transferWithKey`
7681

7782
```solidity
78-
function transferWithKey(uint256 id, string memory key) external;
83+
function transferWithKey(uint256 id, bytes memory key) external;
7984
```
8085

8186
Called from either the buyer or the seller of the token
@@ -93,14 +98,14 @@ The interface `ILockingContract`:
9398

9499
```solidity
95100
interface ILockingContract {
96-
event TransferIncepted(uint256 id, int amount, address from, address to, string keyHashedSeller, string keyEncryptedSeller);
97-
event TransferConfirmed(uint256 id, int amount, address from, address to, string keyHashedBuyer, string keyEncryptedBuyer);
98-
event TokenClaimed(uint256 id, string key);
99-
event TokenReclaimed(uint256 id, string key);
100-
101-
function inceptTransfer(uint256 id, int amount, address from, string memory keyHashedSeller, string memory keyEncryptedSeller) external;
102-
function confirmTransfer(uint256 id, int amount, address to, string memory keyHashedBuyer, string memory keyEncryptedBuyer) external;
103-
function transferWithKey(uint256 id, string memory key) external;
101+
event TransferIncepted(uint256 id, int amount, address from, address to, bytes keyHashedSeller, bytes keyEncryptedSeller);
102+
event TransferConfirmed(uint256 id, int amount, address from, address to, bytes keyHashedBuyer, bytes keyEncryptedBuyer);
103+
event TokenClaimed(uint256 id, bytes key);
104+
event TokenReclaimed(uint256 id, bytes key);
105+
106+
function inceptTransfer(uint256 id, int amount, address from, bytes memory keyHashedSeller, bytes memory keyEncryptedSeller) external;
107+
function confirmTransfer(uint256 id, int amount, address to, bytes memory keyHashedBuyer, bytes memory keyEncryptedBuyer) external;
108+
function transferWithKey(uint256 id, bytes memory key) external;
104109
}
105110
```
106111

@@ -113,7 +118,7 @@ documentation [`IDecryptionContract.sol`](../assets/eip-7573/contracts/IDecrypti
113118
##### Initiation of Transfer: `inceptTransfer`
114119

115120
```solidity
116-
function inceptTransfer(uint256 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
121+
function inceptTransfer(uint256 id, int amount, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
117122
```
118123

119124
Called from the receiver of the amount to initiate payment transfer. Emits a `TransferIncepted`.
@@ -124,7 +129,7 @@ The parameter `keyEncryptedFailure` is an encryption of a key and will be decryp
124129
##### Transfer: `transferAndDecrypt`
125130

126131
```solidity
127-
function transferAndDecrypt(uint256 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
132+
function transferAndDecrypt(uint256 id, int amount, address to, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
128133
```
129134

130135
Called from the sender of the amount to initiate completion of the payment transfer. Emits a `TransferKeyRequested` with keys depending on completion success.
@@ -138,7 +143,7 @@ do not match a previous call to `inceptTransfer`.
138143
##### Cancelation of Transfer: `cancelAndDecrypt`
139144

140145
```solidity
141-
function cancelAndDecrypt(uint256 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
146+
function cancelAndDecrypt(uint256 id, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
142147
```
143148

144149
Called from the receiver of the amount to cancel payment transfer (cancels the incept transfer).
@@ -152,7 +157,7 @@ then this method emits a `TransferKeyRequested` with the key `keyEncryptedFailur
152157
##### Release of ILockingContract Access Key: `releaseKey`
153158

154159
```solidity
155-
function releaseKey(uint256 id, string memory key) external;
160+
function releaseKey(uint256 id, bytes memory key) external;
156161
```
157162

158163
Called from the (possibly external) decryption oracle.
@@ -165,14 +170,14 @@ The interface `IDecryptionContract`:
165170

166171
```solidity
167172
interface IDecryptionContract {
168-
event TransferIncepted(uint256 id, int amount, address from, address to, string keyEncryptedSuccess, string keyEncryptedFailure);
169-
event TransferKeyRequested(address sender, uint256 id, string encryptedKey);
170-
event TransferKeyReleased(address sender, uint256 id, bool success, string key);
171-
172-
function inceptTransfer(uint256 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
173-
function transferAndDecrypt(uint256 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
174-
function cancelAndDecrypt(uint256 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
175-
function releaseKey(uint256 id, string memory key) external;
173+
event TransferIncepted(uint256 id, int amount, address from, address to, bytes keyEncryptedSuccess, bytes keyEncryptedFailure);
174+
event TransferKeyRequested(address sender, uint256 id, bytes encryptedKey);
175+
event TransferKeyReleased(address sender, uint256 id, bool success, bytes key);
176+
177+
function inceptTransfer(uint256 id, int amount, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
178+
function transferAndDecrypt(uint256 id, int amount, address to, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
179+
function cancelAndDecrypt(uint256 id, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
180+
function releaseKey(uint256 id, bytes memory key) external;
176181
}
177182
```
178183

@@ -255,6 +260,50 @@ A corresponding XML sample is shown below.
255260
</releaseKey>
256261
```
257262

263+
### Multi-Party Delivery versus Payment
264+
265+
#### Locking is a Feature
266+
267+
In Delivery-versus-Payment (DvP) protocols like [ERC-7573](../EIPS/eip-7573.html), at least one token must be locked to ensure atomicity, even if only for a short period during the transaction.
268+
269+
While locking may appear as an inconvenient necessity, it is in fact a feature that becomes valuable in the construction of conditional trades or multi-party DvPs.
270+
271+
If *n* parties wish to perform bilateral transactions atomically, there are *at least* *m := 2 • (n - 1)* transactions, of which *m-1* require locking. The last one can operate directly, and its success or failure decides whether the other locks are released or reverted.
272+
273+
A multi-party delivery versus payment is a valuable trade feature. Consider, for example, the case where counterparty A wishes to buy a token *Y* (e.g., a bond) from counterparty C, but in order to fund this transaction, counterparty A wishes to sell a token *X* (e.g., another bond) to counterparty B. However, A does not want to sell bond *X* if the purchase of *Y* fails. A multi-party DvP allows these two transactions to be bound into a single atomic unit.
274+
275+
While for a two-party DvP with two tokens only one token requires locking—and hence a DvP can be constructed without locking on the cash chain—a three-party DvP with three tokens in general requires the ability to lock all three tokens.
276+
277+
This highlights that locking is not just a constraint, but a required feature to enable advanced and economically meaningful protocols.
278+
279+
#### N-DvP with [ERC-7573](../EIPS/eip-7573.html)
280+
281+
A multi-party DvP can be created elegantly by combining multiple (*n-1*) two-party DvPs, for example based on the [ERC-7573](../EIPS/eip-7573.html) protocol.
282+
283+
The procedure is simple: instead of finalizing the respective two-party DvP by a call to `transferAndDecrypt`, the two-party DvP is first confirmed with a call to `confirm`, leaving the finalization open.
284+
285+
At any time, any party can call `cancelAndDecrypt` to release the failure key and revert all lockings.
286+
287+
Once all parties are linked with their respective two-party DvPs, a single call to `transferAndDecrypt` performs locking of the token implementing the `IDecryptionContract` and releases either the success key on success or the failure key on failure.
288+
289+
##### Initiation and Finalization
290+
291+
The counterparty that initiates the multi-party DvP by making the first call
292+
to the `IDecryptionContract` is the one that is allowed to finalize it via `transferAndDecrypt`, the other may cancel via `cancelAndDecrypt`.
293+
294+
##### Sequence Diagram
295+
296+
Below we depict the corresponding sequence diagram of a multi-party DvP via [ERC-7573](../EIPS/eip-7573.html).
297+
Note that the individual DvP may come in two different flavors depending on which counterparty is the receiver of the token on the `IDecryptionContract`.
298+
299+
The diagram depicts a multi-party dvp with n+1 counterparties trading n+1 tokens out of which
300+
the DvPs are bound by the contract on token 0.
301+
302+
![sequence diagram multi party dvp](../assets/eip-7573/doc/multi-party-dvp.svg)
303+
304+
*Note: The more general case of N counterparties trading
305+
M tokens is just a special case where we enumerate all combination as new counterparties and new tokens.*
306+
258307
## Security Considerations
259308

260309
The decryption oracle does not need to be a single trusted entity. Instead, a threshold decryption scheme can be employed, where multiple oracles perform partial decryption, requiring a quorum of them to reconstruct the secret key. This enhances security by mitigating the risk associated with a single point of failure or trust.

assets/erc-7573/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,18 @@ The smart contract implementing `IDecryptionContract`, decrypts one of two keys
1515

1616
### Provided Contracts
1717

18+
#### DvP
19+
1820
- `contracts/ILockingContract.sol` - Contract locking transfer with given encrypted keys or hashes.
1921
- `contracts/IDecryptionContract.sol` - Contract performing conditional upon transfer decryption (possibly based on an external oracle).
2022

23+
#### Decryption Oracle
24+
25+
- `contracts/IDecryptionOracle.sol` - Interface implemented by a decryption oracle proxy contract.
26+
- `contracts/IDecryptionOracleCallback.sol` - Interface to be implemented by a callback receiving the decrypted key.
27+
2128
### Documentation
2229

23-
- `doc/DvP-Seq-Diag.png` - Sequence diagram.
30+
- `doc/DvP-Seq-Diag.png` - Sequence diagram of the DvP
31+
- `doc/multi-party-dvp.svg` - Sequence diagram of a multi-party-dvp.
32+

assets/erc-7573/contracts/IDecryptionContract.sol

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,26 @@ interface IDecryptionContract {
3838
* @param keyEncryptedSuccess Encryption of the key that is emitted upon success.
3939
* @param keyEncryptedFailure Encryption of the key that is emitted upon failure.
4040
*/
41-
event TransferIncepted(uint256 id, int amount, address from, address to, string keyEncryptedSuccess, string keyEncryptedFailure);
41+
event TransferIncepted(uint256 id, int amount, address from, address to, bytes keyEncryptedSuccess, bytes keyEncryptedFailure);
42+
43+
/**
44+
* @dev Emitted when the transfer is confirmed.
45+
* @param id the trade identifier of the trade.
46+
* @param amount the amount to be transferred.
47+
* @param from The address of the sender of the payment.
48+
* @param to The address of the receiver of the payment.
49+
* @param keyEncryptedSuccess Encryption of the key that is emitted upon success.
50+
* @param keyEncryptedFailure Encryption of the key that is emitted upon failure.
51+
*/
52+
event TransferConfirmed(uint256 id, int amount, address from, address to, bytes keyEncryptedSuccess, bytes keyEncryptedFailure);
4253

4354
/**
4455
* @dev Emitted when a transfer has been performed with a success or failure.
4556
* @param sender a sender. May provide information of the origin of this request.
4657
* @param id the trade ID.
4758
* @param encryptedKey The encrypted key associated with the transaction status.
4859
*/
49-
event TransferKeyRequested(address sender, uint256 id, string encryptedKey);
60+
event TransferKeyRequested(address sender, uint256 id, bytes encryptedKey);
5061

5162
/**
5263
* @dev Emitted when the decrypted key has been obtained.
@@ -55,7 +66,7 @@ interface IDecryptionContract {
5566
* @param success a boolean indicating the status. True: success. False: failure.
5667
* @param key the decrypted key.
5768
*/
58-
event TransferKeyReleased(address sender, uint256 id, bool success, string key);
69+
event TransferKeyReleased(address sender, uint256 id, bool success, bytes key);
5970

6071
/*------------------------------------------- FUNCTIONALITY ---------------------------------------------------------------------------------------*/
6172

@@ -68,18 +79,27 @@ interface IDecryptionContract {
6879
* @param keyEncryptedSuccess Encryption of the key that is emitted upon success.
6980
* @param keyEncryptedFailure Encryption of the key that is emitted upon failure.
7081
*/
71-
function inceptTransfer(uint256 id, int amount, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
82+
function inceptTransfer(uint256 id, int amount, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
7283

7384
/**
74-
* @notice Called from the sender of the amount to initiate completion of the payment transfer.
75-
* @dev emits a {TransferKeyRequested} with keys depending on completion success.
85+
* @notice Called by the sender of the amount to confirm the payment transfer.
86+
* @dev emits a {TransferConfirmed}
7687
* @param id the trade identifier of the trade.
7788
* @param amount the amount to be transferred.
7889
* @param to The address of the receiver of the payment. Note: the sender of the payment (from) is implicitly the message.sender.
7990
* @param keyEncryptedSuccess Encryption of the key that is emitted upon success.
8091
* @param keyEncryptedFailure Encryption of the key that is emitted upon failure.
8192
*/
82-
function transferAndDecrypt(uint256 id, int amount, address to, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
93+
function confirmTransfer(uint256 id, int amount, address to, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
94+
95+
/**
96+
* @notice Called by the sender of (first) confirmTransfer initiate completion of the payment transfer(s).
97+
* Note: In case of a multi party DvP there may be multiple incept/confirm pays.
98+
* In case of single DvP the previous confirmTransfer may directly call transferAndDecrypt.
99+
* @dev emits a {TransferKeyRequested} with keys depending on completion success.
100+
* @param id the trade identifier of the trade.
101+
*/
102+
function transferAndDecrypt(uint256 id) external;
83103

84104
/**
85105
* @notice Called from the receiver of the amount to cancel payment transfer (cancels the incept transfer).
@@ -89,13 +109,13 @@ interface IDecryptionContract {
89109
* @param keyEncryptedSuccess Encryption of the key that is emitted upon success.
90110
* @param keyEncryptedFailure Encryption of the key that is emitted upon failure.
91111
*/
92-
function cancelAndDecrypt(uint256 id, address from, string memory keyEncryptedSuccess, string memory keyEncryptedFailure) external;
112+
function cancelAndDecrypt(uint256 id, address from, bytes memory keyEncryptedSuccess, bytes memory keyEncryptedFailure) external;
93113

94114
/*+
95115
* @notice Called from the (possibly external) decryption oracle.
96116
* @dev emits a {TransferKeyReleased} (if the call was eligible).
97117
* @param id the trade identifier of the trade.
98118
* @param key Decrypted key.
99119
*/
100-
function releaseKey(uint256 id, string memory key) external;
120+
function releaseKey(uint256 id, bytes memory key) external;
101121
}

0 commit comments

Comments
 (0)