diff --git a/theories/examples/swap_mapper.v b/theories/examples/swap_mapper.v
index bffe65d10bb926f1eb236e2bfeb090927a07ccdf..f85329686f7a41ad8c5481aa4cbc8a60dbd5d595 100644
--- a/theories/examples/swap_mapper.v
+++ b/theories/examples/swap_mapper.v
@@ -23,140 +23,193 @@ Section with_Σ.
     ProtoUnfold (mapper_prot) (mapper_prot_aux mapper_prot).
   Proof. apply proto_unfold_eq, (fixpoint_unfold mapper_prot_aux). Qed.
 
-  Definition mapper_prot_twice :=
+  Definition map_once prot :=
     (<!> MSG (LitV $ true);
-     <! (x1 : T) (v1 : val)> MSG v1 {{ IT x1 v1 }};
-     <? (w1 : val)> MSG w1 {{ IU (f x1) w1 }};
-     <!> MSG (LitV $ true);
-     <! (x2 : T) (v2 : val)> MSG v2 {{ IT x2 v2 }};
-     <? (w2 : val)> MSG w2 {{ IU (f x2) w2 }};
-      <!> MSG (LitV $ false);
-      END)%proto.
+     <! (x : T) (v : val)> MSG v {{ IT x v }};
+     <? (w : val)> MSG w {{ IU (f x) w }};
+     prot)%proto.
+
+  Lemma map_once_mono prot1 prot2 :
+    ▷ (prot1 ⊑ prot2) -∗ map_once prot1 ⊑ map_once prot2.
+  Proof.
+    iIntros "Hsub".
+    rewrite /map_once.
+    iModIntro.
+    iIntros (x v) "Hv". iExists x, v. iFrame "Hv". iModIntro.
+    iIntros (w) "Hw". iExists w. iFrame "Hw". iModIntro.
+    iApply "Hsub".
+  Qed.
+
+  Global Instance map_once_from_modal p1 p2 :
+    FromModal (modality_instances.modality_laterN 1) (p1 ⊑ p2)
+              ((map_once p1) ⊑ (map_once p2)) (p1 ⊑ p2).
+  Proof. apply map_once_mono. Qed.
+
+  Definition mapper_prot_once :=
+    (map_once mapper_prot)%proto.
+
+  Lemma subprot_once :
+    ⊢ mapper_prot ⊑ mapper_prot_once.
+  Proof.
+    rewrite /mapper_prot /mapper_prot_once.
+    rewrite fixpoint_unfold /mapper_prot_aux.
+    rewrite /iProto_choice.
+    iExists true.
+    iModIntro.
+    iApply iProto_le_refl.
+  Qed.
+
+  Definition mapper_prot_twice :=
+    map_once $ map_once $ mapper_prot.
+
+  Lemma subprot_twice :
+    ⊢ mapper_prot ⊑ mapper_prot_twice.
+  Proof.
+    iApply iProto_le_trans.
+    { iApply subprot_once. }
+    iModIntro.
+    iApply subprot_once.
+  Qed.
 
   Definition mapper_prot_twice_swap :=
-    (<!> MSG (LitV $ true) {{ True }};
+    (<!> MSG (LitV $ true);
      <! (x1 : T) (v1 : val)> MSG v1 {{ IT x1 v1 }};
-     <!> MSG (LitV $ true) {{ True }};
+     <!> MSG (LitV $ true);
      <! (x2 : T) (v2 : val)> MSG v2 {{ IT x2 v2 }};
-     <!> MSG (LitV $ false) {{ True }};
      <? (w1 : val)> MSG w1 {{ IU (f x1) w1 }};
      <? (w2 : val)> MSG w2 {{ IU (f x2) w2 }};
-    END)%proto.
+     mapper_prot)%proto.
 
-  Lemma subprot_twice :
+  Lemma subprot_twice_swap :
     ⊢ mapper_prot ⊑ mapper_prot_twice_swap.
   Proof.
