diff --git a/Assets/Scripts/GenerateDemoFiles.cs b/Assets/Scripts/GenerateDemoFiles.cs
index 771caf8fa4589320650d4b97a4bd7947f980ba69..4b74c75422ca383a6c3335577dea7faf0e3f1994 100644
--- a/Assets/Scripts/GenerateDemoFiles.cs
+++ b/Assets/Scripts/GenerateDemoFiles.cs
@@ -6,6 +6,7 @@
 using static CanonBallProblemCalculator;
 using Unity.Mathematics;
 using System;
+using static SOMDocManager;
 
 public class GenerateDemoFiles
 {
@@ -248,11 +249,32 @@ public static void GenerateCanonBallStage()
         }
 
         // Set Solution
+        #region  CannonBallScroll
         StageStatic.stage.solution.Add( // for CannonBallScroll
             new ListFact(Walls.Select(w => w.Topology.Id).ToArray(), typeof(LineFact), StageStatic.stage.solution),
             out bool _, true, null, null
         );
 
+        // special case for Prototype
+        string[] RRRRTupel = new string[Walls.Count];
+        for (int i = 0; i < Walls.Count; i++)
+        {
+            RRRRTupel[i] = StageStatic.stage.solution.Add(
+                new TupelFact(null,
+                    new[] {
+                        SOMDoc.MakeTupel(new OMF[] { new(Walls[i].Topology.Point1.Point[dim_A]), new(Walls[i].Topology.Point1.Point[dim_B]) }),
+                        SOMDoc.MakeTupel(new OMF[] { new(Walls[i].Topology.Point2.Point[dim_A]), new(Walls[i].Topology.Point2.Point[dim_B]) }),
+                    },
+                    StageStatic.stage.solution),
+                out bool _, true, null, null
+            );
+        }
+        StageStatic.stage.solution.Add(
+            new ListFact(RRRRTupel, typeof(TupelFact), StageStatic.stage.solution),
+            out bool _, true, null, null
+        );
+        #endregion CannonBallScroll
+
         string BallURI = StageStatic.stage.solution.Add(
             new PointFact(StartPos, Vector3.up, StageStatic.stage.solution),
             out _, false, null, null);
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs b/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
index 6d74682be3a6c4dcf8dc0563c5b44ffc6ae8dd10..1f8db6a5fa66d4dd4a985529f222842ba39c7daf 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/Facts/Fact.cs
@@ -7,6 +7,9 @@
 using System.Linq;
 using REST_JSON_API;
 using static SOMDocManager;
+using UnityEngine.ProBuilder;
+using Unity.Mathematics;
+using System.Runtime.ExceptionServices;
 
 public static class ParsingDictionary
 {
@@ -119,7 +122,7 @@ public abstract class Fact
 
     /// <returns><see langword="true"/> if Fact depends on other \ref Fact "Facts"; equivalent to <see cref="getDependentFactIds"/> returns non empty array</returns>
     [JsonIgnore]
-    public abstract bool HasDependentFacts { get; }
+    public virtual bool HasDependentFacts => DependentFactIds.Length > 0;
 
     /// <returns> array of Fact <see cref="Id"> Ids </see> on which this Fact depends.</returns>
     /// <example><see cref="AngleFact"/> needs 3 <see cref="PointFact"/>s to be defined.</example>
@@ -2344,7 +2347,7 @@ protected override string[] GetGetDependentFactIds()
     public override MMTDeclaration MakeMMTDeclaration()
     {
         OMA List = SOMDoc.MakeList(lids, typeURI);
-        return new MMTSymbolDeclaration(Label, List.applicant, List.applicant);
+        return new MMTSymbolDeclaration(Label, List.applicant, List.arguments[0]);
     }
 
     public static new ListFact parseFact(MMTDeclaration fact)
@@ -2420,6 +2423,88 @@ protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, F
         => new ListFact(lids.Select(id => old_to_new[id]).ToArray(), ListType, organizer);
 }
 
