Skip to content

Commit

Permalink
Merge pull request #12 from Trust-Machines/GRNT-1164
Browse files Browse the repository at this point in the history
GRNT-1164: additional overlay checks
  • Loading branch information
hackercf authored Dec 6, 2024
2 parents 75b14a0 + d74dd20 commit 2f4ab60
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 8 deletions.
15 changes: 12 additions & 3 deletions contracts/pyth-governance-v1.clar
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
(define-constant ERR_INVALID_PTGM (err u4007))
;; Error not standard principal
(define-constant ERR_NOT_STANDARD_PRINCIPAL (err u4008))
;; Error Ptgm overlay bytes
(define-constant ERR_PTGM_CHECK_OVERLAY (err u4009))

(define-data-var governance-data-source
{ emitter-chain: uint, emitter-address: (buff 32) }
Expand Down Expand Up @@ -365,7 +367,8 @@
(cursor-target-chain-id (unwrap! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-buff-2 (get next cursor-action))
ERR_INVALID_PTGM))
(cursor-body (unwrap! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-buff-8192-max (get next cursor-target-chain-id) none)
ERR_INVALID_PTGM)))
ERR_INVALID_PTGM))
(overlay-check (asserts! (is-eq (get pos (get next cursor-body)) (len ptgm-bytes)) ERR_PTGM_CHECK_OVERLAY)))
;; Check magic bytes
(asserts! (is-eq (get value cursor-magic) PTGM_MAGIC) ERR_INVALID_PTGM)
;; Check target-chain-id
Expand All @@ -390,6 +393,7 @@
ERR_INVALID_ACTION_PAYLOAD))
(cursor-exponent (unwrap! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-uint-64 (get next cursor-mantissa))
ERR_INVALID_ACTION_PAYLOAD)))
(asserts! (is-eq (get pos (get next cursor-exponent)) (len ptgm-body)) ERR_PTGM_CHECK_OVERLAY)
(ok {
mantissa: (get value cursor-mantissa),
exponent: (get value cursor-exponent)
Expand All @@ -399,6 +403,7 @@
(let ((cursor-ptgm-body (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 new ptgm-body none))
(cursor-stale-price-threshold (unwrap! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-uint-64 (get next cursor-ptgm-body))
ERR_INVALID_ACTION_PAYLOAD)))
(asserts! (is-eq (get pos (get next cursor-stale-price-threshold)) (len ptgm-body)) ERR_PTGM_CHECK_OVERLAY)
(ok (get value cursor-stale-price-threshold))))

(define-private (parse-and-verify-governance-data-source (ptgm-body (buff 8192)))
Expand All @@ -409,6 +414,7 @@
ERR_INVALID_ACTION_PAYLOAD))
(cursor-emitter-address (unwrap! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-buff-32 (get next cursor-emitter-sequence))
ERR_INVALID_ACTION_PAYLOAD)))
(asserts! (is-eq (get pos (get next cursor-emitter-address)) (len ptgm-body)) ERR_PTGM_CHECK_OVERLAY)
(ok {
emitter-chain: (get value cursor-emitter-chain),
emitter-sequence: (get value cursor-emitter-sequence),
Expand All @@ -420,22 +426,25 @@
(cursor-principal-len (try! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-uint-8 (get next cursor-ptgm-body))))
(principal-bytes (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 slice (get next cursor-principal-len) (some (get value cursor-principal-len))))
(new-principal (unwrap! (from-consensus-buff? principal principal-bytes) ERR_UNEXPECTED_ACTION_PAYLOAD)))
(asserts! (is-eq (+ (get pos (get next cursor-principal-len)) (get value cursor-principal-len)) (len ptgm-body)) ERR_PTGM_CHECK_OVERLAY)
(asserts! (is-standard new-principal) ERR_NOT_STANDARD_PRINCIPAL)
(ok new-principal)))

(define-private (parse-and-verify-prices-data-sources (ptgm-body (buff 8192)))
(let ((cursor-ptgm-body (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 new ptgm-body none))
(cursor-num-data-sources (try! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-uint-8 (get next cursor-ptgm-body))))
(cursor-data-sources-bytes (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 slice (get next cursor-num-data-sources) none))
(data-sources (get result (fold parse-data-source cursor-data-sources-bytes {
(data-sources-bundle (fold parse-data-source cursor-data-sources-bytes {
result: (list),
cursor: {
index: u0,
next-update-index: u0
},
bytes: cursor-data-sources-bytes,
limit: (get value cursor-num-data-sources)
}))))
}))
(data-sources (get result data-sources-bundle)))
(asserts! (is-eq (get next-update-index (get cursor data-sources-bundle)) (len cursor-data-sources-bytes)) ERR_PTGM_CHECK_OVERLAY)
(ok data-sources)))

