Haskell Plutus : Lift, UnsafeLift, and safeLift
📚 Haskell Plutus : Lift
, UnsafeLift
, and safeLift
Lift
, UnsafeLift
, and safeLift
Table of Contents
🔍 Introduction to Lifting
🧱
Lift
Typeclass: The Bridge from Haskell to Plutus Core⚠️
UnsafeLift
: Risky but Flexible🛡️
safeLift
: Your Safety Net🧪 Example: Custom Type Lifting
🧠 Quiz Yourself
📘 Glossary of Terms
🧩 Summary and Best Practices
1. 🔍 Introduction to Lifting
In Plutus, lifting refers to the process of converting Haskell values into Plutus Core constants so they can be used inside on-chain scripts. This is crucial because:
Plutus Core (on-chain) has a limited set of primitive types.
Haskell (off-chain) has a much richer type system.
➡️ Lifting makes Haskell data available inside Plutus scripts.
2. 🧱 Lift
Typeclass: The Bridge from Haskell to Plutus Core
Lift
Typeclass: The Bridge from Haskell to Plutus CoreThe Lift
typeclass in Plutus defines how a Haskell value is converted (lifted) into a Plutus Core term.
📦 Module
PlutusTx.Lift
🧾 Class Definition
class Lift a where
lift :: a -> Q (TExp (CompiledCode a))
✅ Usage
You derive Lift
for your types so that they can be compiled into Plutus scripts:
{-# LANGUAGE TemplateHaskell #-}
import PlutusTx.Lift
data Color = Red | Blue | Green
PlutusTx.makeLift ''Color
This allows Color
to be used in on-chain logic.
3. ⚠️ UnsafeLift
: Risky but Flexible
UnsafeLift
: Risky but FlexibleThe UnsafeLift
typeclass is a more permissive lifting mechanism introduced in newer Plutus versions.
😬 Why “Unsafe”?
It doesn’t guarantee that the lifted representation will preserve semantics safely.
It’s used internally by
Lift
andsafeLift
, but shouldn’t be relied on directly unless you know what you're doing.
🧾 Class
class UnsafeLift a where
makeUnsafeLift :: a -> CompiledCode a
💡 Usually, you don’t use this directly.
4. 🛡️ safeLift
: Your Safety Net
safeLift
: Your Safety NetThe safeLift
function uses the UnsafeLift
instance but adds compile-time guarantees using Template Haskell.
✅ Safer Interface
safeLift :: UnsafeLift a => a -> Q (TExp (CompiledCode a))
This is the preferred way to lift Haskell values inside Template Haskell expressions.
💡 Example
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
import PlutusTx
import PlutusTx.Lift (safeLift)
import GHC.Generics (Generic)
data Token = Token { symbol :: BuiltinByteString, name :: BuiltinByteString }
deriving (Generic, ToData, FromData)
PlutusTx.makeLift ''Token
myLiftedToken :: Q (TExp (CompiledCode Token))
myLiftedToken = safeLift (Token "ADA" "Coin")
5. 🧪 Example: Custom Type Lifting
Let's walk through lifting a custom record type:
🧾 Type Definition
data User = User
{ userId :: Integer
, username :: BuiltinByteString
} deriving (Generic, ToData, FromData)
✅ Derive Lift
PlutusTx.makeLift ''User
🚀 Lift a Value
liftedUser :: Q (TExp (CompiledCode User))
liftedUser = safeLift (User 101 "cardanoFan")
This allows User
to be safely passed into on-chain logic.
6. 🧠 Quiz Yourself
✅ Which of the following is the safest way to lift a value?
A.
lift value
B.makeUnsafeLift value
C.safeLift value
D.compile value
Answer: ✅ C. safeLift value
7. 📘 Glossary of Terms
Lift
A typeclass allowing Haskell values to be embedded in Plutus Core
PlutusTx
Module containing TH-based tools for Plutus
Template Haskell (TH)
Meta-programming in Haskell to generate code at compile-time
CompiledCode
A wrapper type representing compiled Plutus Core
BuiltinByteString
Optimized byte strings for on-chain Plutus logic
Q
The Template Haskell monad used for generating code
TExp
A typed Template Haskell expression
UnsafeLift
An internal or low-level way to lift values without checks
safeLift
A safer way to lift using Template Haskell and UnsafeLift
8. 🧩 Summary and Best Practices
Use safeLift
for all Template Haskell-based lifting
Use UnsafeLift
unless you really know what you’re doing
Derive Lift
with makeLift
or makeLiftData
Manually implement Lift
unless needed
Keep lifted types small and serializable
Lift large Haskell types with complex dependencies
Use BuiltinByteString
, Integer
, etc. for compatibility
Use String
, Int
, or complex types directly
Last updated