Skip to content

Latest commit

 

History

History
270 lines (122 loc) · 24.8 KB

example-contracts.md

File metadata and controls

270 lines (122 loc) · 24.8 KB

Marlowe Contracts

Simple Examples

This simple contract takes as deposit, waits for a notification, makes a payment, waits for another notification, and then closes the contract.

This zero-coupon bond has one party borrow and another pay back with interest. It uses role tokens.

This escrow contract is for the purchase of an item at a price. The buyer may complain that there is a problem, asking for a refund. If the seller disputes that complaint, then a mediator decides. There are four potential outcomes:

In this example execution of a contract for differences, the party and counterparty each make a deposit to cover margin, an oracle reports prices, and the price change is settled among the parties.

This swap contract swaps native tokens between two parties.

This option contract transfers a token if the counter-party exercises the option.

ACTUS Financial Contracts

ACTUS (Algorithmic Contract Types Unified Standards) covers a large number of common financial contract. Marlowe implements the suite of ACTUS contracts in a Haskell package, marlowe-actus that will generate the Marlowe code for an ACTUS contract.

Taxonomy of ACTUS contracts

This zero-coupon bond has one party borrow and another pay back with interest. It uses role tokens.

Examples in Marlowe Playground

The following contract examples are available in Marlowe Playground in Haskell, TypeScript, Marlowe, and Blockly formats. They can be exported as JSON from the Playground and run using the marlowe-cli or marlowe tools.

Escrow

Regulates a money exchange between a "Buyer" and a "Seller". If there is a disagreement, an "Mediator" will decide whether the money is refunded or paid to the "Seller".

Escrow With Collateral

Regulates a money exchange between a "Buyer" and a "Seller" using a collateral from both parties to incentivize collaboration. If there is a disagreement the collateral is burned.

Zero Coupon Bond

A simple loan. The investor pays the issuer the discounted price at the start, and is repaid the full (notional) price at the end.

Coupon Bond Guaranteed

Debt agreement between an "Lender" and an "Borrower". "Lender" will advance the "Principal" amount at the beginning of the contract, and the "Borrower" will pay back "Interest installment" every 30 slots and the "Principal" amount by the end of 3 installments. The debt is backed by a collateral provided by the "Guarantor" which will be refunded as long as the "Borrower" pays back on time.

Swap

Takes Ada from one party and dollar tokens from another party, and it swaps them atomically.

Contract For Differences

"Party" and "Counterparty" deposit 100 Ada and after 60 slots is redistributed depending on the change in a given trade price reported by "Oracle". If the price increases, the difference goes to "Counterparty"; if it decreases, the difference goes to "Party", up to a maximum of 100 Ada.

Contract For Differences with Oracle

"Party" and "Counterparty" deposit 100 Ada and after 60 slots these assets are redistributed depending on the change in price of 100 Ada worth of dollars between the start and the end of the contract. If the price increases, the difference goes to "Counterparty"; if it decreases, the difference goes to "Party", up to a maximum of 100 Ada.

Generating Marlowe from Haskell

The marlowe-contracts Haskell package contains the generators for the following types of Marlowe contracts:

Marlowe Runtime

Marlowe Runtime is the new backend for running Marlowe contracts. Here are examples of running contracts with Marlowe Runtime:

Cookbook of Miscellaneous Contracts

In this example, Christopher Marlowe sells the Swan Theatre to Francis Beaumont for 2250 DjedUSD. The Swan Theatre is represented as an NFT.

This contract demonstrates the use of Cardano address in a Marlowe contract, where formerly public-key hashes were used to identify non-role parties in a contract. The contract itself is a simple airdrop of tokens to three recipients, where the airdrop must occur after a specified time (via a Notify containing a TimeIntervalStart condition).

This revenue-based loan involves variable payments that are computed as a fixed percentage of the borrower's revenue during each period of the loan. The payments continue until principal plus interest is paid off. There is no penalty for missing a payment. An oracle reports the borrower's revenue each period, prior to the borrower depositing that amount. The contract was both simulated and run on the Cardano blockchain: that involved 8 transactions.

