In this post I’ll provide two examples of DL logics. They are not meant to describe the most common use cases, these are just two examples that are meant to highlight the programmability features of the kudos application.
Example one: named token
Function
Condition
Issue/Burn
Can only be done by a certain entity
Transfer/Swap
Allowed only if 2% of the transferred value is sent to the issuer, i.e., if the sender and receiver are not issuer, then there must be another resource with quantity 0.02q that is sent by the same owner and received by the receiver
Example two: Loyalty Points
Function
Condition
Issue
Can only be issued by a certain entity. Each token has an associated expiration date
Burn
No extra constraints
Burn for reward
The owner can issue a burn intent claiming reward from the issuer for burning their loyalty points. Only for non-expired tokens.
Transfer/Swap
No extra constraints
A note on burn-for-reward mechanics
While working on this example, I came up with an idea of burn/issue-for-reward mechanics. I described my thoughts in more details here. This is not a crucial question for this example, so I don’t want to think too much on how to implement it the best way. A simple option to implement it on the DL side is to always verify that there is some extra logic (intent) associated with the burn. For “simple” burns, the intent is always satisfied.
Could you pls clarify the constraints, witnesses and instances of the DL? And what’s in labels and values?
If the KL and DL description is complete, it would be helpful to see concrete transaction examples. For instance, for a named token issue transaction/action, how many resources are needed (including padding and dummy resources) in practice, and how they are constrained, and correlated.
Thanks for posting the details. I have a few questions mostly to ensure I understand correctly.
It implies that denomination resources are always ephemeral and have a quantity of 0. Does “consumed/created” and “ephemeral/persistent” refer to the status of kudo resources? Is self.quantity kind of ambiguous if it refers to kudo quantity while self is a denomination resource?
Is the label for denomination resources empty?
The consumed ephemeral constraints describe issuance checks. Are consumed persistent constraints missing to indicate persistent resource consumption via Signature.Verify(owner_pk, cms + nfs, Sig) = True?
Are you charging 2% to the sender’s or receiver’s quantity? The constraint r.quantity = 0.02 * self.quantity applies to created persistent resources, meaning sender.quantity = receiver.quantity + 0.02 * receiver.quantity and the transferred value is based on receiver’s.
Ephemeral created resources are constrained by Signature.Verify(issuer_pk, cms + nfs, Sig) = True. Does this imply only the issuer can burn these resources?
How many resources does the DL expect? I think three: the self denomination resource, the kudo resource, and an extra kudo resource sent to the issuer. Is it correct?
Yes, you are right! I accidentally wrote everything from the kudo perspective, not the DL resource perspective. I’ll edit the post to make it clearer.
I think in this case it can be empty or we can put some data in it for ensuring uniqueness. Might also put the issuer’s pk in it.
Transferring persistent resources doesn’t require issuer’s signature, and if it is a burn, the signature is already verified on the balancing ephemeral resource.
Yes, that is what I meant to say.
Not directly. If the user burning resources can somehow obtain the signature over these tags, they can do it too. But practically speaking I guess so
Yes, for this example it is at most 3 resources that are checked in the logic
How does an owner authorize kudo resource consumption? Is signature verification used, or are other methods employed? It depends on how you define the identity and authorization for the application.
In this particular example the denomination allows any transfers as long as 2% goes to the issuer, so the owner doesn’t have extra control over the transaction in case they decide to delegate the token creation to a solver.
We can also introduce another example, a simple signature one, where issuance, burn, and transfer are authorised with the signature and the 2% rule doesn’t apply. Issue and burn are authorised by the issuer, transfer is authorised by the sender. This example in some sense is more practical.
Got it. It seems there is no ownership in this example and anyone who knows the plaintext of resources can consume them.
Can we use this example for our first implementation instance so that we can use the signature for authorization?
Beside the DL examples, could you also share a simple receive logic example as it is mandatory?
Only allow receiving tokens of non-zero quantity of the listed assets.
Constraints:
There is a created kudo ‘r’ in the same action s.t.:
r.owner = self.label.owner (checking that the kudo is created for the person whose receive logic is currently being checked)
r.kind() is in allowedKinds. List of allowed kinds is hardcoded in the logic in this example. We can imagine that it is something like this: allowedKinds = [apple, orange, banana] (the list contains specific kinds instead of letters)
r.quantity > 0
The constraint is triggered for all receive logic resources (we only create ephemeral ones to trigger the logic by design, but we can just not check it since it doesn’t seem to allow any invalid behaviour)