Skip to content

Commit

Permalink
Merge pull request #533 from skywinder/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
yaroslavyaroslav committed Apr 19, 2022
2 parents cbdde45 + 4b4ab1b commit add3342
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 30 deletions.
20 changes: 13 additions & 7 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,35 +74,41 @@ Here are quick references for essential features:

- [x] [EIP-155](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-155.md) (Replay attacks protection) *enforced!*

- [x] [EIP-165](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-165.md) (Standard Interface Detection, also known as ERC-165)

- [x] [EIP-681](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-681.md) (A standard way of representing various transactions, especially payment requests in Ethers and ERC-20 tokens as URLs)

- [x] [EIP-721](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-721.md) (A standard interface for non-fungible tokens, also known as deeds - ERC-721)

- [x] [EIP-165](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-165.md) (Standard Interface Detection, also known as ERC-165)
- [x] [EIP-721x](https://github.com/loomnetwork/erc721x) (An extension of ERC721 that adds support for multi-fungible tokens and batch transfers, while being fully backward-compatible, also known as ERC-721x)

- [x] [EIP-777](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-777.md) (New Advanced Token Standard, also known as ERC-777)

- [x] [EIP-820](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-820.md) (Pseudo-introspection Registry Contract, also known as ERC-820)

- [x] [EIP-888](https://github.com/ethereum/EIPs/issues/888) (MultiDimensional Token Standard, also known as ERC-888)

- [x] [EIP-1155](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-1155.md) (Multi Token Standard, also known as ERC-1155)

- [x] [EIP-1376](https://github.com/ethereum/EIPs/issues/1376) (Service-Friendly Token, also known as ERC-1376)

- [x] [EIP-1400](https://github.com/ethereum/EIPs/issues/1411) (Security Token Standard, also known as ERC-1400)

- [x] [EIP-1410](https://github.com/ethereum/EIPs/issues/1410) (Partially Fungible Token Standard, also known as ERC-1410)

- [x] [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) (Fee market change for ETH 1.0 chain)

- [x] [EIP-1594](https://github.com/ethereum/EIPs/issues/1594) (Core Security Token Standard, also known as ERC-1594)

- [x] [EIP-1633](https://github.com/ethereum/EIPs/issues/1634) (Re-Fungible Token, also known as ERC-1633)

- [x] [EIP-1643](https://github.com/ethereum/EIPs/issues/1643) (Document Management Standard, also known as ERC-1643)

- [x] [EIP-1644](https://github.com/ethereum/EIPs/issues/1644) (Controller Token Operation Standard, also known as ERC-1644)

- [x] [EIP-1633](https://github.com/ethereum/EIPs/issues/1634) (Re-Fungible Token, also known as ERC-1633)

- [x] [EIP-721x](https://github.com/loomnetwork/erc721x) (An extension of ERC721 that adds support for multi-fungible tokens and batch transfers, while being fully backward-compatible, also known as ERC-721x)

- [x] [EIP-1155](https://github.com/ethereum/EIPs/blob/develop/EIPS/eip-1155.md) (Multi Token Standard, also known as ERC-1155)
- [x] [EIP-2718](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2718.md) (Typed Transaction Envelope)

- [x] [EIP-1376](https://github.com/ethereum/EIPs/issues/1376) (Service-Friendly Token, also known as ERC-1376)
- [x] [EIP-2930](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2930.md) (Optional access lists)

- [x] [ST-20](https://github.com/PolymathNetwork/polymath-core) - ST-20 token is an Ethereum-based token implemented on top of the ERC-20 protocol that adds the ability for tokens to control transfers based on specific rules

Expand Down
35 changes: 35 additions & 0 deletions Documentation/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
- [Send ERC-20 Token](#send-erc-20-token)
- [Write Transaction and call smart contract method](#write-transaction-and-call-smart-contract-method)
- [Read Transaction to call smart contract method](#read-transaction-to-call-smart-contract-method)
- [Other Transaction Types (EIP-1559)](#other-transaction-types)
- [Send Transaction](#send-transaction)
- [Write](#write)
- [Read](#read)
Expand Down Expand Up @@ -355,6 +356,40 @@ let result = try! transaction.send(password: password)
let result = try! transaction.call()
```

##### Other Transaction Types

By default a `legacy` transaction will be created which is compatible across all chains, regardless of which fork.
To create one of the new transaction types introduced with the `london` fork you will need to set some additonal parameters
in the `TransactionOptions` object. Note you should only try to send one of tehse new types of transactions if you are on a chain
that supports them.

To send an EIP-2930 style transacton with an access list you need to set the transaction type, and the access list,
in addition what is shown in the examples above.
```swift
let accessList: [AccessListEntry] = [
AccessListEntry(
address: EthereumAddress("0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae"),
storageKeys: [BigUInt(3), BigUInt(7)]
),
AccessListEntry(
address: EthereumAddress("0xbb9bc244d798123fde783fcc1c72d3bb8c189413"),
storageKeys: []
)
]

options.type = .eip2930
options.accessList = accessList
```

To send an EIP-1559 style transaction you set the transaction type, and the new gas parameters `maxFeePerGas` and `maxPriorityFeePerGas`
(you may also send an AccessList with an EIP-1559 transaction) When sending an EIP-1559 transaction, the older `gasPrice` parameter is ignored.
```swift
options.type = .eip1559
options.maxFeePerGas = .manual(...) // the maximum price per unit of gas, inclusive of baseFee and tip
options.maxPriorityFeePerGas = .manual(...) // the tip to be paid to the miner, per unit of gas
```
Note there is a new `Oracle` object available that can be used to assist with estimating the new gas fees

### Chain state

#### Get Block number
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
- [x]**Literally following the standards** (BIP, EIP, etc):

- [x] **[BIP32](https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki) (HD Wallets), [BIP39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) (Seed phrases), [BIP44](https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki) (Key generation prefixes)**
- [x] **[EIP-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md)** (Standart interface for tokens - ERC-20), **[EIP-67](https://github.com/ethereum/EIPs/issues/67)** (Standard URI scheme), **[EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md)** (Replay attacks protection)
- [x] **[EIP-20](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20.md)** (Standart interface for tokens - ERC-20), **[EIP-67](https://github.com/ethereum/EIPs/issues/67)** (Standard URI scheme), **[EIP-155](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md)** (Replay attacks protection), **[EIP-2718](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2718.md)** (Typed Transaction Envelope), **[EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md)** (Gas Fee market change)
- [x] **And many others** *(For details about this EIP's look at [Documentation page](https://github.com/skywinder/web3swift/blob/master/Documentation/))*: EIP-681, EIP-721, EIP-165, EIP-777, EIP-820, EIP-888, EIP-1400, EIP-1410, EIP-1594, EIP-1643, EIP-1644, EIP-1633, EIP-721, EIP-1155, EIP-1376, ST-20

- [x] 🗜 **Batched requests** in concurrent mode
Expand Down
18 changes: 1 addition & 17 deletions Sources/web3swift/Transaction/EIP1559Envelope.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ public struct EIP1559Envelope: EIP2718Envelope {
public var maxFeePerGas: BigUInt
public var accessList: [AccessListEntry] // from EIP-2930

/// EIP-1159 trnsactions do not have a gasPrice parameter
/// However, it appears that some nodes report a gasPrice, even for EIP-1159 transactions
/// thus for a temporary workaround we capture and store gasPrice if initialized from a JSON transaction
/// decided form a node. This is currently needed for Oracle to work
private var gasPrice: BigUInt = 0

// for CustomStringConvertible
public var description: String {
var toReturn = ""
Expand Down Expand Up @@ -76,9 +70,6 @@ public struct EIP1559Envelope: EIP2718Envelope {
value: value,
data: data,
gasLimit: gasLimit,
// MARK: workaround for gasPrice coming from nodes for EIP-1159 - this allows Oracle to work for now
gasPrice: gasPrice,

maxFeePerGas: maxFeePerGas,
maxPriorityFeePerGas: maxPriorityFeePerGas,
accessList: accessList
Expand All @@ -94,8 +85,6 @@ public struct EIP1559Envelope: EIP2718Envelope {
maxFeePerGas = val.maxFeePerGas ?? maxFeePerGas
maxPriorityFeePerGas = val.maxPriorityFeePerGas ?? maxPriorityFeePerGas
accessList = val.accessList ?? accessList
// MARK: workaround for gasPrice coming from nodes for EIP-1159 - this allows Oracle to work for now
gasPrice = val.gasPrice ?? gasPrice
}
}

Expand All @@ -117,8 +106,6 @@ extension EIP1559Envelope {
case v
case r
case s
// MARK: workaround for gasPrice coming from nodes for EIP-1159 - this allows Oracle to work for now
case gasPrice
}

public init?(from decoder: Decoder) throws {
Expand Down Expand Up @@ -147,9 +134,6 @@ extension EIP1559Envelope {
self.to = ethAddr
}

// MARK: workaround for gasPrice coming from nodes for EIP-1159 - this allows Oracle to work for now
self.gasPrice = try container.decodeHexIfPresent(BigUInt.self, forKey: .gasPrice) ?? 5000000000

self.value = try container.decodeHexIfPresent(BigUInt.self, forKey: .value) ?? 0
self.maxPriorityFeePerGas = try container.decodeHexIfPresent(BigUInt.self, forKey: .maxPriorityFeePerGas) ?? 0
self.maxFeePerGas = try container.decodeHexIfPresent(BigUInt.self, forKey: .maxFeePerGas) ?? 0
Expand Down Expand Up @@ -212,7 +196,7 @@ extension EIP1559Envelope {

// swiftlint:disable force_unwrapping
switch rlpItem[RlpKey.destination.rawValue]!.content {
// swiftlint:enable force_unwrapping
// swiftlint:enable force_unwrapping
case .noItem:
self.to = EthereumAddress.contractDeploymentAddress()
case .data(let addressData):
Expand Down
57 changes: 57 additions & 0 deletions Sources/web3swift/Transaction/EthereumMetadata.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Package: web3swift
// Created by Alex Vlasov.
// Copyright © 2018 Alex Vlasov. All rights reserved.
//
// Additions for metadata by Mark Loit 2022

import Foundation
import BigInt

/// This structure holds additional data
/// returned by nodes when reading a transaction
/// from the blockchain. The data here is not
/// part of the transaction itself
public struct EthereumMetadata {

/// hash for the block that contains this transaction on chain
var blockHash: Data?

/// block number for the block containing this transaction on chain
var blockNumber: BigUInt?

/// index for this transaction within the containing block
var transactionIndex: UInt?

/// hash for this transaction as returned by the node [not computed]
/// this can be used for validation against the computed hash returned
/// by the transaction envelope.
var transactionHash: Data?

/// gasPrice value returned by the node
/// note this is a duplicate value for legacy and EIP-2930 transaction types
/// but is included here since EIP-1559 does not contain a `gasPrice`, but
/// nodes still report the value.
var gasPrice: BigUInt?
}

public extension EthereumMetadata {
private enum CodingKeys: String, CodingKey {
case blockHash
case blockNumber
case transactionIndex
case transactionHash
case gasPrice
}

/// since metadata realistically can only come when a transaction is created from
/// JSON returned by a node, we only provide an intializer from JSON
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

self.blockHash = try container.decodeHexIfPresent(Data.self, forKey: .blockHash)
self.transactionHash = try container.decodeHexIfPresent(Data.self, forKey: .transactionHash)
self.transactionIndex = try container.decodeHexIfPresent(UInt.self, forKey: .transactionIndex)
self.blockNumber = try container.decodeHexIfPresent(BigUInt.self, forKey: .blockNumber)
self.gasPrice = try container.decodeHexIfPresent(BigUInt.self, forKey: .gasPrice)
}
}
11 changes: 7 additions & 4 deletions Sources/web3swift/Transaction/EthereumTransaction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public struct EthereumTransaction: CustomStringConvertible {
/// and type specific implementation
internal var envelope: AbstractEnvelope

/// storage container for additional metadata returned by the node
/// when a transaction is decoded form a JSON stream
public var meta: EthereumMetadata?

// convenience accessors to the common envelope fields
// everything else should come from getOpts/setOpts
/// The type of the transacton being represented, see TransactionType enum
Expand Down Expand Up @@ -227,6 +231,8 @@ extension EthereumTransaction: Decodable {
public init(from decoder: Decoder) throws {
guard let env = try EnvelopeFactory.createEnvelope(from: decoder) else { throw Web3Error.dataError }
self.envelope = env
// capture any metadata that might be present
self.meta = try EthereumMetadata(from: decoder)
}
}

Expand Down Expand Up @@ -330,10 +336,7 @@ extension EthereumTransaction {
guard let env = self.envelope as? EIP2930Envelope else { preconditionFailure("Unable to downcast to EIP2930Envelope") }
return env.parameters.gasPrice ?? 0
case .eip1559:
// MARK: workaround for gasPrice coming from nodes for EIP-1159 - this allows Oracle to work for now
guard let env = self.envelope as? EIP1559Envelope else { preconditionFailure("Unable to downcast to EIP1559Envelope") }
return env.parameters.gasPrice ?? 0
// preconditionFailure("EIP1559Envelope has no member gasPrice")
preconditionFailure("EIP1559Envelope has no member gasPrice")
}
}
set(value) {
Expand Down
2 changes: 1 addition & 1 deletion Sources/web3swift/Web3/Web3+GasOracle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ extension Web3 {
return transaction
}
}
.map { $0.gasPrice }
.map { $0.meta?.gasPrice ?? 0 }

return calculatePercentiles(for: lastNthBlockGasPrice)
}
Expand Down
4 changes: 4 additions & 0 deletions web3swift.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
6049F416280616FC00DFE624 /* LegacyEnvelope.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6049F40F280616FC00DFE624 /* LegacyEnvelope.swift */; };
6049F4182806171300DFE624 /* Web3+Signing.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6049F4172806171300DFE624 /* Web3+Signing.swift */; };
604FA4FF27ECBDC80021108F /* DataConversionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 604FA4FE27ECBDC80021108F /* DataConversionTests.swift */; };
60C1786E2809BA0C0083F064 /* EthereumMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C1786D2809BA0C0083F064 /* EthereumMetadata.swift */; };
CB50A52827060BD600D7E39B /* EIP712Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB50A52727060BD600D7E39B /* EIP712Tests.swift */; };
D606A56B279F5D59003643ED /* web3swiftDecodeSolidityErrorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = D606A56A279F5D59003643ED /* web3swiftDecodeSolidityErrorType.swift */; };
D6A3D9B827F1E785009E3BCF /* ABIEncoderSoliditySha3Test.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3D9B727F1E785009E3BCF /* ABIEncoderSoliditySha3Test.swift */; };
Expand Down Expand Up @@ -433,6 +434,7 @@
6049F40F280616FC00DFE624 /* LegacyEnvelope.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LegacyEnvelope.swift; sourceTree = "<group>"; };
6049F4172806171300DFE624 /* Web3+Signing.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Web3+Signing.swift"; sourceTree = "<group>"; };
604FA4FE27ECBDC80021108F /* DataConversionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataConversionTests.swift; sourceTree = "<group>"; };
60C1786D2809BA0C0083F064 /* EthereumMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumMetadata.swift; sourceTree = "<group>"; };
CB50A52727060BD600D7E39B /* EIP712Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP712Tests.swift; sourceTree = "<group>"; };
CB50A52927060C5300D7E39B /* EIP712.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EIP712.swift; sourceTree = "<group>"; };
D606A56A279F5D59003643ED /* web3swiftDecodeSolidityErrorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swiftDecodeSolidityErrorType.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -720,6 +722,7 @@
6049F40F280616FC00DFE624 /* LegacyEnvelope.swift */,
3AA8153D2276E44100F5DB52 /* BloomFilter.swift */,
3AA8153F2276E44100F5DB52 /* EthereumTransaction.swift */,
60C1786D2809BA0C0083F064 /* EthereumMetadata.swift */,
);
path = Transaction;
sourceTree = "<group>";
Expand Down Expand Up @@ -1349,6 +1352,7 @@
3AA815C12276E44100F5DB52 /* Web3+BrowserFunctions.swift in Sources */,
3AA815E82276E44100F5DB52 /* Extensions.swift in Sources */,
3AA815FE2276E44100F5DB52 /* Web3+ERC820.swift in Sources */,
60C1786E2809BA0C0083F064 /* EthereumMetadata.swift in Sources */,
3AA815DB2276E44100F5DB52 /* Web3+TxPool.swift in Sources */,
3AA8160A2276E44100F5DB52 /* Web3+ERC1594.swift in Sources */,
3AA815FB2276E44100F5DB52 /* Promise+Web3+Personal+UnlockAccount.swift in Sources */,
Expand Down

0 comments on commit add3342

Please sign in to comment.