diff --git a/Processes/Sibyll/Interaction.cc b/Processes/Sibyll/Interaction.cc
index 8300462c6de387e9f0ed62d8adca49db96c3fcd3..d738dc81caa233416e74b1ca56d5e6e3d5662473 100644
--- a/Processes/Sibyll/Interaction.cc
+++ b/Processes/Sibyll/Interaction.cc
@@ -312,26 +312,26 @@ namespace corsika::process::sibyll {
           auto const pCoM = Vector<hepmomentum_d>(csPrime, tmp);
           HEPEnergyType const eCoM = psib.GetEnergy();
           auto const Plab = boost.fromCoM(FourVector(eCoM, pCoM));
-
-          auto const pid = process::sibyll::ConvertFromSibyll(psib.GetPID());
+          auto const p3lab = Plab.GetSpaceLikeComponents();
+          assert(p3lab.GetCoordinateSystem() == originalCS); // just to be sure!
 
           // add to corsika stack
           auto pnew = vP.AddSecondary(
               tuple<particles::Code, units::si::HEPEnergyType, stack::MomentumVector,
                     geometry::Point, units::si::TimeType>{
-                  pid, Plab.GetTimeLikeComponent(), Plab.GetSpaceLikeComponents(), pOrig,
-                  tOrig});
+                  process::sibyll::ConvertFromSibyll(psib.GetPID()),
+                  Plab.GetTimeLikeComponent(), p3lab, pOrig, tOrig});
 
           Plab_final += pnew.GetMomentum();
           Elab_final += pnew.GetEnergy();
           Ecm_final += psib.GetEnergy();
         }
         cout << "conservation (all GeV):" << endl
-             << "Ecm_initial=" << Ecm / 1_GeV << " Ecm_final=" << Ecm_final / 1_GeV
-             << endl
-             << "Elab_initial=" << eProjectileLab / 1_GeV
-             << " Elab_final=" << Elab_final / 1_GeV
-             << " diff (%)=" << (Elab_final / eProjectileLab / get_nwounded() - 1) * 100
+             << "Ecm_initial(per nucleon)=" << Ecm / 1_GeV << " Ecm_final(per nucleon)="
+             << Ecm_final * 2. / (get_nwounded() + 1) / 1_GeV << endl
+             << "Elab_initial=" << Etot / 1_GeV << " Elab_final=" << Elab_final / 1_GeV
+             << " diff (%)=" << (Elab_final / Etot / get_nwounded() - 1) * 100
+             << " E in nucleons=" << constants::nucleonMass * get_nwounded() / 1_GeV
              << endl
              << "Plab_initial=" << (pProjectileLab / 1_GeV).GetComponents()
              << ", Plab_final=" << (Plab_final / 1_GeV).GetComponents() << endl;
