-- SPDX-FileCopyrightText: 2021 Oxhead Alpha
-- SPDX-License-Identifier: LicenseRef-MIT-OA

-- TODO [#606]: reconsider the implementation

-- | Functions to originate large smart contracts via @octez-client@ and node RPC.
--
-- This is based on a workaround leveraging the lack of gas cost limits on
-- internal transactions produced by @CREATE_CONTRACT@.
--
-- So, in brief, we cannot directly originate a contract that's too large, but
-- we can originate a small "originator" contract, progressively load a packed
-- lambda into it in chunks and finally unpack and execute it, which will
-- run the actual large contract origination.
module Morley.Client.Action.Origination.Large
  ( LargeOriginationData (..)
  , SomeLargeContractOriginator (..)
  , mkLargeOriginationData
  , mkSomeLargeContractOriginator

    -- * Originator contract
  , LargeOriginatorParam
  , LargeOriginatorStore
  , largeContractOriginator

    -- * Origination lambda
  , divideValueInChunks
  , mkOriginationLambda

    -- * Utilities
  , mkLargeOriginatorStore
  , mkLargeOriginatorData
  , mkLargeOriginatorTransactions
  , retrieveLargeContracts
  ) where

import Prelude hiding (concat, drop, swap)

import Data.ByteString.Lazy qualified as LBS

import Lorentz hiding (bytes)
import Morley.Client.Action.Common
import Morley.Client.RPC.Class
import Morley.Client.RPC.Error
import Morley.Client.RPC.Getters (getContractStorage)
import Morley.Client.TezosClient
import Morley.Micheline (fromExpression)
import Morley.Michelson.Interpret.Pack (packValue)
import Morley.Michelson.Parser (notes)
import Morley.Michelson.Typed qualified as T
import Morley.Michelson.Typed.Instr
import Morley.Michelson.Typed.Scope
import Morley.Michelson.Typed.Util (PushableStorageSplit(..), splitPushableStorage)
import Morley.Michelson.Typed.Value
import Morley.Michelson.Untyped.Annotation (annQ, noAnn)
import Morley.Tezos.Address
import Morley.Tezos.Address.Alias
import Morley.Util.Constrained

-- | Just a utility type to hold 'SomeLargeContractOriginator' and its large
-- contract 'OriginationData'.
data LargeOriginationData = LargeOriginationData
  { LargeOriginationData -> SomeLargeContractOriginator
largeOriginator :: SomeLargeContractOriginator
  , LargeOriginationData -> OriginationData
largeContractData :: OriginationData
  }

-- | Contains the 'Value heavy' with all the large contract @big_map@s
-- and @ticket@s, the 'largeContractOriginator' for it as well as the lambda
-- to use there.
data SomeLargeContractOriginator where
  SomeLargeContractOriginator
    :: forall heavy. StorageScope heavy
    => Value heavy
    -> T.Contract LargeOriginatorParam (LargeOriginatorStore heavy)
    -> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
    -> SomeLargeContractOriginator

mkLargeOriginationData :: OriginationData -> LargeOriginationData
mkLargeOriginationData :: OriginationData -> LargeOriginationData
mkLargeOriginationData largeContractData :: OriginationData
largeContractData@OriginationData{Maybe Mutez
Maybe KeyHash
Mutez
ContractAlias
Value st
Contract cp st
AliasBehavior
odAliasBehavior :: AliasBehavior
odName :: ContractAlias
odBalance :: Mutez
odContract :: Contract cp st
odStorage :: Value st
odDelegate :: Maybe KeyHash
odMbFee :: Maybe Mutez
odAliasBehavior :: OriginationData -> AliasBehavior
odName :: OriginationData -> ContractAlias
odBalance :: OriginationData -> Mutez
odContract :: ()
odStorage :: ()
odDelegate :: OriginationData -> Maybe KeyHash
odMbFee :: OriginationData -> Maybe Mutez
..} = LargeOriginationData{OriginationData
SomeLargeContractOriginator
largeOriginator :: SomeLargeContractOriginator
largeContractData :: OriginationData
largeContractData :: OriginationData
largeOriginator :: SomeLargeContractOriginator
..}
  where
    largeOriginator :: SomeLargeContractOriginator
largeOriginator = Value st -> Contract cp st -> Mutez -> SomeLargeContractOriginator
forall (param :: T) (store :: T).
(ParameterScope param, StorageScope store) =>
Value store
-> Contract param store -> Mutez -> SomeLargeContractOriginator
mkSomeLargeContractOriginator Value st
odStorage Contract cp st
odContract Mutez
odBalance

mkSomeLargeContractOriginator
  :: (ParameterScope param, StorageScope store)
  => Value store -- ^ initial storage of the large contract
  -> T.Contract param store -- ^ large contract
  -> Mutez -- ^ balance to tranfer during contract creation
  -> SomeLargeContractOriginator
mkSomeLargeContractOriginator :: forall (param :: T) (store :: T).
(ParameterScope param, StorageScope store) =>
Value store
-> Contract param store -> Mutez -> SomeLargeContractOriginator
mkSomeLargeContractOriginator Value store
store Contract param store
largeContract Mutez
xtzs =
  case Value store -> PushableStorageSplit '[] store
forall (t :: T) (s :: [T]).
StorageScope t =>
Value t -> PushableStorageSplit s t
splitPushableStorage Value store
store of
    ConstantStorage Value store
val ->
      let origContract :: Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
origContract = Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
forall (heavy :: T).
StorageScope heavy =>
Contract LargeOriginatorParam (LargeOriginatorStore heavy)
largeContractOriginator
          origLambda :: Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
origLambda = Instr '[ 'TUnit] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
forall (param :: T) (store :: T) (heavy :: T).
(ParameterScope param, StorageScope store, StorageScope heavy) =>
Instr '[heavy] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
mkOriginationLambda (Instr '[ 'TUnit] '[]
forall (a :: T) (out :: [T]). Instr (a : out) out
DROP Instr '[ 'TUnit] '[]
-> Instr '[] '[store] -> Instr '[ 'TUnit] '[store]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Value store -> Instr '[] '[store]
forall {inp :: [T]} {out :: [T]} (t :: T) (s :: [T]).
(inp ~ s, out ~ (t : s), ConstantScope t) =>
Value' Instr t -> Instr inp out
PUSH Value store
val) Contract param store
largeContract Mutez
xtzs
      in Value 'TUnit
-> Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
-> Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
-> SomeLargeContractOriginator
forall (heavy :: T).
StorageScope heavy =>
Value heavy
-> Contract LargeOriginatorParam (LargeOriginatorStore heavy)
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
-> SomeLargeContractOriginator
SomeLargeContractOriginator Value 'TUnit
forall (instr :: [T] -> [T] -> *). Value' instr 'TUnit
VUnit Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
origContract Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
origLambda

    PushableValueStorage Instr '[] '[store]
instr ->
      let origContract :: Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
origContract = Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
forall (heavy :: T).
StorageScope heavy =>
Contract LargeOriginatorParam (LargeOriginatorStore heavy)
largeContractOriginator
          origLambda :: Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
origLambda = Instr '[ 'TUnit] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
forall (param :: T) (store :: T) (heavy :: T).
(ParameterScope param, StorageScope store, StorageScope heavy) =>
Instr '[heavy] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
mkOriginationLambda (Instr '[ 'TUnit] '[]
forall (a :: T) (out :: [T]). Instr (a : out) out
DROP Instr '[ 'TUnit] '[]
-> Instr '[] '[store] -> Instr '[ 'TUnit] '[store]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr '[] '[store]
instr) Contract param store
largeContract Mutez
xtzs
      in Value 'TUnit
-> Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
-> Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
-> SomeLargeContractOriginator
forall (heavy :: T).
StorageScope heavy =>
Value heavy
-> Contract LargeOriginatorParam (LargeOriginatorStore heavy)
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
-> SomeLargeContractOriginator
SomeLargeContractOriginator Value 'TUnit
forall (instr :: [T] -> [T] -> *). Value' instr 'TUnit
VUnit Contract LargeOriginatorParam (LargeOriginatorStore 'TUnit)
origContract Value (ToT (Lambda (Value 'TUnit) (Address, [Operation])))
origLambda

    PartlyPushableStorage Value heavy
val Instr '[heavy] '[store]
instr ->
      let origLambda :: Value (ToT (Lambda (Value heavy) (Address, [Operation])))
origLambda = Instr '[heavy] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
forall (param :: T) (store :: T) (heavy :: T).
(ParameterScope param, StorageScope store, StorageScope heavy) =>
Instr '[heavy] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
mkOriginationLambda Instr '[heavy] '[store]
instr Contract param store
largeContract Mutez
xtzs
      in Value heavy
-> Contract LargeOriginatorParam (LargeOriginatorStore heavy)
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
-> SomeLargeContractOriginator
forall (heavy :: T).
StorageScope heavy =>
Value heavy
-> Contract LargeOriginatorParam (LargeOriginatorStore heavy)
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
-> SomeLargeContractOriginator
SomeLargeContractOriginator Value heavy
val Contract LargeOriginatorParam (LargeOriginatorStore heavy)
forall (heavy :: T).
StorageScope heavy =>
Contract LargeOriginatorParam (LargeOriginatorStore heavy)
largeContractOriginator Value (ToT (Lambda (Value heavy) (Address, [Operation])))
origLambda


--------------------------------------------------------------------------------
-- Originator contract
--------------------------------------------------------------------------------

-- | Parameter of the originator contract.
type LargeOriginatorParam = 'T.TOr 'T.TBytes 'T.TUnit

-- | Storage of the originator contract.
type LargeOriginatorStore heavy =
  'T.TPair 'T.TAddress ('T.TOr 'T.TAddress ('T.TPair 'T.TBytes heavy))

-- | Large Originator contract.
--
-- Only keeps track of the "owner" address and either
-- - the heavy entries and packed lambda to do the generation (if still loading), or
-- - the resulting address of the originated large contract.
--
-- If the large contract was originated any call will result in a failure containing
-- its address.
-- Any call from an address that's not the "owner" will result in a failure.
largeContractOriginator
  :: StorageScope heavy
  => T.Contract LargeOriginatorParam (LargeOriginatorStore heavy)
largeContractOriginator :: forall (heavy :: T).
StorageScope heavy =>
Contract LargeOriginatorParam (LargeOriginatorStore heavy)
largeContractOriginator = T.Contract{Notes ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
ContractCode'
  Instr
  LargeOriginatorParam
  ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
ViewsSet'
  Instr ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
EntriesOrder
ParamNotes LargeOriginatorParam
forall {b :: T}.
ContractCode'
  Instr
  ('TOr 'TBytes b)
  ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cParamNotes :: ParamNotes LargeOriginatorParam
cStoreNotes :: Notes ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cEntriesOrder :: EntriesOrder
cViews :: ViewsSet'
  Instr ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cCode :: forall {b :: T}.
ContractCode'
  Instr
  ('TOr 'TBytes b)
  ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cCode :: ContractCode'
  Instr
  LargeOriginatorParam
  ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cEntriesOrder :: EntriesOrder
cParamNotes :: ParamNotes LargeOriginatorParam
cStoreNotes :: Notes ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cViews :: ViewsSet'
  Instr ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
..}
  where
    epsNotes :: Notes LargeOriginatorParam
epsNotes = [notes|or (bytes %load_lambda) (unit %run_lambda)|]
    cParamNotes :: ParamNotes LargeOriginatorParam
cParamNotes = ParamNotes LargeOriginatorParam
-> Either ParamEpError (ParamNotes LargeOriginatorParam)
-> ParamNotes LargeOriginatorParam
forall b a. b -> Either a b -> b
fromRight ParamNotes LargeOriginatorParam
forall (t :: T). SingI t => ParamNotes t
T.starParamNotes (Either ParamEpError (ParamNotes LargeOriginatorParam)
 -> ParamNotes LargeOriginatorParam)
-> Either ParamEpError (ParamNotes LargeOriginatorParam)
-> ParamNotes LargeOriginatorParam
forall a b. (a -> b) -> a -> b
$ Notes LargeOriginatorParam
-> Annotation FieldTag
-> Either ParamEpError (ParamNotes LargeOriginatorParam)
forall (t :: T).
Notes t
-> Annotation FieldTag -> Either ParamEpError (ParamNotes t)
T.mkParamNotes Notes LargeOriginatorParam
epsNotes Annotation FieldTag
forall {k} (a :: k). Annotation a
noAnn

    stateNotes :: Notes ('TOr 'TAddress ('TPair 'TBytes heavy))
stateNotes = Annotation TypeTag
-> Annotation FieldTag
-> Annotation FieldTag
-> Notes 'TAddress
-> Notes ('TPair 'TBytes heavy)
-> Notes ('TOr 'TAddress ('TPair 'TBytes heavy))
forall (p :: T) (q :: T).
Annotation TypeTag
-> Annotation FieldTag
-> Annotation FieldTag
-> Notes p
-> Notes q
-> Notes ('TOr p q)
T.NTOr Annotation TypeTag
forall {k} (a :: k). Annotation a
noAnn [annQ|originated|] [annQ|loading|] Notes 'TAddress
forall (t :: T). SingI t => Notes t
T.starNotes Notes ('TPair 'TBytes heavy)
forall (t :: T). SingI t => Notes t
T.starNotes
    cStoreNotes :: Notes ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cStoreNotes = Annotation TypeTag
-> Annotation FieldTag
-> Annotation FieldTag
-> VarAnn
-> VarAnn
-> Notes 'TAddress
-> Notes ('TOr 'TAddress ('TPair 'TBytes heavy))
-> Notes ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
forall (p :: T) (q :: T).
Annotation TypeTag
-> Annotation FieldTag
-> Annotation FieldTag
-> VarAnn
-> VarAnn
-> Notes p
-> Notes q
-> Notes ('TPair p q)
T.NTPair Annotation TypeTag
forall {k} (a :: k). Annotation a
noAnn [annQ|owner|] Annotation FieldTag
forall {k} (a :: k). Annotation a
noAnn VarAnn
forall {k} (a :: k). Annotation a
noAnn VarAnn
forall {k} (a :: k). Annotation a
noAnn Notes 'TAddress
forall (t :: T). SingI t => Notes t
T.starNotes Notes ('TOr 'TAddress ('TPair 'TBytes heavy))
stateNotes

    cEntriesOrder :: EntriesOrder
cEntriesOrder = EntriesOrder
forall a. Default a => a
def

    cViews :: ViewsSet'
  Instr ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cViews = ViewsSet'
  Instr ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
forall a. Default a => a
def
    cCode :: ContractCode'
  Instr
  ('TOr 'TBytes b)
  ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
cCode = (IsNotInView =>
 Instr
   (ContractInp
      ('TOr 'TBytes b)
      ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
   (ContractOut
      ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))))
-> ContractCode'
     Instr
     ('TOr 'TBytes b)
     ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
forall (instr :: [T] -> [T] -> *) (cp :: T) (st :: T).
(IsNotInView => instr (ContractInp cp st) (ContractOut st))
-> ContractCode' instr cp st
T.mkContractCode ((IsNotInView =>
  Instr
    (ContractInp
       ('TOr 'TBytes b)
       ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
    (ContractOut
       ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))))
 -> ContractCode'
      Instr
      ('TOr 'TBytes b)
      ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
-> (IsNotInView =>
    Instr
      (ContractInp
         ('TOr 'TBytes b)
         ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
      (ContractOut
         ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))))
-> ContractCode'
     Instr
     ('TOr 'TBytes b)
     ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
forall a b. (a -> b) -> a -> b
$
      Instr
  (ContractInp
     ('TOr 'TBytes b)
     ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
  '[ 'TOr 'TBytes b,
     'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ ('TPair a b : s), out ~ (a : b : s)) =>
Instr inp out
UNPAIR Instr
  (ContractInp
     ('TOr 'TBytes b)
     ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
  '[ 'TOr 'TBytes b,
     'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
-> Instr
     '[ 'TOr 'TBytes b,
        'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
-> Instr
     (ContractInp
        ('TOr 'TBytes b)
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
      -- make checks on the storage
      Instr
  '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
  '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TOr 'TBytes b,
        'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
     '[ 'TOr 'TBytes b, 'TBytes, heavy, 'TAddress]
forall (a :: [T]) (c :: [T]) (b :: T).
Instr a c -> Instr (b : a) (b : c)
DIP
        ( Instr
  '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ ('TPair a b : s), out ~ (a : b : s)) =>
Instr inp out
UNPAIR Instr
  '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
-> Instr
     '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
     '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
-> Instr
     '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
     '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr '[ 'TAddress, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TPair 'TBytes heavy, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
     '[ 'TBytes, heavy, 'TAddress]
forall (a :: T) (s :: [T]) (out :: [T]) (b :: T).
Instr (a : s) out -> Instr (b : s) out -> Instr ('TOr a b : s) out
IF_LEFT
            -- if the large contract has already been originated, fails with its address
            Instr '[ 'TAddress, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
forall (a :: T) (s :: [T]) (out :: [T]).
(SingI a, ConstantScope a) =>
Instr (a : s) out
FAILWITH
            -- otherwise, check for the sender
            ( Instr
  '[ 'TPair 'TBytes heavy, 'TAddress]
  '[ 'TAddress, 'TPair 'TBytes heavy]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TPair 'TBytes heavy, 'TAddress]
  '[ 'TAddress, 'TPair 'TBytes heavy]
-> Instr
     '[ 'TAddress, 'TPair 'TBytes heavy] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TPair 'TBytes heavy, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
forall {inp :: [T]} {out :: [T]} (a :: T) (s :: [T]).
(inp ~ (a : s), out ~ (a : a : s), DupableScope a) =>
Instr inp out
DUP Instr
  '[ 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
-> Instr
     '[ 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TPair 'TBytes heavy] '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TAddress, 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
forall {inp :: [T]} {out :: [T]} (s :: [T]).
(inp ~ s, out ~ ('TAddress : s)) =>
Instr inp out
SENDER Instr
  '[ 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TAddress, 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
-> Instr
     '[ 'TAddress, 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TInt, 'TAddress, 'TPair 'TBytes heavy]
forall {inp :: [T]} {out :: [T]} (n :: T) (s :: [T]).
(inp ~ (n : n : s), out ~ ('TInt : s), Comparable n) =>
Instr inp out
COMPARE Instr
  '[ 'TAddress, 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TInt, 'TAddress, 'TPair 'TBytes heavy]
-> Instr
     '[ 'TInt, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TAddress, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TInt, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TBool, 'TAddress, 'TPair 'TBytes heavy]
forall {inp :: [T]} {out :: [T]} (n :: T) (s :: [T]).
(inp ~ (n : s), out ~ (UnaryArithRes Eq' n : s),
 UnaryArithOp Eq' n) =>
Instr inp out
T.EQ Instr
  '[ 'TInt, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TBool, 'TAddress, 'TPair 'TBytes heavy]
-> Instr
     '[ 'TBool, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TInt, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TPair 'TBytes heavy] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TPair 'TBytes heavy] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TBool, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
forall (s :: [T]) (out :: [T]).
Instr s out -> Instr s out -> Instr ('TBool : s) out
IF
                ( Instr
  '[ 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TPair 'TBytes heavy, 'TAddress]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TPair 'TBytes heavy, 'TAddress]
-> Instr
     '[ 'TPair 'TBytes heavy, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TPair 'TBytes heavy] '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TPair 'TBytes heavy, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ ('TPair a b : s), out ~ (a : b : s)) =>
Instr inp out
UNPAIR )
                ( Value' Instr 'TString
-> Instr
     '[ 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TString, 'TAddress, 'TPair 'TBytes heavy]
forall {inp :: [T]} {out :: [T]} (t :: T) (s :: [T]).
(inp ~ s, out ~ (t : s), ConstantScope t) =>
Value' Instr t -> Instr inp out
PUSH (MText -> Value' Instr 'TString
forall (instr :: [T] -> [T] -> *). MText -> Value' instr 'TString
VString [mt|sender is not originator owner|]) Instr
  '[ 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TString, 'TAddress, 'TPair 'TBytes heavy]
-> Instr
     '[ 'TString, 'TAddress, 'TPair 'TBytes heavy]
     '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TAddress, 'TPair 'TBytes heavy] '[ 'TBytes, heavy, 'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TString, 'TAddress, 'TPair 'TBytes heavy]
  '[ 'TBytes, heavy, 'TAddress]
forall (a :: T) (s :: [T]) (out :: [T]).
(SingI a, ConstantScope a) =>
Instr (a : s) out
FAILWITH )
            )
        ) Instr
  '[ 'TOr 'TBytes b,
     'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
  '[ 'TOr 'TBytes b, 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TOr 'TBytes b, 'TBytes, heavy, 'TAddress]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
-> Instr
     '[ 'TOr 'TBytes b,
        'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
      -- stack at this point:
      -- parameter : packed lambda : heavy : owner address : []
      Instr
  '[ 'TBytes, 'TBytes, heavy, 'TAddress]
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
-> Instr
     '[b, 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TOr 'TBytes b, 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (a :: T) (s :: [T]) (out :: [T]) (b :: T).
Instr (a : s) out -> Instr (b : s) out -> Instr ('TOr a b : s) out
IF_LEFT
        -- if still loading lambda just concat to the exising 'bytes'
        ( Instr
  '[ 'TBytes, 'TBytes, heavy, 'TAddress]
  '[ 'TBytes, heavy, 'TAddress]
forall {inp :: [T]} {out :: [T]} (c :: T) (s :: [T]).
(inp ~ (c : c : s), out ~ (c : s), ConcatOp c) =>
Instr inp out
CONCAT Instr
  '[ 'TBytes, 'TBytes, heavy, 'TAddress]
  '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TBytes, 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TBytes, heavy, 'TAddress] '[ 'TPair 'TBytes heavy, 'TAddress]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ (a : b : s), out ~ ('TPair a b : s)) =>
Instr inp out
PAIR Instr
  '[ 'TBytes, heavy, 'TAddress] '[ 'TPair 'TBytes heavy, 'TAddress]
-> Instr
     '[ 'TPair 'TBytes heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TPair 'TBytes heavy, 'TAddress]
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ (b : s), out ~ ('TOr a b : s), SingI a) =>
Instr inp out
RIGHT Instr
  '[ 'TPair 'TBytes heavy, 'TAddress]
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
-> Instr
     '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TPair 'TBytes heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
forall {inp :: [T]} {out :: [T]} (p :: T) (s :: [T]).
(inp ~ s, out ~ ('TList p : s), SingI p) =>
Instr inp out
NIL)
        -- otherwise extract and run the origination lambda
        ( Instr '[b, 'TBytes, heavy, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
forall (a :: T) (out :: [T]). Instr (a : out) out
DROP Instr '[b, 'TBytes, heavy, 'TAddress] '[ 'TBytes, heavy, 'TAddress]
-> Instr
     '[ 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[b, 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TBytes, heavy, 'TAddress]
  '[ 'TOption
       ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation))),
     heavy, 'TAddress]