-    rewrite /mapper_prot /mapper_prot_twice.
-    rewrite fixpoint_unfold fixpoint_unfold fixpoint_unfold /mapper_prot_aux.
-    iApply (iProto_le_trans _ mapper_prot_twice).
-    { rewrite /iProto_choice.
-      iExists true. iModIntro.
-      iIntros (x1 v1) "Hv1". iExists x1, v1. iFrame "Hv1". iModIntro.
-      iIntros (w1) "Hw1". iExists w1. iFrame "Hw1". iModIntro.
-      iExists true. iModIntro.
-      iIntros (x2 v2) "Hv2". iExists x2, v2. iFrame "Hv2". iModIntro.
-      iIntros (w2) "Hw2". iExists w2. iFrame "Hw2". iModIntro.
-      iExists false. eauto. }
-    rewrite /mapper_prot_twice /mapper_prot_twice_swap.
+    iApply iProto_le_trans.
+    { iApply subprot_twice. }
     iModIntro.
     iIntros (x1 v1) "Hv1". iExists x1, v1. iFrame "Hv1". iModIntro.
     iIntros (w1) "Hw1".
-    iApply (iProto_le_trans); first by iApply iProto_le_base_swap.
+    iApply iProto_le_trans.
+    { iApply iProto_le_base_swap. }
     iModIntro.
     iIntros (x2 v2) "Hv2".
     iApply (iProto_le_trans with "[Hv2]").
-    { iModIntro. iExists x2, v2. iFrame "Hv2". iModIntro. iApply iProto_le_refl. }
-    iApply (iProto_le_trans).
+    { iModIntro. iExists x2, v2. iFrame "Hv2". iApply iProto_le_refl. }
+    iApply iProto_le_trans.
     { iApply iProto_le_base_swap. }
     iModIntro.
+    iExists (w1). iFrame "Hw1". iModIntro.
+    iApply iProto_le_refl.
+  Qed.
+
+  Definition mapper_prot_twice_swap_end :=
+    (<!> MSG (LitV $ true);
+     <! (x1 : T) (v1 : val)> MSG v1 {{ IT x1 v1 }};
+     <!> MSG (LitV $ true);
+     <! (x2 : T) (v2 : val)> MSG v2 {{ IT x2 v2 }};
+     <!> MSG (LitV $ false);
+     <? (w1 : val)> MSG w1 {{ IU (f x1) w1 }};
+     <? (w2 : val)> MSG w2 {{ IU (f x2) w2 }};
+     END)%proto.
+
+  Lemma subprot_twice_swap_end :
+    ⊢ mapper_prot ⊑ mapper_prot_twice_swap_end.
+  Proof.
+    iApply iProto_le_trans.
+    { iApply subprot_twice_swap. }
+    rewrite /mapper_prot_twice_swap /mapper_prot_twice_swap_end.
+    iModIntro.
+    iIntros (x1 v1) "Hv1". iExists x1, v1. iFrame "Hv1". iModIntro.
+    iModIntro.
+    iIntros (x2 v2) "Hv2". iExists x2, v2. iFrame "Hv2". iModIntro.
     iApply iProto_le_trans.
-    { iModIntro. iIntros (w2) "Hw2".
+    { iIntros (w1) "Hw1". iExists w1. iSplitL. iExact "Hw1". iModIntro.
+      iIntros (w2) "Hw2". iExists w2. iSplitL. iExact "Hw2". iModIntro.
+      rewrite /mapper_prot fixpoint_unfold /mapper_prot_aux /iProto_choice.
+      iExists false. iApply iProto_le_refl. }
+    iApply iProto_le_trans.
+    { iIntros (w1) "Hw1". iExists w1. iSplitL. iExact "Hw1". iModIntro.
+      iIntros (w2) "Hw2".
       iApply iProto_le_trans.
       { iApply iProto_le_base_swap. }
-      iModIntro. iExists (w2). iSplitL. iExact "Hw2". iApply iProto_le_refl. }
+      iModIntro. iExists w2. iSplitL. iExact "Hw2". iApply iProto_le_refl. }
+    iIntros (w1) "Hw1".
     iApply iProto_le_trans.
     { iApply iProto_le_base_swap. }
-    iModIntro.
-    iExists (w1). iFrame "Hw1". iModIntro.
-    eauto.
+    iModIntro. iExists w1. iSplitL. iExact "Hw1". iApply iProto_le_refl.
   Qed.
 
-  Fixpoint mapper_prot_list n : iProto Σ :=
+  Fixpoint mapper_prot_n n prot : iProto Σ :=
     match n with
