Skip to content

Commit

Permalink
Add SIP-010 print detection post-execution to the example folder
Browse files Browse the repository at this point in the history
  • Loading branch information
BowTiedRadone committed Feb 4, 2025
1 parent 0abdf0c commit 149b329
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 3 deletions.
24 changes: 21 additions & 3 deletions example/contracts/rendezvous-token.clar
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

(define-fungible-token rendezvous)

(define-constant deployer tx-sender)

(define-constant ERR_UNAUTHORIZED (err u400))

;; SIP-010 methods.

(define-read-only (get-total-supply)
Expand Down Expand Up @@ -34,8 +38,22 @@
(recipient principal)
(memo (optional (buff 34)))
)
(match (ft-transfer? rendezvous amount sender recipient)
response (ok response)
error (err error)
(begin
;; This print event is required for rendezvous to be a SIP-010 compliant
;; fungible token. Comment out this line and run the following command to
;; see the `dialers` in action:
;; ```rv example rendezvous-token invariant --dial=example/sip010.js```
;; (match memo to-print (print to-print) 0x)
(match (ft-transfer? rendezvous amount sender recipient)
response (ok response)
error (err error)
)
)
)

(define-public (mint (recipient principal) (amount uint))
(begin
(asserts! (is-eq contract-caller deployer) ERR_UNAUTHORIZED)
(ft-mint? rendezvous amount recipient)
)
)
7 changes: 7 additions & 0 deletions example/contracts/rendezvous-token.tests.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
;; Invariants

;; This invariant returns true regardless of the state of the contract. Its
;; purpose is to allow the demonstration of the `dialers` feature.
(define-read-only (invariant-always-true)
true
)
63 changes: 63 additions & 0 deletions example/sip010.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const { cvToHex } = require("@stacks/transactions");

async function postTransferSip010PrintEvent(context) {
const selectedFunction = context.selectedFunction;
// A fungible token complies with the SIP-010 standard if the transfer event
// always emits the print event with the `memo` content.
if (selectedFunction.name !== "transfer") {
return;
}

const functionCall = context.functionCall;
const functionCallEvents = functionCall.events;

if (functionCallEvents.length === 0) {
throw new Error(
"No transfer events. The transfer function must emit the SIP-010 print event!"
);
}

// The `memo` parameter is the fourth parameter of the `transfer` function.
const memoParameterIndex = 3;

const memoArg = context.clarityValueArguments[memoParameterIndex];

// The `memo` argument is optional. If `none`, nothing has to be printed.
if (memoArg.type === 9) {
return;
}

// The `memo` argument must be `some`. Otherwise, the generated clarity
// argument is invalid.
if (memoArg.type !== 10) {
return;
}

// Turn the inner value of the `some` type into a hex to compare it with the
// print event data.
const hexMemoArgValue = cvToHex(memoArg.value);

const sip010PrintEvent = functionCallEvents.find(
(ev) => ev.event === "print_event"
);

if (!sip010PrintEvent) {
throw new Error(
"No print event found. The transfer function must emit the SIP-010 print event!"
);
}

const sip010PrintEventValue = sip010PrintEvent.data.raw_value;

if (sip010PrintEventValue !== hexMemoArgValue) {
throw new Error(
`The print event memo value is not equal to the memo parameter value: ${hexMemoArgValue} !== ${sip010PrintEventValue}`
);
}

return;
}

module.exports = {
postTransferSip010PrintEvent,
};

0 comments on commit 149b329

Please sign in to comment.