forall {inp :: [T]} {out :: [T]} (a :: T) (s :: [T]).
(inp ~ ('TBytes : s), out ~ ('TOption a : s), UnpackedValScope a,
 SingI a) =>
Instr inp out
UNPACK Instr
  '[ 'TBytes, heavy, 'TAddress]
  '[ 'TOption
       ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation))),
     heavy, 'TAddress]
-> Instr
     '[ 'TOption
          ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation))),
        heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TBytes, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
          Instr
  '[heavy, 'TAddress]
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
-> Instr
     '[ 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)), heavy,
        'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TOption
          ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation))),
        heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (s :: [T]) (out :: [T]) (a :: T).
Instr s out -> Instr (a : s) out -> Instr ('TOption a : s) out
IF_NONE
            ( Value' Instr 'TString
-> Instr '[heavy, 'TAddress] '[ 'TString, heavy, 'TAddress]
forall {inp :: [T]} {out :: [T]} (t :: T) (s :: [T]).
(inp ~ s, out ~ (t : s), ConstantScope t) =>
Value' Instr t -> Instr inp out
PUSH (MText -> Value' Instr 'TString
forall (instr :: [T] -> [T] -> *). MText -> Value' instr 'TString
VString [mt|failed to unpack lambda|]) Instr '[heavy, 'TAddress] '[ 'TString, heavy, 'TAddress]
-> Instr
     '[ 'TString, heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[heavy, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TString, heavy, 'TAddress]
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
forall (a :: T) (s :: [T]) (out :: [T]).
(SingI a, ConstantScope a) =>
Instr (a : s) out
FAILWITH )
            ( Instr
  '[ 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)), heavy,
     'TAddress]
  '[heavy, 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)),
    'TAddress]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)), heavy,
     'TAddress]
  '[heavy, 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)),
    'TAddress]
-> Instr
     '[heavy, 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)),
       'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)), heavy,
        'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[heavy, 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)),
    'TAddress]
  '[ 'TPair 'TAddress ('TList 'TOperation), 'TAddress]
