diff --git a/src/status_im/extensions/ethereum.cljs b/src/status_im/extensions/ethereum.cljs index 91999e4dd6..479c7746b2 100644 --- a/src/status_im/extensions/ethereum.cljs +++ b/src/status_im/extensions/ethereum.cljs @@ -26,11 +26,13 @@ (fn [_ [_ on-failure message]] (when on-failure (on-failure {:value message})))) -(defn- wrap-with-resolution [db arguments address-keyword f] +(defn- wrap-with-resolution "function responsible to resolve ens taken from argument and call the specified function with resolved address" + [db arguments address-keyword f] (let [address (get arguments address-keyword) - first-address (if (vector? address) ;; currently we only support one ens for address + ;; currently we only support one ens for address + first-address (if (vector? address) (first address) address)] (if (ens/is-valid-eth-name? first-address) @@ -100,7 +102,7 @@ (cond (= "0x" result) nil (and outputs result) - (abi-spec/decode (string/replace result #"^0x" "") outputs) + (abi-spec/decode result outputs) :else result))) (defn- execute-ethcall [_ {:keys [to method params outputs on-success on-failure]}] @@ -236,38 +238,47 @@ (let [eventid (str event "(" (string/join "," params) ")")] (abi-spec/sha3 eventid))) -; Return a vector without indexed elements -(defn- get-no-indexed [X indexed] +(defn- get-no-indexed + "Return a vector without indexed elements" + [X indexed] (as-> (into [] (take (count X) (range))) $ (zipmap $ X) (into [] (vals (apply dissoc $ indexed))))) -; Return a vector with indexed elements -(defn- get-indexed [X indexed] +(defn- get-indexed + "Return a vector with indexed elements" + [X indexed] (let [keys (into [] (take (count X) (range)))] (mapv #((zipmap keys X) %) indexed))) -; Return the hint with the specified event (Topic0) from a vector of event hints given by the user -(defn- get-hint [hints first-topic] +(defn- get-hint + "Return the hint with the specified event (Topic0) from a vector of event hints given by the user" + [hints first-topic] (as-> hints $ (mapv #(event-topic-enc (% :event) (% :params)) $) (.indexOf $ first-topic) (get hints $))) -; Return a map with all data params decoded -(defn- decode-data [data hint] +(defn- decode-data + "Return a map with all data params decoded" + [data hint] (let [indexes (hint :indexed) params (get-no-indexed (hint :params) indexes) - names (mapv keyword (get-no-indexed (hint :names) indexes)) ; Exclude indexed params and names from decode in data, these are decoded in topics + ;; Exclude indexed params and names from decode in data, + ;; these are decoded in topics + names (mapv keyword (get-no-indexed (hint :names) indexes)) data-values (mapv (partial apply str) (partition 64 (string/replace-first data #"0x" "")))] (zipmap names (mapv abi-spec/hex-to-value data-values params)))) -; This assumes that Topic 0 is filtered and return a map with all topics decoded -(defn- decode-topics [topics hint] - (zipmap [:topic1 :topic2 :topic3] (mapv abi-spec/hex-to-value topics (get-indexed (hint :params) (hint :indexed))))) ; Solidity indexed event params may number up to 3 (max 4 Topics) +(defn- decode-topics + "This assumes that Topic 0 is filtered and return a map with all topics decoded" + [topics hint] + ;; Solidity indexed event params may number up to 3 (max 4 Topics) + (zipmap [:topic1 :topic2 :topic3] (mapv abi-spec/hex-to-value topics (get-indexed (hint :params) (hint :indexed))))) -; Flatten the input of event provided by an developer of extensions and return a 1 depth vector -(defn- flatten-input [input] +(defn- flatten-input + "Flatten the input of event provided by an developer of extensions and return a 1 depth vector" + [input] (into [] (flatten input))) (defn parse-log [events-hints {:keys [address transactionHash blockHash transactionIndex topics blockNumber logIndex removed data]}] @@ -276,7 +287,7 @@ :address address :removed removed} - ; filter useless topic 0 and decode topics + ;; filter useless topic 0 and decode topics (when (and topics (seq events-hints)) {:topics (decode-topics (filterv #(not (= (first topics) %)) topics) (get-hint events-hints (first topics)))}) (when (and data (seq events-hints)) {:data (decode-data data (get-hint events-hints (first topics)))}) (when logIndex {:log-index (abi-spec/hex-to-number logIndex)}) diff --git a/src/status_im/utils/ethereum/abi_spec.cljs b/src/status_im/utils/ethereum/abi_spec.cljs index 77ead115f1..f9854a43db 100644 --- a/src/status_im/utils/ethereum/abi_spec.cljs +++ b/src/status_im/utils/ethereum/abi_spec.cljs @@ -386,6 +386,8 @@ (hex-to-value val type))))) (defn decode [bytes types] - (when-not (empty? bytes) - (let [offsets (get-offsets types)] - (map (dec-type bytes) offsets types)))) + (when bytes + (let [bytes (subs bytes 2)] + (when-not (empty? bytes) + (let [offsets (get-offsets types)] + (map (dec-type bytes) offsets types)))))) diff --git a/src/status_im/utils/ethereum/stickers.cljs b/src/status_im/utils/ethereum/stickers.cljs index e22ebf2685..d78fe5d128 100644 --- a/src/status_im/utils/ethereum/stickers.cljs +++ b/src/status_im/utils/ethereum/stickers.cljs @@ -20,7 +20,7 @@ (ethereum/call web3 (ethereum/call-params contract "getPackData(uint256)" (ethereum/int->hex pack-id)) (fn [_ data] - (cb (when data (abi-spec/decode (subs data 2) ["bytes4[]" "address" "bool" "uint256" "uint256" "bytes"])))))) + (cb (abi-spec/decode data ["bytes4[]" "address" "bool" "uint256" "uint256" "bytes"]))))) (defn owned-tokens "Returns vector of owned tokens ids in the contract by address" @@ -28,7 +28,7 @@ (ethereum/call web3 (ethereum/call-params contract "tokensOwnedBy(address)" (ethereum/normalized-address address)) (fn [_ data] - (cb (when data (first (abi-spec/decode (subs data 2) ["uint256[]"]))))))) + (cb (first (abi-spec/decode data ["uint256[]"])))))) (defn token-pack-id "Returns pack id in the contract by token id" diff --git a/test/cljs/status_im/test/utils/ethereum/abi_spec.cljs b/test/cljs/status_im/test/utils/ethereum/abi_spec.cljs index 35e9a0456e..7082b4fd2e 100644 --- a/test/cljs/status_im/test/utils/ethereum/abi_spec.cljs +++ b/test/cljs/status_im/test/utils/ethereum/abi_spec.cljs @@ -25,7 +25,7 @@ "0x809a9e55000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000000003e8"))) (deftest test-decode - (is (= (abi-spec/decode "000000000000000000000000000000000000000000000000000000005bc741cd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000013b86dbf1a83c9e6a492914a0ee39e8a5b7eb60700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e516d533152484e4a57414b356e426f6f57454d34654d644268707a35666e325764557473457357754a4b79356147000000000000000000000000000000000000" + (is (= (abi-spec/decode "0x000000000000000000000000000000000000000000000000000000005bc741cd00000000000000000000000000000000000000000000000000000000000000a000000000000000000000000013b86dbf1a83c9e6a492914a0ee39e8a5b7eb60700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002e516d533152484e4a57414b356e426f6f57454d34654d644268707a35666e325764557473457357754a4b79356147000000000000000000000000000000000000" ["uint256" "bytes" "address" "uint256" "uint256"]) '(1539785165 "0x516d533152484e4a57414b356e426f6f57454d34654d644268707a35666e325764557473457357754a4b79356147" @@ -33,27 +33,27 @@ 0 0))) - (is (= (abi-spec/decode "0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000d7621dc58210000" + (is (= (abi-spec/decode "0x0000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000000000000000000000000000000d7621dc58210000" ["uint256" "uint256"]) '(1000000000000000000 970000000000000000))) - (is (= (abi-spec/decode "000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000000003e8" + (is (= (abi-spec/decode "0x000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee000000000000000000000000eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee00000000000000000000000000000000000000000000000000000000000003e8" ["address" "address" "uint256"]) '("0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee" 1000))) - (is (= (abi-spec/decode "00000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001" + (is (= (abi-spec/decode "0x00000000000000000000000000000000000000000000000000000000000000450000000000000000000000000000000000000000000000000000000000000001" ["uint32" "bool"]) '(69 true))) (is (= (map abi-spec/hex-to-utf8 - (first (abi-spec/decode "61626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000" + (first (abi-spec/decode "0x61626300000000000000000000000000000000000000000000000000000000006465660000000000000000000000000000000000000000000000000000000000" ["bytes3[2]"]))) '("abc" "def"))) - (is (= (abi-spec/decode "0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" + (is (= (abi-spec/decode "0x0000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003" ["string" "bool" "uint256[]"]) '("dave" true [1 2 3]))) - (is (= (abi-spec/decode "00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000" + (is (= (abi-spec/decode "0x00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000" ["uint" "uint32[]" "bytes10" "bytes"]) '(291 [1110 1929] "31323334353637383930" "0x48656c6c6f2c20776f726c6421"))))