Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Commit

Permalink
Added solidity function parser
Browse files Browse the repository at this point in the history
Solidity function encoder now supports any type of data
Added a lot of decode functions
Fixed RLP crash
  • Loading branch information
v57 committed Oct 26, 2018
1 parent 54cf23b commit 0eea1e6
Show file tree
Hide file tree
Showing 13 changed files with 501 additions and 106 deletions.
24 changes: 24 additions & 0 deletions web3swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,16 @@
1323B8062177B85F00306BBB /* ERC721.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1323B8042177B85F00306BBB /* ERC721.swift */; };
1323B80B2177BA9700306BBB /* ERC777.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1323B80A2177BA9700306BBB /* ERC777.swift */; };
1323B80C2177BA9700306BBB /* ERC777.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1323B80A2177BA9700306BBB /* ERC777.swift */; };
134B10CF2182447600113663 /* Int+Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134B10CE2182447600113663 /* Int+Sequence.swift */; };
134B10D02182447600113663 /* Int+Sequence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 134B10CE2182447600113663 /* Int+Sequence.swift */; };
13A24E4E21629CBC004C48A0 /* Promise+Web3+Eth+EstimateGas.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81A1823F20D79FDB0016741F /* Promise+Web3+Eth+EstimateGas.swift */; };
13A24E51216365A4004C48A0 /* EthURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13A24E50216365A4004C48A0 /* EthURL.swift */; };
13A24E52216365A4004C48A0 /* EthURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13A24E50216365A4004C48A0 /* EthURL.swift */; };
13A24EE7216F988C004C48A0 /* UInt256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13A24EE6216F988C004C48A0 /* UInt256.swift */; };
13A24EE8216F9899004C48A0 /* UInt256.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13A24EE6216F988C004C48A0 /* UInt256.swift */; };
13FD60DF21821A1100D73D4E /* SolidityFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13FD60DE21821A1100D73D4E /* SolidityFunctionTests.swift */; };
13FD60F521822FAE00D73D4E /* SolidityDataWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13FD60F421822FAE00D73D4E /* SolidityDataWriter.swift */; };
13FD60F621822FAE00D73D4E /* SolidityDataWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 13FD60F421822FAE00D73D4E /* SolidityDataWriter.swift */; };
1CD91B321FD769A6007BFB45 /* MainTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CD91B311FD769A6007BFB45 /* MainTests.swift */; };
1CD91B341FD769A6007BFB45 /* web3swift_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD91AFC1FD76910007BFB45 /* web3swift_iOS.framework */; };
3790E56739A28FF8E4CF5A5A /* libPods-web3swift-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = B431175BA31FF402281E09CD /* libPods-web3swift-macOS.a */; };
Expand Down Expand Up @@ -257,8 +262,11 @@
1323B8042177B85F00306BBB /* ERC721.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ERC721.swift; sourceTree = "<group>"; };
1323B80A2177BA9700306BBB /* ERC777.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ERC777.swift; sourceTree = "<group>"; };
1323B80D2178C16700306BBB /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
134B10CE2182447600113663 /* Int+Sequence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Int+Sequence.swift"; sourceTree = "<group>"; };
13A24E50216365A4004C48A0 /* EthURL.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthURL.swift; sourceTree = "<group>"; };
13A24EE6216F988C004C48A0 /* UInt256.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UInt256.swift; sourceTree = "<group>"; };
13FD60DE21821A1100D73D4E /* SolidityFunctionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolidityFunctionTests.swift; sourceTree = "<group>"; };
13FD60F421822FAE00D73D4E /* SolidityDataWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SolidityDataWriter.swift; sourceTree = "<group>"; };
1CD91AFC1FD76910007BFB45 /* web3swift_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = web3swift_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
1CD91AFF1FD76910007BFB45 /* web3swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = web3swift.h; sourceTree = "<group>"; };
1CD91B001FD76910007BFB45 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
Expand Down Expand Up @@ -434,6 +442,7 @@
isa = PBXGroup;
children = (
1323B7FF2177A83000306BBB /* BetterERC20Tests.swift */,
13FD60DE21821A1100D73D4E /* SolidityFunctionTests.swift */,
);
path = BetterABI;
sourceTree = "<group>";
Expand All @@ -456,6 +465,14 @@
path = Contracts;
sourceTree = "<group>";
};
13FD60F321822F9700D73D4E /* DataManagers */ = {
isa = PBXGroup;
children = (
13FD60F421822FAE00D73D4E /* SolidityDataWriter.swift */,
);
path = DataManagers;
sourceTree = "<group>";
};
1CD91AF21FD76910007BFB45 = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -483,6 +500,7 @@
1CD91AFE1FD76910007BFB45 /* web3swift */ = {
isa = PBXGroup;
children = (
13FD60F321822F9700D73D4E /* DataManagers */,
13A24EDF216E4BF5004C48A0 /* Contracts */,
13A24E4F21636541004C48A0 /* EthURL */,
81FECD43211ADE20006DA367 /* ObjectiveCbridge */,
Expand Down Expand Up @@ -686,6 +704,7 @@
8113D2B01FD7E1590074282C /* CryptoExtensions.swift */,
13A24EE6216F988C004C48A0 /* UInt256.swift */,
8113D2B21FD7E1590074282C /* LibSecp256k1Extension.swift */,
134B10CE2182447600113663 /* Int+Sequence.swift */,
8113DE7B1FD8514400CD8DF1 /* NSRegularExpressionExtension.swift */,
817EBB1E2006265400E02EAA /* Base58.swift */,
817EBB22200649E000E02EAA /* RIPEMD160+StackOveflow.swift */,
Expand Down Expand Up @@ -1042,6 +1061,7 @@
81D7D97220A31FB700A193EC /* ComparisonExtensions.swift in Sources */,
817EBB27200673D100E02EAA /* KeystoreV3JSONStructure.swift in Sources */,
81C5DA11207254F600424CD6 /* ABIv2.swift in Sources */,
13FD60F521822FAE00D73D4E /* SolidityDataWriter.swift in Sources */,
1323B7F72176255900306BBB /* SolidityTypes.swift in Sources */,
817EBB102004FE2800E02EAA /* EthereumAddress.swift in Sources */,
81FB21FE207BB297007F9A83 /* EIP67Code.swift in Sources */,
Expand Down Expand Up @@ -1100,6 +1120,7 @@
1323B80B2177BA9700306BBB /* ERC777.swift in Sources */,
81A1821520D5A2700016741F /* Promise+Web3+Eth+GetBalance.swift in Sources */,
0073F22820D94A11000791F1 /* BlockExplorer+GetTransactionHistory.swift in Sources */,
134B10CF2182447600113663 /* Int+Sequence.swift in Sources */,
0073F22620D949F7000791F1 /* BlockExplorer.swift in Sources */,
81C0FD012044A89300D82FAF /* Web3+TransactionIntermediate.swift in Sources */,
81A1823C20D79C270016741F /* Promise+Web3+Eth+Call.swift in Sources */,
Expand Down Expand Up @@ -1130,6 +1151,7 @@
E23B5ADF20EA68FA00DC7F32 /* SECP256K1Tests.swift in Sources */,
1323B7F42174BB1E00306BBB /* Support.swift in Sources */,
00E5FE7E20EA3A3F0030E0D6 /* ABITests.swift in Sources */,
13FD60DF21821A1100D73D4E /* SolidityFunctionTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand All @@ -1139,6 +1161,7 @@
files = (
4194811B203630530065A83B /* Web3+HttpProvider.swift in Sources */,
4194811E203630530065A83B /* Web3.swift in Sources */,
134B10D02182447600113663 /* Int+Sequence.swift in Sources */,
4194811F203630530065A83B /* Web3+Instance.swift in Sources */,
41948120203630530065A83B /* Web3+Contract.swift in Sources */,
41948121203630530065A83B /* Web3+Utils.swift in Sources */,
Expand Down Expand Up @@ -1199,6 +1222,7 @@
81C0FD052044A8AE00D82FAF /* Web3+Protocols.swift in Sources */,
81A1823520D6E1FD0016741F /* Promise+Web3+Eth+GetBlockByNumber.swift in Sources */,
81A1822920D678BF0016741F /* Promise+Web3+Eth+GetAccounts.swift in Sources */,
13FD60F621822FAE00D73D4E /* SolidityDataWriter.swift in Sources */,
81C5DA322074EC1E00424CD6 /* ContractProtocol.swift in Sources */,
81C5DA232072DFE600424CD6 /* ABIv2TypeParser.swift in Sources */,
81A1824C20D7DF1B0016741F /* Promise+Web3+Personal+UnlockAccount.swift in Sources */,
Expand Down
128 changes: 48 additions & 80 deletions web3swift/ABIv2/SolidityFunction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ import PromiseKit

public protocol SolidityDataRepresentable {
var solidityData: Data { get }
var isSolidityBinaryType: Bool { get }
}
public extension SolidityDataRepresentable {
var isSolidityBinaryType: Bool { return false }
}

extension BinaryInteger {
public var solidityData: Data { return BigInt(self).abiEncode(bits: 256) }

}
extension Int: SolidityDataRepresentable {}
extension Int8: SolidityDataRepresentable {}
Expand All @@ -33,23 +39,56 @@ extension EthereumAddress: SolidityDataRepresentable {
}
extension Data: SolidityDataRepresentable {
public var solidityData: Data { return self }
public var isSolidityBinaryType: Bool { return true }
}
extension String: SolidityDataRepresentable {
public var solidityData: Data { return data }
public var isSolidityBinaryType: Bool { return true }
}
extension Array where Element == SolidityDataRepresentable {
extension Array: SolidityDataRepresentable where Element == SolidityDataRepresentable {
public var solidityData: Data {
var data = Data(capacity: 32 * count)
for element in self {
data.append(element.solidityData)
}
return data
}

// func dynamicSolidityData() -> Data {
// var data = Data(capacity: 32 * (count+1))
// data.append(count.solidityData)
// for element in self {
// data.append(element.solidityData)
// }
// return data
// }
// func staticSolidityData(count: Int) -> Data {
// let capacity = 32 * count
// var data = Data(capacity: capacity)
// for element in self {
// data.append(element.solidityData)
// }
// if data.count < capacity {
// data.append(Data(count: capacity - data.count))
// }
// return data
// }
func data(function: String) -> Data {
return reduce(into: function.keccak256()[0..<4], { $0.append($1.solidityData) })
var data = Data(capacity: count * 32 + 4)
data.append(function.keccak256()[0..<4])
for element in self {
data.append(element.solidityData)
}
return data
}
}

extension EthereumAddress {
public func assemble(_ function: String, _ arguments: [Any], web3: Web3 = .default, options: Web3Options? = nil, onBlock: String = "pending") -> Promise<EthereumTransaction> {
let options = web3.options.merge(with: options)

let data = arguments.compactMap { value in
return value as? SolidityDataRepresentable
}.data(function: function)
let function = try! SolidityFunction(function: function)
let data = function.encode(arguments as! [SolidityDataRepresentable])
var assembledTransaction = EthereumTransaction(to: self, data: data, options: options)
let queue = web3.requestDispatcher.queue
let returnPromise = Promise<EthereumTransaction> { seal in
Expand Down Expand Up @@ -106,7 +145,8 @@ extension EthereumAddress {
}
public func call(_ function: String, _ arguments: [Any], web3: Web3 = .default, options: Web3Options? = nil, onBlock: String = "latest") -> Promise<Web3DataResponse> {
let options = web3.options.merge(with: options)
let data = arguments.compactMap { $0 as? SolidityDataRepresentable }.data(function: function)
let function = try! SolidityFunction(function: function)
let data = function.encode(arguments as! [SolidityDataRepresentable])
let assembledTransaction = EthereumTransaction(to: self, data: data, options: options)
let queue = web3.requestDispatcher.queue
return Promise<Web3DataResponse> { seal in
Expand All @@ -125,7 +165,8 @@ extension EthereumAddress {
}
public func estimateGas(_ function: String, _ arguments: [Any], web3: Web3 = .default, options: Web3Options? = nil, onBlock: String = "latest") -> Promise<BigUInt> {
let options = web3.options.merge(with: options)
let data = arguments.compactMap { $0 as? SolidityDataRepresentable }.data(function: function)
let function = try! SolidityFunction(function: function)
let data = function.encode(arguments as! [SolidityDataRepresentable])
let assembledTransaction = EthereumTransaction(to: self, data: data, options: options)
let queue = web3.requestDispatcher.queue
return Promise<BigUInt> { seal in
Expand All @@ -139,76 +180,3 @@ extension EthereumAddress {
}
}
}

//public class UnsafeSolidityFunction {
// public let name: String
// public init(_ name: String) {
// self.name = name
// }
// public var hash: Data {
// return name.data.sha3(.keccak256)[0..<4]
// }
// public func data(with arguments: [SolidityDataRepresentable]) -> Data {
// return arguments.reduce(into: hash, { $0.append($1.solidityData) })
// }
// public func data(with arguments: SolidityDataRepresentable...) -> Data {
// return data(with: arguments)
// }
//}

//protocol SolidityConvertable {
// func write(type: SolidityType) throws
//}
//enum SolidityType {
// case address
// case
//}

//extension String {
// var solidityType: String {
// switch self {
// case "uint":
// return "uint256"
// case "int":
// return "int256"
// default:
// return self
// }
// }
//}
//

//class SafeSolidityFunction: CustomStringConvertible {
// enum Error: Swift.Error {
// case corrupted
// case emptyFunctionName
// }
// let name: String
// let arguments: [String]
// init(function: String) throws {
// var function = function.trimmingCharacters(in: .whitespacesAndNewlines)
// guard let index = function.index(of: "(") else { throw Error.corrupted }
// name = function[..<index].trimmingCharacters(in: .whitespacesAndNewlines)
// guard name.count > 0 else { throw Error.emptyFunctionName }
// guard function.hasSuffix(")") else { throw Error.corrupted }
// function.removeLast()
// let arguments = function[function.index(after: index)...]
// self.arguments = arguments.split(separator: ",").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
// }
// var description: String {
// return "\(name)(\(arguments.joined(separator: ",")))"
// }
//}

/*
converts:
"balanceOf(address)"
"transfer(address,address,uint256)"
"transfer(address, address, uint256)"
"transfer(address, address, uint256)"
"transfer (address, address, uint)"
" transfer ( address , address , uint256 ) "
to
.name: String
.arguments: [String]
*/
Loading

0 comments on commit 0eea1e6

Please sign in to comment.