forall {inp :: [T]} {out :: [T]} (t1 :: T) (t2 :: T) (s :: [T]).
(inp ~ (t1 : 'TLambda t1 t2 : s), out ~ (t2 : s)) =>
Instr inp out
EXEC Instr
  '[heavy, 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)),
    'TAddress]
  '[ 'TPair 'TAddress ('TList 'TOperation), 'TAddress]
-> Instr
     '[ 'TPair 'TAddress ('TList 'TOperation), 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[heavy, 'TLambda heavy ('TPair 'TAddress ('TList 'TOperation)),
       'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TPair 'TAddress ('TList 'TOperation), 'TAddress]
  '[ 'TAddress, 'TList 'TOperation, 'TAddress]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ ('TPair a b : s), out ~ (a : b : s)) =>
Instr inp out
UNPAIR Instr
  '[ 'TPair 'TAddress ('TList 'TOperation), 'TAddress]
  '[ 'TAddress, 'TList 'TOperation, 'TAddress]
-> Instr
     '[ 'TAddress, 'TList 'TOperation, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TPair 'TAddress ('TList 'TOperation), 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TList 'TOperation, 'TAddress]
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TList 'TOperation,
     'TAddress]
forall {inp :: [T]} {out :: [T]} (b :: T) (a :: T) (s :: [T]).
(inp ~ (a : s), out ~ ('TOr a b : s), SingI b) =>
Instr inp out
LEFT Instr
  '[ 'TAddress, 'TList 'TOperation, 'TAddress]
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TList 'TOperation,
     'TAddress]
-> Instr
     '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TList 'TOperation,
        'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
-> Instr
     '[ 'TAddress, 'TList 'TOperation, 'TAddress]
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TList 'TOperation,
     'TAddress]
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP
            )
        ) Instr
  '[ 'TOr 'TBytes b, 'TBytes, heavy, 'TAddress]
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
-> Instr
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
-> Instr
     '[ 'TOr 'TBytes b, 'TBytes, heavy, 'TAddress]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
      -- reconstruct the overall storage
      Instr
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
  '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