diff --git a/Processes/Sibyll/testSibyll.cc b/Processes/Sibyll/testSibyll.cc
index 308e8ea1835d8bea50f57c79d4074024d595ba3f..dee7ee31b722aaabdde09e864c0bbfe80d0b36b3 100644
--- a/Processes/Sibyll/testSibyll.cc
+++ b/Processes/Sibyll/testSibyll.cc
@@ -117,7 +117,7 @@ TEST_CASE("SibyllInterface", "[processes]") {
 
   random::RNGManager::GetInstance().RegisterRandomStream("sibyll");
 
-  SECTION("InteractionInterface") {
+  SECTION("InteractionInterface - low energy") {
 
     setup::Stack stack;
     const HEPEnergyType E0 = 60_GeV;
@@ -136,8 +136,99 @@ TEST_CASE("SibyllInterface", "[processes]") {
     Interaction model;
 
     [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile);
-    [[maybe_unused]] auto const pSum = sumMomentum(view, cs);
+    auto const pSum = sumMomentum(view, cs);
+
+    /*
+      Interactions between hadrons (h) and nuclei (A) in Sibyll are treated in the
+      hadron-nucleon center-of-mass frame (hnCoM). The incoming hadron (h) and
+      nucleon (N) are assumed massless, such that the energy and momentum in the hnCoM are
+      : E_i_cm = 0.5 * SQS and P_i_cm = +- 0.5 * SQS  where i is either the projectile
+      hadron or the target nucleon and SQS is the hadron-nucleon center-of-mass energy.
+
+      The true energies and momenta, accounting for the hadron masses, are: E_i = ( S +
+      m_i**2 - m_j**2 ) / (2 * SQS) and Pcm = +-
+      sqrt( (S-(m_j+m_i)**2) * (s-(m_j-m_i)**2) ) / (2*SQS) where m_i is the projectiles
+      mass and m_j is the target particles mass. In terms of lab. frame variables Pcm =
+      m_j * Plab_i / SQS, where Plab_i is the momentum of the projectile (i) in the lab.
+      and m_j is the mass of the target, i.e. the particle at rest (usually a nucleon).
+
+      Any hadron-nucleus event can contain several nucleon interactions. In case of Nw
+      (number of wounded nucleons) nucleons interacting in the hadron-nucleus interaction,
+      the total energy and momentum in the hadron(i)-nucleon(N) center-of-mass frame are:
+      momentum: p_projectile + p_nucleon_1 + p_nucleon_2 + .... p_nucleon_Nw = -(Nw-1) *
+      Pcm with center-of-mass momentum Pcm = p_projectile = - p_nucleon_i. For the energy:
+      E_projectile + E_nucleon_1 + ... E_nucleon_Nw = E_projectile + Nw * E_nucleon.
+
+      Using the above definitions of center-of-mass energies and momenta this leads to the
+      total energy: E_tot = SQS/2 * (1+Nw) + (m_N**2-m_i**2)/(2*SQS) * (Nw-1) and P_tot
+      = -m_N * Plab_i / SQS * (Nw-1).
+
+      A Lorentztransformation of these quantities to the lab. frame recovers Plab_i for
+      the total momentum, so momentum is exactly conserved, and Elab_i + Nw * m_N for the
+      total energy. Not surprisingly the total energy differs from the total energy before
+      the collision by the mass of the additional nucleons (Nw-1)*m_N. In relative terms
+      the additional energy is entirely negligible and as it is not kinetic energy there
+      is zero influence on the shower development.
+
+      Due to the ommission of the hadron masses in Sibyll, the total energy and momentum
+      in the center-of-mass system after the collision are just: E_tot = SQS/2 * (1+Nw)
+      and P_tot = SQS/2 * (1-Nw). After the Lorentztransformation the total momentum in
+      the lab. thus differs from the initial value by (1-Nw)/2 * ( m_N + m_i**2 / (2 *
+      Plab_i) ) and momentum is NOT conserved. Note however that the second term quickly
+      vanishes as the lab. momentum of the projectile increases. The first term is fixed
+      as it depends only on the number of additional nucleons, in relative terms it is
+      always small at high energies.
+
+      For this reason the numerical precision in these tests is limited to 5% to still
+      pass at low energies and no absolute check is implemented, e.g.
+
+          CHECK(pSum.GetComponents(cs).GetX() / P0 == Approx(1).margin(0.05));
+          CHECK((pSum - plab).norm()/1_GeV == Approx(0).margin(plab.norm() * 0.05/1_GeV));
+
+      /FR'2020
+
+      See also:
+
+      Issue 272 / MR 204
+      https://gitlab.ikp.kit.edu/AirShowerPhysics/corsika/-/merge_requests/204
+
+    */
+
+    CHECK(pSum.GetComponents(cs).GetX() / P0 == Approx(1).margin(0.05));
+    CHECK(pSum.GetComponents(cs).GetY() / 1_GeV == Approx(0).margin(1e-4));
+    CHECK(pSum.GetComponents(cs).GetZ() / 1_GeV == Approx(0).margin(1e-4));
+
+    CHECK((pSum - plab).norm() / 1_GeV == Approx(0).margin(plab.norm() * 0.05 / 1_GeV));
+    CHECK(pSum.norm() / P0 == Approx(1).margin(0.05));
+    [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle);
+  }
+
+  SECTION("InteractionInterface - high energy") {
+
+    setup::Stack stack;
+    const HEPEnergyType E0 = 60_EeV;
+    HEPMomentumType P0 =
+        sqrt(E0 * E0 - particles::Proton::GetMass() * particles::Proton::GetMass());
+    auto plab = corsika::stack::MomentumVector(cs, {P0, 0_eV, 0_eV});
+    geometry::Point pos(cs, 0_m, 0_m, 0_m);
+    auto particle = stack.AddParticle(
+        std::tuple<particles::Code, units::si::HEPEnergyType,
+                   corsika::stack::MomentumVector, geometry::Point, units::si::TimeType>{
+            particles::Code::Proton, E0, plab, pos, 0_ns});
+    particle.SetNode(nodePtr);
+    corsika::stack::SecondaryView view(particle);
+    auto projectile = view.GetProjectile();
+
+    Interaction model;
+
+    [[maybe_unused]] const process::EProcessReturn ret = model.DoInteraction(projectile);
+    auto const pSum = sumMomentum(view, cs);
+    CHECK(pSum.GetComponents(cs).GetX() / P0 == Approx(1).margin(0.001));
+    CHECK(pSum.GetComponents(cs).GetY() / 1_GeV == Approx(0).margin(1e-4));
+    CHECK(pSum.GetComponents(cs).GetZ() / 1_GeV == Approx(0).margin(1e-4));
 
+    CHECK((pSum - plab).norm() / 1_GeV == Approx(0).margin(plab.norm() * 0.001 / 1_GeV));
+    CHECK(pSum.norm() / P0 == Approx(1).margin(0.05));
     [[maybe_unused]] const GrammageType length = model.GetInteractionLength(particle);
   }