diff --git a/_CoqProject b/_CoqProject
index 1edebe4042a1be5df87b93f1ecc0baa43771f35c..c6c303def85db26ec48340b847851d9f77e42307 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -2,6 +2,8 @@
 -arg -w -arg -notation-overridden,-redundant-canonical-projection,-several-object-files
 theories/prelude/ctx_subst.v
 theories/prelude/tactics.v
+theories/prelude/asubst.v
+
 theories/logic/spec_ra.v
 theories/logic/spec_rules.v
 theories/logic/model.v
diff --git a/theories/prelude/asubst.v b/theories/prelude/asubst.v
new file mode 100644
index 0000000000000000000000000000000000000000..15e1b7c316f8af8ef059b220808f2bb690ce0305
--- /dev/null
+++ b/theories/prelude/asubst.v
@@ -0,0 +1,21 @@
+(** Autosubst helper lemmata *)
+From stdpp Require Export base numbers.
+From Coq.ssr Require Export ssreflect.
+Global Open Scope general_if_scope.
+(* ^ otherwise ssreflects overwrites `if` *)
+From Autosubst Require Export Autosubst.
+
+Section Autosubst_Lemmas.
+  Context {term : Type} {Ids_term : Ids term}
+          {Rename_term : Rename term} {Subst_term : Subst term}
+          {SubstLemmas_term : SubstLemmas term}.
+
+  Lemma iter_up (m x : nat) (f : var → term) :
+    upn m f x = if decide (x < m) then ids x else rename (+m) (f (x - m)).
+  Proof.
+    revert x; induction m as [|m IH]=> -[|x];
+    repeat (case_match || asimpl || rewrite IH); auto with omega.
+    { exfalso. clear Heqs. revert l. lia. }
+    { exfalso. apply n. lia. }
+  Qed.
+End Autosubst_Lemmas.
diff --git a/theories/prelude/tactics.v b/theories/prelude/tactics.v
index cb2ed338218574d1b2c65474f3849657cb157cfd..067834fceda9317698c017cd4e2075abb48f0d20 100644
--- a/theories/prelude/tactics.v
+++ b/theories/prelude/tactics.v
@@ -1,5 +1,8 @@
 From stdpp Require Export tactics.
 From iris.algebra Require Export ofe.
+From iris.base_logic Require Export base_logic lib.invariants.
+From iris.program_logic Require Import weakestpre.
+Import uPred.
 
 (* Hmmm *)
 Ltac my_prepare :=
@@ -16,3 +19,20 @@ Ltac solve_proper_from_ne :=
     match goal with
     | [H : _ ≡ _ |- _] => setoid_rewrite equiv_dist in H; rewrite H
     end] ].
+
+Ltac properness :=
+  repeat match goal with
+  | |- (∃ _: _, _)%I ≡ (∃ _: _, _)%I => apply exist_proper =>?
+  | |- (∀ _: _, _)%I ≡ (∀ _: _, _)%I => apply forall_proper =>?
+  | |- (_ ∧ _)%I ≡ (_ ∧ _)%I => apply and_proper
+  | |- (_ ∨ _)%I ≡ (_ ∨ _)%I => apply or_proper
+  | |- (_ → _)%I ≡ (_ → _)%I => apply impl_proper
+  | |- (_ -∗ _)%I ≡ (_ -∗ _)%I => apply wand_proper
+  | |- (WP _ @ _ {{ _ }})%I ≡ (WP _ @ _ {{ _ }})%I => apply wp_proper =>?
+  | |- (▷ _)%I ≡ (▷ _)%I => apply later_proper
+  | |- (□ _)%I ≡ (□ _)%I => apply intuitionistically_proper
+  | |- (|={_,_}=> _ )%I ≡ (|={_,_}=> _ )%I => apply fupd_proper
+  | |- (_ ∗ _)%I ≡ (_ ∗ _)%I => apply sep_proper
+  | |- (inv _ _)%I ≡ (inv _ _)%I => apply (contractive_proper _)
+  end.
+
diff --git a/theories/typing/interp.v b/theories/typing/interp.v
index 00e4fa56cfb8b15d9a8b40376718740bad6a1c07..c92a1ec053f6fb71131e61b6051534a13801e407 100644
--- a/theories/typing/interp.v
+++ b/theories/typing/interp.v
@@ -4,17 +4,15 @@ From iris.algebra Require Export list.
 From iris.proofmode Require Import tactics.
 From reloc.typing Require Export types.
 From reloc.logic Require Import model.
