5

Context

I'm creating scripts with hardcoded parameters in my smartcontract and I would like to reduce footprint of them to reduce transaction fees. Right now i'm doing so using parameterized smartcontracts. I can't provide source but I read or heard somewhere that using parameterized smartcontracts use up a lot of ExMemory. When building plutus scripts i'm using evaluateScriptCounting which after compilation shows me ExCPU and ExMemory of my script. So far I have found the only way to hardcode parameters without using parameterized smartcontracts with BuiltinByteStrings is doing something like this:

{-# INLINABLE flattenBuiltinByteString #-}
flattenBuiltinByteString :: [BuiltinByteString] -> BuiltinByteString
flattenBuiltinByteString [] = emptyByteString 
flattenBuiltinByteString (x:xs) = appendByteString x (flattenBuiltinByteString xs)

{-# INLINABLE getPkh #-}
getPkh :: PubKeyHash
getPkh = PubKeyHash { getPubKeyHash = flattenBuiltinByteString [ consByteString x emptyByteString |x <- [128,164,244,91,86,184,141,17,57,218,35,188,76,60,117,236,109,50,148,60,8,127,37,11,134,25,60,167]]}

I was expecting that this way I would get lower ExCPU and ExMemory units. But I did some tests and to my surprise my smartcontract without parameterized parameters was bigger!

Tests

  1. ExCPU -> 8366313, ExMemory -> 28200. Plain always succeeds.
  2. ExCPU -> 8366313, ExMemory -> 28200. BuiltinByteString, no checks, no datum.
  3. ExCPU -> 9080865, ExMemory -> 30600. Parameterized no checks, no datum.
  4. ExCPU -> 9438141, ExMemory -> 31800. Parameterized no checks, added typed datum with 4 fields.
  5. ExCPU -> 10152693, ExMemory -> 34200. Parameterized 4 checks against typed datum.
  6. ExCPU -> 11135202, ExMemory -> 37500. BuiltinByteString 4 checks against typed datum.

Questions

  1. My flattenBuiltinByteString is doing the flattening foldr style which is ineffective and I suppose is why i'm having such big jump in ExMemory units. I was looking for foldl' in Plutus library but couldn't find anything. Does Plutus have something simillar to seq so that I could make my own foldl' implementation?
  2. Are there other more effective ways to flatten BuiltinByteString list on-chain?
  3. What over tricks I could do besides using BuiltinData types instead of my own custom typed data types to optimize my smartcontracts?
  4. Should I even be bothering with optimizations like this, whats the upper ExCPU and ExMemory limit?

2 Answers 2

1

I am building a dApp myself and I am running into similar issues related to hitting the current mainnet's maxTxExUnits upper boundaries of exUnitsMem and exUnitsSteps.

In regards to question 4:

You can find the current upper limits by querying your cardano node for protocol parameters like so:

cardano-cli query protocol-parameters $MAGIC --out-file protocol-parameters.json

The limits can be found under: maxTxExecutionUnits

I resolved some of my issues related to exceeding the ExMemory upper limit by:

  • simplifying/ optimizing the contract logic
  • removing traceIfFalse statements or at least decreasing long log message string down to error codes
  • using Bang Pattern in let-bindings
  • avoid exhaustive case patterns and instead rely on Plutus' throwing an error for a missing pattern match

There are many more resources you can read below for further possible code improvements to optimize your script.

Sources:

1
  • The biggest decrease in mem usage I was able to achieve is by pattern matching against function inputs - especially when it comes to ScriptContext. Try to always pattern match unless you really need every field inside a given type. Good examples for that are TxOut, Maybe types and any of your datums
    – Will
    Commented Aug 3, 2022 at 6:14
1

Mlabs created excelent tool to quickly check and analyse size of smartcontracts. Github repo is here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.