Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

XLS-39 Clawback: #4553

Merged
merged 19 commits into from Jun 26, 2023
Merged

XLS-39 Clawback: #4553

merged 19 commits into from Jun 26, 2023

Conversation

shawnxie999
Copy link
Collaborator

@shawnxie999 shawnxie999 commented May 31, 2023

High Level Overview of Change

Introduces:

Context

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Refactor (non-breaking change that only restructures code)
  • Tests (You added tests for code that already exists, or your new feature included in this PR)
  • Documentation Updates
  • Release

@shawnxie999 shawnxie999 changed the title Clawback support XLS-39 Clawback May 31, 2023
@shawnxie999 shawnxie999 changed the title XLS-39 Clawback XLS-39 Clawback: May 31, 2023
@shawnxie999 shawnxie999 force-pushed the clawback branch 2 times, most recently from 9af831d to 4b3c4d7 Compare May 31, 2023 15:32
@shawnxie999 shawnxie999 mentioned this pull request May 31, 2023
7 tasks
@shawnxie999 shawnxie999 marked this pull request as ready for review May 31, 2023 16:01
Copy link
Contributor

@nbougalis nbougalis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some comments that need to be addressed before I give this one a pass.

Also, I notice that there no invariant checkers where added. At least one should be possible to add (see one of the comments in this review).

src/ripple/app/tx/impl/Clawback.cpp Outdated Show resolved Hide resolved
Comment on lines 79 to 87
STAmount const balance = sleRippleState->getFieldAmount(sfBalance);

// If balance is positive, issuer must have higher address than holder
if (balance > beast::zero && issuer < holder)
return tecNO_PERMISSION;

// If balance is negative, issuer must have lower address than holder
if (balance < beast::zero && issuer > holder)
return tecNO_PERMISSION;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're doing precisely what you advise should not be done in your comment a few lines down (starting on line 89).

I think the better path forward is to add a flag to accountHolds similar to fhIGNORE_FREEZE, called fhINCLUDE_ESCROW which instructs that function to return the full balance, including any escrowed amounts (since, IMO, the issuer should be able to clawback escrowed amounts), and leaving it up to the IOU escrow code to handle the situation in accountHolds when/if it gets merged.

Also, I think that tecINSUFFICIENT_FUNDS is a better error code here.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This if-condition is purely used to check that the account of this transaction is the issuer, by comparing high/low account with the polarity of the balance. It's not used to check the balance.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if we want to be able to claw back escrowed amounts, I think it would be better to propose a separate amendment after both PRs are merged. I'm don't think it is a good idea to have two PRs making changes for it in parallel

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think escrow or pay channels should be included in the clawback if AMM is excluded.

The justification is "it only allows an issuer to claw back the funds that are spendable".

Escrowed or Paychan iou tokens are locked and are not spendable. Therefore escrow and paychannel should be excluded.

Comment on lines +74 to +77
auto const sleRippleState =
ctx.view.read(keylet::line(holder, issuer, clawAmount.getCurrency()));
if (!sleRippleState)
return tecNO_LINE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Loading a SLE is an expensive operation, and you could avoid it, since accountHolds will also do it. Of course, it won't tell you if the trust line doesn't exist, but you could (a) either improve the interface of the (legacy) accountHolds to return an std::optional<STAmount>; or (b) by returning a more generic error code.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SLE of the trustline is fetched to check the account must be the issuer in the trustline. Without loading it and purely by using accountHolds, I would not be able to know that

    // If balance is positive, issuer must have higher address than holder
    if (balance > beast::zero && issuer < holder)
        return tecNO_PERMISSION;

    // If balance is negative, issuer must have lower address than holder
    if (balance < beast::zero && issuer > holder)
        return tecNO_PERMISSION;

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i would like to explicitly check the high/low account and the balance polarity to verify that the issuer is the one who submitted this transaction. Even though checking the sign of what accountHolds returns could work too, but that is not the purpose of this function, and behaviors could possibly change too. I think making an extra call is worth it in this case, because I would like to be fully confident that the real issuer is the one submitting this transaction, not the token holder.