(define-private (parse-data-source
Expand Down
11 changes: 8 additions & 3 deletions contracts/pyth-pnau-decoder-v1.clar
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@
(define-constant ERR_UNAUTHORIZED_FLOW (err u2404))
;; Price update not signed by an authorized source
(define-constant ERR_UNAUTHORIZED_PRICE_UPDATE (err u2401))
;; VAA buffer has unused, extra leading bytes (overlay)
(define-constant ERR_OVERLAY_PRESENT (err u2402))

;;;; Public functions
(define-public (decode-and-verify-price-feeds (pnau-bytes (buff 8192)) (wormhole-core-address <wormhole-core-trait>))
Expand Down Expand Up @@ -115,7 +117,7 @@
;; Check major version
(asserts! (is-eq (get value cursor-version-maj) PYTHNET_MAJOR_VERSION) ERR_VERSION_MAJ)
;; Check minor version
(asserts! (is-eq (get value cursor-version-min) PYTHNET_MINOR_VERSION) ERR_VERSION_MIN)
(asserts! (>= (get value cursor-version-min) PYTHNET_MINOR_VERSION) ERR_VERSION_MIN)
;; Check proof type
(asserts! (is-eq (get value cursor-proof-type) u0) ERR_PROOF_TYPE)
(ok {
Expand All @@ -132,20 +134,23 @@
(define-private (parse-and-verify-prices-updates (bytes (buff 8192)) (merkle-root-hash (buff 20)))
(let ((cursor-num-updates (try! (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 read-uint-8 { bytes: bytes, pos: u0 })))
(cursor-updates-bytes (contract-call? 'SP2J933XB2CP2JQ1A4FGN8JA968BBG3NK3EKZ7Q9F.hk-cursor-v2 slice (get next cursor-num-updates) none))
(updates (get result (fold parse-price-info-and-proof cursor-updates-bytes {
(updates-data (fold parse-price-info-and-proof cursor-updates-bytes {
result: (list),
cursor: {
index: u0,
next-update-index: u0
},
bytes: cursor-updates-bytes,
limit: (get value cursor-num-updates)
})))
}))
(updates (get result updates-data))
(merkle-proof-checks-success (get result (fold check-merkle-proof updates {
result: true,
merkle-root-hash: merkle-root-hash
}))))
(asserts! merkle-proof-checks-success MERKLE_ROOT_MISMATCH)
;; Overlay check; 1 is added because 1 byte is used to store "cursor-num-updates"
(asserts! (is-eq (+ u1 (get next-update-index (get cursor updates-data))) (len bytes)) ERR_OVERLAY_PRESENT)
(ok updates)))

(define-private (check-merkle-proof
Expand Down
4 changes: 4 additions & 0 deletions contracts/wormhole/wormhole-core-v2.clar
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@
(define-constant ERR_GSU_CHECK_EMITTER (err u1305))
;; First guardian set is not being updated by the deployer
(define-constant ERR_NOT_DEPLOYER (err u1306))
;; Overlay present in vaa bytes
(define-constant ERR_GSU_CHECK_OVERLAY (err u1307))

;; Guardian set upgrade emitting address
(define-constant GSU-EMITTING-ADDRESS 0x0000000000000000000000000000000000000000000000000000000000000004)
Expand Down Expand Up @@ -153,6 +155,7 @@
message-hash: vaa-body-hash,
value: (list)
})))
(asserts! (is-eq (get pos (get next cursor-payload)) (len vaa-bytes)) ERR_GSU_CHECK_OVERLAY)
(print { payload: (get value cursor-payload) })
(ok {
vaa: {
Expand Down Expand Up @@ -350,6 +353,7 @@
ERR_GSU_PARSING_GUARDIANS_BYTES))
(guardians-cues (get result (fold is-guardian-cue (get value guardians-bytes) { cursor: u0, result: (list) })))
(eth-addresses (get result (fold parse-guardian guardians-cues { bytes: (get value guardians-bytes), result: (list) }))))
(asserts! (is-eq (get pos (get next guardians-bytes)) (len bytes)) ERR_GSU_CHECK_OVERLAY)
;; Ensure that this message was emitted from authorized module
(asserts! (is-eq (get value cursor-module) 0x00000000000000000000000000000000000000000000000000000000436f7265)
ERR_GSU_CHECK_MODULE)
Expand Down
4 changes: 2 additions & 2 deletions unit-tests/pyth/pnau.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ describe("pyth-pnau-decoder-v1::decode-and-verify-price-feeds failures", () => {
expect(res.result).toBeErr(Cl.uint(2002));
});

it("should fail if PNAU minor version is incorrect", () => {
it("should not fail if PNAU minor version is above minimum minor due to forward compatibility", () => {
let actualPricesUpdates = pyth.buildPriceUpdateBatch([
[pyth.BtcPriceIdentifier, { price: 100n }],
]);
Expand Down Expand Up @@ -597,7 +597,7 @@ describe("pyth-pnau-decoder-v1::decode-and-verify-price-feeds failures", () => {
[Cl.buffer(pnau), executionPlan],
sender,
);
expect(res.result).toBeErr(Cl.uint(2003));
expect(res.result.type).toBe(ClarityType.ResponseOk)
});

it("should fail if PNAU proof type version is incorrect", () => {
Expand Down

0 comments on commit 2f4ab60

Please sign in to comment.