mirror of
https://github.com/luxfi/safe-ios.git
synced 2026-10-30 15:19:20 +00:00
70 lines
3.1 KiB
Swift
70 lines
3.1 KiB
Swift
//
|
|
// SafeContract.swift
|
|
// Multisig
|
|
//
|
|
// Created by Andrey Scherbovich on 02.02.21.
|
|
// Copyright © 2021 Gnosis Ltd. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
class SafeContract: Contract {
|
|
/// @param to Destination address of Safe transaction.
|
|
/// @param value Ether value of Safe transaction.
|
|
/// @param data Data payload of Safe transaction.
|
|
/// @param operation Operation type of Safe transaction.
|
|
/// @param safeTxGas Gas that should be used for the Safe transaction.
|
|
/// @param baseGas Gas costs for that are indipendent of the transaction execution(e.g. base transaction fee, signature check, payment of the refund)
|
|
/// @param gasPrice Gas price that should be used for the payment calculation.
|
|
/// @param gasToken Token address (or 0 if ETH) that is used for the payment.
|
|
/// @param refundReceiver Address of receiver of gas payment (or 0 if tx.origin).
|
|
/// @param signatures Packed signature data ({bytes32 r}{bytes32 s}{uint8 v})
|
|
private let execTransactionsMethodSignature =
|
|
"execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)"
|
|
|
|
func nonce() throws -> UInt256 {
|
|
try decodeUInt(invoke("nonce()"))
|
|
}
|
|
|
|
func execTransaction(_ tx: Transaction,
|
|
confirmations: [SCGModels.Confirmation],
|
|
confirmationsRequired: UInt64) -> Data {
|
|
let txData = tx.data?.data ?? Data()
|
|
let txDataOffset = 320 // tx.data offset is always 32*10
|
|
let txDataEncoded = encodeBytes(txData)
|
|
|
|
let signaturesOffset = txDataOffset + txDataEncoded.count
|
|
let signaturesData = signatures(confirmations: confirmations, confirmationsRequired: confirmationsRequired)
|
|
let signaturesEncoded = encodeBytes(signaturesData)
|
|
|
|
return invocation(execTransactionsMethodSignature,
|
|
encodeAddress(tx.to.address),
|
|
encodeUInt(tx.value.value),
|
|
encodeUInt(txDataOffset),
|
|
encodeUInt(tx.operation.uint256),
|
|
encodeUInt(tx.safeTxGas.value),
|
|
encodeUInt(tx.baseGas.value),
|
|
encodeUInt(tx.gasPrice.value),
|
|
encodeAddress(tx.gasToken.address),
|
|
encodeAddress(tx.refundReceiver.address),
|
|
encodeUInt(signaturesOffset),
|
|
txDataEncoded,
|
|
signaturesEncoded)
|
|
}
|
|
|
|
// https://docs.gnosis.io/safe/docs/contracts_signatures/
|
|
func signatures(confirmations: [SCGModels.Confirmation], confirmationsRequired: UInt64) -> Data {
|
|
// The most gas efficient are ECDSA signatures
|
|
// Second most gas efficient are Pre-Validated Signatures
|
|
// The least gas efficient are Contract Signatures (EIP-1271)
|
|
|
|
// currently all confirmations are ECDSA signatures at this stage
|
|
let sortedRequiredConfirmationsHex = confirmations
|
|
.sorted(by: { $0.signer.value.description < $1.signer.value.description })[0..<Int(confirmationsRequired)]
|
|
.map { $0.signature.data.toHexString() }
|
|
.joined()
|
|
|
|
return Data(hex: sortedRequiredConfirmationsHex)
|
|
}
|
|
}
|