Skip to Content
Scalus Club is now open! Join us to get an early access to new features 🎉

Builtin Functions

Cardano Plutus provides built-in functions optimized for blockchain execution. Scalus exposes these functions through the Builtins object with familiar Scala syntax.

These builtin functions are automatically recognized by the Scalus compiler and compiled to their corresponding Plutus operations for efficient on-chain execution.

Integer Operations

Arithmetic and comparison operations on arbitrary-precision integers (BigInt).

import scalus.builtin.Builtins // Arithmetic val sum = Builtins.addInteger(BigInt(10), BigInt(20)) val diff = Builtins.subtractInteger(BigInt(100), BigInt(30)) val product = Builtins.multiplyInteger(BigInt(5), BigInt(7)) val quotient = Builtins.divideInteger(BigInt(20), BigInt(4)) // floor division val quot = Builtins.quotientInteger(BigInt(20), BigInt(4)) // truncated division val remainder = Builtins.remainderInteger(BigInt(17), BigInt(5)) val modulo = Builtins.modInteger(BigInt(17), BigInt(5)) // Comparison val eq = Builtins.equalsInteger(BigInt(42), BigInt(42)) val lt = Builtins.lessThanInteger(BigInt(3), BigInt(7)) val lte = Builtins.lessThanEqualsInteger(BigInt(5), BigInt(5)) // Or use operators val sumOp = BigInt(10) + BigInt(20) val eqOp = BigInt(42) == BigInt(42)

ByteString Operations

Operations on immutable byte arrays, organized by category.

Constructing

import scalus.builtin.{Builtins, ByteString} // Append two ByteStrings val concatenated = Builtins.appendByteString( ByteString.fromHex("dead"), ByteString.fromHex("beef") ) // Prepend a byte (0-255) val withPrefix = Builtins.consByteString(BigInt(0xFF), ByteString.fromHex("1234"))

Inspecting

// Length of ByteString val length = Builtins.lengthOfByteString(ByteString.fromHex("deadbeef")) // 4 // Get byte at index val byte = Builtins.indexByteString(ByteString.fromHex("deadbeef"), BigInt(0)) // 0xDE // Slice ByteString val slice = Builtins.sliceByteString(BigInt(1), BigInt(2), ByteString.fromHex("deadbeef")) // hex"adbe"

Comparing

// Equality val eq = Builtins.equalsByteString( ByteString.fromHex("deadbeef"), ByteString.fromHex("deadbeef") ) // true // Lexicographic comparison val lt = Builtins.lessThanByteString( ByteString.fromHex("1234"), ByteString.fromHex("5678") ) // true val lte = Builtins.lessThanEqualsByteString( ByteString.fromHex("1234"), ByteString.fromHex("1234") ) // true

Bitwise Operations

Perform bitwise operations on ByteStrings. The shouldPad parameter controls behavior when ByteStrings have different lengths.

// Bitwise AND val and = Builtins.andByteString(false, ByteString.fromHex("0FFF"), ByteString.fromHex("FF")) // hex"0F" val andPad = Builtins.andByteString(true, ByteString.fromHex("0FFF"), ByteString.fromHex("FF")) // hex"0FFF" // Bitwise OR val or = Builtins.orByteString(false, ByteString.fromHex("0FFF"), ByteString.fromHex("FF")) // hex"FF" // Bitwise XOR val xor = Builtins.xorByteString(false, ByteString.fromHex("0FFF"), ByteString.fromHex("FF")) // hex"F0" // Bitwise complement (NOT) val complement = Builtins.complementByteString(ByteString.fromHex("FF")) // hex"00"

Shifting and Rotating

// Read a bit at index val bit = Builtins.readBit(ByteString.fromHex("80"), BigInt(0)) // true (MSB is 1) // Write a bit at index val modified = Builtins.writeBits(ByteString.fromHex("00"), List((BigInt(0), true))) // hex"80" // Replicate a byte n times val repeated = Builtins.replicateByte(BigInt(4), BigInt(0xFF)) // hex"FFFFFFFF" // Shift bits left/right val shiftLeft = Builtins.shiftByteString(ByteString.fromHex("01"), BigInt(1)) // hex"02" val shiftRight = Builtins.shiftByteString(ByteString.fromHex("02"), BigInt(-1)) // hex"01" // Rotate bits val rotateLeft = Builtins.rotateByteString(ByteString.fromHex("0102"), BigInt(8)) // hex"0201"

Transforming

// Count set bits (population count) val popcount = Builtins.countSetBits(ByteString.fromHex("FF")) // 8 // Find first set bit index val firstSet = Builtins.findFirstSetBit(ByteString.fromHex("08")) // 3 // Convert to/from integer val toInt = Builtins.byteStringToInteger(true, ByteString.fromHex("1234")) // 4660 (big-endian) val fromInt = Builtins.integerToByteString(true, BigInt(2), BigInt(4660)) // hex"1234"

String Operations

UTF-8 string operations.

// Concatenate strings val greeting = Builtins.appendString("Hello, ", "Cardano!") // Equality val eq = Builtins.equalsString("test", "test") // Convert to/from UTF-8 ByteString val encoded = Builtins.encodeUtf8("Hello") val decoded = Builtins.decodeUtf8(encoded)

List Operations