-    | O   => (<!> MSG (LitV $ false); END)%proto
+    | O   => prot
     | S n => (<!> MSG (LitV $ true);
               <! (x : T) (v : val)> MSG v {{ IT x v }};
-              <? (w : val)> MSG w {{ IU (f x) w }}; mapper_prot_list n)%proto
+              <? (w : val)> MSG w {{ IU (f x) w }}; mapper_prot_n n prot)%proto
     end.
 
-  Lemma subprot_list n :
-    ⊢ mapper_prot ⊑ mapper_prot_list n.
+  Lemma subprot_n n :
+    ⊢ mapper_prot ⊑ mapper_prot_n n mapper_prot.
   Proof.
-    iEval (rewrite /mapper_prot).
-    iInduction n as [|n] "IH"; iEval (rewrite fixpoint_unfold /mapper_prot_aux).
-    - rewrite /iProto_choice. iExists false. eauto.
-    - rewrite /iProto_choice /=.
-      iExists true. iModIntro.
-      iIntros (x1 v1) "Hv1". iExists x1, v1. iFrame "Hv1". iModIntro.
-      iIntros (w1) "Hw1". iExists w1. iFrame "Hw1". iModIntro. iApply "IH".
+    iInduction n as [|n] "IH"=> //.
+    simpl.
+    iApply (iProto_le_trans).
+    { iApply subprot_once. }
+    rewrite /mapper_prot_once.
+    iModIntro. iApply "IH".
   Qed.
 
-  Fixpoint mapper_prot_list_swap_tail xs :=
+  Fixpoint recv_list xs prot :=
     match xs with
-    | []    => END%proto
+    | [] => prot
     | x::xs => (<? (w : val)> MSG w {{ IU (f x) w }};
-                    mapper_prot_list_swap_tail xs)%proto
-    end.
+               recv_list xs prot)%proto
+  end.
 
-  Fixpoint mapper_prot_list_swap n xs :=
+  Lemma recv_list_mono xs prot1 prot2 :
+    prot1 ⊑ prot2 -∗ recv_list xs prot1 ⊑ recv_list xs prot2.
+  Proof.
+    iIntros "Hsub".
+    iInduction xs as [|xs] "IHxs"=> //.
+    simpl.
+    iIntros (w) "Hw". iExists w. iFrame "Hw". iModIntro.
+    by iApply "IHxs".
+  Qed.
+
+  Fixpoint mapper_prot_n_swap n xs prot :=
     match n with
-    | O   => (<!> MSG (LitV $ false); mapper_prot_list_swap_tail (rev xs))%proto
+    | O   => recv_list (rev xs) prot%proto
     | S n => (<!> MSG (LitV $ true);
               <! (x : T) (v : val)> MSG v {{ IT x v }};
-              mapper_prot_list_swap n (x::xs))%proto
+              mapper_prot_n_swap n (x::xs) prot)%proto
     end.
 
-  Fixpoint mapper_prot_list_swap_recv_head xs prot :=
-    match xs with
-    | [] => prot
-    | x::xs => (<? w> MSG w {{ IU (f x) w }};
-               mapper_prot_list_swap_recv_head xs prot)%proto
-  end.
-
-  Lemma mapper_prot_list_swap_forward xs w prot :
-    ⊢ (mapper_prot_list_swap_recv_head xs (<!> MSG w; prot))%proto ⊑
-      (<!> MSG w; mapper_prot_list_swap_recv_head xs prot)%proto.
+  Lemma recv_list_fwd xs v prot :
+    ⊢ recv_list xs (<!> MSG v ; prot)%proto ⊑ (<!> MSG v ; recv_list xs prot)%proto.
   Proof.
     iInduction xs as [|x xs] "IH"=> //=.
-    iIntros (v) "Hv".
-    iApply (iProto_le_trans _ (<!> MSG w; <?> MSG v ;_)%proto); last first.
-    { iModIntro. iExists v. iFrame "Hv". eauto. }
+    iIntros (w) "Hw".
+    iApply (iProto_le_trans _ (<!> MSG v; <?> MSG w ;_)%proto); last first.
+    { iModIntro. iExists w. iFrame "Hw". eauto. }
     iApply iProto_le_trans; last first.
     { iApply iProto_le_base_swap. }
     iModIntro. iApply "IH".
   Qed.
 
