Skip to content

Commit

Permalink
GH-2886 test happy case
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitryBespalov committed Nov 21, 2023
1 parent 1e1490d commit 2b1b52c
Show file tree
Hide file tree
Showing 6 changed files with 364 additions and 38 deletions.
10 changes: 8 additions & 2 deletions Multisig.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,6 @@
04FEFE8128C6304B0028A349 /* TokenDistributionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 04FEFE7F28C6304B0028A349 /* TokenDistributionViewController.xib */; };
0A007124254B255C00A57CAF /* UIFont+Styles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A007123254B255C00A57CAF /* UIFont+Styles.swift */; };
0A00712A254B379000A57CAF /* UIColor+Styles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A007129254B379000A57CAF /* UIColor+Styles.swift */; };
0A01DCE42770B0A100A87D7A /* TransactionIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A01DCE32770B0A100A87D7A /* TransactionIntegrationTests.swift */; };
0A0391CB27C565D4003C871A /* IconButtonTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0A0391C727C565D3003C871A /* IconButtonTableViewCell.xib */; };
0A0391CC27C565D4003C871A /* HelpTextTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A0391C827C565D3003C871A /* HelpTextTableViewCell.swift */; };
0A0391CD27C565D4003C871A /* HelpTextTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0A0391C927C565D3003C871A /* HelpTextTableViewCell.xib */; };
Expand Down Expand Up @@ -1026,6 +1025,8 @@
B32620492A961E690003A2F0 /* AddSafeFlow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B32620482A961E690003A2F0 /* AddSafeFlow.swift */; };
B343BEB32A77DDA1006BF46B /* DMSans-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 0491067C28F99246005A4A99 /* DMSans-Bold.ttf */; };
B35BFD0F2A937DC000A9FB15 /* NavigationRouterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B35BFD0E2A937DC000A9FB15 /* NavigationRouterTests.swift */; };
B367AED02B0CB69200F06B86 /* TransactionValidationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B367AECE2B0CB59700F06B86 /* TransactionValidationTests.swift */; };
B367AED22B0CB89600F06B86 /* TransactionValidationTestCase1.json in Resources */ = {isa = PBXBuildFile; fileRef = B367AED12B0CB89600F06B86 /* TransactionValidationTestCase1.json */; };
B3710B3D2AD584BE002E503B /* SecureConfig in Frameworks */ = {isa = PBXBuildFile; productRef = B3710B3C2AD584BE002E503B /* SecureConfig */; };
B3710B442AD5AAD7002E503B /* config.bundle in Resources */ = {isa = PBXBuildFile; fileRef = B3710B432AD5AAD7002E503B /* config.bundle */; };
B3B6044F2A850F5E007BDAC0 /* UIAlertControllerStyle+Multiplatform.swift in Sources */ = {isa = PBXBuildFile; fileRef = B3B6044E2A850F5E007BDAC0 /* UIAlertControllerStyle+Multiplatform.swift */; };
Expand Down Expand Up @@ -2082,6 +2083,8 @@
B300E8CA2AF3A7A90073A908 /* SafeNoncesRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafeNoncesRequest.swift; sourceTree = "<group>"; };
B32620482A961E690003A2F0 /* AddSafeFlow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddSafeFlow.swift; sourceTree = "<group>"; };
B35BFD0E2A937DC000A9FB15 /* NavigationRouterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouterTests.swift; sourceTree = "<group>"; };
B367AECE2B0CB59700F06B86 /* TransactionValidationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionValidationTests.swift; sourceTree = "<group>"; };
B367AED12B0CB89600F06B86 /* TransactionValidationTestCase1.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = TransactionValidationTestCase1.json; sourceTree = "<group>"; };
B3710B3B2AD58492002E503B /* SecureConfig */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = SecureConfig; path = Packages/SecureConfig; sourceTree = "<group>"; };
B3710B432AD5AAD7002E503B /* config.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = config.bundle; sourceTree = "<group>"; };
B3710B452AD5AE9D002E503B /* apis-prod.example.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "apis-prod.example.json"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3477,6 +3480,8 @@
6A91EFD827DA2C45009E63E9 /* Data */,
0A3DFF002667D7DA00B45770 /* CoreData */,
0A64313F247ED1AA006FD30A /* MultisigIntegrationTests.xctestplan */,
B367AECE2B0CB59700F06B86 /* TransactionValidationTests.swift */,
B367AED12B0CB89600F06B86 /* TransactionValidationTestCase1.json */,
0A802B8F24E581A50001790F /* SafeClientGatewayServiceIntegrationTests.swift */,
0A513A9C2768EBC900F07D5A /* DelegateKeyTests.swift */,
5532D4D02449A1E40067505A /* MockLogger.swift */,
Expand Down Expand Up @@ -5219,6 +5224,7 @@
0A61E8452670E632009D68A4 /* __Snapshots__ in Resources */,
6A91EFDA27DA2C8D009E63E9 /* wc_registry_wallets.json in Resources */,
0AA5F55D28BF667000D6D220 /* claiming_test_fixtures.json in Resources */,
B367AED22B0CB89600F06B86 /* TransactionValidationTestCase1.json in Resources */,
0A74719A269F152D008E9F2D /* chains_4_safes_0x1230B3d59858296A31053C1b8562Ecf89A2f888b_balances_usd.json in Resources */,
0A3DFEFE2667D3A700B45770 /* README.md in Resources */,
);
Expand Down Expand Up @@ -5996,13 +6002,13 @@
0A9BC35F246058F800EB9C5D /* MockLogger.swift in Sources */,
550A6182268A23A9002C02E1 /* SafeNetworkMigrationTests.swift in Sources */,
0A7B3518288071EB00EC04EC /* TestCoreDataStack.swift in Sources */,
0A01DCE42770B0A100A87D7A /* TransactionIntegrationTests.swift in Sources */,
0A65522B28816B9900701238 /* TestingAppDelegate.swift in Sources */,
0A61E83E2670DED5009D68A4 /* BalanceTableViewCellTests.swift in Sources */,
0A3DFEF72667D1C000B45770 /* CoreDataTestCase.swift in Sources */,
0A06532F27B68AF40008C5F1 /* WebConnectionRepositoryTests.swift in Sources */,
0A6552282881642300701238 /* UIIntegrationTestCase.swift in Sources */,
0A802B9024E581A50001790F /* SafeClientGatewayServiceIntegrationTests.swift in Sources */,
B367AED02B0CB69200F06B86 /* TransactionValidationTests.swift in Sources */,
0AC62ED628783700007945A1 /* CreatePasscodeFlowTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,17 @@ class TransactionDetailCellBuilder {
tableView.registerCell(WarningTableViewCell.self)
}

func build(_ tx: SCGModels.TransactionDetails, _ safe: Safe?) -> [UITableViewCell] {
func build(_ tx: SCGModels.TransactionDetails) -> [UITableViewCell] {
result = []
buildTransaction(tx, safe)
buildTransaction(tx)
return result
}

func buildTransaction(_ tx: SCGModels.TransactionDetails, _ safe: Safe? = nil) {
func buildTransaction(_ tx: SCGModels.TransactionDetails) {
let isCreationTx = buildCreationTx(tx)
if !isCreationTx {
buildWarning(tx)
buildHeader(tx)
// buildWarning(tx, safe)
buildAssetContract(tx)
buildStatus(tx)
buildMultisigInfo(tx)
Expand Down Expand Up @@ -433,15 +433,14 @@ class TransactionDetailCellBuilder {
isOutgoing: isOutgoing)
}

// TODO: Move this out into a class or function and Unit-Test it and / or Integration Test it.
func buildWarning(_ tx: SCGModels.TransactionDetails, _ safe: Safe? = nil) {
func validate(tx: SCGModels.TransactionDetails, safe: Safe) throws {
guard tx.txStatus.isAwatingConfiramtions || tx.txStatus == .awaitingExecution else {
// don't warn outside of signature or execution requests
return
}

// safe has owners
guard let safe = safe, let ownersInfo = safe.ownersInfo, !ownersInfo.isEmpty else {
guard let ownersInfo = safe.ownersInfo, !ownersInfo.isEmpty else {
// not enough data for further checks
return
}
Expand All @@ -454,16 +453,14 @@ class TransactionDetailCellBuilder {
}

guard !txMultisigInfo.confirmations.isEmpty else {
warningCell("Warning: transaction has no confirmations. This may be a dangerous transaction")
return
throw "Transaction has no confirmations. This may be a dangerous transaction"
}

// all confirming addresses are from safe owners
guard txMultisigInfo.confirmations.allSatisfy({ confirmation in
ownerAddresses.contains(confirmation.signer.value.address)
}) else {
warningCell("Warning: not all confirmations are from safe owners.")
return
throw "Not all confirmations are from safe owners."
}

// transaction hash is valid
Expand All @@ -482,8 +479,7 @@ class TransactionDetailCellBuilder {
let computedSafeTxHash = transaction.safeTransactionHash(),
transaction.safeTxHash == computedSafeTxHash
else {
warningCell("Warning: safeTxHash is invalid. This may be a dangerous transaction.")
return
throw "Invalid safeTxHash. This may be a dangerous transaction."
}

// all confirming signatures are from a confirming addresses
Expand All @@ -493,9 +489,9 @@ class TransactionDetailCellBuilder {
return nil
}

let v: UInt8 = signature[0]
let r: Data /* 32 bytes */ = signature[1...32]
let s: Data /* 32 bytes */ = signature[33...64]
let r: Data /* 32 bytes */ = signature[0..<32]
let s: Data /* 32 bytes */ = signature[32..<64]
let v: UInt8 = signature[64]

