Skip to content

Commit fe029ac

Browse files
committed
resolve timestamp check issue
1 parent 18c6742 commit fe029ac

File tree

4 files changed

+63
-20
lines changed

4 files changed

+63
-20
lines changed

stacks/Clarinet.toml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,10 @@ authors = []
55
telemetry = false
66
cache_dir = './.cache'
77

8-
[[project.requirements]]
9-
contract_id = 'SP1E0XBN9T4B10E9QMR7XMFJPMA19D77WY3KP2QKC.self-listing-helper-v3'
108
[contracts.executor-state]
119
path = 'contracts/executor-state.clar'
1210
clarity_version = 3
1311
epoch = 'latest'
14-
requirements = ['SP1E0XBN9T4B10E9QMR7XMFJPMA19D77WY3KP2QKC.self-listing-helper-v3']
1512

1613
[contracts.executor]
1714
path = 'contracts/executor.clar'

stacks/contracts/executor-state.clar

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@
2323
;; Anyone can call this to register themselves as a payee
2424
(define-public (register-payee (stacks-addr principal))
2525
(let (
26-
(p-as-string (contract-call?
27-
'SP1E0XBN9T4B10E9QMR7XMFJPMA19D77WY3KP2QKC.self-listing-helper-v3
28-
principal-to-string stacks-addr
29-
))
26+
(p-as-string (principal-to-string stacks-addr))
3027
(universal-addr (keccak256 (string-ascii-to-buff p-as-string)))
3128
)
3229
;; Check if payee already exists
@@ -44,6 +41,54 @@
4441

4542
;;;; Read-only functions
4643

44+
;; Constants for principal-to-string conversion (extracted from self-listing-helper-v3)
45+
(define-constant C32 "0123456789ABCDEFGHJKMNPQRSTVWXYZ")
46+
(define-constant LIST_15 (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
47+
(define-constant LIST_24 (list 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))
48+
(define-constant LIST_39 (concat LIST_24 LIST_15))
49+
50+
;; @desc Convert principal to string representation
51+
;; Extracted from self-listing-helper-v3 to eliminate external dependencies
52+
(define-read-only (principal-to-string (p principal))
53+
(let (
54+
(destructed (match (principal-destruct? p) ok-value ok-value err-value err-value))
55+
(checksum (unwrap-panic (slice? (sha256 (sha256 (concat (get version destructed) (get hash-bytes destructed)))) u0 u4)))
56+
(data (unwrap-panic (as-max-len? (concat (get hash-bytes destructed) checksum) u24)))
57+
(result (concat (concat "S" (unwrap-panic (element-at? C32 (buff-to-uint-be (get version destructed))))) (append-leading-0 data (trim-leading-0 (hash-bytes-to-string data)))))
58+
)
59+
(match (get name destructed) n (concat (concat result ".") n) result)
60+
)
61+
)
62+
63+
;; Helper functions for principal-to-string conversion
64+
(define-private (c32-to-string-iter (idx int) (it { s: (string-ascii 39), r: uint }))
65+
{ s: (unwrap-panic (as-max-len? (concat (unwrap-panic (element-at? C32 (mod (get r it) u32))) (get s it)) u39)), r: (/ (get r it) u32) })
66+
67+
(define-private (hash-bytes-to-string (data (buff 24)))
68+
(let (
69+
;; fixed-length: 8 * 15 / 5 = 24
70+
(low-part (get s (fold c32-to-string-iter LIST_24 { s: "", r: (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? data u9 u24)) u16)))})))
71+
;; fixed-length: ceil(8 * 9 / 5) = 15
72+
(high-part (get s (fold c32-to-string-iter LIST_15 { s: "", r: (buff-to-uint-be (unwrap-panic (as-max-len? (unwrap-panic (slice? data u0 u9)) u16)))})))
73+
)
74+
(unwrap-panic (as-max-len? (concat high-part low-part) u39))
75+
)
76+
)
77+
78+
(define-private (trim-leading-0-iter (idx int) (it (string-ascii 39)))
79+
(if (is-eq (element-at? it u0) (some "0")) (unwrap-panic (slice? it u1 (len it))) it))
80+
81+
(define-private (trim-leading-0 (s (string-ascii 39)))
82+
(fold trim-leading-0-iter LIST_39 s))
83+
84+
(define-private (append-leading-0-iter (idx int) (it { hash-bytes: (buff 24), address: (string-ascii 39)}))
85+
(if (is-eq (element-at? (get hash-bytes it) u0) (some 0x00))
86+
{ hash-bytes: (unwrap-panic (slice? (get hash-bytes it) u1 (len (get hash-bytes it)))), address: (unwrap-panic (as-max-len? (concat "0" (get address it)) u39)) }
87+
it))
88+
89+
(define-private (append-leading-0 (hash-bytes (buff 24)) (s (string-ascii 39)))
90+
(get address (fold append-leading-0-iter LIST_24 { hash-bytes: hash-bytes, address: s })))
91+
4792
;; @desc Helper function to convert string to buffer for hashing
4893
;; Matches the exact implementation from Wormhole Core
4994
(define-read-only (string-ascii-to-buff (s (string-ascii 256)))

stacks/contracts/executor.clar

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
(define-constant ERR-UNREGISTERED-PAYEE (err u1004))
2121
(define-constant ERR-INVALID-PAYEE-ADDRESS (err u1005))
2222
(define-constant ERR-BUFFER-PARSE-ERROR (err u1006))
23+
(define-constant ERR-STACKS-TIMESTAMP (err u1007))
2324
;;
2425

2526
;; data vars
@@ -154,12 +155,12 @@
154155
quote-dst-chain (match (extract-uint64-be signed-quote-bytes u60)
155156
expiry-time (if (is-eq quote-src-chain OUR-CHAIN)
156157
(if (is-eq quote-dst-chain dst-chain)
157-
;; Compare Unix timestamp expiry-time with current block timestamp
158-
(if (> expiry-time
159-
(unwrap-panic (get-stacks-block-info? time stacks-block-height))
158+
;; Get previous block's timestamp for reliable comparison
159+
(let ((current-time (unwrap! (get-stacks-block-info? time (- stacks-block-height u1)) ERR-STACKS-TIMESTAMP)))
160+
(if (> expiry-time current-time)
161+
(ok true)
162+
ERR-QUOTE-EXPIRED
160163
)
161-
(ok true)
162-
ERR-QUOTE-EXPIRED
163164
)
164165
ERR-QUOTE-DST-CHAIN-MISMATCH
165166
)

stacks/tests/executor.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe("Executor Contract Tests", () => {
5757
});
5858

5959
describe("validate-quote-header", () => {
60-
it.skip("should validate a correct quote header", () => {
60+
it("should validate a correct quote header", () => {
6161
// Create a valid quote buffer
6262
const validQuote = createSignedQuoteBuffer({
6363
srcChain: 1, // OUR-CHAIN = 1
@@ -109,20 +109,20 @@ describe("Executor Contract Tests", () => {
109109
expect(result).toBeErr(Cl.uint(1002)); // ERR-QUOTE-DST-CHAIN-MISMATCH
110110
});
111111

112-
it.skip("should reject expired quote", () => {
112+
it("should reject expired quote", () => {
113113
const expiredQuote = createSignedQuoteBuffer({
114114
srcChain: 1,
115115
dstChain: 2,
116116
expiryTime: 1000000000 // Past timestamp placeholder // 1 hour ago (expired)
117117
});
118-
118+
119119
const { result } = simnet.callReadOnlyFn(
120120
"executor",
121121
"validate-quote-header",
122122
[Cl.buffer(expiredQuote), Cl.uint(2)],
123123
address1
124124
);
125-
125+
126126
expect(result).toBeErr(Cl.uint(1003)); // ERR-QUOTE-EXPIRED
127127
});
128128

@@ -629,7 +629,7 @@ describe("Executor Contract Tests", () => {
629629
return (result as any).value;
630630
}
631631

632-
it.skip("should execute successfully with valid quote and registered relayer", () => {
632+
it("should execute successfully with valid quote and registered relayer", () => {
633633
// Register a relayer first
634634
const relayerAddr = accounts.get("wallet_2")!;
635635
const universalAddr = registerTestPayee(relayerAddr);
@@ -724,7 +724,7 @@ describe("Executor Contract Tests", () => {
724724
expect(result).toBeErr(Cl.uint(1002)); // ERR-QUOTE-DST-CHAIN-MISMATCH
725725
});
726726

727-
it.skip("should fail with expired quote", () => {
727+
it("should fail with expired quote", () => {
728728
const relayerAddr = accounts.get("wallet_2")!;
729729
const universalAddr = registerTestPayee(relayerAddr);
730730

@@ -753,7 +753,7 @@ describe("Executor Contract Tests", () => {
753753
expect(result).toBeErr(Cl.uint(1003)); // ERR-QUOTE-EXPIRED
754754
});
755755

756-
it.skip("should fail with unregistered relayer", () => {
756+
it("should fail with unregistered relayer", () => {
757757
// Create quote with unregistered payee address
758758
const unregisteredPayee = new Uint8Array(32);
759759
unregisteredPayee.fill(0xFF); // Address that's not registered
@@ -783,7 +783,7 @@ describe("Executor Contract Tests", () => {
783783
expect(result).toBeErr(Cl.uint(1004)); // ERR-UNREGISTERED-RELAYER
784784
});
785785

786-
it.skip("should emit correct event data", () => {
786+
it("should emit correct event data", () => {
787787
const relayerAddr = accounts.get("wallet_3")!;
788788
const universalAddr = registerTestPayee(relayerAddr);
789789

0 commit comments

Comments
 (0)