Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: stacks #394

Open
wants to merge 13 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions contracts/stacks/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
tests/** linguist-vendored
vitest.config.js linguist-vendored
* text=lf
13 changes: 13 additions & 0 deletions contracts/stacks/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

**/settings/Mainnet.toml
**/settings/Testnet.toml
.cache/**
history.txt

logs
*.log
npm-debug.log*
coverage
*.info
costs-reports.json
node_modules
69 changes: 69 additions & 0 deletions contracts/stacks/Clarinet.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
[project]
name = 'stacks'
description = ''
authors = []
telemetry = true
cache_dir = './.cache'

[contracts.centralized-connection]
path = 'contracts/connections/centralized-connection.clar'
clarity_version = 2
epoch = 2.5

[contracts.mock-dapp]
path = 'tests/mocks/mock-dapp.clar'
clarity_version = 2
epoch = 2.5

[contracts.rlp-decode]
path = 'lib/rlp/rlp-decode.clar'
clarity_version = 2
epoch = 2.5

[contracts.rlp-encode]
path = 'lib/rlp/rlp-encode.clar'
clarity_version = 2
epoch = 2.5

[contracts.util]
path = 'contracts/util.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-common-trait]
path = 'contracts/xcall/xcall-common-trait.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-impl]
path = 'contracts/xcall/xcall-impl.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-impl-trait]
path = 'contracts/xcall/xcall-impl-trait.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-proxy]
path = 'contracts/xcall/xcall-proxy.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-proxy-trait]
path = 'contracts/xcall/xcall-proxy-trait.clar'
clarity_version = 2
epoch = 2.5

[contracts.xcall-receiver-trait]
path = 'contracts/xcall/xcall-receiver-trait.clar'
clarity_version = 2
epoch = 2.5
[repl.analysis]
passes = ['check_checker']

[repl.analysis.check_checker]
strict = false
trusted_sender = false
trusted_caller = false
callee_filter = false
98 changes: 98 additions & 0 deletions contracts/stacks/contracts/connections/centralized-connection.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
(use-trait xcall-impl-trait .xcall-impl-trait.xcall-impl-trait)

(define-constant ERR_UNAUTHORIZED (err u100))
(define-constant ERR_INVALID_FEE (err u101))
(define-constant ERR_DUPLICATE_MESSAGE (err u102))
(define-constant ERR_XCALL_NOT_SET (err u103))

(define-data-var xcall (optional principal) none)
(define-data-var admin principal tx-sender)
(define-data-var conn-sn int 0)

(define-map message-fees {network-id: (string-ascii 128)} uint)
(define-map response-fees {network-id: (string-ascii 128)} uint)
(define-map receipts {network-id: (string-ascii 128), conn-sn: int} bool)

(define-read-only (get-xcall)
(ok (var-get xcall)))

(define-read-only (get-admin)
(ok (var-get admin)))

(define-read-only (get-conn-sn)
(ok (var-get conn-sn)))

(define-read-only (get-fee (to (string-ascii 128)) (response bool))
(let
((message-fee (default-to u0 (map-get? message-fees {network-id: to}))))
(if response
(let
((response-fee (default-to u0 (map-get? response-fees {network-id: to}))))
(ok (+ message-fee response-fee)))
(ok message-fee))))

(define-read-only (get-receipt (src-network (string-ascii 128)) (conn-sn-in int))
(ok (default-to false (map-get? receipts {network-id: src-network, conn-sn: conn-sn-in}))))

(define-private (is-admin)
(is-eq tx-sender (var-get admin)))

(define-private (is-xcall)
(match (var-get xcall)
xcall-contract (is-eq tx-sender xcall-contract)
false
))

(define-public (initialize (xcall-contract principal) (admin-address principal))
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(var-set xcall (some xcall-contract))
(var-set admin admin-address)
(ok true)))

(define-public (set-fee (network-id (string-ascii 128)) (message-fee uint) (response-fee uint))
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(map-set message-fees {network-id: network-id} message-fee)
(map-set response-fees {network-id: network-id} response-fee)
(ok true)))

(define-public (claim-fees)
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(as-contract (stx-transfer? (stx-get-balance (as-contract tx-sender)) tx-sender (var-get admin)))))

(define-public (set-admin (new-admin principal))
(begin
(asserts! (is-admin) ERR_UNAUTHORIZED)
(var-set admin new-admin)
(ok true)))

(define-private (emit-message-event (to (string-ascii 128)) (sn int) (msg (buff 2048)))
(print
{
event: "Message",
to: to,
sn: sn,
msg: msg
}
)
)

(define-public (send-message (to (string-ascii 128)) (svc (string-ascii 128)) (sn int) (msg (buff 2048)) (implementation <xcall-impl-trait>))
(begin
(asserts! (is-xcall) ERR_UNAUTHORIZED)
AntonAndell marked this conversation as resolved.
Show resolved Hide resolved
(let
((fee (unwrap! (get-fee to (> sn 0)) ERR_INVALID_FEE)))
(asserts! (>= (stx-get-balance tx-sender) fee) ERR_INVALID_FEE)
(var-set conn-sn (+ (var-get conn-sn) 1))
(as-contract (unwrap-panic (contract-call? .xcall-proxy handle-message to msg implementation)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was added for testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yeah I think this was when I was initially trying to figure out how to call the proxy

(emit-message-event to (var-get conn-sn) msg)
(ok (var-get conn-sn)))))

(define-public (recv-message (src-network-id (string-ascii 128)) (conn-sn-in int) (msg (buff 2048)) (implementation <xcall-impl-trait>))
(begin
(asserts! (is-eq tx-sender (var-get admin)) ERR_UNAUTHORIZED)
(asserts! (is-none (map-get? receipts {network-id: src-network-id, conn-sn: conn-sn-in})) ERR_DUPLICATE_MESSAGE)
(map-set receipts {network-id: src-network-id, conn-sn: conn-sn-in} true)
(as-contract (contract-call? .xcall-proxy handle-message src-network-id msg implementation))))
72 changes: 72 additions & 0 deletions contracts/stacks/contracts/util.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
(define-constant C32SET "0123456789ABCDEFGHJKMNPQRSTVWXYZ")

(define-constant ERR_INVALID_ADDRESS (err u1000))
(define-constant ERR_INVALID_CONTRACT_NAME (err u1001))

(define-data-var result-var (buff 400) 0x)
(define-data-var addr-var (buff 400) 0x)

(define-public (address-string-to-principal (address (string-ascii 128)))
(let (
(period-index (index-of address "."))
)
(if (is-some period-index)
(let (
(address-part (unwrap-panic (slice? address u0 (unwrap-panic period-index))))
(contract-name-part (unwrap-panic (slice? address u42 (len address))))
)
(begin
(asserts! (is-eq (unwrap-panic period-index) u41) ERR_INVALID_ADDRESS)
(asserts! (is-valid-c32 address-part) ERR_INVALID_ADDRESS)
(ok (unwrap-panic (c32-decode address-part (as-max-len? contract-name-part u40))))
)
)
(begin
(asserts! (is-eq (len address) u41) ERR_INVALID_ADDRESS)
(asserts! (is-valid-c32 address) ERR_INVALID_ADDRESS)
(ok (unwrap-panic (c32-decode address none)))
)
)
)
)

(define-private (c32-decode-aux (input (string-ascii 1)) (res {bit-buff: uint, bits-remaining: uint}))
(let ((index (unwrap-panic (index-of? C32SET input)))
(bit-buff (bit-or (bit-shift-left (get bit-buff res) u5) index))
(bits-remaining (+ (get bits-remaining res) u5)))
(if (>= bits-remaining u8)
(let ((char (to-buff (bit-and (bit-shift-right bit-buff (- bits-remaining u8)) u255)))
(bits-remaining1 (- bits-remaining u8))
(bit-buff1 (bit-and bit-buff (- (bit-shift-left u1 bits-remaining1) u1))))
(set (unwrap-panic (as-max-len? (var-get addr-var) u399)) char)
(tuple (bit-buff bit-buff1) (bits-remaining bits-remaining1)))
(tuple (bit-buff bit-buff) (bits-remaining bits-remaining)))))

(define-private (c32-decode (address (string-ascii 128)) (contract-name (optional (string-ascii 40))))
(begin
(var-set addr-var 0x)
(fold c32-decode-aux (unwrap-panic (slice? address u1 (- (len address) u5))) (tuple (bit-buff u0) (bits-remaining u0)))
(let ((version (to-buff (unwrap-panic (index-of? C32SET (unwrap-panic (element-at? address u1))))))
(pub-key-hash (unwrap-panic (slice? (var-get addr-var) u1 u21))))
(if (is-some contract-name)
(principal-construct? version (unwrap-panic (as-max-len? pub-key-hash u20)) (unwrap-panic contract-name))
(principal-construct? version (unwrap-panic (as-max-len? pub-key-hash u20)))
)
)
)
)

(define-private (set (address (buff 399)) (char (buff 1)))
(var-set addr-var (concat address char)))

(define-private (to-buff (data uint))
(begin
(let ((encoded (unwrap-panic (to-consensus-buff? data))))
(unwrap-panic (element-at? encoded (- (len encoded) u1))))))


(define-private (is-valid-c32 (address (string-ascii 128)))
(fold is-c32-char address true))

(define-private (is-c32-char (char (string-ascii 1)) (valid bool))
(and valid (is-some (index-of C32SET char))))
6 changes: 6 additions & 0 deletions contracts/stacks/contracts/xcall/xcall-common-trait.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(define-trait xcall-common-trait
(
(get-network-address () (response (string-ascii 128) uint))
(send-call-message ((string-ascii 128) (buff 2048) (optional (buff 1024)) (optional (list 10 (string-ascii 128))) (optional (list 10 (string-ascii 128)))) (response uint uint))
)
)
27 changes: 27 additions & 0 deletions contracts/stacks/contracts/xcall/xcall-impl-trait.clar
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(use-trait xcall-receiver-trait .xcall-receiver-trait.xcall-receiver-trait)
(use-trait xcall-common-trait .xcall-common-trait.xcall-common-trait)

(define-trait xcall-impl-trait
(
(send-call ((string-ascii 128) (buff 2048)) (response uint uint))

(execute-call (uint (buff 2048) <xcall-receiver-trait> <xcall-common-trait>) (response bool uint))
(execute-rollback (uint <xcall-receiver-trait> <xcall-common-trait>) (response bool uint))

(verify-success (uint) (response bool uint))

(handle-message ((string-ascii 128) (buff 2048)) (response bool uint))
(handle-error (uint) (response bool uint))

(set-admin (principal) (response bool uint))
(set-protocol-fee-handler (principal) (response bool uint))
(set-protocol-fee (uint) (response bool uint))
(set-default-connection ((string-ascii 128) (string-ascii 128)) (response bool uint))
(set-trusted-protocols ((string-ascii 128) (list 10 (string-ascii 128))) (response bool uint))

(get-network-address () (response (string-ascii 257) uint))
(get-network-id () (response (string-ascii 128) uint))
(get-protocol-fee () (response uint uint))
(get-fee ((string-ascii 128) bool (optional (list 10 (string-ascii 128)))) (response uint uint))
)
)
Loading
Loading