From a3c626988ccc1e184c447d287d49304327a5f1a1 Mon Sep 17 00:00:00 2001 From: FlorianSAW Date: Tue, 18 Oct 2022 17:12:50 +0100 Subject: [PATCH 1/4] Add getCreate2Address function --- Sources/Core/Toolbox/EthereumUtils.swift | 26 ++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 Sources/Core/Toolbox/EthereumUtils.swift diff --git a/Sources/Core/Toolbox/EthereumUtils.swift b/Sources/Core/Toolbox/EthereumUtils.swift new file mode 100644 index 00000000..48a667f3 --- /dev/null +++ b/Sources/Core/Toolbox/EthereumUtils.swift @@ -0,0 +1,26 @@ + +import Foundation + +enum getCreateAddressError: Error { +case saltNot32BytesError +case initCodeHashNot32BytesError +} + +public func getCreate2Address(from: String, salt: [UInt8], initCodeHash: [UInt8]) throws -> String { + if salt.count != 32 { + throw getCreateAddressError.saltNot32BytesError + } + if initCodeHash.count != 32 { + throw getCreateAddressError.initCodeHashNot32BytesError + } + + var concat: [UInt8] = [0xff] + concat.append(contentsOf: try EthereumAddress(hex: from, eip55: false).rawAddress) + concat.append(contentsOf: salt) + concat.append(contentsOf: initCodeHash) + + let hash = concat.sha3(.keccak256) + let hexSlice = Array(hash[12...]) + + return try EthereumAddress(hex: hexSlice.toHexString(), eip55: false).hex(eip55: true) +} From 346ab94335a3b3acc7243e45cb745e0384117d7a Mon Sep 17 00:00:00 2001 From: FlorianSAW Date: Tue, 18 Oct 2022 17:25:57 +0100 Subject: [PATCH 2/4] Change public func to be member of struct --- Sources/Core/Toolbox/EthereumUtils.swift | 34 +++++++++++++----------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/Sources/Core/Toolbox/EthereumUtils.swift b/Sources/Core/Toolbox/EthereumUtils.swift index 48a667f3..cff29d4e 100644 --- a/Sources/Core/Toolbox/EthereumUtils.swift +++ b/Sources/Core/Toolbox/EthereumUtils.swift @@ -6,21 +6,25 @@ case saltNot32BytesError case initCodeHashNot32BytesError } -public func getCreate2Address(from: String, salt: [UInt8], initCodeHash: [UInt8]) throws -> String { - if salt.count != 32 { - throw getCreateAddressError.saltNot32BytesError - } - if initCodeHash.count != 32 { - throw getCreateAddressError.initCodeHashNot32BytesError - } +public struct EthereumUtils { - var concat: [UInt8] = [0xff] - concat.append(contentsOf: try EthereumAddress(hex: from, eip55: false).rawAddress) - concat.append(contentsOf: salt) - concat.append(contentsOf: initCodeHash) - - let hash = concat.sha3(.keccak256) - let hexSlice = Array(hash[12...]) + public static func getCreate2Address(from: String, salt: [UInt8], initCodeHash: [UInt8]) throws -> String { + if salt.count != 32 { + throw getCreateAddressError.saltNot32BytesError + } + if initCodeHash.count != 32 { + throw getCreateAddressError.initCodeHashNot32BytesError + } + + var concat: [UInt8] = [0xff] + concat.append(contentsOf: try EthereumAddress(hex: from, eip55: false).rawAddress) + concat.append(contentsOf: salt) + concat.append(contentsOf: initCodeHash) + + let hash = concat.sha3(.keccak256) + let hexSlice = Array(hash[12...]) + + return try EthereumAddress(hex: hexSlice.toHexString(), eip55: false).hex(eip55: true) + } - return try EthereumAddress(hex: hexSlice.toHexString(), eip55: false).hex(eip55: true) } From 123317e8a8b7545efcea94eb84e9e0e129d7b0fa Mon Sep 17 00:00:00 2001 From: FlorianSAW Date: Wed, 19 Oct 2022 12:28:30 +0100 Subject: [PATCH 3/4] Add test cases for EthereumUtils.getCreate2Address Overload getCreate2Address function to allow init code input without hashing --- Sources/Core/Toolbox/EthereumUtils.swift | 19 +++-- .../ToolboxTests/EthereumUtilsTests.swift | 71 +++++++++++++++++++ 2 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift diff --git a/Sources/Core/Toolbox/EthereumUtils.swift b/Sources/Core/Toolbox/EthereumUtils.swift index cff29d4e..5ce1da65 100644 --- a/Sources/Core/Toolbox/EthereumUtils.swift +++ b/Sources/Core/Toolbox/EthereumUtils.swift @@ -1,19 +1,21 @@ import Foundation -enum getCreateAddressError: Error { -case saltNot32BytesError -case initCodeHashNot32BytesError -} + public struct EthereumUtils { + enum Error: Swift.Error { + case saltNot32BytesError + case initCodeHashNot32BytesError + } + public static func getCreate2Address(from: String, salt: [UInt8], initCodeHash: [UInt8]) throws -> String { if salt.count != 32 { - throw getCreateAddressError.saltNot32BytesError + throw Error.saltNot32BytesError } if initCodeHash.count != 32 { - throw getCreateAddressError.initCodeHashNot32BytesError + throw Error.initCodeHashNot32BytesError } var concat: [UInt8] = [0xff] @@ -27,4 +29,9 @@ public struct EthereumUtils { return try EthereumAddress(hex: hexSlice.toHexString(), eip55: false).hex(eip55: true) } + public static func getCreate2Address(from: String, salt: [UInt8], initCode: [UInt8]) throws -> String { + let initCodeHash: [UInt8] = initCode.sha3(.keccak256) + return try getCreate2Address(from: from, salt: salt, initCodeHash: initCodeHash) + } + } diff --git a/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift b/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift new file mode 100644 index 00000000..00747d5a --- /dev/null +++ b/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift @@ -0,0 +1,71 @@ + +import Quick +import Nimble +@testable import Web3 + +final class EthereumUtilsTests: QuickSpec { + + override func spec() { + + describe("getCreate2Address") { + context("various addresses") { + let address0: String = "0x0000000000000000000000000000000000000000" + let salt0: [UInt8] = "0x0000000000000000000000000000000000000000000000000000000000000000".hexToBytes() + let init_code_hash0: [UInt8] = "0x00".hexToBytes().sha3(.keccak256) + + let address1: String = "0xdeadbeef00000000000000000000000000000000" + let salt1: [UInt8] = "0x000000000000000000000000feed000000000000000000000000000000000000".hexToBytes() + let init_code_hash1: [UInt8] = "0xdeadbeef".hexToBytes().sha3(.keccak256) + + let address2: String = "0x00000000000000000000000000000000deadbeef" + let salt2: [UInt8] = "0x00000000000000000000000000000000000000000000000000000000cafebabe".hexToBytes() + let init_code0: [UInt8] = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".hexToBytes() + let init_code1: [UInt8] = "0x".hexToBytes() + + it("should be 0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38") { + let result = try EthereumUtils.getCreate2Address( + from: address0, salt: salt0, initCodeHash: init_code_hash0) + expect(result) == "0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38" + } + + it("should be 0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3") { + let result = try EthereumUtils.getCreate2Address( + from: address1, salt: salt0, initCodeHash: init_code_hash0) + expect(result) == "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3" + } + + it("should be 0xD04116cDd17beBE565EB2422F2497E06cC1C9833") { + let result = try EthereumUtils.getCreate2Address( + from: address1, salt: salt1, initCodeHash: init_code_hash0) + expect(result) == "0xD04116cDd17beBE565EB2422F2497E06cC1C9833" + } + + it("should be 0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e") { + let result = try EthereumUtils.getCreate2Address( + from: address0, salt: salt0, initCodeHash: init_code_hash1) + expect(result) == "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e" + } + + it("should be 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7") { + let result = try EthereumUtils.getCreate2Address( + from: address2, salt: salt2, initCodeHash: init_code_hash1) + expect(result) == "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7" + } + + it("should be 0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C") { + let result = try EthereumUtils.getCreate2Address( + from: address2, salt: salt2, initCode: init_code0) + expect(result) == "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C" + } + + it("should be 0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0") { + let result = try EthereumUtils.getCreate2Address( + from: address0, salt: salt0, initCode: init_code1) + expect(result) == "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0" + } + + } + + } + } +} From 1e91fc2712aa4339a7a85dbd7f7df3439e0c66d3 Mon Sep 17 00:00:00 2001 From: Koray Koska <11356621+koraykoska@users.noreply.github.com> Date: Fri, 21 Oct 2022 14:26:28 +0100 Subject: [PATCH 4/4] chore: reformat to match style --- Sources/Core/Toolbox/EthereumUtils.swift | 28 +++++++---------- .../ToolboxTests/EthereumUtilsTests.swift | 31 +++++++++---------- 2 files changed, 26 insertions(+), 33 deletions(-) diff --git a/Sources/Core/Toolbox/EthereumUtils.swift b/Sources/Core/Toolbox/EthereumUtils.swift index 5ce1da65..7b841859 100644 --- a/Sources/Core/Toolbox/EthereumUtils.swift +++ b/Sources/Core/Toolbox/EthereumUtils.swift @@ -1,37 +1,33 @@ - import Foundation - - public struct EthereumUtils { - + enum Error: Swift.Error { - case saltNot32BytesError - case initCodeHashNot32BytesError + case saltNot32BytesError + case initCodeHashNot32BytesError } - - public static func getCreate2Address(from: String, salt: [UInt8], initCodeHash: [UInt8]) throws -> String { + + public static func getCreate2Address(from: EthereumAddress, salt: [UInt8], initCodeHash: [UInt8]) throws -> String { if salt.count != 32 { throw Error.saltNot32BytesError } if initCodeHash.count != 32 { throw Error.initCodeHashNot32BytesError } - + var concat: [UInt8] = [0xff] - concat.append(contentsOf: try EthereumAddress(hex: from, eip55: false).rawAddress) + concat.append(contentsOf: from.rawAddress) concat.append(contentsOf: salt) concat.append(contentsOf: initCodeHash) - + let hash = concat.sha3(.keccak256) let hexSlice = Array(hash[12...]) - + return try EthereumAddress(hex: hexSlice.toHexString(), eip55: false).hex(eip55: true) } - - public static func getCreate2Address(from: String, salt: [UInt8], initCode: [UInt8]) throws -> String { - let initCodeHash: [UInt8] = initCode.sha3(.keccak256) + + public static func getCreate2Address(from: EthereumAddress, salt: [UInt8], initCode: [UInt8]) throws -> String { + let initCodeHash = initCode.sha3(.keccak256) return try getCreate2Address(from: from, salt: salt, initCodeHash: initCodeHash) } - } diff --git a/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift b/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift index 00747d5a..71147913 100644 --- a/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift +++ b/Tests/Web3Tests/ToolboxTests/EthereumUtilsTests.swift @@ -1,71 +1,68 @@ - import Quick import Nimble @testable import Web3 final class EthereumUtilsTests: QuickSpec { - + override func spec() { - + describe("getCreate2Address") { context("various addresses") { - let address0: String = "0x0000000000000000000000000000000000000000" + let address0 = try! EthereumAddress(hex: "0x0000000000000000000000000000000000000000", eip55: false) let salt0: [UInt8] = "0x0000000000000000000000000000000000000000000000000000000000000000".hexToBytes() let init_code_hash0: [UInt8] = "0x00".hexToBytes().sha3(.keccak256) - - let address1: String = "0xdeadbeef00000000000000000000000000000000" + + let address1 = try! EthereumAddress(hex: "0xdeadbeef00000000000000000000000000000000", eip55: false) let salt1: [UInt8] = "0x000000000000000000000000feed000000000000000000000000000000000000".hexToBytes() let init_code_hash1: [UInt8] = "0xdeadbeef".hexToBytes().sha3(.keccak256) - - let address2: String = "0x00000000000000000000000000000000deadbeef" + + let address2 = try! EthereumAddress(hex: "0x00000000000000000000000000000000deadbeef", eip55: false) let salt2: [UInt8] = "0x00000000000000000000000000000000000000000000000000000000cafebabe".hexToBytes() let init_code0: [UInt8] = "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef".hexToBytes() let init_code1: [UInt8] = "0x".hexToBytes() - + it("should be 0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38") { let result = try EthereumUtils.getCreate2Address( from: address0, salt: salt0, initCodeHash: init_code_hash0) expect(result) == "0x4D1A2e2bB4F88F0250f26Ffff098B0b30B26BF38" } - + it("should be 0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3") { let result = try EthereumUtils.getCreate2Address( from: address1, salt: salt0, initCodeHash: init_code_hash0) expect(result) == "0xB928f69Bb1D91Cd65274e3c79d8986362984fDA3" } - + it("should be 0xD04116cDd17beBE565EB2422F2497E06cC1C9833") { let result = try EthereumUtils.getCreate2Address( from: address1, salt: salt1, initCodeHash: init_code_hash0) expect(result) == "0xD04116cDd17beBE565EB2422F2497E06cC1C9833" } - + it("should be 0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e") { let result = try EthereumUtils.getCreate2Address( from: address0, salt: salt0, initCodeHash: init_code_hash1) expect(result) == "0x70f2b2914A2a4b783FaEFb75f459A580616Fcb5e" } - + it("should be 0x60f3f640a8508fC6a86d45DF051962668E1e8AC7") { let result = try EthereumUtils.getCreate2Address( from: address2, salt: salt2, initCodeHash: init_code_hash1) expect(result) == "0x60f3f640a8508fC6a86d45DF051962668E1e8AC7" } - + it("should be 0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C") { let result = try EthereumUtils.getCreate2Address( from: address2, salt: salt2, initCode: init_code0) expect(result) == "0x1d8bfDC5D46DC4f61D6b6115972536eBE6A8854C" } - + it("should be 0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0") { let result = try EthereumUtils.getCreate2Address( from: address0, salt: salt0, initCode: init_code1) expect(result) == "0xE33C0C7F7df4809055C3ebA6c09CFe4BaF1BD9e0" } - } - } } }