Skip to content

Amendment XLS-35: URIToken — Lightweight first-class NFTs #4456

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

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from

Conversation

dangell7
Copy link
Collaborator

@dangell7 dangell7 commented Mar 9, 2023

High Level Overview of Change

The URIToken Amendment (XLS-35d) provides a lightweight alternative to XLS20 suitable for both main-net and side-chains.

The amendment adds:

A new type of ledger object: ltURI_TOKEN
A new serialized field: URITokenID
Five new transaction types:

URITokenMint
URITokenBurn
URITokenBuy
URITokenCreateSellOffer
URITokenCancelSellOffer

  • New feature (non-breaking change which adds functionality)

@intelliot
Copy link
Collaborator

@dangell7 is this ready for review?

@intelliot
Copy link
Collaborator

note: there are merge conflicts you'd need to resolve

@dangell7
Copy link
Collaborator Author

@dangell7 is this ready for review?

Ready for review

@intelliot intelliot changed the title Amendment XLS-35 Amendment XLS-35: URIToken — Lightweight first-class NFTs May 1, 2023
@RichardAH
Copy link
Collaborator

I am requesting a code review on this. Anyone feel like reviewing it please?

@kennyzlei
Copy link
Collaborator

I am requesting a code review on this. Anyone feel like reviewing it please?

From the ripple side, @ledhed2222 will be able to help provide code review on this. In terms of timing, I'm predicting he will be able to get to this in two weeks or so

It would be great if we can seek additional help from non-ripple in terms for code review so that we can get more community representation/participation in this process. Would anyone else be able to help review? 🙏

@ledhed2222
Copy link
Contributor

just started taking a look at this :)

//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2014 Ripple Labs Inc.
Copy link
Collaborator

Choose a reason for hiding this comment

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

year is 2023

//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2017 Ripple Labs Inc.
Copy link
Contributor

Choose a reason for hiding this comment

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

please use 2023 :)


auto const uri = ctx.tx.getFieldVL(sfURI);

if (uri.size() < 1 || uri.size() > 256)
Copy link
Contributor

Choose a reason for hiding this comment

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

what do you think about making 256 a constant in the header file?

switch (tt)
{
case ttURITOKEN_MINT: {
if (flags & tfURITokenMintMask)
Copy link
Contributor

Choose a reason for hiding this comment

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

what do you think about splitting out the bodies of each switch statement into their own functions, for readability?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

answered below in followup question.

if (flags & tfURITokenNonMintMask)
return temINVALID_FLAG;

auto amt = ctx.tx.getFieldAmount(sfAmount);
Copy link
Contributor

Choose a reason for hiding this comment

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

i believe this could be const


switch (tt)
{
case ttURITOKEN_MINT: {
Copy link
Contributor

Choose a reason for hiding this comment

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

what's the rationale behind using a switch here (and above)? avoiding a new call stack frame?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@RichardAH thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

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

a switch is the correct structure to use here:

  • preflight checks are identical between two pairs of the five txn types, the switch allows fall through logic.
  • the code is very clear, using another structure would make it less clear.


case ttURITOKEN_CREATE_SELL_OFFER: {
if (account_ != *owner)
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.

nit - i think this is already checked in preclaim, right?

return tesSUCCESS;
}

case ttURITOKEN_CREATE_SELL_OFFER: {
Copy link
Contributor

Choose a reason for hiding this comment

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

what do you think about the idea of adding these fields to the mint transaction, so that a user can mint and set a sale price (poss with destination) in one tx? since this is the same object seems like that could be useful and easy

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@RichardAH thoughts?

Copy link
Collaborator

Choose a reason for hiding this comment

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

this a pretty good idea imho

if (!sle)
return tefINTERNAL;

uint16_t tt = ctx_.tx.getFieldU16(sfTransactionType);
Copy link
Contributor

Choose a reason for hiding this comment

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

could be const i believe

return tecINSUFFICIENT_RESERVE;
}

uint32_t flags = ctx_.tx.getFlags();
Copy link
Contributor

Choose a reason for hiding this comment

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

could be const i believe


switch (tt)
{
case ttURITOKEN_MINT: {
Copy link
Contributor

Choose a reason for hiding this comment

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

what do you think about making each of these switch bodies their own private methods, for readability?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Do you mean creating a preflight/preclaim/doApply for each or just moving them into a different method?

sleU->makeFieldAbsent(sfDestination);
view().update(sleU);
return tesSUCCESS;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

it's a bit surprising to me that buying my own token has the same behavior as canceling my sell offer. what's the rationale?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

What behavior would you expect or anything specific that made you question it?

From an accounting/reconciliation POV I can see your point as this might need to be recorded for those purposes.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's a valid purchase it just results in 0 movement of objects or funds.

Copy link
Contributor

Choose a reason for hiding this comment

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

i think a comment to clarify would be helpful :)

Copy link
Contributor

Choose a reason for hiding this comment

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

this also allows me to buy it from myself even though i haven't listed it for sale. it's really confusing to me and i'm not sure that that means it is a valid purchase. i could see it in the case where i have listed it for sale and then i attempt to buy it from myself


dstAmt = purchaseAmount;
static Rate const parityRate(QUALITY_ONE);
auto xferRate = transferRate(view(), saleAmount->getIssuer());
Copy link
Contributor

Choose a reason for hiding this comment

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

can be const

@dangell7
Copy link
Collaborator Author

@ledhed2222 Thank you very much for your time and review of the code. I have marked everything that I have updated with a thumbs up.

Richard and I are going to address some of the other comments and then I will push the changes for a second review.

@intelliot intelliot added API Change Feature Request Used to indicate requests to add new features Amendment Will Need Documentation labels Jun 23, 2023
0, // quality in
0, // quality out
j); // journal
!isTesSuccess(ter))
Copy link
Contributor

Choose a reason for hiding this comment

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

i like that you commented all these arguments 👍 :)

// if a trustline was created then the ownercount stays the same on
// the seller +1 TL -1 URIToken
if (!lineCreated && !isXRP(purchaseAmount))
adjustOwnerCount(view(), sleOwner, -1, j);
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't we also decrement the owner count if the purchase isXRP too?

@@ -139,6 +139,13 @@ enum TxType : std::uint16_t
/** This transaction accepts an existing offer to buy or sell an existing NFT. */
ttNFTOKEN_ACCEPT_OFFER = 29,

/** This transaction mints/burns/buys/sells a URI TOKEN */
Copy link
Contributor

@ledhed2222 ledhed2222 Jun 29, 2023

Choose a reason for hiding this comment

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

nit, These transactions mint/burn/buy/sell a URI TOKEN

Copy link
Contributor

@ledhed2222 ledhed2222 left a comment

Choose a reason for hiding this comment

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

see comments :)

@intelliot
Copy link
Collaborator

@dangell7 - at your convenience, please respond to the comments above

@intelliot intelliot added this to the 2024 release milestone Oct 3, 2023
@intelliot
Copy link
Collaborator

lacks reviews - community is welcome to review.

@intelliot intelliot removed this from the 2.1.0 (Mar 2024) milestone Feb 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: 📋 Backlog
Development

Successfully merging this pull request may close these issues.

6 participants