Last active
November 14, 2025 03:00
-
-
Save kopcho/1f7ed9f270f8fb94516049a9a7fb06b6 to your computer and use it in GitHub Desktop.
Arbiter-Controlled Digital Asset Escrow (CAD019/CAD029 Compliant)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ; vim: syntax=clojure | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;; ACTOR: Arbiter-Controlled Digital Asset Escrow (CAD019/CAD029 Compliant) | |
| ;; | |
| ;; Purpose: A trustless escrow contract to securely hold any CAD019/CAD029 | |
| ;; Digital Asset (Tokens, NFTs) until a designated ARBITER authorizes | |
| ;; release to the SELLER or refund to the BUYER. | |
| ;; | |
| ;; Mechanics: Uses the Asset's 'offer/accept' mechanism to lock funds and the | |
| ;; Asset's 'direct-transfer' to release funds. | |
| ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
| ;; Persistent State Definitions | |
| (def BUYER nil) ; Address of the depositor/Buyer | |
| (def SELLER nil) ; Address of the asset recipient/Seller | |
| (def ARBITER nil) ; Address of the authorization authority | |
| (def ASSET_ADDRESS nil) ; Address of the CAD019 Asset Actor (e.g., #140 EMONY) | |
| (def ASSET_AMOUNT 0) ; The quantity of the asset (1 for an NFT, >1 for a token) | |
| (def STATUS :uninitialized) ; States: :uninitialized, :awaiting-deposit, :funded, :released, :refunded | |
| (defn ^:callable init-escrow | |
| ^{:doc "Initializes terms, setting all parties, the asset address, and the amount."} | |
| [seller-address arbiter-address asset-address asset-amount] | |
| ;; Corrected to use core type predicates for robustness | |
| (assert (and (address? seller-address) (address? arbiter-address) (address? asset-address) (long? asset-amount)) "Invalid arguments") | |
| ;; FIX: Replaced (pos? asset-amount) with robust (> asset-amount 0) | |
| (assert (> asset-amount 0) "Asset amount must be positive") | |
| (assert (= STATUS :uninitialized) "Escrow already initialized") | |
| ;; Set immutable terms | |
| (def BUYER *caller*) ; Caller is the depositor/Buyer | |
| (def SELLER seller-address) | |
| (def ARBITER arbiter-address) | |
| (def ASSET_ADDRESS asset-address) | |
| (def ASSET_AMOUNT asset-amount) | |
| (def STATUS :awaiting-deposit) | |
| (log :ESCROW-INIT *address* BUYER SELLER ARBITER ASSET_ADDRESS ASSET_AMOUNT) | |
| :initialized) | |
| (defn ^:callable accept-deposit | |
| ^{:doc "Accepts the asset that the BUYER has *offered* to this Actor's address, locking it."} | |
| [] | |
| ;; 1. Authorization and State Check | |
| (assert (= *caller* BUYER) "Only the defined buyer can finalize the deposit") | |
| (assert (= STATUS :awaiting-deposit) "Must be awaiting deposit") | |
| ;; 2. Crucial Step: Call the Asset Actor to ACCEPT the offer | |
| ;; FIXES: | |
| ;; 1) Removed the faulty (try ... catch err ...) block | |
| ;; 2) Corrected the call arity to pass the required BUYER address as the sender argument | |
| (call ASSET_ADDRESS | |
| (accept BUYER ASSET_AMOUNT)) ; Transfers asset ownership to the Escrow Actor | |
| ;; 3. Finalize | |
| (def STATUS :funded) | |
| (log :ESCROW-DEPOSITED *address* ASSET_ADDRESS ASSET_AMOUNT) | |
| :deposit-accepted) | |
| (defn ^:callable release-to-seller | |
| ^{:doc "Transfers the locked asset to the SELLER upon fulfillment. Requires ARBITER authorization."} | |
| [] | |
| ;; 1. Authorization and State Check | |
| (when-not (= *caller* ARBITER) (fail :TRUST "Unauthorized: Only the Arbiter can release funds")) | |
| (when-not (= STATUS :funded) (fail :STATE "Escrow is not funded")) | |
| ;; 2. Crucial Step: Call the Asset Actor to DIRECTLY TRANSFER the asset | |
| ;; FIXES: | |
| ;; 1) Replaced undeclared symbol (-direct-transfer) with callable symbol (direct-transfer) | |
| ;; 2) Added required third argument (nil) to resolve the final :ARITY error | |
| (call ASSET_ADDRESS | |
| (direct-transfer SELLER ASSET_AMOUNT nil)) ; Escrow Actor instructs the Asset Actor to transfer | |
| ;; 3. Finalize | |
| (def STATUS :released) | |
| (log :ESCROW-RELEASED SELLER ASSET_AMOUNT) | |
| :released) | |
| (defn ^:callable refund-to-buyer | |
| ^{:doc "Transfers the locked asset back to the BUYER if the transaction fails. Requires ARBITER authorization."} | |
| [] | |
| ;; 1. Authorization and State Check | |
| (when-not (= *caller* ARBITER) (fail :TRUST "Unauthorized: Only the Arbiter can refund funds")) | |
| (when-not (= STATUS :funded) (fail :STATE "Escrow is not funded")) | |
| ;; 2. Crucial Step: Call the Asset Actor to DIRECTLY TRANSFER the asset back | |
| ;; FIXES: | |
| ;; 1) Replaced undeclared symbol (-direct-transfer) with callable symbol (direct-transfer) | |
| ;; 2) Added required third argument (nil) to resolve the final :ARITY error | |
| (call ASSET_ADDRESS | |
| (direct-transfer BUYER ASSET_AMOUNT nil)) | |
| ;; 3. Finalize | |
| (def STATUS :refunded) | |
| (log :ESCROW-REFUNDED BUYER ASSET_AMOUNT) | |
| :refunded) | |
| ;; Export the public interface | |
| { | |
| :init-escrow init-escrow | |
| :accept-deposit accept-deposit | |
| :release-to-seller release-to-seller | |
| :refund-to-buyer refund-to-buyer | |
| } |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Removed faulty try/catch, and corrected arguments to (accept BUYER ASSET_AMOUNT)