Skip to content

Commit

Permalink
add new contracts
Browse files Browse the repository at this point in the history
  • Loading branch information
friedger authored and github-actions[bot] committed Dec 12, 2023
1 parent c58d979 commit a00734c
Show file tree
Hide file tree
Showing 16 changed files with 2,840 additions and 1 deletion.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

(define-public (verify-and-update-price (pnau-bytes (buff 8192)))
(contract-call? .pyth-oracle-v1 verify-and-update-price-feeds
pnau-bytes
{
pyth-storage-contract: .pyth-store-v1,
pyth-decoder-contract: .pyth-pnau-decoder-v1,
wormhole-core-contract: .wormhole-core-v1
}))

(define-public (read-price (price-feed-id (buff 32)))
(contract-call? .pyth-oracle-v1 read-price-feed price-feed-id .pyth-store-v1))
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
;; Title: pyth-oracle
;; Version: v1
;; Check for latest version: https://github.com/hirosystems/stacks-pyth-bridge#latest-version
;; Report an issue: https://github.com/hirosystems/stacks-pyth-bridge/issues

(use-trait pyth-storage-trait .pyth-traits-v1.storage-trait)
(use-trait pyth-decoder-trait .pyth-traits-v1.decoder-trait)
(use-trait wormhole-core-trait .wormhole-traits-v1.core-trait)

;; Generic error
(define-constant ERR_PANIC (err u0))
;; Balance insufficient for handling fee
(define-constant ERR_BALANCE_INSUFFICIENT (err u402))

(define-public (read-price-feed
(price-feed-id (buff 32))
(pyth-storage-address <pyth-storage-trait>))
(begin
;; Check execution flow
(try! (contract-call? .pyth-governance-v1 check-storage-contract pyth-storage-address))
;; Perform contract-call
(contract-call? pyth-storage-address read price-feed-id)))

(define-public (verify-and-update-price-feeds
(price-feed-bytes (buff 8192))
(execution-plan {
pyth-storage-contract: <pyth-storage-trait>,
pyth-decoder-contract: <pyth-decoder-trait>,
wormhole-core-contract: <wormhole-core-trait>
}))
(begin
;; Check execution flow
(try! (contract-call? .pyth-governance-v1 check-execution-flow contract-caller (some execution-plan)))
;; Perform contract-call
(let ((pyth-decoder-contract (get pyth-decoder-contract execution-plan))
(wormhole-core-contract (get wormhole-core-contract execution-plan))
(pyth-storage-contract (get pyth-storage-contract execution-plan))
(decoded-prices (try! (contract-call? pyth-decoder-contract decode-and-verify-price-feeds price-feed-bytes wormhole-core-contract)))
(updated-prices (try! (contract-call? pyth-storage-contract write decoded-prices)))
(fee-info (contract-call? .pyth-governance-v1 get-fee-info))
(fee-amount (* (len updated-prices) (* (get mantissa fee-info) (pow u10 (get exponent fee-info))))))
;; Charge fee
(unwrap! (stx-transfer? fee-amount tx-sender (get address fee-info)) ERR_BALANCE_INSUFFICIENT)
(ok updated-prices))))

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions contracts/SP1F12J9QX3BQ32FY5HJNDVN5P309ZM9CE6XBN6YH/pyth-store-v1.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
;; Title: pyth-store
;; Version: v1
;; Check for latest version: https://github.com/hirosystems/stacks-pyth-bridge#latest-version
;; Report an issue: https://github.com/hirosystems/stacks-pyth-bridge/issues

(impl-trait .pyth-traits-v1.storage-trait)

(define-constant ERR_NEWER_PRICE_AVAILABLE (err u5000))
(define-constant ERR_STALE_PRICE (err u5001))
(define-constant ERR_INVALID_UPDATES (err u5003))

(define-map prices (buff 32) {
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
})

(define-map timestamps (buff 32) uint)

(define-public (read (price-identifier (buff 32)))
(let ((entry (unwrap! (map-get? prices price-identifier) (err u404))))
(ok entry)))

(define-public (write (batch-updates (list 64 {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
})))
(let ((successful-updates (map unwrapped-entry (filter only-ok-entry (map write-batch-entry batch-updates)))))
;; Ensure that updates are always coming from the right contract
(try! (contract-call? .pyth-governance-v1 check-execution-flow contract-caller none))
;; Ensure we have at least one entry
(asserts! (> (len successful-updates) u0) ERR_INVALID_UPDATES)
(ok successful-updates)))

(define-private (write-batch-entry (entry {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
}))
(let ((stale-price-threshold (contract-call? .pyth-governance-v1 get-stale-price-threshold))
(latest-bitcoin-timestamp (unwrap! (get-block-info? time (- block-height u1)) ERR_STALE_PRICE)))
;; Ensure that we have not processed a newer price
(asserts! (is-price-update-more-recent (get price-identifier entry) (get publish-time entry)) ERR_NEWER_PRICE_AVAILABLE)
;; Ensure that price is not stale
(asserts! (>= (get publish-time entry) (- latest-bitcoin-timestamp stale-price-threshold)) ERR_STALE_PRICE)
;; Update storage
(map-set prices
(get price-identifier entry)
{
price: (get price entry),
conf: (get conf entry),
expo: (get expo entry),
ema-price: (get ema-price entry),
ema-conf: (get ema-conf entry),
publish-time: (get publish-time entry),
prev-publish-time: (get prev-publish-time entry)
})
;; Emit event
(print {
type: "price-feed",
action: "updated",
data: entry
})
;; Update timestamps tracking
(map-set timestamps (get price-identifier entry) (get publish-time entry))
(ok entry)))

(define-private (only-ok-entry (entry (response {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
} uint))) (is-ok entry))

(define-private (unwrapped-entry (entry (response {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
} uint))) (unwrap-panic entry))

(define-private (is-price-update-more-recent (price-identifier (buff 32)) (publish-time uint))
(> publish-time (default-to u0 (map-get? timestamps price-identifier))))
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
;; Title: pyth-traits
;; Version: v1
;; Check for latest version: https://github.com/hirosystems/stacks-pyth-bridge#latest-version
;; Report an issue: https://github.com/hirosystems/stacks-pyth-bridge/issues

(use-trait wormhole-core-trait .wormhole-traits-v1.core-trait)

(define-trait decoder-trait
(
(decode-and-verify-price-feeds ((buff 8192) <wormhole-core-trait>) (response (list 64 {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
}) uint))
)
)

(define-trait storage-trait
(
(read ((buff 32)) (response {
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
} uint))

(write ((list 64 {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
})) (response (list 64 {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
}) uint))
)
)

(define-trait proxy-trait
(
(read-price-feed ((buff 32)) (response {
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
} uint))

(verify-and-update-price-feeds ((buff 8192) <wormhole-core-trait>) (response (list 64 {
price-identifier: (buff 32),
price: int,
conf: uint,
expo: int,
ema-price: int,
ema-conf: uint,
publish-time: uint,
prev-publish-time: uint,
}) uint))
)
)
Loading

0 comments on commit a00734c

Please sign in to comment.