diff --git a/_CoqProject b/_CoqProject
index 2ba6e8277457b4a8270442bfc92a51eead1d0ea9..5f6394889ab8ab02e269ea3a4233094483f26b56 100644
--- a/_CoqProject
+++ b/_CoqProject
@@ -63,6 +63,7 @@ algebra/updates.v
 algebra/local_updates.v
 algebra/gset.v
 algebra/coPset.v
+algebra/double_negation.v
 program_logic/model.v
 program_logic/adequacy.v
 program_logic/lifting.v
diff --git a/algebra/double_negation.v b/algebra/double_negation.v
new file mode 100644
index 0000000000000000000000000000000000000000..a016681c14a23439141f80f313499d6225ce1bb1
--- /dev/null
+++ b/algebra/double_negation.v
@@ -0,0 +1,141 @@
+From iris.algebra Require Import upred.
+Import upred.
+
+(* In this file we show that the rvs can be thought of a kind of
+   step-indexed double-negation when our meta-logic is classical *)
+
+(* To define this, we need a way to talk about iterated later modalities: *)
+Definition uPred_laterN {M} (n : nat) (P : uPred M) : uPred M :=
+  Nat.iter n uPred_later P.
+Instance: Params (@uPred_laterN) 2.
+Notation "â–·^ n P" := (uPred_laterN n P)
+  (at level 20, n at level 9, right associativity,
+   format "â–·^ n  P") : uPred_scope.
+
+Definition uPred_nnvs {M} (P: uPred M) : uPred M :=
+  ∀ n, (P -★ ▷^n False) -★ ▷^n False.
+
+Notation "|=n=> Q" := (uPred_nnvs Q)
+  (at level 99, Q at level 200, format "|=n=>  Q") : uPred_scope.
+Notation "P =n=> Q" := (P ⊢ |=n=> Q)
+  (at level 99, Q at level 200, only parsing) : C_scope.
+Notation "P =n=★ Q" := (P -★ |=n=> Q)%I
+  (at level 99, Q at level 200, format "P  =n=★  Q") : uPred_scope.
+
+(* Our goal is to prove that:
+  (1) |=n=> has (nearly) all the properties of the |=r=> modality that are used in Iris
+  (2) If our meta-logic is classical, then |=n=> and |=r=> are equivalent
+*)
+
+Section rvs_nn.
+Context {M : ucmraT}.
+Implicit Types φ : Prop.
+Implicit Types P Q : uPred M.
+Implicit Types A : Type.
+Implicit Types x : M.
+Import uPred.
+
+(* Helper lemmas about iterated later modalities *)
+Lemma laterN_big n a x φ: ✓{n} x →  a ≤ n → (▷^a (■ φ))%I n x → φ.
+Proof.
+  induction 2 as [| ?? IHle].
+  - induction a; repeat (rewrite //= || uPred.unseal). 
+    intros Hlater. apply IHa; auto using cmra_validN_S.
+    move:Hlater; repeat (rewrite //= || uPred.unseal). 
+  - intros. apply IHle; auto using cmra_validN_S.
+    eapply uPred_closed; eauto using cmra_validN_S.
+Qed.
+
+Lemma laterN_small n a x φ: ✓{n} x →  n < a → (▷^a (■ φ))%I n x.
+Proof.
+  induction 2.
+  - induction n as [| n IHn]; [| move: IHn];
+      repeat (rewrite //= || uPred.unseal).
+    naive_solver eauto using cmra_validN_S.
+  - induction n as [| n IHn]; [| move: IHle];
+      repeat (rewrite //= || uPred.unseal).
+    red; rewrite //=. intros.
+    eapply (uPred_closed _ _ (S n)); eauto using cmra_validN_S.
+Qed.
+
+(* First we prove that rvs implies nn *)
+Lemma rvs_nn P: (|=r=> P) ⊢ |=n=> P.
+Proof.
+  split. rewrite /uPred_nnvs. repeat uPred.unseal. intros n x ? Hrvs a.
+  red; rewrite //= => n' yf ??.
+  edestruct Hrvs as (x'&?&?); eauto.
+  case (decide (a ≤ n')).
+  - intros Hle Hwand.
+    exfalso. eapply laterN_big; last (uPred.unseal; eapply (Hwand n' x')); eauto.
+    * rewrite comm. done. 
+    * rewrite comm. done. 
+  - intros; assert (n' < a). omega.
+    move: laterN_small. uPred.unseal.
+    naive_solver.
+Qed.
+
+Lemma nn_intro P : P =n=> P.
+Proof. apply forall_intro=>?. apply wand_intro_l, wand_elim_l. Qed.
+Lemma nn_mono P Q : (P ⊢ Q) → (|=n=> P) =n=> Q.
+Proof.
+  intros HPQ. apply forall_intro=>n.
+  apply wand_intro_l.  rewrite -{1}HPQ.
+  rewrite /uPred_nnvs (forall_elim n).
+  apply wand_elim_r.
+Qed.
+(* Question: is there a clean direct proof of this? *)
+(*
+Lemma nn_trans P : (|=n=> |=n=> P) =n=> P.
+Proof.
+  apply forall_intro=>n. apply wand_intro_l.
+  rewrite /uPred_nnvs.
+  rewrite {1}(nn_intro (P -★ ▷^ n False)).
+  rewrite /uPred_nnvs. rewrite comm (forall_elim n).
+  apply wand_elim_r. Qed.
+*)
+Lemma nn_frame_r P R : (|=n=> P) ★ R =n=> P ★ R.
+Proof.
+  apply forall_intro=>n. apply wand_intro_r.
+  rewrite (comm _ P) -wand_curry.
+  rewrite /uPred_nnvs (forall_elim n).
+  by rewrite -assoc wand_elim_r wand_elim_l.
+Qed.
+Lemma nn_ownM_updateP x (Φ : M → Prop) :
+  x ~~>: Φ → uPred_ownM x =n=> ∃ y, ■ Φ y ∧ uPred_ownM y.
+Proof. intros. rewrite -rvs_nn. by apply rvs_ownM_updateP. Qed.
+Lemma except_last_nn P : ◇ (|=n=> P) ⊢ (|=n=> ◇ P).
+Proof.
+  rewrite /uPred_except_last. apply or_elim.
+  - by rewrite -nn_intro -or_intro_l.
+  - by apply nn_mono, or_intro_r. 
+Qed.
+
+(* Now we show, nn implies rvs, for which we need a classical axiom: *)
+Require Coq.Logic.Classical_Pred_Type.
+Lemma nn_rvs P:  (|=n=> P) ⊢ (|=r=> P).
+Proof.
+  rewrite /uPred_nnvs.
+  split. uPred.unseal; red; rewrite //=.
+  intros n x ? Hforall k yf Hle ?.
+  apply Classical_Pred_Type.not_all_not_ex.
+  intros Hfal.
+  specialize (Hforall k k).
+  eapply laterN_big; last (uPred.unseal; red; rewrite //=; eapply Hforall);
+    eauto.
+  red; rewrite //= => n' x' ???.
+  case (decide (n' = k)); intros.
+  - subst. exfalso. eapply Hfal. rewrite (comm op); eauto.
+  - assert (n' < k). omega.
+    move: laterN_small. uPred.unseal. naive_solver.
+Qed.
+
+(* Questions:
+   1) Can one prove an adequacy theorem for the |=n=> modality without axioms?
+   2) If not, can we prove a weakened form of adequacy, such as :
+
+      Lemma adequacy' φ n : (True ⊢ Nat.iter n (λ P, |=n=> ▷ P) (■ φ)) → ¬¬ φ.
+
+   3) Do the basic properties of the |=r=> modality (rvs_intro, rvs_mono, rvs_trans, rvs_frame_r,
+      rvs_ownM_updateP, and adequacy) characterize |=r=>?
+ *)
+End rvs_nn.
\ No newline at end of file