Escrow Contract

I have tried to implement a smart contract that allows to users to make a deal about a sale.
User A (buyer) deposit some stx or tokens in an escrow account, user B (seller) delivers something, both agree that the deal was as agreed and the money is transferred from the escrow account to the seller.

Here is an implementation for STX:

However, in clarity, there is no way to transfer STX tokens from a third party account or make a STX transaction in the name of an other account (tx-sender must be the sender of STX).

Therefore, I was trying to implement this using my own (fungible) token. (That works. It is possible to send my tokens from the escrow account to the seller. Now, the question is how this is useful for an escrow contract. If the escrow tokens are minted and transferred to e.g. the developer account, then the whole deal depends on whether the developer is willing to exchange the escrow tokens. Not a good solution business model wise.

Is there anything I am missing? Is there a better/real way to implement an escrow contract?


For use cases like this, you want to be able to send tokens to a contract principal. That allows the contract (not the developer) to spend the tokens. To do that, the contract needs to use the as-contract function, which executes a command with tx-sender set to the contract’s principal. For example:

;; a function that will send `amount` stx to the contract's principal
(define-public (send-to-contract (amount uint))
  (stx-transfer? tx-sender (as-contract tx-sender) amount))
;; a function that will send 1 stx from the contract to the sender
;;   of the calling transaction
(define-public (faucet)
  (let ((original-sender tx-sender))
     (as-contract (stx-transfer? tx-sender original-sender u1)))

@aaron Thank you for that. What is the contract principal exactly? Could you elaborate how this works?

Yep – the contract principal is an identifier unique to each contract that can “own” assets/tokens (exactly like a Stacks address). Unlike a normal Stacks address, a contract principal cannot sign and send a transaction, because the contract principal does not correspond to a private key/public key pair.

The contract principal itself is composed of two items:

  • the issuer address – this is the Stacks address of the sender of the contract’s contract-publish transaction.
  • the contract name – the name given to the contract

For example, if someone with STX address “SP139Q3N9RXCJCD1XVA4N5RYWQ5K9XQ0T9PKQ8EE5” published a contract called “faucet”, the contract identifier would be 'SP139Q3N9RXCJCD1XVA4N5RYWQ5K9XQ0T9PKQ8EE5.faucet, which you could use directly in the Clarity code (or use the shorthand form .faucet if that contract has the same issuer).

This section of SIP-002 talks a little bit more about principals in Clarity: SIP-002: Principals and Owner Verification.

1 Like