This video shows the contract being run in Marlowe Playground.

This English Auction with five bidders and three rounds of bidding demonstrates the use of merkleization for Marlowe contracts. Because bidders may bid in any order and may bid more than once, unless they are disqualified by an illegal bid or timeout, the contract involves a combinatorial explosion of possibilities. Without merkleization, the contract JSON file is 990MB in size and contains 940k Case statements, but after merkleization the JSON file is 9.8MB and it contains just 1150 merkleized Case statements. The contract was both simulated and run on the Cardano blockchain: that involved 18 transactions.

This collective-loan contract lets lenders deposit currency such as DjedUSD in exchange for liquidity tokens, and then lets borrowers draw funds from the contract as loans. After the borrowers pay back their borrowings with interest to the collective loan, the lenders then redeem their liquidity tokens for DjedUSD that includes profit from the lending. A central administrator manages approvals. The Marlowe contract for this collective loan is scalable to an arbitrarily large number of lenders or borrowers, so long as the trusted central administrator is relied upon to disperse role tokens on a just-in-time basis. (Less centralized versions may be feasible, but they would be more rigid in terms of sequence of participation of the lenders and borrowers.) The contract was both simulated and run on the Cardano blockchain: that involved 3 lenders, 5 borrowers, and ~60 transactions.

See also this video that walks through this example in Marlowe Playground and on the Marlowe testnet.

This collective-loan contract lets lenders deposit currency such as DjedUSD in exchange for liquidity tokens, and then lets borrowers draw funds from the contract as loans. After the borrowers pay back their borrowings with interest to the collective loan, the lenders then redeem their liquidity tokens for DjedUSD that includes profit from the lending. A central administrator manages approvals. The Marlowe contract for this collective loan is scalable to an arbitrarily large number of lenders or borrowers, so long as the trusted central administrator is relied upon to disperse role tokens on a just-in-time basis. (Less centralized versions may be feasible, but they would be more rigid in terms of sequence of participation of the lenders and borrowers.) The contract was both simulated and run on the Cardano blockchain: that involved 30 lenders, 70 borrowers, and ~530 transactions.

This collective loan includes multiple investors and multiple borrowers, where the pool is supervised by an administrator and where a stabilization fund guarantees returns to investors, subject to a cap on losses.

Although this contract is simulatable without difficulty, this contract fails to execute on both the Preview testnet (due to its exceed the transaction-size limit) and the Pioneers testnet (due its execution memory and steps, even though this network has generously larger resources limits). (See Step 5 below for more details.) See stabilized-collective-loan-success.ipynb for an example of how including extra Notifys works around resource limits.

This collective loan includes multiple investors and multiple borrowers, where the pool is supervised by an administrator and where a stabilization fund guarantees returns to investors, subject to a cap on losses. Although this contract is simulatable without difficulty, it would fail on a network like preview or mainnet due to its exceed the execution-memory limit if it didn't include extra Notify terms to split steps into small transactions. Also note that this contract is a proof of principle and that the mathematics underlying it requires review and adjustment. See stabilized-collective-loan-failure.ipynb for an example of how not including these extra Notifys causes transactions to fail.

This Marlowe contract demonstrates how to store private data on the public blockchain in a Marlowe contract. It uses the fact that it is difficult to factor the product of two prime numbers.

We introduce new variants of marlowe-cli run execute and marlowe-cli run withdraw that automatically handle the UTxOs management, coin selection, and balancing, so that one doesn't need to specify --tx-in and --tx-out for Marlowe transactions.

We introduce new variants of marlowe-cli run execute and marlowe-cli run withdraw that automatically handle the UTxOs management, coin selection, and balancing, so that one doesn't need to specify --tx-in and --tx-out for Marlowe transactions.

This notebook demonstrates submitting Marlowe transactions in the Babbage Era using the low-level functions of marlowe-cli to create the Marlowe's Plutus script and the datums and redeemers needed when running Marlowe transactions. It uses cardano-cli to build, sign, and submit the transactions.

