Source Code

;; Title: BME006 Treasury
;; Synopsis:
;; A treasury that can manage STX, SIP009, SIP010, and SIP013 tokens.
;; Description:
;; An extension contract that is meant to hold tokens on behalf of the
;; DAO. It can hold and transfer STX, SIP009, SIP010, and SIP013 tokens.
;; They can be deposited by simply transferring them to the contract.
;; Any extension or executing proposal can trigger transfers.
;; Technically, the ExecutorDAO core can hold and transfer tokens
;; directly. The treasury extension merely adds a bit of separation.

(impl-trait 'SP3JP0N1ZXGASRJ0F7QAHWFPGTVK9T2XNXDB908Z.extension-trait.extension-trait)
(use-trait prediction-market-trait .prediction-market-trait.prediction-market-trait)
(use-trait ft-velar-token 'SP2AKWJYC7BNY18W1XXKPGP0YVEK63QJG4793Z2D4.sip-010-trait-ft-standard.sip-010-trait)

(define-constant err-unauthorised (err u3000))
(define-constant err-invalid-amount (err u3001))

(define-constant slippage-bips u500)
(define-constant share-fee-to 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-share-fee-to) 

;; --- Transferable traits

(define-trait sip009-transferable
	(
		(transfer (uint principal principal) (response bool uint))
	)
)

(define-trait sip010-transferable
	(
		(transfer (uint principal principal (optional (buff 34))) (response bool uint))
	)
)

(define-trait sip013-transferable
	(
		(transfer (uint uint principal principal) (response bool uint))
		(transfer-memo (uint uint principal principal (buff 34)) (response bool uint))
	)
)

(define-trait sip013-transferable-many
	(
		(transfer-many ((list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal})) (response bool uint))
		(transfer-many-memo ((list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal, memo: (buff 34)})) (response bool uint))
	)
)

;; --- Authorisation check

(define-public (is-dao-or-extension)
	(ok (asserts! (or (is-eq tx-sender .bigmarket-dao) (contract-call? .bigmarket-dao is-extension contract-caller)) err-unauthorised))
)

;; --- Internal DAO functions

(define-public (swap-tokens
		(token0 <ft-velar-token>)
		(token1 <ft-velar-token>)
		(token-in <ft-velar-token>)
		(token-out <ft-velar-token>)
		(amount uint)
	)
	(let (
			(min-amount (/ (* amount (- u10000 slippage-bips)) u10000))
		)
		;; Auth check: must be DAO or approved extension
		(try! (is-dao-or-extension))

		(asserts! (> amount u0) err-invalid-amount)
		(asserts! (> amount min-amount) err-invalid-amount)

		;; Call Velar swap
		(try! (as-contract (contract-call? 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router swap-exact-tokens-for-tokens u0 token0 token1 token-in token-out share-fee-to amount min-amount)))

		(print {event: "swap-tokens", token-in: token-in, token-out: token-out, amount: amount, min-amount: min-amount})
		(ok true)
	)
)

;; STX

(define-public (stx-transfer (amount uint) (recipient principal) (memo (optional (buff 34))))
	(begin
		(try! (is-dao-or-extension))
		(match memo to-print (print to-print) 0x)
		(as-contract (stx-transfer? amount tx-sender recipient))
	)
)

(define-public (stx-transfer-many (transfers (list 200 {amount: uint, recipient: principal, memo: (optional (buff 34))})))
	(begin
		(try! (is-dao-or-extension))
		(as-contract (fold stx-transfer-many-iter transfers (ok true)))
	)
)

;; SIP009

(define-public (sip009-transfer (token-id uint) (recipient principal) (asset <sip009-transferable>))
	(begin
		(try! (is-dao-or-extension))
		(as-contract (contract-call? asset transfer token-id tx-sender recipient))
	)
)

(define-public (sip009-transfer-many (data (list 200 {token-id: uint, recipient: principal})) (asset <sip009-transferable>))
	(begin
		(as-contract (fold sip009-transfer-many-iter data asset))
		(ok true)
	)
)

;; SIP010