+From reloc.prelude Require Import tactics asubst.
 From Autosubst Require Import Autosubst.
 
 Section semtypes.
   Context `{relocG Σ}.
-
   (** Type-level lambdas are interpreted as closures *)
-
   (** DF: lty2_forall is defined here because it depends on TApp *)
   Definition lty2_forall (C : lty2 → lty2) : lty2 := Lty2 (λ w1 w2,
     □ ∀ A : lty2, interp_expr ⊤ (TApp w1) (TApp w2) (C A))%I.
-
   Definition lty2_true : lty2 := Lty2 (λ w1 w2, True)%I.
 
   Program Definition ctx_lookup (x : var) : listC lty2C -n> lty2C := λne Δ,
@@ -113,53 +111,30 @@ Notation "⤉ Γ" := (Autosubst_Classes.subst (ren (+1)%nat) <$> Γ) (at level 1
 
 Section interp_ren.
   Context `{relocG Σ}.
-
-  Import uPred.
-  Ltac properness :=
-    repeat match goal with
-    | |- (∃ _: _, _)%I ≡ (∃ _: _, _)%I => apply exist_proper =>?
-    | |- (∀ _: _, _)%I ≡ (∀ _: _, _)%I => apply forall_proper =>?
-    | |- (_ ∧ _)%I ≡ (_ ∧ _)%I => apply and_proper
-    | |- (_ ∨ _)%I ≡ (_ ∨ _)%I => apply or_proper
-    | |- (_ → _)%I ≡ (_ → _)%I => apply impl_proper
-    | |- (_ -∗ _)%I ≡ (_ -∗ _)%I => apply wand_proper
-    | |- (WP _ @ _ {{ _ }})%I ≡ (WP _ @ _ {{ _ }})%I => apply wp_proper =>?
-    | |- (▷ _)%I ≡ (▷ _)%I => apply later_proper
-    | |- (□ _)%I ≡ (□ _)%I => apply intuitionistically_proper
-    | |- (|={_,_}=> _ )%I ≡ (|={_,_}=> _ )%I => apply fupd_proper
-    | |- (_ ∗ _)%I ≡ (_ ∗ _)%I => apply sep_proper
-    | |- (inv _ _)%I ≡ (inv _ _)%I => apply (contractive_proper _)
-    end.
-
+  Implicit Types Δ : list lty2.
 
   (* TODO: why do I need to unfold lty2_car here? *)
-  Lemma interp_ren_up Δ1 Δ2 τ τi :
+  Lemma interp_ren_up (Δ1 Δ2 : list lty2) τ τi :
     interp τ (Δ1 ++ Δ2) ≡ interp (τ.[upn (length Δ1) (ren (+1)%nat)]) (Δ1 ++ τi :: Δ2).
   Proof.
