diff --git a/substrate/frame/contracts/src/exec.rs b/substrate/frame/contracts/src/exec.rs
index 894667280b71d3a81cdb7ab0f9cc1033562ea3a3..fdb30310ef7053a03701ce555b07e804f05b1aa8 100644
--- a/substrate/frame/contracts/src/exec.rs
+++ b/substrate/frame/contracts/src/exec.rs
@@ -1625,13 +1625,13 @@ mod tests {
 	}
 
 	struct MockCtx<'a> {
-		ext: &'a mut dyn Ext<T = Test>,
+		ext: &'a mut MockStack<'a>,
 		input_data: Vec<u8>,
 	}
 
 	#[derive(Clone)]
 	struct MockExecutable {
-		func: Rc<dyn Fn(MockCtx, &Self) -> ExecResult + 'static>,
+		func: Rc<dyn for<'a> Fn(MockCtx<'a>, &Self) -> ExecResult + 'static>,
 		func_type: ExportedFunction,
 		code_hash: CodeHash<Test>,
 		code_info: CodeInfo<Test>,
@@ -1724,6 +1724,16 @@ mod tests {
 			if let &Constructor = function {
 				Self::increment_refcount(self.code_hash).unwrap();
 			}
+			// # Safety
+			//
+			// We know that we **always** call execute with a `MockStack` in this test.
+			//
+			// # Note
+			//
+			// The transmute is necessary because `execute` has to be generic over all
+			// `E: Ext`. However, `MockExecutable` can't be generic over `E` as it would
+			// constitute a cycle.
+			let ext = unsafe { std::mem::transmute(ext) };
 			if function == &self.func_type {
 				(self.func)(MockCtx { ext, input_data }, &self)
 			} else {