Skip to content

Commit

Permalink
fix collecting contract address
Browse files Browse the repository at this point in the history
  • Loading branch information
llbartekll committed Feb 7, 2025
1 parent 801ece1 commit e7a4900
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Sources/WalletConnectRelay/RelayClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ public final class RelayClient {
return
}
#endif
let request = Publish(params: .init(topic: topic, message: payload, ttl: ttl, prompt: prompt, tag: tag, correlationId: nil, tvfData: nil)).asRPCRequest()
let request = Publish(params: .init(topic: topic, message: payload, ttl: ttl, prompt: prompt, tag: tag, correlationId: coorelationId, tvfData: tvfData)).asRPCRequest()
let message = try request.asJSONEncodedString()

logger.debug("[Publish] Sending payload on topic: \(topic)")
Expand Down
24 changes: 14 additions & 10 deletions Sources/WalletConnectUtils/TVFCollector.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation
struct EthSendTransaction: Codable {
let from: String?
let to: String?
let data: String?
let data: String? // This field contains the call data
let value: String?
}

Expand Down Expand Up @@ -99,7 +99,8 @@ public struct TVFCollector {
return nil
}

// 2. Gather contract addresses if this is eth_sendTransaction
// 2. Gather contract addresses if this is an eth_sendTransaction
// Now we check the call data (the "data" field) instead of "to".
let contractAddresses = extractContractAddressesIfNeeded(
rpcMethod: rpcMethod,
rpcParams: rpcParams
Expand All @@ -125,7 +126,8 @@ public struct TVFCollector {

// MARK: - Private Helpers

/// Parse contract addresses from `rpcParams` if the method is `"eth_sendTransaction"`.
/// Parse contract addresses from `rpcParams` if the method is "eth_sendTransaction".
/// Now, instead of checking the "to" field, we check the "data" field.
private func extractContractAddressesIfNeeded(rpcMethod: String,
rpcParams: AnyCodable) -> [String]? {
guard rpcMethod == Self.ETH_SEND_TRANSACTION else {
Expand All @@ -134,12 +136,13 @@ public struct TVFCollector {
do {
// Attempt to decode the array of EthSendTransaction from AnyCodable
let transactions = try rpcParams.get([EthSendTransaction].self)
if let firstTo = transactions.first?.to {
// Use our contract data check: if it is valid contract call data, then return it.
if TVFCollector.isValidContractData(firstTo) {
return [firstTo]
} else {
return nil
if let transaction = transactions.first,
let callData = transaction.data,
!callData.isEmpty,
TVFCollector.isValidContractData(callData) {
// If the call data is valid contract call data, return the "to" address.
if let to = transaction.to {
return [to]
}
}
} catch {
Expand Down Expand Up @@ -199,12 +202,13 @@ public struct TVFCollector {

extension TVFCollector {
/// Checks whether a given hex string (possibly prefixed with "0x") is valid contract call data.
/// This function is now meant to check the transaction's call data.
public static func isValidContractData(_ data: String) -> Bool {
var hex = data
if hex.hasPrefix("0x") {
hex = String(hex.dropFirst(2))
}
// Ensure there are at least 136 hex characters (8 for method, 64 for recipient, 64 for amount)
// Require at least 73 hex characters:
guard !hex.isEmpty, hex.count >= 73 else { return false }
let methodId = hex.prefix(8)
guard !methodId.isEmpty else { return false }
Expand Down
23 changes: 11 additions & 12 deletions Tests/WalletConnectUtilsTests/TVFCollectorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ final class TVFCollectorTests: XCTestCase {
return .response(AnyCodable(any: value))
}

// Helper: define sample .error(RPCError)
private func makeError(code: Int, message: String) -> RPCResult {
return .error(JSONRPCError(code: code, message: message))
}
Expand All @@ -29,14 +28,14 @@ final class TVFCollectorTests: XCTestCase {
XCTAssertNil(data)
}

func testSessionRequest_EthSendTransaction_ParsesContractAddress() {
// "eth_sendTransaction" — parse the "to" field from rpcParams.
// Here we supply a normal address string "0x1234567890abcdef" which is not long enough to be valid contract data.
// Therefore, the updated collector should return an empty array rather than returning the address.
func testSessionRequest_EthSendTransaction_NormalTransaction_NoContractData() {
// Supply a normal transaction with empty call data.
// In this case the transaction is not a contract call so contractAddresses should be nil.
let rpcParams = AnyCodable([
[
"from": "0x9876543210fedcba",
"to": "0x1234567890abcdef"
"to": "0x1234567890abcdef",
"data": "" // empty data indicates no contract call
]
])
let data = tvf.collect(
Expand All @@ -49,8 +48,7 @@ final class TVFCollectorTests: XCTestCase {
XCTAssertNotNil(data)
XCTAssertEqual(data?.rpcMethods, ["eth_sendTransaction"])
XCTAssertEqual(data?.chainId?.absoluteString, "eip155:1")
// Expecting an empty array because "0x1234567890abcdef" is invalid contract call data.
XCTAssertEqual(data?.contractAddresses, nil)
XCTAssertNil(data?.contractAddresses)
XCTAssertNil(data?.txHashes)
}

Expand All @@ -73,12 +71,13 @@ final class TVFCollectorTests: XCTestCase {
// Construct a valid contract call data string:
// - 8 hex chars for method ID: "abcd1234"
// - 64 hex chars for recipient: "0000000000000000000000001111111111111111111111111111111111111111"
// - 64 hex chars for amount: "00000000000000000000000000000000000000000000000000000000000000f0"
// - At least 1 hex char for amount (here we use 62 zeros then "f0")
let validContractData = "0xabcd12340000000000000000000000111111111111111111111111111111111111111110000000000000000000000000000000000000000000000000000000000000f0"
let rpcParams = AnyCodable([
[
"from": "0x9876543210fedcba",
"to": validContractData
"to": "0x1234567890abcdef",
"data": validContractData
]
])
let data = tvf.collect(
Expand All @@ -89,8 +88,8 @@ final class TVFCollectorTests: XCTestCase {
tag: 1108
)
XCTAssertNotNil(data)
// When contract data is valid the collector returns the value.
XCTAssertEqual(data?.contractAddresses, [validContractData])
// Expecting the valid contract call data to be detected so that the "to" address is returned.
XCTAssertEqual(data?.contractAddresses, ["0x1234567890abcdef"])
}

// MARK: - Session Response (tag = 1109)
Expand Down

0 comments on commit e7a4900

Please sign in to comment.