(define-public (sip010-transfer (amount uint) (recipient principal) (memo (optional (buff 34))) (asset <sip010-transferable>))
	(begin
		(try! (is-dao-or-extension))
		(as-contract (contract-call? asset transfer amount tx-sender recipient memo))
	)
)

(define-public (sip010-transfer-many (data (list 200 {amount: uint, recipient: principal, memo: (optional (buff 34))})) (asset <sip010-transferable>))
	(begin
		(as-contract (fold sip010-transfer-many-iter data asset))
		(ok true)
	)
)

;; SIP013

(define-public (sip013-transfer (token-id uint) (amount uint) (recipient principal) (memo (optional (buff 34))) (asset <sip013-transferable>))
	(begin
		(try! (is-dao-or-extension))
		(as-contract (match memo memo-buff
			(contract-call? asset transfer-memo token-id amount tx-sender recipient memo-buff)
			(contract-call? asset transfer token-id amount tx-sender recipient)
		))
	)
)

(define-public (sip013-transfer-many (transfers (list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal})) (asset <sip013-transferable-many>))
	(begin
		(try! (is-dao-or-extension))
		(as-contract (contract-call? asset transfer-many transfers))
	)
)

(define-public (sip013-transfer-many-memo (transfers (list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal, memo: (buff 34)})) (asset <sip013-transferable-many>))
	(begin
		(try! (is-dao-or-extension))
		(as-contract (contract-call? asset transfer-many-memo transfers))
	)
)

;; --- Iterator functions

(define-private (stx-transfer-many-iter (data {amount: uint, recipient: principal, memo: (optional (buff 34))}) (previous-result (response bool uint)))
	(begin
		(try! previous-result)
		(match (get memo data) to-print (print to-print) 0x)
		(stx-transfer? (get amount data) tx-sender (get recipient data))
	)
)

(define-private (sip009-transfer-many-iter (data {token-id: uint, recipient: principal}) (asset <sip009-transferable>))
	(begin
		(unwrap-panic (contract-call? asset transfer (get token-id data) tx-sender (get recipient data)))
		asset
	)
)

(define-private (sip010-transfer-many-iter (data {amount: uint, recipient: principal, memo: (optional (buff 34))}) (asset <sip010-transferable>))
	(begin
		(unwrap-panic (contract-call? asset transfer (get amount data) tx-sender (get recipient data) (get memo data)))
		asset
	)
)

;; --- Extension callback

(define-public (callback (sender principal) (memo (buff 34)))
	(ok true)
)

(define-public (claim-for-dao (market <prediction-market-trait>) (market-id uint) (token <ft-velar-token>))
  (begin
    (as-contract
      (contract-call? market claim-winnings market-id token)
    )
  )
)

Functions (14)

FunctionAccessArgs
is-dao-or-extensionpublic
stx-transferpublicamount: uint, recipient: principal, memo: (optional (buff 34
stx-transfer-manypublictransfers: (list 200 {amount: uint, recipient: principal, memo: (optional (buff 34
sip009-transferpublictoken-id: uint, recipient: principal, asset: <sip009-transferable>
sip009-transfer-manypublicdata: (list 200 {token-id: uint, recipient: principal}
sip010-transferpublicamount: uint, recipient: principal, memo: (optional (buff 34
sip010-transfer-manypublicdata: (list 200 {amount: uint, recipient: principal, memo: (optional (buff 34
sip013-transferpublictoken-id: uint, amount: uint, recipient: principal, memo: (optional (buff 34
sip013-transfer-manypublictransfers: (list 200 {token-id: uint, amount: uint, sender: principal, recipient: principal}
stx-transfer-many-iterprivatedata: {amount: uint, recipient: principal, memo: (optional (buff 34
sip009-transfer-many-iterprivatedata: {token-id: uint, recipient: principal}, asset: <sip009-transferable>
sip010-transfer-many-iterprivatedata: {amount: uint, recipient: principal, memo: (optional (buff 34
callbackpublicsender: principal, memo: (buff 34
claim-for-daopublicmarket: <prediction-market-trait>, market-id: uint, token: <ft-velar-token>