let contractSignature: UInt8 = 0
let approvedHashSignature: UInt8 = 1
Expand All @@ -522,9 +518,11 @@ class TransactionDetailCellBuilder {
return owner

default:
let message = transaction.encodeTransactionData()

let pubKey = try? EthereumPublicKey(
message: computedSafeTxHash.hash.makeBytes(),
v: EthereumQuantity(quantity: BigUInt(v)),
message: message.makeBytes(),
v: EthereumQuantity(quantity: v >= 27 ? BigUInt(v) - 27 : BigUInt(v)),
r: EthereumQuantity(r.makeBytes()),
s: EthereumQuantity(s.makeBytes())
)
Expand All @@ -537,33 +535,38 @@ class TransactionDetailCellBuilder {
let owner = (try? Sol.Address(data: r)).map { Address($0) }
return owner
default:
let message = transaction.encodeTransactionData()

let pubKey = try? EthereumPublicKey(
message: computedSafeTxHash.hash.makeBytes(),
v: EthereumQuantity(quantity: BigUInt(v)),
message: message.makeBytes(),
v: EthereumQuantity(quantity: v >= 27 ? BigUInt(v) - 27 : BigUInt(v)),
r: EthereumQuantity(r.makeBytes()),
s: EthereumQuantity(s.makeBytes())
)
let owner = pubKey.map(\.address).map(Address.init)
return owner

}
}
}