-    revert Δ1 Δ2. induction τ => Δ1 Δ2; simpl; eauto.
-    - intros v1 v2. unfold lty2_car. simpl. properness; eauto.
-        by apply IHÏ„1. by apply IHÏ„2.
-    - intros v1 v2. unfold lty2_car. simpl. properness; eauto.
-        by apply IHÏ„1. by apply IHÏ„2.
-    - intros v1 v2. unfold lty2_car. simpl.
-      unfold interp_expr. properness; eauto.
-        by apply IHÏ„1. by apply IHÏ„2.
+    revert Δ1 Δ2. induction τ => Δ1 Δ2; simpl; eauto;
+    try by
+      (intros ? ?; unfold lty2_car; simpl; properness; repeat f_equiv=>//).
     - apply fixpoint_proper=> Ï„' w1 w2 /=.
       unfold lty2_car. simpl.
       properness; auto. apply (IHÏ„ (_ :: _)).
-    - intros v1 v2; simpl. admit.
-      (* rewrite iter_up; destruct lt_dec as [Hl | Hl]; simpl; properness. *)
-      (* { by rewrite !lookup_app_l. } *)
-      (* change (bi_ofeC (uPredI (iResUR Σ))) with (uPredC (iResUR Σ)). *)
-      (* rewrite !lookup_app_r; [|lia ..]. *)
-      (* assert ((length Δ1 + S (x - length Δ1) - length Δ1) = S (x - length Δ1)) as Hwat. *)
-      (* { lia. } *)
-      (* rewrite Hwat. simpl. done. *)
+    - intros v1 v2; simpl.
+      rewrite iter_up. case_decide; simpl; properness.
+      { by rewrite !lookup_app_l. }
+      change (bi_ofeC (uPredI (iResUR Σ))) with (uPredC (iResUR Σ)).
+      rewrite !lookup_app_r; [|lia..].
+      assert ((length Δ1 + S (x - length Δ1) - length Δ1) = S (x - length Δ1))%nat as Hwat.
+      { lia. }
+      rewrite Hwat. simpl. done.
     - intros v1 v2; unfold lty2_car; simpl; unfold interp_expr;
         simpl; properness; auto. apply (IHÏ„ (_ :: _)).
     - intros ??; unfold lty2_car; simpl; properness; auto. apply (IHÏ„ (_ :: _)).
-    - intros ??; unfold lty2_car; simpl; properness; auto. by apply IHÏ„.
-  Admitted.
+  Qed.
 
   Lemma interp_ren A Δ (Γ : gmap string type) :
     ((λ τ, interp τ (A::Δ)) <$> ⤉Γ) ≡ ((λ τ, interp τ Δ) <$> Γ).
@@ -170,8 +145,53 @@ Section interp_ren.
     symmetry. apply (interp_ren_up []).
   Qed.
 
+  Lemma interp_weaken (Δ1 Π Δ2 : list lty2) τ :
+    interp (τ.[upn (length Δ1) (ren (+ length Π))]) (Δ1 ++ Π ++ Δ2)
+    ≡ interp τ (Δ1 ++ Δ2).
+  Proof.
+    revert Δ1 Π Δ2. induction τ=> Δ1 Π Δ2; simpl; eauto;
+    try by
+      (intros ? ?; simpl; unfold lty2_car; simpl; repeat f_equiv =>//).
+    - apply fixpoint_proper=> Ï„i ?? /=.
+      unfold lty2_car; simpl.
+      properness; auto. apply (IHÏ„ (_ :: _)).
+    - intros ??; simpl; properness; auto.
+      rewrite iter_up; case_decide; properness; simpl.
+      { by rewrite !lookup_app_l. }
+      rewrite !lookup_app_r ;[| lia ..]. do 3 f_equiv. lia.
+    - intros ??; simpl; unfold lty2_car; simpl; unfold interp_expr.
+      properness; auto. by apply (IHÏ„ (_ :: _)).
+    - intros ??; unfold lty2_car; simpl; properness; auto.
+        by apply (IHÏ„ (_ :: _)).
+  Qed.
+
+  Lemma interp_subst_up (Δ1 Δ2 : list lty2) τ τ' :
+    interp τ (Δ1 ++ interp τ' Δ2 :: Δ2)
+    ≡ interp (τ.[upn (length Δ1) (τ' .: ids)]) (Δ1 ++ Δ2).
+  Proof.
+    revert Δ1 Δ2; induction τ=> Δ1 Δ2; simpl; eauto;
+    try by
+      (intros ? ?; unfold lty2_car; simpl; properness; repeat f_equiv=>//).
+    - apply fixpoint_proper=> Ï„i ?? /=.
+      unfold lty2_car. simpl.
+      properness; auto. apply (IHÏ„ (_ :: _)).
+    - intros w1 w2; simpl.
+      rewrite iter_up; case_decide; simpl; properness.
+      { by rewrite !lookup_app_l. }
+      rewrite !lookup_app_r; [|lia..].
+      case EQ: (x - length Δ1)%nat => [|n]; simpl.
+      { symmetry.
+        pose (HW := interp_weaken [] Δ1 Δ2 τ' w1 w2).
+        etrans; last by apply HW.
+        asimpl. reflexivity. }
+      rewrite !lookup_app_r; [|lia ..]. repeat f_equiv. lia.
+    - intros ??. unfold lty2_car; simpl; unfold interp_expr.
+      properness; auto. apply (IHÏ„ (_ :: _)).
+    - intros ??; unfold lty2_car; simpl; properness; auto. apply (IHÏ„ (_ :: _)).
+  Qed.
+
   Lemma interp_subst Δ2 τ τ' :
     interp τ (interp τ' Δ2 :: Δ2) ≡ interp (τ.[τ'/]) Δ2.
-  Proof. Admitted.
+  Proof. apply (interp_subst_up []). Qed.
 
 End interp_ren.