This example shows how to use the marlowe-cli and cardano-cli tools to submit Marlowe transactions that involve reference scripts. The marlowe-cli tool is used to generate the script, datum, and redeemers, while the cardano-cli tool is used to submit transactions and query the blockchain. Using a reference script significantly reduces the cost of a Marlowe transaction.

The first Plutus V2 script ever run on mainnet was this simple token-drop Marlowe contract.

This transcript documents the first-ever use of a reference script on mainnet. The scenario is that John Fletcher trades 300 Globe tokens with Thomas Kyd for 500 Swan tokens.

This example demonstrates the use of marlowe-cli with Plutus V2 reference scripts for the two Marlowe validators on mainnet. It is a three-party contract for a guaranteed loan, where a guarantor deposits principal plus interest before a lender makes the loan to the borrower. As the borrower pays principal and/or interest, the guarantor receives the relevant part of their guarantee back while the lender receives the repayment. The total fee (Plutus and non-Plutus) paid in this example is approximately 10 Ada.

We present a novel synergy between the Cardano Beam Dapp and the Marlowe Dapp, where Cardano Beam is used to geolocate the role tokens needed for authorization of Marlowe transactions. This enables use cases such as geocaching, scavenger hunts, or token drops that are linked to Marlowe contracts: this melds the geolocation capabilities of Cardano Beam with the contract-logic capabilities of Marlowe.

A video that shows this example being run is available here.

Solutions to Hackathon Challenges

English auctions (difficult)

In live terms, English auctions are where bids are announced by the bidders and winners pay what they bid to receive the object. The common operational method of the format is that it is an ascending bid auction in which bids are open for all to see. The winner is the highest bidder and the price is the highest bid.

Solution: Haskell, Marlowe, core JSON extended JSON, TypeScript.

Dutch auctions (difficult)

Dutch auctions are the reverse of English auctions whereby the price begins high and is systematically lowered until a buyer accepts the price.

Solution: Haskell, Marlowe, core JSON, extended JSON, TypeScript.

First-price open-bid (easy)

First-price open-bid auctions are when a single bid is made by all bidding parties and the single highest bidder wins, and pays what they bid. This contract is not realistic because it can easily be gamed by waiting to bid last.

Solution: Haskell, Marlowe, core JSON, extended JSON, TypeScript.

A very difficult variant of this in Marlowe is the first-price sealed-bid auction, where participants commit their bids before any of them reveal their bids.

Second-price open-bid (intermediate)

Second-price open-bid auctions are when a single bid is made by all bidding parties and the single highest bidder wins, and pays what the second-highest bidder bid. This contract is not realistic because it can easily be gamed through collusion.

Solution: Haskell, Marlowe, core JSON, extended JSON, TypeScript.

A very difficult variant of this in Marlowe is the Vickrey second-price sealed-bid auction, where participants commit their bids before any of them reveal their bids.

Reverse auction (intermediate)

Reverse auctions are where the roles of buyer and seller are reversed. Multiple sellers compete to obtain the buyer's business and prices typically decrease over time as new offers are made.

Solution: Haskell, Marlowe, core JSON, extended JSON, TypeScript.

Bidding fee auction (difficult)

A bidding fee auction (also known as a penny auction) requires customers to pay the auction owner for bids, which they can increment an auction price one unit of currency at a time. On English auctions for example, the price goes up in 1 pence (0.01 GBP) increments.

Solution: Haskell, Marlowe, core JSON, extended JSON, TypeScript.

Stable coin (easy)

The Marlowe analog of a stable coin is a contract that pays the party the value in a base currency (say, USD) of the ADA that they initially deposit in a contract. A counterparty deposits collateral, according to a specified reserve ratio (i.e., the ratio of the total ADA in the contract to the ADA deposited by the party), to cover price changes in ADA. When the party withdraws their funds, they receive the ADA corresponding to the base-currency value initially deposited, and the counterparty receives the remaining ADA.

Solution: Haskell, Marlowe, core JSON, extended JSON, TypeScript.