Blog > 2025 > February > Plutus Tx gets a makeover: meet Plinth

Plutus Tx gets a makeover: meet Plinth

Plutus Tx is now Plinth, with new capabilities. The renaming clarifies the distinction between high-level smart contract development and the Plutus Core execution layer on Cardano

20 February 2025 Ziyang Liu 7 mins read

Plutus Tx gets a makeover: meet Plinth

In the evolving landscape of Cardano’s smart contract capabilities, clarity and precision are key. The recent rebranding of Plutus Tx to Plinth represents a step in this direction. This change, approved during the recent Plutus working group meeting, aims to clarify the distinction between Plutus Tx and Plutus Core, addressing a common source of confusion in the ecosystem.

What is Plinth?

Plinth, formerly known as Plutus Tx, is a high-level language for writing smart contracts on Cardano. It allows developers to write their contracts in a subset of Haskell, which then gets compiled into Untyped Plutus Core (UPLC) – the language that Cardano nodes use to execute scripts. This makes Cardano approachable for developers familiar with Haskell, as well as those interested in learning it.

Why was Plutus Tx renamed to Plinth?

The renaming aims to eliminate confusion around the term ‘Plutus’, which has been ambiguously used to refer to both Plutus Tx and Plutus Core. This often led to misunderstandings – particularly the incorrect assumption that Cardano’s on-chain execution language is Haskell-based.

In reality, Cardano executes smart contracts using UPLC, a low-level language based on lambda calculus. Plinth is one of several high-level languages that compile to UPLC, alongside Aiken, OpShin, plu-ts, Plutarch, and Scalus. For more details, see an overview of languages compiling to UPLC in the Plinth user guide.

To avoid ambiguity, ‘Plutus’ should either be avoided on its own or used exclusively to refer to Untyped Plutus Core.

What’s new in Plinth beyond its name change?

Plinth’s original appeal lies in its simplicity – it is a subset of Haskell rather than a standalone language or embedded domain-specific language (DSL). This makes it accessible even to those without prior Haskell experience, especially with modern AI tools, which can effectively generate and explain simple Haskell code. Additionally, Plinth is fully compatible with existing Haskell tooling and frameworks, including Cabal, GHCi, the language server, and Template Haskell for metaprogramming.

However, efficiency has been a key concern. Since transaction fees depend on script execution costs and sizes – and Cardano imposes strict limits on both – optimization is essential. To address this, Plinth has recently gained several enhancements to improve script efficiency. Below is a brief overview.

Data-encoded ScriptContext

Previously, Plinth introduced a third way to encode data types, alongside Scott encoding and sums-of-products (SOP): encoding data types using Data, a built-in type in Plutus Core. In most alternatives to Plinth, this is the only available encoding method, as Scott and SOP encodings are not supported. More recently, a new Plutus ledger API based on Data encoding has been introduced. This API extends support to ScriptContext, Map, List, and various other types.

Data encoding comes with trade-offs. It is generally slower to process – except for equality checks, which benefit from the equalsData primitive – and less expressive, as Data objects cannot contain functions. However, its key advantage is efficiency in script execution: since scripts receive arguments (notably ScriptContext) as Data, and the output datum is also a Data object, using Data directly eliminates the need for conversions between Data and Scott/SOP encodings.

The conventional approach in Plinth has been to use unsafeFromBuiltinData to convert all script arguments to Scott/SOP encoding. This has led to concerns that even a trivial ‘always succeed’ script in Plinth is significantly more expensive than some alternatives. While avoiding this overhead by working directly with Data has always been possible, doing so required low-level, type-unsafe code.

Now, Plinth allows developers to choose the most efficient encoding scheme for each data type in their scripts:

  • To use the Data-encoded ScriptContext, import from PlutusLedgerApi.Data.V3 (or V1/V2) instead of PlutusLedgerApi.V3 (or V1/V2)
  • To apply Data encoding to custom types, wrap the definition in asData.

The process of constructing and inspecting these data types remains largely unchanged. For more details, see Optimizing scripts with asData in the Plinth user guide.

More inlining controls

Inlining involves a trade-off between script cost and size. More inlining reduces script execution costs but may increase script size – though inlining can also enable further optimizations, mitigating size growth. Traditionally, the Plinth compiler has taken a conservative approach, prioritizing script size constraints. However, many users prefer faster execution, as lower script costs can reduce transaction fees, particularly with reference scripts.

To provide more control over inlining, Plinth now includes the following features:

  • inline-fix compiler flag – instructs the compiler to inline all fixed-point combinators, which are inserted automatically when compiling recursive bindings. Benchmarking indicates that enabling this flag reduces script costs, with only a mild increase in script size when applicable. As a result, inline-fix is enabled by default.
  • PlutusTx.Optimize.Inline.inline function – instructs the Plinth compiler to inline a binding at a specific callsite, regardless of size, as long as the binding is not recursive. This function serves as Plinth’s equivalent of GHC.Magic.inline. To inline a binding at all callsites, use the INLINE pragma instead.

Other compiler flags that impact script costs include inline-constants and preserve-logging. For a full list of flags, see Plinth compiler options in the user guide.

Recursion unrolling

Beyond inlining, another approach to balancing script cost and size is recursion unrolling, similar to loop unrolling in imperative languages. While this optimization could be handled by the compiler in the future, Plinth currently provides utilities for recursion unrolling at the language level using Template Haskell.

Specifically, the PlutusTx.Optimize.SpaceTime module introduces two functions:

  • peel – removes a specified number of recursion layers
  • unroll – repeatedly peels a set number of layers until the recursion is fully unrolled, mimicking traditional loop unrolling.

As an example, one can use peel to peel off three layers of the length function:

lengthPeeled :: [Integer] -> Integer
lengthPeeled =
  $$( peel 3 $ \self ->
        [||
        \case
          [] -> 0
          _ : xs -> 1 + $$self xs
        ||]
    )

This approach requires Template Haskell, which can be a challenging concept in Haskell. However, the usage here is relatively straightforward.

There are plans to introduce recursion unrolling directly in the compiler, allowing developers to write standard recursive functions – such as length – without additional transformations.

That said, understanding this technique can be valuable. If a similar optimization is needed, developers can implement it themselves using peel and unroll, rather than waiting for compiler support.

What's next for Plinth?

High Assurance: automated smart contract verification

The Plutus team is developing an automated formal verification tool for Cardano smart contracts. The tool ensures correctness and security by utilizing SMT solving and the Lean theorem prover. It introduces an annotation language that allows developers to formally specify contract properties in surface languages, including Plinth.

The expressive power of the annotation language will enable users to describe both global properties related to the blockchain state and transaction-related or temporal properties. This capability will allow the formal verification of individual smart contracts, as well as entire DApp protocols.

Certified compilation

The team is working on enhancing the Plinth compiler with a translation certification framework formalized in Agda. When compiling a Plinth program, the compiler generates translation certificates – Agda proof objects – corresponding to the transformations applied to the code. This provides additional assurance that the compiler has accurately translated the Plinth source code to UPLC.

The final word

The rebranding of Plutus Tx to Plinth is more than just a name change. It is a move towards greater clarity on the languages available to developers across the Cardano ecosystem. As Cardano grows, tools like Plinth will play a vital role in enabling developers to build sophisticated, high-assurance applications on the blockchain.

This blog post has been written in collaboration with Lars Brünjes and Olga Hryniuk. We also thank Philip DiSarro for the valuable perspectives he shared.