-> Instr
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
     '[ 'TList 'TOperation,
        'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
forall (a :: [T]) (c :: [T]) (b :: T).
Instr a c -> Instr (b : a) (b : c)
DIP (Instr
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
-> Instr
     '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
     '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
-> Instr
     '[ 'TOr 'TAddress ('TPair 'TBytes heavy), 'TAddress]
     '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TOr 'TAddress ('TPair 'TBytes heavy)]
  '[ 'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ (a : b : s), out ~ ('TPair a b : s)) =>
Instr inp out
PAIR) Instr
  '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
     'TAddress]
  '[ 'TList 'TOperation,
     'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
-> Instr
     '[ 'TList 'TOperation,
        'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
-> Instr
     '[ 'TList 'TOperation, 'TOr 'TAddress ('TPair 'TBytes heavy),
        'TAddress]
     (ContractOut
        ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
      -- pair with operations and return
      Instr
  '[ 'TList 'TOperation,
     'TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))]
  (ContractOut
     ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy))))
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ (a : b : s), out ~ ('TPair a b : s)) =>
Instr inp out
PAIR

--------------------------------------------------------------------------------
-- Origination lambda
--------------------------------------------------------------------------------

-- | Returns bytes that fit into transaction limits from 'mkOriginationLambda'.
--
-- Note: these have the original order, meaning they should be given to the
-- originator contract from last to first.
divideValueInChunks :: ConstantScope val => Value val -> [ByteString]
divideValueInChunks :: forall (val :: T). ConstantScope val => Value val -> [ByteString]
divideValueInChunks = LByteString -> [ByteString]
divideInChunks (LByteString -> [ByteString])
-> (Value val -> LByteString) -> Value val -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value val -> LByteString
forall (t :: T). PackedValScope t => Value t -> LByteString
packValue

-- | Returns strict bytes chunks that fit into transaction limits of the input.
divideInChunks :: LByteString -> [ByteString]
divideInChunks :: LByteString -> [ByteString]
divideInChunks LByteString
bytes
  | LByteString -> Bool
LBS.null LByteString
bytes = []
  | Bool
otherwise =
    -- Note: the size is quite a bit below 16k for safety:
    let (LByteString
chunk, LByteString
rest) = Int64 -> LByteString -> (LByteString, LByteString)
LBS.splitAt Int64
14000 LByteString
bytes
    in LByteString -> ByteString
LBS.toStrict LByteString
chunk ByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
: LByteString -> [ByteString]
divideInChunks LByteString
rest

-- | Generates the lambda to originate a large contract.
mkOriginationLambda
  :: (ParameterScope param, StorageScope store, StorageScope heavy)
  => Instr '[heavy] '[store] -- ^ instruction to recreate the initial storage
  -> T.Contract param store -- ^ large contract
  -> Mutez -- ^ balance to tranfer during contract creation
  -> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
mkOriginationLambda :: forall (param :: T) (store :: T) (heavy :: T).
(ParameterScope param, StorageScope store, StorageScope heavy) =>
Instr '[heavy] '[store]
-> Contract param store
-> Mutez
-> Value (ToT (Lambda (Value heavy) (Address, [Operation])))
mkOriginationLambda Instr '[heavy] '[store]
instr Contract param store
largeContract Mutez
xtzs = (IsNotInView =>
 RemFail Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)])
-> Value'
     Instr ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation)))
forall (inp :: T) (out :: T) (instr :: [T] -> [T] -> *).
(SingI inp, SingI out,
 forall (i :: [T]) (o :: [T]). Show (instr i o),
 forall (i :: [T]) (o :: [T]). Eq (instr i o),
 forall (i :: [T]) (o :: [T]). NFData (instr i o)) =>
(IsNotInView => RemFail instr '[inp] '[out])
-> Value' instr ('TLambda inp out)
mkVLam ((IsNotInView =>
  RemFail Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)])
 -> Value'
      Instr ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation))))
-> (IsNotInView =>
    RemFail Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)])
-> Value'
     Instr ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation)))
forall a b. (a -> b) -> a -> b
$ Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)]
-> RemFail Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)]
forall {k} (instr :: k -> k -> *) (i :: k) (o :: k).
instr i o -> RemFail instr i o
RfNormal (Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)]
 -> RemFail
      Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)])
-> Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)]
-> RemFail Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)]
forall a b. (a -> b) -> a -> b
$
  Instr '[heavy] '[store]