src/ripple/app/tx/impl/Clawback.cpp Outdated Show resolved Hide resolved
src/ripple/app/tx/impl/Clawback.cpp Outdated Show resolved Hide resolved
src/ripple/app/tx/impl/Clawback.cpp Outdated Show resolved Hide resolved
src/ripple/app/tx/impl/Clawback.cpp Show resolved Hide resolved
src/ripple/app/tx/impl/Clawback.cpp Outdated Show resolved Hide resolved
Comment on lines +593 to +598
if (ctx_.view().rules().enabled(featureClawback) &&
uSetFlag == asfAllowClawback)
{
JLOG(j_.trace()) << "set allow clawback";
uFlagsOut |= lsfAllowClawback;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code to clear the lsfAllowClawback flag (i.e. to disclaim your ability to clawback) is missing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this flag is never meant to be cleared. Once set, it cannot be cleared

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But why? This is the inverse of "no freeze" and it should definitely be a flag you can clear.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nbougalis The reason for making clawback opt-out by default was purely because, having clawback opt-in was a poor idea and would raise a lot of concerns, just like how having freeze opt-in by default was a bad choice. The verdict is that we would like "opt-out" these kind of regulatory features in the future, and clawback would be the first one to follow that.

What is really the incentive for making allow clawback a mutable field? If they really want to mutate it, then I don't see why can't they create a new account. It would also create unnecessary complexity and confusion as well, since AllowClawback and NoFreeze are interdependent on each other.

But I think it would be a good practice to stick with immutable fields for regulatory features like freeze or clawback.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you misunderstand: I'm not suggesting that clawback should be opt-out, that would be a bad idea. I was just saying that I would allow it to be unset, but I don't feel strongly enough about it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not quite sure if there is any need for this. But if we find out that unsetting the flag is really wanted somehow, I think it would be fine to add it through an amendment later. This would be a rather small change. But I think it would be a good idea to keep it simple for now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Going on a tangent here: Since Clawback and NoFreeze are complimentary to one another, is it a good idea to frame this condition as an invariant? I would eliminate such a check in other parts of the code right?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ckeshava I don't think this change would eliminate such checks in other parts of the code. Invariant check is executed after a transaction.

And it will still be mandatory to check this complementary property during the preclaim (before an transaction) of an AccountSet.

src/ripple/app/tx/impl/Clawback.cpp Show resolved Hide resolved
@shawnxie999
Copy link
Collaborator Author

shawnxie999 commented Jun 2, 2023

Ready for re-review

Copy link
Collaborator

@seelabs seelabs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@shawnxie999
Copy link
Collaborator Author

@nbougalis do you mind revisiting the PR to see it looks acceptable? Thanks

@intelliot
Copy link
Collaborator

(note: nbougalis intends to review by this weekend)

@kennyzlei kennyzlei added the Passed Passed code review & PR owner thinks it's ready to merge. Perf sign-off may still be required. label Jun 26, 2023
@kennyzlei kennyzlei merged commit b7e902d into XRPLF:develop Jun 26, 2023
15 checks passed
@intelliot intelliot added this to the 1.12 milestone Jun 26, 2023
intelliot pushed a commit that referenced this pull request Jul 5, 2023
* Update the `account_info` API so that the `allowClawback` flag is
  included in the response.
  * The proposed `Clawback` amendement added an `allowClawback` flag in
    the `AccountRoot` object.
  * In the API response, under `account_flags`, there is now an
    `allowClawback` field with a boolean (`true` or `false`) value.
  * For reference, the XLS-39 Clawback implementation can be found in
    #4553

Fix #4588
ckeshava pushed a commit to ckeshava/rippled that referenced this pull request Jul 10, 2023
Introduces:
* AccountRoot flag: lsfAllowClawback
* New Clawback transaction
* More info on clawback spec: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-39d-clawback
ckeshava pushed a commit to ckeshava/rippled that referenced this pull request Jul 10, 2023
* Update the `account_info` API so that the `allowClawback` flag is
  included in the response.
  * The proposed `Clawback` amendement added an `allowClawback` flag in
    the `AccountRoot` object.
  * In the API response, under `account_flags`, there is now an
    `allowClawback` field with a boolean (`true` or `false`) value.
  * For reference, the XLS-39 Clawback implementation can be found in
    XRPLF#4553

Fix XRPLF#4588
intelliot added a commit to intelliot/rippled that referenced this pull request Jul 18, 2023
intelliot pushed a commit that referenced this pull request Aug 16, 2023
Introduces:
* AccountRoot flag: lsfAllowClawback
* New Clawback transaction
* More info on clawback spec: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-39d-clawback
ckeshava pushed a commit to ckeshava/rippled that referenced this pull request Sep 22, 2023
Introduces:
* AccountRoot flag: lsfAllowClawback
* New Clawback transaction
* More info on clawback spec: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-39d-clawback
ckeshava pushed a commit to ckeshava/rippled that referenced this pull request Sep 22, 2023
* Update the `account_info` API so that the `allowClawback` flag is
  included in the response.
  * The proposed `Clawback` amendement added an `allowClawback` flag in
    the `AccountRoot` object.
  * In the API response, under `account_flags`, there is now an
    `allowClawback` field with a boolean (`true` or `false`) value.
  * For reference, the XLS-39 Clawback implementation can be found in
    XRPLF#4553

Fix XRPLF#4588
ckeshava pushed a commit to ckeshava/rippled that referenced this pull request Sep 25, 2023
Introduces:
* AccountRoot flag: lsfAllowClawback
* New Clawback transaction
* More info on clawback spec: https://github.com/XRPLF/XRPL-Standards/tree/master/XLS-39d-clawback
ckeshava pushed a commit to ckeshava/rippled that referenced this pull request Sep 25, 2023
* Update the `account_info` API so that the `allowClawback` flag is
  included in the response.
  * The proposed `Clawback` amendement added an `allowClawback` flag in
    the `AccountRoot` object.
  * In the API response, under `account_flags`, there is now an
    `allowClawback` field with a boolean (`true` or `false`) value.
  * For reference, the XLS-39 Clawback implementation can be found in
    XRPLF#4553

Fix XRPLF#4588
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Added to API Changelog Amendment API Change Clio Reviewed Passed Passed code review & PR owner thinks it's ready to merge. Perf sign-off may still be required. Will Need Documentation
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

None yet

9 participants