Conversation
File
|
|
The commit 7e9eb24 (as a parent of 070030a) contains errors. |
Co-authored-by: Andrew B Coathup <28278242+abcoathup@users.noreply.github.com>
| - MUST return a pointer to false OR revert if `canSend(from)` returns false, unless `from` is the zero address. | ||
| - MUST return a pointer to false OR revert if `canReceive(to)` returns false, unless `to` is the zero address. | ||
| - MUST return a pointer to false OR revert if any other rule would prevent the transfer (such as vesting, balance caps, etc). | ||
| - MUST return a pointer to false if `amount` exceeds the value returned by `confidentialAvailableBalanceOf(from)`, unless `from` is the zero address. |
There was a problem hiding this comment.
Anyone can call confidentialCanTransfer with any from and any amount, and the result is false exactly when amount exceeds from's available balance. If the caller can resolve the returned pointer, that is a balance oracle: about 64 calls with a binary search give you anyone's exact available balance. confidentialAvailableBalanceOf(account) does the same in one call. The spec leaves "who can resolve a pointer" to the implementation, so a naive implementation that grants the caller access is compliant. Can we say who may resolve the results (e.g. only from/operator for confidentialCanTransfer, only account and parties it authorised for confidentialAvailableBalanceOf)?
There was a problem hiding this comment.
Further, an implementation would also need to limit calls to this function somehow (either flow limiting or only to trusted operators) since even a user calling confidentialCanTransfer from themselves would be able to bypass some expected confidentiality by trying to send different amounts to a given recipient.
|
|
||
| ### Token | ||
|
|
||
| Compliant tokens MUST implement [ERC-7984](./eip-7984.md) and [ERC-165](./eip-165.md). The `supportsInterface` function MUST return `true` when the `interfaceID` argument is `0x00000000`. |
There was a problem hiding this comment.
Replace if/when any signature changes
| Compliant tokens MUST implement [ERC-7984](./eip-7984.md) and [ERC-165](./eip-165.md). The `supportsInterface` function MUST return `true` when the `interfaceID` argument is `0x00000000`. | |
| Compliant tokens MUST implement [ERC-7984](./eip-7984.md) and [ERC-165](./eip-165.md). The `supportsInterface` function MUST return `true` when the `interfaceID` argument is `0xcd0f4d6c`. |
| - MAY move 0 tokens if `amount` exceeds `confidentialAvailableBalanceOf(from)` | ||
| - MUST revert if `canReceive(to)` returns false. | ||
| - MUST NOT call `confidentialCanTransfer`. |
There was a problem hiding this comment.
Forced transfers usually is to move frozen funds. With "MAY move 0 tokens if amount exceeds confidentialAvailableBalanceOf(from)", a compliant token can refuse that, so an issuer can't rely on the function across implementations. It also doesn't say whether canSend(from) is bypassed, or what happens to the frozen amount after part of it is seized. ERC-7943 unfreezes first. "MUST NOT call confidentialCanTransfer" describes the implementation, but what we mean is that the Transfer Behavior rule doesn't apply here. Can we decide the frozen-funds case explicitly and state the canSend bypass?
There was a problem hiding this comment.
Definitely can state the canSend bypass. We've discussed the concept of moving frozen funds a couple times in the past, will come back to it.
There was a problem hiding this comment.
Following up on the MAY: it makes forced-transfer behaviour unpredictable across implementations. I don't see why a forced transfer shouldn't be able to take the whole balance. And since, unlike ERC-7943, this ERC doesn't standardize freezing, an issuer would first have to lift the restrictions in an implementation-specific way to make the whole balance available, and only then force the transfer. Could this be a MUST?
| - MAY move 0 tokens if `amount` exceeds `confidentialAvailableBalanceOf(from)` | |
| - MUST revert if `canReceive(to)` returns false. | |
| - MUST NOT call `confidentialCanTransfer`. | |
| - MUST NOT be limited by `confidentialAvailableBalanceOf(from)`. | |
| - MUST revert if `canReceive(to)` returns false. | |
| - MUST NOT call `canSend(from)`. | |
| - MUST NOT call `confidentialCanTransfer`. |
| - MAY move 0 tokens if `amount` exceeds `confidentialAvailableBalanceOf(from)` | ||
| - MUST revert if `canReceive(to)` returns false. | ||
| - MUST NOT call `confidentialCanTransfer`. | ||
| - MUST emit `ConfidentialTransfer` as defined by [ERC-7984](./eip-7984.md), in addition to `ConfidentialForcedTransfer`. |
There was a problem hiding this comment.
Can we be specific this is the pointer and not the amount?
| - MUST emit `ConfidentialTransfer` as defined by [ERC-7984](./eip-7984.md), in addition to `ConfidentialForcedTransfer`. | |
| - MUST emit `ConfidentialTransfer` as defined by [ERC-7984](./eip-7984.md), in addition to `ConfidentialForcedTransfer`, both with the returned pointer as `amount`. |
There was a problem hiding this comment.
Note that line 36 already says the following:
All amounts are confidential pointers represented as
bytes32values, as defined by ERC-7984. The mechanism by which a pointer is resolved, and the mechanism by which an account is authorized to resolve one, are implementation specific.
Do you think further clarification is needed here?
Maybe we should add a requirement that the return amount is equal to the event amount?
Co-authored-by: eitjuh <1449065+eitjuh@users.noreply.github.com>
Co-authored-by: eitjuh <1449065+eitjuh@users.noreply.github.com>
| Returns a pointer to the largest amount `account` could transfer at the time of the call, disregarding rules that depend on the recipient. | ||
| - MUST be less than or equal to `confidentialBalanceOf(account)`. | ||
| - MUST account for every restriction the implementation applies to the account's own balance, including issuer freezes, lockups, vesting schedules, and pledged amounts. | ||
| - SHOULD NOT revert. |
There was a problem hiding this comment.
"SHOULD NOT revert" reads as applying to every caller, which conflicts with restricting who may query this (see the thread on L101). Reverting because the caller isn't authorised discloses nothing, since isOperator is public. What must not revert is anything that depends on confidential state. Could the two be split?
| - SHOULD NOT revert. | |
| - MUST revert unless the caller is `account`, an operator of `account`, or a party the implementation authorizes to resolve `account`'s balance. | |
| - MUST NOT revert for any reason that depends on confidential state. |
There was a problem hiding this comment.
I would prefer an implementation gate access to this function via handle access control as opposed to explicitly reverting on the call to confidentialAvailableBalanceOf. This allows relayers etc to facilitate user interactions without gaining access to private data.
Co-authored-by: akerbabber <maurizio.murru93@gmail.com>
Co-authored-by: Arr00 <13561405+arr00@users.noreply.github.com>
This PR adds a new ERC that extends ERC-7984 for confidential RWA tokens. As in ERC-7984, confidentiality is maintained via an implementation-specific pointer-based confidentiality system.