diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/RealmExtensions.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/RealmExtensions.kt
index 8e658aab5c..8934bdb0b6 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/RealmExtensions.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/extensions/RealmExtensions.kt
@@ -19,7 +19,5 @@ package im.vector.matrix.android.internal.extensions
 import io.realm.RealmObject
 
 internal fun RealmObject.assertIsManaged() {
-    if (!isManaged) {
-        throw IllegalStateException("${javaClass.simpleName} entity should be managed to use this function")
-    }
+    check(isManaged) { "${javaClass.simpleName} entity should be managed to use this function" }
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
index 68669171c7..11be821d7e 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/relation/DefaultRelationService.kt
@@ -32,10 +32,8 @@ import im.vector.matrix.android.api.session.room.timeline.TimelineEvent
 import im.vector.matrix.android.api.util.Cancelable
 import im.vector.matrix.android.api.util.Optional
 import im.vector.matrix.android.api.util.toOptional
-import im.vector.matrix.android.internal.database.helper.addSendingEvent
 import im.vector.matrix.android.internal.database.mapper.asDomain
 import im.vector.matrix.android.internal.database.model.EventAnnotationsSummaryEntity
-import im.vector.matrix.android.internal.database.model.RoomEntity
 import im.vector.matrix.android.internal.database.query.where
 import im.vector.matrix.android.internal.di.UserId
 import im.vector.matrix.android.internal.session.room.send.EncryptEventWorker
@@ -67,9 +65,7 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
 
     override fun sendReaction(targetEventId: String, reaction: String): Cancelable {
         val event = eventFactory.createReactionEvent(roomId, targetEventId, reaction)
-                .also {
-                    saveLocalEcho(it)
-                }
+                .also { saveLocalEcho(it) }
         val sendRelationWork = createSendEventWork(event, true)
         TimelineSendEventWorkCommon.postWork(context, roomId, sendRelationWork)
         return CancelableWork(context, sendRelationWork.id)
@@ -89,9 +85,8 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
                     // TODO?
                 }
                 data.redactEventId?.let { toRedact ->
-                    val redactEvent = eventFactory.createRedactEvent(roomId, toRedact, null).also {
-                        saveLocalEcho(it)
-                    }
+                    val redactEvent = eventFactory.createRedactEvent(roomId, toRedact, null)
+                            .also { saveLocalEcho(it) }
                     val redactWork = createRedactEventWork(redactEvent, toRedact, null)
 
                     TimelineSendEventWorkCommon.postWork(context, roomId, redactWork)
@@ -125,9 +120,7 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
                                  compatibilityBodyText: String): Cancelable {
         val event = eventFactory
                 .createReplaceTextEvent(roomId, targetEventId, newBodyText, newBodyAutoMarkdown, msgType, compatibilityBodyText)
-                .also {
-                    saveLocalEcho(it)
-                }
+                .also { saveLocalEcho(it) }
         return if (cryptoService.isRoomEncrypted(roomId)) {
             val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
             val workRequest = createSendEventWork(event, false)
@@ -149,9 +142,7 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
                         replyToEdit,
                         originalTimelineEvent,
                         newBodyText, true, MessageType.MSGTYPE_TEXT, compatibilityBodyText)
-                .also {
-                    saveLocalEcho(it)
-                }
+                .also { saveLocalEcho(it) }
         return if (cryptoService.isRoomEncrypted(roomId)) {
             val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
             val workRequest = createSendEventWork(event, false)
@@ -174,9 +165,9 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
     }
 
     override fun replyToMessage(eventReplied: TimelineEvent, replyText: String, autoMarkdown: Boolean): Cancelable? {
-        val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText, autoMarkdown)?.also {
-            saveLocalEcho(it)
-        } ?: return null
+        val event = eventFactory.createReplyTextEvent(roomId, eventReplied, replyText, autoMarkdown)
+                ?.also { saveLocalEcho(it) }
+                ?: return null
 
         return if (cryptoService.isRoomEncrypted(roomId)) {
             val encryptWork = createEncryptEventWork(event, listOf("m.relates_to"))
@@ -220,10 +211,6 @@ internal class DefaultRelationService @AssistedInject constructor(@Assisted priv
      * the same transaction id is received (in unsigned data)
      */
     private fun saveLocalEcho(event: Event) {
-        monarchy.writeAsync { realm ->
-            val roomEntity = RoomEntity.where(realm, roomId = roomId).findFirst()
-                    ?: return@writeAsync
-            roomEntity.addSendingEvent(event)
-        }
+        eventFactory.saveLocalEcho(monarchy, event)
     }
 }
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/TextContent.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/TextContent.kt
index ff31fc30c8..27b68e95eb 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/TextContent.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/send/TextContent.kt
@@ -26,7 +26,6 @@ import im.vector.matrix.android.api.util.ContentUtils.extractUsefulTextFromReply
  */
 data class TextContent(
         val text: String,
-
         val formattedText: String? = null
 ) {
     fun takeFormatted() = formattedText ?: text
diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventDecryptor.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventDecryptor.kt
index 62ae5f621b..967dd66397 100644
--- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventDecryptor.kt
+++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/internal/session/room/timeline/TimelineEventDecryptor.kt
@@ -39,8 +39,8 @@ internal class TimelineEventDecryptor(
         override fun onNewSession(roomId: String?, senderKey: String, sessionId: String) {
             synchronized(unknownSessionsFailure) {
                 unknownSessionsFailure[sessionId]
+                        ?.toList()
                         .orEmpty()
-                        .toList()
                         .also {
                             unknownSessionsFailure[sessionId]?.clear()
                         }
@@ -55,7 +55,7 @@ internal class TimelineEventDecryptor(
     // Set of eventIds which are currently decrypting
     private val existingRequests = mutableSetOf<String>()
     // sessionId -> list of eventIds
-    private val unknownSessionsFailure = mutableMapOf<String, MutableList<String>>()
+    private val unknownSessionsFailure = mutableMapOf<String, MutableSet<String>>()
 
     fun start() {
         executor = Executors.newSingleThreadExecutor()
@@ -84,11 +84,10 @@ internal class TimelineEventDecryptor(
             }
         }
         synchronized(existingRequests) {
-            if (eventId in existingRequests) {
+            if (!existingRequests.add(eventId)) {
                 Timber.d("Skip Decryption request for event $eventId, already requested")
                 return
             }
-            existingRequests.add(eventId)
         }
         executor?.execute {
             Realm.getInstance(realmConfiguration).use { realm ->
@@ -120,7 +119,7 @@ internal class TimelineEventDecryptor(
                 event.content?.toModel<EncryptedEventContent>()?.let { content ->
                     content.sessionId?.let { sessionId ->
                         synchronized(unknownSessionsFailure) {
-                            val list = unknownSessionsFailure.getOrPut(sessionId) { ArrayList() }
+                            val list = unknownSessionsFailure.getOrPut(sessionId) { mutableSetOf() }
                             list.add(eventId)
                         }
                     }
diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt
index 7e00295a48..36f26452f0 100644
--- a/tools/check/forbidden_strings_in_code.txt
+++ b/tools/check/forbidden_strings_in_code.txt
@@ -156,3 +156,6 @@ Formatter\.formatFileSize===1
 
 ### Use TextUtils.formatFileSize with short format param to true
 Formatter\.formatShortFileSize===1
+
+### Use kotlin stdlib to test or compare strings
+android\.text\.TextUtils