+/// <summary>
+/// 
+/// </summary>
+/// <seealso cref="SOMDoc.MakeTupel(SOMDoc[])"/>
+/// <remarks>Needed to refere to tupels serverside</remarks>
+public class TupelFact : FactWrappedCRTP<ListFact>
+{
+    public string[] lids = new string[0];
+
+    public SOMDoc[] payload = new SOMDoc[0];
+
+    public TupelFact() : base() { }
+
+    public TupelFact(string[] lids, SOMDoc[] payload, FactOrganizer organizer) : base(organizer)
+    {
+        Init(lids, payload);
+        SendToMMT();
+    }
+
+    public TupelFact(string[] lids, SOMDoc[] payload, string backendURI, FactOrganizer organizer) : base(organizer)
+    {
+        Init(lids, payload);
+        _URI = backendURI;
+    }
+
+    private void Init(string[] lids, SOMDoc[] payload)
+    {
+        this.lids = lids ?? new string[0];
+        if (!HasDependentFacts)
+        {
+            if (payload.Any(p => p == null))
+                throw new ArgumentException(nameof(payload) + "must not include null elements iff " + nameof(lids) + " is all nulls or empty!");
+
+            this.payload = payload;
+        }
+        else
+        {
+            this.payload = new SOMDoc[math.max(lids.Length, payload.Length)];
+
+            for (int i = 0; i < this.payload.Length; i++)
+                if (lids[i] != null)
+                    payload[i] = new OMS(lids[i]);
+                else
+                if (lids[i] == null && payload[i] == null)
+                    throw new ArgumentException(nameof(lids) + " and " + nameof(payload) + " have to be complementary not null!");
+        }
+    }
+
+    protected override Fact _ReInitializeMe(Dictionary<string, string> old_to_new, FactOrganizer organizer)
+        => new TupelFact(lids.Select(id => old_to_new[id]).ToArray(), payload, organizer);
+
+    public static new TupelFact parseFact(MMTDeclaration fact)
+    {
+        if (fact is not MMTSymbolDeclaration MMTSymbol
+         || MMTSymbol.defines is not OMA defineOMA)
+        {
+            return null;
+        }
+
+        string[] lids = defineOMA.arguments
+            .Select(oms => (oms as OMS)?.uri)
+            .ToArray();
+
+        return new(lids, defineOMA.arguments, fact.@ref.uri, StageStatic.stage.factState);
+    }
+
+    public override MMTDeclaration MakeMMTDeclaration()
+    {
+        OMA List = SOMDoc.MakeTupel(payload);
+        return new MMTSymbolDeclaration(Label, List.applicant, List);
+    }
+
+    protected override string[] GetGetDependentFactIds()
+        => lids.Where(lid => lid != null).ToArray();
+
+    protected override void RecalculateTransform() { }
+
+    protected override bool EquivalentWrapped(ListFact f1, ListFact f2)
+        => f1.typeURI == f2.typeURI
+        && DependentFactsEquivalent(f1, f2);
+}
+
 
 #pragma warning disable // Testing...
 
diff --git a/Assets/Scripts/InventoryStuff/ScrollDetails.cs b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
index 7441648340364a9ac0d5fa6b5fcb032b27582307..bcde7ff522008e8ef52e280bb2128e698d989d60 100644
--- a/Assets/Scripts/InventoryStuff/ScrollDetails.cs
+++ b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
@@ -143,7 +143,10 @@ private int[] PrePopulateActiveScroll()
         switch (ActiveScroll.ScrollReference)
         {
             case MMT_OMS_URI.ScrollCannonBall:
-                string lid_override = StageStatic.stage.solution.MyFactSpace.Values.FirstOrDefault(sol => sol is ListFact)?.Id;
+                string lid_override = StageStatic.stage.solution.MyFactSpace.Values
+                    .FirstOrDefault(sol => sol is ListFact lf && lf.ListType == typeof(TupelFact))
+                    ?.Id;
+
                 if (lid_override == null)
                     goto default;
 
diff --git a/Assets/Scripts/SOMDocManager.cs b/Assets/Scripts/SOMDocManager.cs
index 81400f56d515e2526475024548f1a37688eb2c53..5961c709e0ebd830ca2f2512b495a47b5e4c9baf 100644
--- a/Assets/Scripts/SOMDocManager.cs
+++ b/Assets/Scripts/SOMDocManager.cs
@@ -142,7 +142,7 @@ public static class MMT_OMS_URI
             { RealLit,
                 typeof(float) },
             { Tuple,
-                typeof(Vector3) },
+                typeof(TupelFact) },
             { ListType,
                 typeof(List<>) },
 
@@ -164,13 +164,15 @@ public static class MMT_OMS_URI
                 typeof(double) },
             { typeof(string).ToString(),
                 typeof(string) },
-            { typeof(Vector3).ToString(),
-                typeof(Vector3) },
         };
 
         static MMT_OMS_URI()
         {
-            Dictionary<Type, string> _TYPE_TO_OMS = new();
+            Dictionary<Type, string> _TYPE_TO_OMS = new() {
+                { typeof(Vector3),
+                    Tuple },
+            };
+
             foreach (KeyValuePair<string, Type> KeyVal in OMS_TO_TYPE)
                 if (KeyVal.Value != null)
                     _TYPE_TO_OMS.TryAdd(KeyVal.Value, KeyVal.Key);