instr Instr '[heavy] '[store]
-> Instr '[store] '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr '[heavy] '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Value' Instr 'TMutez -> Instr '[store] '[ 'TMutez, store]
forall {inp :: [T]} {out :: [T]} (t :: T) (s :: [T]).
(inp ~ s, out ~ (t : s), ConstantScope t) =>
Value' Instr t -> Instr inp out
PUSH (Mutez -> Value' Instr 'TMutez
forall (instr :: [T] -> [T] -> *). Mutez -> Value' instr 'TMutez
VMutez Mutez
xtzs) Instr '[store] '[ 'TMutez, store]
-> Instr
     '[ 'TMutez, store] '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr '[store] '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr '[ 'TMutez, store] '[ 'TOption 'TKeyHash, 'TMutez, store]
forall {inp :: [T]} {out :: [T]} (a :: T) (s :: [T]).
(inp ~ s, out ~ ('TOption a : s), SingI a) =>
Instr inp out
NONE Instr '[ 'TMutez, store] '[ 'TOption 'TKeyHash, 'TMutez, store]
-> Instr
     '[ 'TOption 'TKeyHash, 'TMutez, store]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr
     '[ 'TMutez, store] '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
  Contract param store
-> Instr
     '[ 'TOption 'TKeyHash, 'TMutez, store] '[ 'TOperation, 'TAddress]
forall {inp :: [T]} {out :: [T]} (p :: T) (g :: T) (s :: [T]).
(inp ~ ('TOption 'TKeyHash : 'TMutez : g : s),
 out ~ ('TOperation : 'TAddress : s), ParameterScope p,
 StorageScope g, IsNotInView) =>
Contract' Instr p g -> Instr inp out
CREATE_CONTRACT Contract param store
largeContract Instr
  '[ 'TOption 'TKeyHash, 'TMutez, store] '[ 'TOperation, 'TAddress]
