8
8
9
9
import Foundation
10
10
import BigInt
11
- import Core
12
11
13
12
/// Standard representation of a smart contract.
13
+ ///
14
+ /// ## How to
15
+ /// To create a smart contract deployment transaction there is only one requirement - `bytecode`.
16
+ /// That is the compiled smart contract that is ready to be executed by EVM, or eWASM if that is a Serenity.
17
+ /// Creating a transaction is as simple as:
18
+ ///
19
+ /// ```swift
20
+ /// contractInstance.deploy(bytecode: smartContractBytecode)
21
+ /// ```
22
+ ///
23
+ /// One of the default implementations of `ContractProtocol` is ``EthereumContract``.
24
+ /// ```swift
25
+ /// let contract = EthereumContract(abi: [])
26
+ /// contract.deploy(bytecode: smartContractBytecode)
27
+ /// ```
28
+ ///
29
+ /// ### Setting constructor arguments
30
+ /// Some smart contracts expect input arguments for a constructor that is called on contract deployment.
31
+ /// To set these input arguments you must provide `constructor` and `parameters`.
32
+ /// Constructor can be statically created if you know upfront what are the input arguments and their exact order:
33
+ ///
34
+ /// ```swift
35
+ /// let inputArgsTypes: [ABI.Element.InOut] = [.init(name: "firstArgument", type: ABI.Element.ParameterType.string),
36
+ /// .init(name: "secondArgument", type: ABI.Element.ParameterType.uint(bits: 256))]
37
+ /// let constructor = ABI.Element.Constructor(inputs: inputArgsTypes, constant: false, payable: payable)
38
+ /// let constructorArguments = ["This is the array of constructor arguments", 10_000] as [AnyObject]
39
+ ///
40
+ /// contract.deploy(bytecode: smartContractBytecode,
41
+ /// constructor: constructor,
42
+ /// parameters: constructorArguments)
43
+ /// ```
44
+ ///
45
+ /// Alternatively, if you have ABI string that holds meta data about the constructor you can use it instead of creating constructor manually.
46
+ /// But you must make sure the arguments for constructor call are of expected type in and correct order.
47
+ /// Example of ABI string can be found in ``Web3/Utils/erc20ABI``.
48
+ ///
49
+ /// ```swift
50
+ /// let contract = EthereumContract(abiString)
51
+ /// let constructorArguments = ["This is the array of constructor arguments", 10_000] as [AnyObject]
52
+ ///
53
+ /// contract.deploy(bytecode: smartContractBytecode,
54
+ /// constructor: contract.constructor,
55
+ /// parameters: constructorArguments)
56
+ /// ```
57
+ ///
58
+ /// ⚠️ If you pass in only constructor or only parameters - it will have no effect on the final transaction object.
59
+ /// Also, you have an option to set any extra bytes at the end of ``CodableTransaction/data`` attribute.
60
+ /// Alternatively you can encode constructor parameters outside of the deploy function and only set `extraData` to pass in these
61
+ /// parameters:
62
+ ///
63
+ /// ```swift
64
+ /// // `encodeParameters` call returns `Data?`. Check it for nullability before calling `deploy`
65
+ /// // function to create `CodableTransaction`.
66
+ /// let encodedConstructorArguments = someConstructor.encodeParameters(arrayOfInputArguments)
67
+ /// constructor.deploy(bytecode: smartContractBytecode, extraData: encodedConstructorArguments)
68
+ /// ```
14
69
public protocol ContractProtocol {
15
70
/// Address of the referenced smart contract. Can be set later, e.g. if the contract is deploying and address is not yet known.
16
71
var address : EthereumAddress ? { get set }
@@ -55,76 +110,19 @@ public protocol ContractProtocol {
55
110
/// new Solidity keywords, types etc. that are not yet supported, etc.
56
111
init ( _ abiString: String , at: EthereumAddress ? ) throws
57
112
58
- /// Creates a smart contract deployment transaction.
59
- ///
60
- /// ## How to
61
- /// To create a smart contract deployment transaction there is only one requirement - `bytecode`.
62
- /// That is the compiled smart contract that is ready to be executed by EVM, or eWASM if that is a Serenity.
63
- /// Creating a transaction is as simple as:
64
- ///
65
- /// ```swift
66
- /// contractInstance.deploy(bytecode: smartContractBytecode)
67
- /// ```
68
- ///
69
- /// One of the default implementations of `ContractProtocol` is ``EthereumContract``.
70
- /// ```swift
71
- /// let contract = EthereumContract(abi: [])
72
- /// contract.deploy(bytecode: smartContractBytecode)
73
- /// ```
74
- ///
75
- /// ### Setting constructor arguments
76
- /// Some smart contracts expect input arguments for a constructor that is called on contract deployment.
77
- /// To set these input arguments you must provide `constructor` and `parameters`.
78
- /// Constructor can be statically created if you know upfront what are the input arguments and their exact order:
79
- ///
80
- /// ```swift
81
- /// let inputArgsTypes: [ABI.Element.InOut] = [.init(name: "firstArgument", type: ABI.Element.ParameterType.string),
82
- /// .init(name: "secondArgument", type: ABI.Element.ParameterType.uint(bits: 256))]
83
- /// let constructor = ABI.Element.Constructor(inputs: inputArgsTypes, constant: false, payable: payable)
84
- /// let constructorArguments = ["This is the array of constructor arguments", 10_000] as [AnyObject]
85
- ///
86
- /// contract.deploy(bytecode: smartContractBytecode,
87
- /// constructor: constructor,
88
- /// parameters: constructorArguments)
89
- /// ```
90
- ///
91
- /// Alternatively, if you have ABI string that holds meta data about the constructor you can use it instead of creating constructor manually.
92
- /// But you must make sure the arguments for constructor call are of expected type in and correct order.
93
- /// Example of ABI string can be found in ``Web3/Utils/erc20ABI``.
94
- ///
95
- /// ```swift
96
- /// let contract = EthereumContract(abiString)
97
- /// let constructorArguments = ["This is the array of constructor arguments", 10_000] as [AnyObject]
98
- ///
99
- /// contract.deploy(bytecode: smartContractBytecode,
100
- /// constructor: contract.constructor,
101
- /// parameters: constructorArguments)
102
- /// ```
103
- ///
104
- /// ⚠️ If you pass in only constructor or only parameters - it will have no effect on the final transaction object.
105
- /// Also, you have an option to set any extra bytes at the end of ``EthereumTransaction/data`` attribute.
106
- /// Alternatively you can encode constructor parameters outside of the deploy function and only set `extraData` to pass in these
107
- /// parameters:
108
- ///
109
- /// ```swift
110
- /// // `encodeParameters` call returns `Data?`. Check it for nullability before calling `deploy`
111
- /// // function to create `EthereumTransaction`.
112
- /// let encodedConstructorArguments = someConstructor.encodeParameters(arrayOfInputArguments)
113
- /// constructor.deploy(bytecode: smartContractBytecode, extraData: encodedConstructorArguments)
114
- /// ```
113
+ /// Prepare transaction data for smart contract deployment transaction.
115
114
///
116
115
/// - Parameters:
117
116
/// - bytecode: bytecode to deploy.
118
117
/// - constructor: constructor of the smart contract bytecode is related to. Used to encode `parameters`.
119
118
/// - parameters: parameters for `constructor`.
120
119
/// - extraData: any extra data. It can be encoded input arguments for a constuctor but then you should set `constructor` and
121
120
/// `parameters` to be `nil`.
122
- /// - Returns: transaction if given `parameters` were successfully encoded in a `constructor`. If any or both are `nil`
123
- /// then no encoding will take place and a transaction with `bytecode + extraData` will be returned.
121
+ /// - Returns: Encoded data for a given parameters, which is should be assigned to ``CodableTransaction.data`` property
124
122
func deploy( bytecode: Data ,
125
123
constructor: ABI . Element . Constructor ? ,
126
124
parameters: [ AnyObject ] ? ,
127
- extraData: Data ? ) -> EthereumTransaction ?
125
+ extraData: Data ? ) -> Data ?
128
126
129
127
/// Creates function call transaction with data set as `method` encoded with given `parameters`.
130
128
/// The `method` must be part of the ABI used to init this contract.
@@ -136,7 +134,7 @@ public protocol ContractProtocol {
136
134
/// - parameters: method input arguments;
137
135
/// - extraData: additional data to append at the end of `transaction.data` field;
138
136
/// - Returns: transaction object if `method` was found and `parameters` were successfully encoded.
139
- func method( _ method: String , parameters: [ AnyObject ] , extraData: Data ? ) -> EthereumTransaction ?
137
+ func method( _ method: String , parameters: [ AnyObject ] , extraData: Data ? ) -> Data ?
140
138
141
139
/// Decode output data of a function.
142
140
/// - Parameters:
@@ -188,7 +186,7 @@ extension ContractProtocol {
188
186
func deploy( _ bytecode: Data ,
189
187
constructor: ABI . Element . Constructor ? = nil ,
190
188
parameters: [ AnyObject ] ? = nil ,
191
- extraData: Data ? = nil ) -> EthereumTransaction ? {
189
+ extraData: Data ? = nil ) -> Data ? {
192
190
deploy ( bytecode: bytecode,
193
191
constructor: constructor,
194
192
parameters: parameters,
@@ -201,7 +199,7 @@ extension ContractProtocol {
201
199
/// See ``ContractProtocol/method(_:parameters:extraData:)`` for details.
202
200
func method( _ method: String = " fallback " ,
203
201
parameters: [ AnyObject ] ? = nil ,
204
- extraData: Data ? = nil ) -> EthereumTransaction ? {
202
+ extraData: Data ? = nil ) -> Data ? {
205
203
self . method ( method, parameters: parameters ?? [ ] , extraData: extraData)
206
204
}
207
205
@@ -220,15 +218,15 @@ extension DefaultContractProtocol {
220
218
public func deploy( bytecode: Data ,
221
219
constructor: ABI . Element . Constructor ? ,
222
220
parameters: [ AnyObject ] ? ,
223
- extraData: Data ? ) -> EthereumTransaction ? {
221
+ extraData: Data ? ) -> Data ? {
224
222
var fullData = bytecode
225
223
226
224
if let constructor = constructor,
227
225
let parameters = parameters,
228
226
!parameters. isEmpty {
229
227
guard constructor. inputs. count == parameters. count,
230
- let encodedData = constructor . encodeParameters ( parameters )
231
- else {
228
+ // FIXME: This should be zipped, because Arrays don't guarantee it's elements order
229
+ let encodedData = constructor . encodeParameters ( parameters ) else {
232
230
NSLog ( " Constructor encoding will fail as the number of input arguments doesn't match the number of given arguments. " )
233
231
return nil
234
232
}
@@ -240,18 +238,15 @@ extension DefaultContractProtocol {
240
238
}
241
239
242
240
// MARK: Writing Data flow
243
- return EthereumTransaction ( to: . contractDeploymentAddress( ) ,
244
- value: BigUInt ( 0 ) ,
245
- data: fullData,
246
- parameters: . init( gasLimit: BigUInt ( 0 ) , gasPrice: BigUInt ( 0 ) ) )
241
+ return fullData
247
242
}
248
243
249
244
/// Call given contract method with given parameters
250
245
/// - Parameters:
251
246
/// - method: Method to call
252
247
/// - parameters: Parameters to pass to method call
253
248
/// - extraData: Any additional data that needs to be encoded
254
- /// - Returns: preset EthereumTransaction with filled date
249
+ /// - Returns: preset CodableTransaction with filled date
255
250
///
256
251
/// Returned transaction have filled following priperties:
257
252
/// - to: contractAddress
@@ -260,14 +255,10 @@ extension DefaultContractProtocol {
260
255
/// - params: EthereumParameters with no contract method call encoded data.
261
256
public func method( _ method: String ,
262
257
parameters: [ AnyObject ] ,
263
- extraData: Data ? ) -> EthereumTransaction ? {
264
- guard let to = self . address else { return nil }
265
-
266
- let params = EthereumParameters ( gasLimit: BigUInt ( 0 ) , gasPrice: BigUInt ( 0 ) )
267
-
258
+ extraData: Data ? ) -> Data ? {
268
259
// MARK: - Encoding ABI Data flow
269
260
if method == " fallback " {
270
- return EthereumTransaction ( to : to , value : BigUInt ( 0 ) , data : extraData ?? Data ( ) , parameters : params )
261
+ return extraData ?? Data ( )
271
262
}
272
263
273
264
let method = Data . fromHex ( method) == nil ? method : method. addHexPrefix ( ) . lowercased ( )
@@ -282,9 +273,7 @@ extension DefaultContractProtocol {
282
273
}
283
274
284
275
// MARK: - Encoding ABI Data flow
285
- // return filled EthereumTransaction, which is could be sent iterate with a contract.
286
- // But no gas related data here yet.
287
- return EthereumTransaction ( to: to, value: BigUInt ( 0 ) , data: encodedData, parameters: params)
276
+ return encodedData
288
277
}
289
278
290
279
public func parseEvent( _ eventLog: EventLog ) -> ( eventName: String ? , eventData: [ String : Any ] ? ) {
0 commit comments