diff --git a/Sources/Ethereum/EthereumAddress.swift b/Sources/Ethereum/EthereumAddress.swift index 681fe52..501a4d5 100644 --- a/Sources/Ethereum/EthereumAddress.swift +++ b/Sources/Ethereum/EthereumAddress.swift @@ -18,21 +18,15 @@ public struct EthereumAddress: Address, Hashable { /// Validates that the string is a valid address. static public func isValid(string: String) -> Bool { - guard let data = Data(hexString: string) else { - return false - } - - let uppers = CharacterSet(charactersIn: "ABCDEF") - let lowers = CharacterSet(charactersIn: "abcdef") - let hasUppers = (string.rangeOfCharacter(from: uppers) != nil) - let hasLowers = (string.rangeOfCharacter(from: lowers) != nil) - - // If all characters are uppercase or lowercase, return true - if (hasUppers && !hasLowers) || (!hasUppers && hasLowers) { + guard !isAdressWithoutChecksum(string: string) else { return true } + guard let data = Data(hexString: string) else { + return false + } + let eip55String = EthereumAddress.computeEIP55String(for: data) return string == eip55String } @@ -56,7 +50,7 @@ public struct EthereumAddress: Address, Hashable { /// Creates an address with an hexadecimal string representation. public init?(string: String) { - guard let data = Data(hexString: string), data.count == EthereumAddress.size else { + guard let data = Data(hexString: string), EthereumAddress.isValid(data: data) else { return nil } self.data = data @@ -97,4 +91,29 @@ extension EthereumAddress { return string } + + fileprivate static func isAdressWithoutChecksum(string: String) -> Bool { + guard string.hasPrefix("0x"), let data = Data(hexString: string), isValid(data: data) else { + return false + } + + var hasUppers: Bool = false + var hasLowers: Bool = false + + for character in string { + switch character { + case "A", "B", "C", "D", "E", "F": hasUppers = true + case "a", "b", "c", "d", "e", "f": hasLowers = true + default: break + } + } + + // If all characters are uppercase or lowercase, return true + if (hasUppers && !hasLowers) || (!hasUppers && hasLowers) { + return true + } + + return false + } + } diff --git a/Tests/Ethereum/EthereumAddressTests.swift b/Tests/Ethereum/EthereumAddressTests.swift index 55fccce..37c44a2 100644 --- a/Tests/Ethereum/EthereumAddressTests.swift +++ b/Tests/Ethereum/EthereumAddressTests.swift @@ -17,7 +17,6 @@ class EthereumAddressTests: XCTestCase { XCTAssertTrue(EthereumAddress.isValid(string: "0xfa52274dd61e1643d2205169732f29114bc240b3")) } - func testInvalid() { XCTAssertNil(EthereumAddress(string: "abc")) XCTAssertNil(EthereumAddress(string: "aaeb60f3e94c9b9a09f33669435e7ef1beaed"))