-> Instr
     '[ 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr
     '[ 'TOption 'TKeyHash, 'TMutez, store]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq`
  Instr
  '[ 'TOperation, 'TAddress]
  '[ 'TList 'TOperation, 'TOperation, 'TAddress]
forall {inp :: [T]} {out :: [T]} (p :: T) (s :: [T]).
(inp ~ s, out ~ ('TList p : s), SingI p) =>
Instr inp out
NIL Instr
  '[ 'TOperation, 'TAddress]
  '[ 'TList 'TOperation, 'TOperation, 'TAddress]
-> Instr
     '[ 'TList 'TOperation, 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr
     '[ 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TList 'TOperation, 'TOperation, 'TAddress]
  '[ 'TOperation, 'TList 'TOperation, 'TAddress]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TList 'TOperation, 'TOperation, 'TAddress]
  '[ 'TOperation, 'TList 'TOperation, 'TAddress]
-> Instr
     '[ 'TOperation, 'TList 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr
     '[ 'TList 'TOperation, 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TOperation, 'TList 'TOperation, 'TAddress]
  '[ 'TList 'TOperation, 'TAddress]
forall {inp :: [T]} {out :: [T]} (a :: T) (s :: [T]).
(inp ~ (a : 'TList a : s), out ~ ('TList a : s)) =>
Instr inp out
CONS Instr
  '[ 'TOperation, 'TList 'TOperation, 'TAddress]
  '[ 'TList 'TOperation, 'TAddress]
-> Instr
     '[ 'TList 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr
     '[ 'TOperation, 'TList 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TList 'TOperation, 'TAddress] '[ 'TAddress, 'TList 'TOperation]
forall (a :: T) (b :: T) (s :: [T]). Instr (a : b : s) (b : a : s)
SWAP Instr
  '[ 'TList 'TOperation, 'TAddress] '[ 'TAddress, 'TList 'TOperation]
-> Instr
     '[ 'TAddress, 'TList 'TOperation]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
-> Instr
     '[ 'TList 'TOperation, 'TAddress]
     '[ 'TPair 'TAddress ('TList 'TOperation)]
forall (inp :: [T]) (b :: [T]) (out :: [T]).
Instr inp b -> Instr b out -> Instr inp out
`Seq` Instr
  '[ 'TAddress, 'TList 'TOperation]
  '[ 'TPair 'TAddress ('TList 'TOperation)]
forall {inp :: [T]} {out :: [T]} (a :: T) (b :: T) (s :: [T]).
(inp ~ (a : b : s), out ~ ('TPair a b : s)) =>
Instr inp out
PAIR


--------------------------------------------------------------------------------
-- Utilities
--------------------------------------------------------------------------------

-- | Helper to create a 'LargeOriginatorStore' 'Value'.
mkLargeOriginatorStore
  :: StorageScope heavy
  => Value heavy
  -> ImplicitAddress
  -> Value (LargeOriginatorStore heavy)
mkLargeOriginatorStore :: forall (heavy :: T).
StorageScope heavy =>
Value heavy
-> ImplicitAddress -> Value (LargeOriginatorStore heavy)
mkLargeOriginatorStore Value heavy
heavyVal ImplicitAddress
owner =
  let vAddr :: Value (ToT Address)
vAddr = Address -> Value (ToT Address)
forall a. IsoValue a => a -> Value (ToT a)
toVal (ImplicitAddress -> Address
forall (kind :: AddressKind). KindedAddress kind -> Address
MkAddress ImplicitAddress
owner) in
  (Value' Instr 'TAddress,
 Value' Instr ('TOr 'TAddress ('TPair 'TBytes heavy)))
-> Value'
     Instr ('TPair 'TAddress ('TOr 'TAddress ('TPair 'TBytes heavy)))
forall (l :: T) (r :: T) (instr :: [T] -> [T] -> *).
(Value' instr l, Value' instr r) -> Value' instr ('TPair l r)
VPair (Value (ToT Address)
Value' Instr 'TAddress
vAddr, Either
  (Value' Instr 'TAddress) (Value' Instr ('TPair 'TBytes heavy))
-> Value' Instr ('TOr 'TAddress ('TPair 'TBytes heavy))
forall (l :: T) (r :: T) (instr :: [T] -> [T] -> *).
(SingI l, SingI r) =>
Either (Value' instr l) (Value' instr r) -> Value' instr ('TOr l r)
VOr (Either
   (Value' Instr 'TAddress) (Value' Instr ('TPair 'TBytes heavy))
 -> Value' Instr ('TOr 'TAddress ('TPair 'TBytes heavy)))
-> Either
     (Value' Instr 'TAddress) (Value' Instr ('TPair 'TBytes heavy))
-> Value' Instr ('TOr 'TAddress ('TPair 'TBytes heavy))
forall a b. (a -> b) -> a -> b
$ Value' Instr ('TPair 'TBytes heavy)
-> Either
     (Value' Instr 'TAddress) (Value' Instr ('TPair 'TBytes heavy))
forall a b. b -> Either a b
Right (Value' Instr ('TPair 'TBytes heavy)
 -> Either
      (Value' Instr 'TAddress) (Value' Instr ('TPair 'TBytes heavy)))
-> Value' Instr ('TPair 'TBytes heavy)
-> Either
     (Value' Instr 'TAddress) (Value' Instr ('TPair 'TBytes heavy))
forall a b. (a -> b) -> a -> b
$ (Value' Instr 'TBytes, Value heavy)
-> Value' Instr ('TPair 'TBytes heavy)
forall (l :: T) (r :: T) (instr :: [T] -> [T] -> *).
(Value' instr l, Value' instr r) -> Value' instr ('TPair l r)
VPair (ByteString -> Value' Instr 'TBytes
forall (instr :: [T] -> [T] -> *).
ByteString -> Value' instr 'TBytes
VBytes ByteString
forall a. Monoid a => a
mempty, Value heavy
heavyVal))

-- | Makes 'OriginationData' of the 'largeContractOriginator' that will generate
-- the large contract of the given 'OriginationData' for the sender
-- t'ImplicitAddress'.
mkLargeOriginatorData
  :: ImplicitAddress
  -> LargeOriginationData
  -> OriginationData
mkLargeOriginatorData :: ImplicitAddress -> LargeOriginationData -> OriginationData
mkLargeOriginatorData ImplicitAddress
sender' LargeOriginationData{OriginationData
SomeLargeContractOriginator
largeOriginator :: LargeOriginationData -> SomeLargeContractOriginator
largeContractData :: LargeOriginationData -> OriginationData
largeOriginator :: SomeLargeContractOriginator
largeContractData :: OriginationData
..} = case SomeLargeContractOriginator
largeOriginator of
  SomeLargeContractOriginator Value heavy
heavyVal Contract LargeOriginatorParam (LargeOriginatorStore heavy)
origContract Value (ToT (Lambda (Value heavy) (Address, [Operation])))
_origLambda -> OriginationData
    { odAliasBehavior :: AliasBehavior
odAliasBehavior = OriginationData -> AliasBehavior
odAliasBehavior OriginationData
largeContractData
    , odName :: ContractAlias
odName = Text -> ContractAlias
ContractAlias (Text -> ContractAlias) -> Text -> ContractAlias
forall a b. (a -> b) -> a -> b
$ Text
"largeOriginator." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ContractAlias -> Text
forall (kind :: AddressKind). Alias kind -> Text
unAlias (OriginationData -> ContractAlias
odName OriginationData
largeContractData)
    , odBalance :: Mutez
odBalance = Mutez
zeroMutez
    -- Note ^ we don't transfer any balance here, we instead do it as part of the
    -- last transaction (where it will be transferred to the large contract)
    , odContract :: Contract LargeOriginatorParam (LargeOriginatorStore heavy)
odContract = Contract LargeOriginatorParam (LargeOriginatorStore heavy)
origContract
    , odStorage :: Value (LargeOriginatorStore heavy)
odStorage = Value heavy
-> ImplicitAddress -> Value (LargeOriginatorStore heavy)
forall (heavy :: T).
StorageScope heavy =>
Value heavy
-> ImplicitAddress -> Value (LargeOriginatorStore heavy)
mkLargeOriginatorStore Value heavy
heavyVal ImplicitAddress
sender'
    , odDelegate :: Maybe KeyHash
odDelegate = OriginationData -> Maybe KeyHash
odDelegate OriginationData
largeContractData
    , odMbFee :: Maybe Mutez
odMbFee = OriginationData -> Maybe Mutez
odMbFee OriginationData
largeContractData
    }

-- | Makes all the 'TransactionData' to feed the origination lambda into a
-- 'largeContractOriginator' from the t'ContractAddress' of the latter.
mkLargeOriginatorTransactions
  :: ContractAddress -> LargeOriginationData
  -> [TransactionData]
mkLargeOriginatorTransactions :: ContractAddress -> LargeOriginationData -> [TransactionData]
mkLargeOriginatorTransactions ContractAddress
originatorAddr LargeOriginationData{OriginationData
SomeLargeContractOriginator
largeOriginator :: LargeOriginationData -> SomeLargeContractOriginator
largeContractData :: LargeOriginationData -> OriginationData
largeOriginator :: SomeLargeContractOriginator
largeContractData :: OriginationData
..} =
  case OriginationData
largeContractData of
    OriginationData{Maybe Mutez
Maybe KeyHash
Mutez
ContractAlias
Value st
Contract cp st
AliasBehavior
odAliasBehavior :: OriginationData -> AliasBehavior
odName :: OriginationData -> ContractAlias
odBalance :: OriginationData -> Mutez
odContract :: ()
odStorage :: ()
odDelegate :: OriginationData -> Maybe KeyHash
odMbFee :: OriginationData -> Maybe Mutez
odAliasBehavior :: AliasBehavior
odName :: ContractAlias
odBalance :: Mutez
odContract :: Contract cp st
odStorage :: Value st
odDelegate :: Maybe KeyHash
odMbFee :: Maybe Mutez
..} -> case SomeLargeContractOriginator
largeOriginator of
      SomeLargeContractOriginator Value heavy
_ Contract LargeOriginatorParam (LargeOriginatorStore heavy)
_ Value (ToT (Lambda (Value heavy) (Address, [Operation])))
origLambda ->
        let lambdaChunks :: [ByteString]
lambdaChunks = Value ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation)))
-> [ByteString]
forall (val :: T). ConstantScope val => Value val -> [ByteString]
divideValueInChunks Value (ToT (Lambda (Value heavy) (Address, [Operation])))
Value ('TLambda heavy ('TPair 'TAddress ('TList 'TOperation)))
origLambda
            doRunLambda :: TransactionData
doRunLambda = forall (t :: T).
ParameterScope t =>
TD (Value t) -> TransactionData
TransactionData @'T.TUnit (TD (Value 'TUnit) -> TransactionData)
-> TD (Value 'TUnit) -> TransactionData
forall a b. (a -> b) -> a -> b
$ TD
              { tdReceiver :: L1Address
tdReceiver = ContractAddress -> L1Address
forall {k} (c :: k -> Constraint) (f :: k -> *) (a :: k).
c a =>
f a -> Constrained c f
Constrained ContractAddress
originatorAddr
              , tdAmount :: Mutez
tdAmount   = Mutez
odBalance
              , tdEpName :: EpName
tdEpName   = EntrypointRef ('Just "Run_lambda") -> EpName
forall (mname :: Maybe Symbol). EntrypointRef mname -> EpName
eprName EntrypointRef ('Just "Run_lambda")
#run_lambda
              , tdParam :: Value 'TUnit
tdParam    = Value 'TUnit
forall (instr :: [T] -> [T] -> *). Value' instr 'TUnit
VUnit
              , tdMbFee :: Maybe Mutez
tdMbFee    = Maybe Mutez
odMbFee
              }
            mkLoadLambda :: ByteString -> TransactionData
mkLoadLambda ByteString
bytes = forall (t :: T).
ParameterScope t =>
TD (Value t) -> TransactionData
TransactionData @'T.TBytes (TD (Value' Instr 'TBytes) -> TransactionData)
-> TD (Value' Instr 'TBytes) -> TransactionData
forall a b. (a -> b) -> a -> b
$ TD
              { tdReceiver :: L1Address
tdReceiver = ContractAddress -> L1Address
forall {k} (c :: k -> Constraint) (f :: k -> *) (a :: k).
c a =>
f a -> Constrained c f
Constrained ContractAddress
originatorAddr
              , tdAmount :: Mutez
tdAmount   = Mutez
zeroMutez
              , tdEpName :: EpName
tdEpName   = EntrypointRef ('Just "Load_lambda") -> EpName
forall (mname :: Maybe Symbol). EntrypointRef mname -> EpName
eprName EntrypointRef ('Just "Load_lambda")
#load_lambda
              , tdParam :: Value' Instr 'TBytes
tdParam    = ByteString -> Value' Instr 'TBytes
forall (instr :: [T] -> [T] -> *).
ByteString -> Value' instr 'TBytes
VBytes ByteString
bytes
              , tdMbFee :: Maybe Mutez
tdMbFee    = Maybe Mutez
odMbFee
              }
        in ([TransactionData] -> Element [ByteString] -> [TransactionData])
-> [TransactionData] -> [ByteString] -> [TransactionData]
forall t b. Container t => (b -> Element t -> b) -> b -> t -> b
forall b.
(b -> Element [ByteString] -> b) -> b -> [ByteString] -> b
foldl' (\[TransactionData]
lst Element [ByteString]
bytes -> ByteString -> TransactionData
mkLoadLambda ByteString
Element [ByteString]
bytes TransactionData -> [TransactionData] -> [TransactionData]
forall a. a -> [a] -> [a]
: [TransactionData]
lst) [TransactionData
doRunLambda] [ByteString]
lambdaChunks

-- | Fetches back the t'ContractAddress' of the large contract generated by a
-- completed 'largeContractOriginator' process.
--
-- It also uses the large contract 'OriginationData' to associate it to the
-- expected alias.
retrieveLargeContracts
  :: (HasTezosRpc m, HasTezosClient m)
  => ContractAddress -> OriginationData -> m ContractAddress
retrieveLargeContracts :: forall (m :: * -> *).
(HasTezosRpc m, HasTezosClient m) =>
ContractAddress -> OriginationData -> m ContractAddress
retrieveLargeContracts ContractAddress
originatorAddr OriginationData{Maybe Mutez
Maybe KeyHash
Mutez
ContractAlias
Value st
Contract cp st
AliasBehavior
odAliasBehavior :: OriginationData -> AliasBehavior
odName :: OriginationData -> ContractAlias
odBalance :: OriginationData -> Mutez
odContract :: ()
odStorage :: ()
odDelegate :: OriginationData -> Maybe KeyHash
odMbFee :: OriginationData -> Maybe Mutez
odAliasBehavior :: AliasBehavior
odName :: ContractAlias
odBalance :: Mutez
odContract :: Contract cp st
odStorage :: Value st
odDelegate :: Maybe KeyHash
odMbFee :: Maybe Mutez
..} = do
  Expression
expr <- ContractAddress -> m Expression
forall (m :: * -> *).
HasTezosRpc m =>
ContractAddress -> m Expression
getContractStorage ContractAddress
originatorAddr
  -- note: for simplicity here we convert the "wrong" value
  -- because we cannot convert from a value with a big_map in its *type*
  -- and also something went wrong if this has a big_map or ticket in its *value*
  let completedStore :: Either FromExpressionError (Value (LargeOriginatorStore 'TUnit))
completedStore = forall a.
FromExp RegularExp a =>
Expression -> Either FromExpressionError a
fromExpression @(Value (LargeOriginatorStore 'T.TUnit)) Expression
expr
  case Either FromExpressionError (Value (LargeOriginatorStore 'TUnit))
completedStore of
    Right (VPair (Value' Instr l
_, VOr (Left Value' Instr l
largeVAddr))) ->
      Address
-> (forall (t :: AddressKind).
    NullConstraint t =>
    KindedAddress t -> m ContractAddress)
-> m ContractAddress
forall {k} (c :: k -> Constraint) (f :: k -> *) r.
Constrained c f -> (forall (t :: k). c t => f t -> r) -> r
withConstrained (forall a. IsoValue a => Value (ToT a) -> a
fromVal @Address Value' Instr l
Value (ToT Address)
largeVAddr) \case
        largeAddr :: KindedAddress t
largeAddr@ContractAddress{} -> do
          AliasBehavior -> ContractAddress -> ContractAlias -> m ()
forall (m :: * -> *).
HasTezosClient m =>
AliasBehavior -> ContractAddress -> ContractAlias -> m ()
rememberContract AliasBehavior
odAliasBehavior KindedAddress t
ContractAddress
largeAddr ContractAlias
odName
          pure KindedAddress t
ContractAddress
largeAddr
        KindedAddress t
_ -> Text -> m ContractAddress
forall a. HasCallStack => Text -> a
error Text
"impossible"
    Either FromExpressionError (Value (LargeOriginatorStore 'TUnit))
_ -> IncorrectRpcResponse -> m ContractAddress
forall (m :: * -> *) e a. (MonadThrow m, Exception e) => e -> m a
throwM IncorrectRpcResponse
RpcOriginatedNoContracts