guard txMultisigInfo.confirmations.allSatisfy({ confirmation in
signer(of: confirmation.signature.data) == confirmation.signer.value.address
}) else {
warningCell("Warning: not all signatures are from safe's owners.")
return
throw "Not all signatures are from safe's owners. This may be a dangerous transaction."
}

// all good! no warnings.
}

func warningCell(_ text: String) {
let cell = newCell(WarningTableViewCell.self)
cell.set(title: text)
result.append(cell)
func buildWarning(_ tx: SCGModels.TransactionDetails) {
do {
guard let aSafe = Safe.by(address: tx.safeAddress.description, chainId: chain.id!) else {
return
}
try validate(tx: tx, safe: aSafe)
} catch {
let cell = newCell(WarningTableViewCell.self)
cell.set(title: "Warning!", description: error.localizedDescription)
result.append(cell)
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ class TransactionDetailsViewController: LoadableViewController, UITableViewDataS
self.tx = transformer.transformed(transaction: self.tx!)

trackScreen()
cells = builder.build(self.tx!, safe)
cells = builder.build(self.tx!)
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
Expand Down
12 changes: 6 additions & 6 deletions MultisigIntegrationTests/TransactionIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ class TransactionIntegrationTests: XCTestCase {
continueAfterFailure = false
let privateKey = try PrivateKey(data: Data(hex: "0xe7979e5f2ceb1d4ef76019d1fdba88b50ceefe0575bbfdf94969837c50a5d895"))

let input = ERC20.transfer(
let callData = ERC20.transfer(
// eoa address
// to: "Ad302A4b09402b41EC3Fb4981B63E4Dd141fed6d",
// safe address
Expand All @@ -170,7 +170,7 @@ class TransactionIntegrationTests: XCTestCase {
value: 1000
).encode()

print("call data", input.toHexStringWithPrefix())
print("call data", callData.toHexStringWithPrefix())

let minerTip = Eth.Amount(value: 2, unit: Eth.Unit.gigawei).converted(to: Eth.Unit.wei).value

Expand All @@ -180,7 +180,7 @@ class TransactionIntegrationTests: XCTestCase {
// erc20 contract address (LOVE)
to: "b3a4Bc89d8517E0e2C9B66703d09D3029ffa1e6d",
// erc20 transfer call
input: Sol.Bytes(storage: input),
input: Sol.Bytes(storage: callData),
fee: Eth.Fee1559(
maxFeePerGas: minerTip,
maxPriorityFee: minerTip
Expand Down Expand Up @@ -405,7 +405,7 @@ class TransactionIntegrationTests: XCTestCase {
confirmation.signature.data
}.joined()

let input = try GnosisSafe_v1_3_0.execTransaction(
let callData = try GnosisSafe_v1_3_0.execTransaction(
to: Sol.Address(txData.to.value.data32),
value: Sol.UInt256(txData.value.data32),
data: Sol.Bytes(storage: txData.hexData?.data ?? Data()),
Expand All @@ -419,15 +419,15 @@ class TransactionIntegrationTests: XCTestCase {
signatures: Sol.Bytes(storage: Data(signatures))
).encode()

print("call data", input.toHexStringWithPrefix())
print("call data", callData.toHexStringWithPrefix())

let minerTip = Eth.Amount(value: 2, unit: Eth.Unit.gigawei).converted(to: Eth.Unit.wei).value

let tx = Eth.TransactionEip1559(
chainId: 4,
from: "728cafe9fB8CC2218Fb12a9A2D9335193caa07e0",
to: "dd1D27C114aB45e8A650B251eDFA1b0795bbe020",
input: Sol.Bytes(storage: input),
input: Sol.Bytes(storage: callData),
fee: Eth.Fee1559(
maxFeePerGas: minerTip,
maxPriorityFee: minerTip
Expand Down
Loading

0 comments on commit 2b1b52c

Please sign in to comment.