diff --git a/Sources/Web3Core/Contract/ContractProtocol.swift b/Sources/Web3Core/Contract/ContractProtocol.swift index 06e3c01a7..43a4c1543 100755 --- a/Sources/Web3Core/Contract/ContractProtocol.swift +++ b/Sources/Web3Core/Contract/ContractProtocol.swift @@ -210,8 +210,8 @@ extension ContractProtocol { func decodeInputData(_ data: Data) -> [String: Any]? { guard data.count >= 4 else { return nil } - let methodId = data[0..<4].toHexString() - let data = data[4...] + let methodId = data[data.startIndex ..< data.startIndex + 4].toHexString() + let data = data[(data.startIndex + 4)...] return decodeInputData(methodId, data: data) } } @@ -333,14 +333,14 @@ extension DefaultContractProtocol { public func decodeInputData(_ data: Data) -> [String: Any]? { guard data.count % 32 == 4 else { return nil } - let methodSignature = data[0..<4].toHexString().addHexPrefix().lowercased() + let methodSignature = data[data.startIndex ..< data.startIndex + 4].toHexString().addHexPrefix().lowercased() guard let function = methods[methodSignature]?.first else { return nil } - return function.decodeInputData(Data(data[4 ..< data.count])) + return function.decodeInputData(Data(data[data.startIndex + 4 ..< data.startIndex + data.count])) } public func getFunctionCalled(_ data: Data) -> ABI.Element.Function? { guard data.count >= 4 else { return nil } - return methods[data[0..<4].toHexString().addHexPrefix()]?.first + return methods[data[data.startIndex ..< data.startIndex + 4].toHexString().addHexPrefix()]?.first } } diff --git a/Sources/Web3Core/EthereumABI/ABIDecoding.swift b/Sources/Web3Core/EthereumABI/ABIDecoding.swift index cb220fec6..5fb9df99b 100755 --- a/Sources/Web3Core/EthereumABI/ABIDecoding.swift +++ b/Sources/Web3Core/EthereumABI/ABIDecoding.swift @@ -34,27 +34,28 @@ extension ABIDecoder { guard let elementItself = elData, let nextElementPointer = nextPtr else { return (nil, nil) } + let startIndex = UInt64(elementItself.startIndex) switch type { case .uint(let bits): guard elementItself.count >= 32 else {break} let mod = BigUInt(1) << bits - let dataSlice = elementItself[0 ..< 32] + let dataSlice = elementItself[startIndex ..< startIndex + 32] let v = BigUInt(dataSlice) % mod return (v, type.memoryUsage) case .int(let bits): guard elementItself.count >= 32 else {break} let mod = BigInt(1) << bits - let dataSlice = elementItself[0 ..< 32] + let dataSlice = elementItself[startIndex ..< startIndex + 32] let v = BigInt.fromTwosComplement(data: dataSlice) % mod return (v, type.memoryUsage) case .address: guard elementItself.count >= 32 else {break} - let dataSlice = elementItself[12 ..< 32] + let dataSlice = elementItself[startIndex + 12 ..< startIndex + 32] let address = EthereumAddress(dataSlice) return (address, type.memoryUsage) case .bool: guard elementItself.count >= 32 else {break} - let dataSlice = elementItself[0 ..< 32] + let dataSlice = elementItself[startIndex ..< startIndex + 32] let v = BigUInt(dataSlice) if v == BigUInt(36) || v == BigUInt(32) || @@ -69,33 +70,33 @@ extension ABIDecoder { } case .bytes(let length): guard elementItself.count >= 32 else {break} - let dataSlice = elementItself[0 ..< length] - return (dataSlice, type.memoryUsage) + let dataSlice = elementItself[startIndex ..< startIndex + length] + return (Data(dataSlice), type.memoryUsage) case .string: guard elementItself.count >= 32 else {break} - var dataSlice = elementItself[0 ..< 32] + var dataSlice = elementItself[startIndex ..< startIndex + 32] let length = UInt64(BigUInt(dataSlice)) - guard elementItself.count >= 32+length else {break} + guard elementItself.count >= 32 + length else {break} dataSlice = elementItself[32 ..< 32 + length] guard let string = String(data: dataSlice, encoding: .utf8) else {break} return (string, type.memoryUsage) case .dynamicBytes: guard elementItself.count >= 32 else {break} - var dataSlice = elementItself[0 ..< 32] + var dataSlice = elementItself[startIndex ..< startIndex + 32] let length = UInt64(BigUInt(dataSlice)) - guard elementItself.count >= 32+length else {break} - dataSlice = elementItself[32 ..< 32 + length] - return (dataSlice, nextElementPointer) + guard elementItself.count >= 32 + length else {break} + dataSlice = elementItself[startIndex + 32 ..< startIndex + 32 + length] + return (Data(dataSlice), nextElementPointer) case .array(type: let subType, length: let length): switch type.arraySize { case .dynamicSize: if subType.isStatic { // uint[] like, expect length and elements guard elementItself.count >= 32 else {break} - var dataSlice = elementItself[0 ..< 32] + var dataSlice = elementItself[startIndex ..< startIndex + 32] let length = UInt64(BigUInt(dataSlice)) guard elementItself.count >= 32 + subType.memoryUsage*length else {break} - dataSlice = elementItself[32 ..< 32 + subType.memoryUsage*length] + dataSlice = elementItself[startIndex + 32 ..< startIndex + 32 + subType.memoryUsage*length] var subpointer: UInt64 = 32 var toReturn = [Any]() for _ in 0 ..< length { @@ -108,10 +109,10 @@ extension ABIDecoder { } else { // in principle is true for tuple[], so will work for string[] too guard elementItself.count >= 32 else {break} - var dataSlice = elementItself[0 ..< 32] + var dataSlice = elementItself[startIndex ..< startIndex + 32] let length = UInt64(BigUInt(dataSlice)) guard elementItself.count >= 32 else {break} - dataSlice = Data(elementItself[32 ..< elementItself.count]) + dataSlice = Data(elementItself[startIndex + 32 ..< UInt64(elementItself.count)]) var subpointer: UInt64 = 0 var toReturn = [Any]() for _ in 0 ..< length { @@ -179,8 +180,8 @@ extension ABIDecoder { } case .function: guard elementItself.count >= 32 else {break} - let dataSlice = elementItself[8 ..< 32] - return (dataSlice, type.memoryUsage) + let dataSlice = elementItself[startIndex + 8 ..< startIndex + 32] + return (Data(dataSlice), type.memoryUsage) } return (nil, nil) } @@ -188,12 +189,12 @@ extension ABIDecoder { fileprivate static func followTheData(type: ABI.Element.ParameterType, data: Data, pointer: UInt64 = 0) -> (elementEncoding: Data?, nextElementPointer: UInt64?) { if type.isStatic { guard data.count >= pointer + type.memoryUsage else {return (nil, nil)} - let elementItself = data[pointer ..< pointer + type.memoryUsage] + let elementItself = data[data.startIndex + Int(pointer) ..< data.startIndex + Int(pointer + type.memoryUsage)] let nextElement = pointer + type.memoryUsage return (Data(elementItself), nextElement) } else { guard data.count >= pointer + type.memoryUsage else {return (nil, nil)} - let dataSlice = data[pointer ..< pointer + type.memoryUsage] + let dataSlice = data[data.startIndex + Int(pointer) ..< data.startIndex + Int(pointer + type.memoryUsage)] let bn = BigUInt(dataSlice) if bn > UInt64.max || bn >= data.count { // there are ERC20 contracts that use bytes32 instead of string. Let's be optimistic and return some data @@ -209,7 +210,8 @@ extension ABIDecoder { return (nil, nil) } let elementPointer = UInt64(bn) - let elementItself = data[elementPointer ..< UInt64(data.count)] + let startIndex = UInt64(data.startIndex) + let elementItself = data[startIndex + elementPointer ..< startIndex + UInt64(data.count)] let nextElement = pointer + type.memoryUsage return (Data(elementItself), nextElement) } diff --git a/Sources/Web3Core/EthereumABI/ABIElements.swift b/Sources/Web3Core/EthereumABI/ABIElements.swift index cdf38ba38..5dca0b331 100755 --- a/Sources/Web3Core/EthereumABI/ABIElements.swift +++ b/Sources/Web3Core/EthereumABI/ABIElements.swift @@ -397,9 +397,9 @@ extension ABI.Element.Function { /// 4) `messageLength` is used to determine where message bytes end to decode string correctly. /// 5) The rest of the `data` must be 0 bytes or empty. if data.bytes.count >= 100, - Data(data[0..<4]) == Data.fromHex("08C379A0"), - BigInt(data[4..<36]) == 32, - let messageLength = Int(Data(data[36..<68]).toHexString(), radix: 16), + Data(data[data.startIndex ..< data.startIndex + 4]) == Data.fromHex("08C379A0"), + BigInt(data[data.startIndex + 4 ..< data.startIndex + 36]) == 32, + let messageLength = Int(Data(data[data.startIndex + 36 ..< data.startIndex + 68]).toHexString(), radix: 16), let message = String(bytes: data.bytes[68..<(68+messageLength)], encoding: .utf8), (68+messageLength == data.count || data.bytes[68+messageLength..= 4, let errors = errors, - let customError = errors[data[0..<4].toHexString().stripHexPrefix()] { + let customError = errors[data[data.startIndex ..< data.startIndex + 4].toHexString().stripHexPrefix()] { var errorResponse: [String: Any] = ["_success": false, "_abortedByRevertOrRequire": true, "_error": customError.errorDeclaration] if (data.count > 32 && !customError.inputs.isEmpty), - let decodedInputs = ABIDecoder.decode(types: customError.inputs, data: Data(data[4..