Operations on immutable linked lists.

import scalus.builtin.{Builtins, BuiltinList} // Choose based on empty/non-empty val result = Builtins.chooseList(List(1, 2, 3), "empty", "not empty") // "not empty" // Construct list val list = Builtins.mkCons(BigInt(0), BuiltinList(1, 2, 3)) // Deconstruct list val head = Builtins.headList(list) // 0 val tail = Builtins.tailList(list) // [1, 2, 3] val isEmpty = Builtins.nullList(list) // false

Pair Operations

Operations on pairs (2-tuples).

import scalus.builtin.{Builtins, BuiltinPair} val pair = BuiltinPair(BigInt(42), ByteString.fromHex("deadbeef")) // Extract elements val first = Builtins.fstPair(pair) // 42 val second = Builtins.sndPair(pair) // hex"deadbeef"

Data Operations

Operations for Plutus’s universal Data type, used for serialization and interoperability.

Creating Data

import scalus.builtin.{Builtins, Data} // Create Data from primitives val intData = Builtins.iData(BigInt(42)) val bytesData = Builtins.bData(ByteString.fromHex("deadbeef")) val listData = Builtins.listData(BuiltinList(intData, bytesData)) val mapData = Builtins.mapData(BuiltinList(Builtins.mkPairData(intData, bytesData))) val constrData = Builtins.constrData(BigInt(0), BuiltinList(intData, bytesData))

Deconstructing Data

// Extract Data values val int = Builtins.unIData(intData) val bytes = Builtins.unBData(bytesData) val list = Builtins.unListData(listData) val map = Builtins.unMapData(mapData) val (tag, fields) = Builtins.unConstrData(constrData)

Data Operations

// Choose based on Data variant val result = Builtins.chooseData( someData, constrCase = "constructor", mapCase = "map", listCase = "list", iCase = "integer", bCase = "bytestring" ) // Compare Data values val eq = Builtins.equalsData(data1, data2) // Serialize Data to CBOR val serialized = Builtins.serialiseData(someData)

Monomorphic Constructors

// Create pairs and lists of Data val pairData = Builtins.mkPairData(intData, bytesData) val emptyList = Builtins.mkNilData() val emptyPairList = Builtins.mkNilPairData()

Cryptography

Hashing

// SHA-2 and SHA-3 hashing val sha2 = Builtins.sha2_256(ByteString.fromString("message")) val sha3 = Builtins.sha3_256(ByteString.fromString("message")) // BLAKE2b hashing (256-bit and 224-bit) val blake256 = Builtins.blake2b_256(ByteString.fromString("message")) val blake224 = Builtins.blake2b_224(ByteString.fromString("message")) // Keccak-256 val keccak = Builtins.keccak_256(ByteString.fromString("message")) // RIPEMD-160 val ripemd = Builtins.ripemd_160(ByteString.fromString("message"))

Digital Signatures

// Ed25519 signature verification val validEd = Builtins.verifyEd25519Signature(publicKey, message, signature) // ECDSA SECP256k1 signature verification val validEcdsa = Builtins.verifyEcdsaSecp256k1Signature(publicKey, message, signature) // Schnorr SECP256k1 signature verification val validSchnorr = Builtins.verifySchnorrSecp256k1Signature(publicKey, message, signature)

BLS12-381 Pairing Operations

Advanced cryptographic operations for zero-knowledge proofs and pairing-based cryptography.

import scalus.builtin.{BLS12_381_G1_Element, BLS12_381_G2_Element} // Group operations val g1Sum = Builtins.bls12_381_G1_add(g1Point1, g1Point2) val g1Neg = Builtins.bls12_381_G1_neg(g1Point1) val g1Scaled = Builtins.bls12_381_G1_scalarMul(scalar, g1Point1) val g2Sum = Builtins.bls12_381_G2_add(g2Point1, g2Point2) val g2Neg = Builtins.bls12_381_G2_neg(g2Point1) val g2Scaled = Builtins.bls12_381_G2_scalarMul(scalar, g2Point1) // Pairing operations val miller = Builtins.bls12_381_millerLoop(g1Point, g2Point) val mulMiller = Builtins.bls12_381_mulMlResult(mlResult1, mlResult2) val final = Builtins.bls12_381_finalVerify(mlResult1, mlResult2) // Hash to curve val hashToG1 = Builtins.bls12_381_G1_hashToGroup(message, dst) val hashToG2 = Builtins.bls12_381_G2_hashToGroup(message, dst) // Compression and serialization val compressed = Builtins.bls12_381_G1_compress(g1Point) val uncompressed = Builtins.bls12_381_G1_uncompress(compressedBytes)

Control Flow

// Conditional execution val result = Builtins.ifThenElse(condition, thenValue, elseValue) // Force evaluation after unit val forced = Builtins.chooseUnit()(computeValue)

Debugging

// Trace a message (printed during evaluation) val result = Builtins.trace("Debug message")(computeValue)

Usage Notes

  • All builtin functions are type-safe and validated at compile time
  • Most builtins have convenient operator syntax (e.g., +, ==, ++)
  • Builtin functions compile directly to Plutus opcodes for maximum efficiency
  • See the Builtins API documentation  for complete details
  • Refer to the Plutus specification  for formal semantics
Last updated on