-  Lemma subprot_list_swap_general xs n :
-    ⊢  mapper_prot_list_swap_recv_head xs (mapper_prot_list n) ⊑
-       mapper_prot_list_swap n (rev xs).
+  Lemma subprot_n_n_swap n xs prot :
+    ⊢ (recv_list xs (mapper_prot_n n prot)) ⊑ mapper_prot_n_swap n (rev xs) prot.
   Proof.
-    iInduction n as [|n] "IHn" forall (xs).
-    - simpl. rewrite rev_involutive.
+    iInduction n as [|n] "IHn" forall (xs) => //.
+    - iInduction xs as [|x xs] "IHxs"=> //=.
+      rewrite rev_unit /= rev_involutive.
+      iIntros (w1) "Hw1". iExists w1. iFrame "Hw1". iModIntro. iApply "IHxs".
+    - simpl.
       iApply iProto_le_trans.
-      { iApply mapper_prot_list_swap_forward. }
-      iModIntro.
-      iInduction xs as [|x xs] "IHxs"=> //.
-      iIntros (w) "Hw". iExists w. iFrame "Hw". iModIntro. iApply "IHxs".
-    - iApply iProto_le_trans.
-      { iApply mapper_prot_list_swap_forward. }
+      { iApply recv_list_fwd. }
       iModIntro.
       iApply (iProto_le_trans _
               (<! (x : T) (v : val)> MSG v {{ IT x v }};
-               mapper_prot_list_swap_recv_head xs
-    (<? (w : val)> MSG w {{
-     IU (f x) w }}; mapper_prot_list n))%proto).
-      {
-        iInduction xs as [|x xs] "IHxs"=> //=.
+               recv_list xs (<? (w : val)> MSG w {{
+     IU (f x) w }}; mapper_prot_n n prot))%proto).
+      { iInduction xs as [|x xs] "IHxs"=> //.
         iIntros (w) "Hw".
         iApply iProto_le_trans.
         { iModIntro. iApply "IHxs". }
@@ -176,12 +229,45 @@ Section with_Σ.
       iApply "IHxs".
   Qed.
 
-  Lemma subprot_list_swap n :
-    ⊢  mapper_prot ⊑ mapper_prot_list_swap n [].
+  Lemma subprot_n_swap n :
+    ⊢ mapper_prot ⊑ mapper_prot_n_swap n [] mapper_prot.
+  Proof.
+    iApply iProto_le_trans.
+    { iApply (subprot_n n). }
+    iInduction n as [|n] "IHn"=> //=.
+    iModIntro.
+    iIntros (x1 v1) "Hv1". iExists x1, v1. iFrame "Hv1". iModIntro.
+    iApply (subprot_n_n_swap n [x1]).
+  Qed.
+
+  Fixpoint mapper_prot_n_swap_fwd n xs prot :=
+    match n with
+    | O   => (<!> MSG LitV $ false; recv_list (rev xs) prot)%proto
+    | S n => (<!> MSG (LitV $ true);
+              <! (x : T) (v : val)> MSG v {{ IT x v }};
+              mapper_prot_n_swap_fwd n (x::xs) prot)%proto
+    end.
+
+  Lemma subprot_n_swap_n_swap_end n xs :
+    ⊢ mapper_prot_n_swap n xs mapper_prot ⊑ mapper_prot_n_swap_fwd n xs END%proto.
+  Proof.
+    iInduction n as [|n] "IHn" forall (xs)=> /=.
+    - iApply iProto_le_trans.
+      { iApply recv_list_mono.
+        rewrite /mapper_prot fixpoint_unfold /mapper_prot_aux /iProto_choice.
+        iExists false. iApply iProto_le_refl. }
+      iApply recv_list_fwd.
+    - iModIntro.
+      iIntros (x1 v1) "Hv1". iExists x1, v1. iFrame "Hv1". iModIntro.
+      iApply "IHn".
+  Qed.
+
+  Lemma subprot_n_swap_end n :
+    ⊢ mapper_prot ⊑ mapper_prot_n_swap_fwd n [] END%proto.
   Proof.
     iApply iProto_le_trans.
-    { iApply (subprot_list n). }
-    iApply (subprot_list_swap_general [] n).
+    { iApply (subprot_n_swap n). }
+    iApply subprot_n_swap_n_swap_end.
   Qed.
 
 End with_Σ.