diff --git a/crates/fuel-core/src/executor.rs b/crates/fuel-core/src/executor.rs index 1453ee84d7..99310c1720 100644 --- a/crates/fuel-core/src/executor.rs +++ b/crates/fuel-core/src/executor.rs @@ -892,7 +892,12 @@ where Input::MessageSigned { message_id, .. } | Input::MessagePredicate { message_id, .. } => { // mark message id as spent - db.storage::().insert(message_id, &())?; + let was_already_spent = + db.storage::().insert(message_id, &())?; + // ensure message wasn't already marked as spent + if was_already_spent.is_some() { + return Err(ExecutorError::MessageAlreadySpent(*message_id)) + } // cleanup message contents db.storage::().remove(message_id)?; } diff --git a/crates/types/src/services/executor.rs b/crates/types/src/services/executor.rs index e20a6ef473..c062147994 100644 --- a/crates/types/src/services/executor.rs +++ b/crates/types/src/services/executor.rs @@ -270,6 +270,8 @@ pub enum Error { InvalidBlockId, #[error("No matching utxo for contract id ${0:#x}")] ContractUtxoMissing(ContractId), + #[error("message already spent {0:#x}")] + MessageAlreadySpent(MessageId), } impl From for Error {