Skip to content

Commit

Permalink
refactor: update Withdraw and Transfer to use `L2_BASE_TOKEN_ADDR…
Browse files Browse the repository at this point in the history
…ESS`
  • Loading branch information
petarTxFusion committed Jun 8, 2024
1 parent 4b5bdc2 commit 04b156e
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Sources/ZkSync2/Accounts/Adapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public protocol AdapterL2 {

// Balance returns the balance of the specified token that can be either ETH or any ERC20 token.
// The block number can be nil, in which case the balance is taken from the latest known block.
func balance(token: String, blockNumber: BlockNumber) async throws -> BigUInt
func balance(token: String?, blockNumber: BlockNumber) async throws -> BigUInt
// AllBalances returns all balances for confirmed tokens given by an associated
// account.
func allBalances(_ address: String) async throws -> Dictionary<String, String>
Expand Down
30 changes: 16 additions & 14 deletions Sources/ZkSync2/Accounts/WalletL1.swift
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ extension WalletL1 {
let params = await _finalizeWithdrawalParams(withdrawHash: withdrawalHash, index: index)
let transaction = CodableTransaction(type: .eip1559, to: EthereumAddress(signer.address)!)

let l1Bridge = ethClient.web3.contract(Web3Utils.IL1Bridge, at: EthereumAddress(try await getL1BridgeContracts().l1SharedDefaultBridge), transaction: transaction)
let l1Bridge = ethClient.web3.contract(Web3Utils.IL1SharedBridge, at: EthereumAddress(try await getL1BridgeContracts().l1SharedDefaultBridge), transaction: transaction)

let writeOperation = l1Bridge!.createWriteOperation("finalizeWithdrawal", parameters: [params])
if var tx = writeOperation?.transaction{
Expand All @@ -151,29 +151,31 @@ extension WalletL1 {
let hexHash = withdrawHash
let proof = try! await zkSync.logProof(txHash: hexHash, logIndex: l2ToL1LogIndex)
let l2BlockNumber = receipt.l1BatchNumber
let chainId = try! await zkSync.chainID()

if sender.lowercased() == EthereumAddress.L2EthTokenAddress.address.lowercased()
|| sender.lowercased() == EthereumAddress.Default.address.lowercased() {
let mainContract = try! await mainContract()
return try! await mainContract.createReadOperation("isEthWithdrawalFinalized", parameters: [l2BlockNumber!, proof.id])?.callContractMethod()["0"] as! Bool
}
var l1Bridge: Web3.Contract

let l2Bridge = zkSync.web3.contract(Web3Utils.IL2Bridge, at: EthereumAddress(sender)!)
let l1BridgeAddress = try! await l2Bridge?.createReadOperation("l1Bridge", parameters: [])?.callContractMethod()["0"] as! EthereumAddress
let l1Bridge = ethClient.web3.contract(Web3Utils.IL1Bridge, at: l1BridgeAddress)
if try! await zkSync.isBaseToken(tokenAddress: sender) {
l1Bridge = ethClient.web3.contract(Web3Utils.IL1SharedBridge, at: EthereumAddress(from: try! await zkSync.bridgeContracts().l1SharedDefaultBridge)!)!
}else{
let l2Bridge = zkSync.web3.contract(Web3Utils.IL2SharedBridge, at: EthereumAddress(sender)!)
let l1BridgeAddress = try! await l2Bridge?.createReadOperation("l1SharedBridge", parameters: [])?.callContractMethod()["0"] as! EthereumAddress
l1Bridge = ethClient.web3.contract(Web3Utils.IL1Bridge, at: l1BridgeAddress)!

}

return try! await l1Bridge!.createReadOperation("isWithdrawalFinalized", parameters: [l2BlockNumber!, proof.id])?.callContractMethod()["0"] as! Bool
return try! await l1Bridge.createReadOperation("isWithdrawalFinalized", parameters: [chainId, l2BlockNumber!, proof.id])?.callContractMethod()["0"] as! Bool
}

func _finalizeWithdrawalParams(withdrawHash: String, index: Int) async -> (BigUInt, Int, UInt, Data, String?, [String]) {
func _finalizeWithdrawalParams(withdrawHash: String, index: Int) async -> (BigUInt, BigUInt, Int, UInt, Data, String?, [String]) {
let receipt = try! await zkSync.web3.eth.transactionReceipt(Data(hex: withdrawHash))
let (log, _) = _getWithdrawalLog(receipt: receipt, index: UInt(index))!
let (l2ToL1LogIndex, _) = _getWithdrawL2ToL1Log(txReceipt: receipt, index: index)!
let sender = log.topics[1].suffix(from: 12).toHexString().addHexPrefix()
let proof = try! await zkSync.logProof(txHash: withdrawHash, logIndex: l2ToL1LogIndex)
let msg = ABIDecoder.decodeSingleType(type: ABI.Element.ParameterType.dynamicBytes, data: log.data).value as! Data

return (receipt.l1BatchNumber!, proof.id, receipt.l1BatchTxIndex!, msg, sender, proof.proof)
let chainId = try! await zkSync.chainID()
return (chainId ,receipt.l1BatchNumber!, proof.id, receipt.l1BatchTxIndex!, msg, sender, proof.proof)
}

func _getWithdrawalLog(receipt: TransactionReceipt, index: UInt = 0) -> (EventLog, Int)?{
Expand Down Expand Up @@ -217,7 +219,7 @@ extension WalletL1 {
let address = try await self.zkSync.mainContract()

let zkSyncContract = self.web.contract(
Web3.Utils.IZkSync,
Web3.Utils.IZkSyncHyperchain,
at: EthereumAddress(address),
transaction: transaction
)!
Expand Down
6 changes: 5 additions & 1 deletion Sources/ZkSync2/Accounts/WalletL2.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
}

extension WalletL2 {
public func balance(token: String = ZkSyncAddresses.EthAddress, blockNumber: BlockNumber = .latest) async -> BigUInt {
public func balance(token: String? = nil, blockNumber: BlockNumber = .latest) async -> BigUInt {
try! await zkSync.getBalance(address: signer.address, blockNumber: blockNumber, token: token)
}

Expand All @@ -40,6 +40,10 @@
}

public func withdraw(_ amount: BigUInt, to: String?, token: String? = nil, options: TransactionOption? = nil, paymasterParams: PaymasterParams? = nil) async throws -> TransactionSendingResult? {
return try await withdraw(amount, to: to, token: token, options: options, paymasterParams: paymasterParams, bridgeAddress: nil)
}

public func withdraw(_ amount: BigUInt, to: String?, token: String? = nil, options: TransactionOption? = nil, paymasterParams: PaymasterParams? = nil, bridgeAddress: String? = nil) async throws -> TransactionSendingResult? {
var transaction = try await zkSync.getWithdrawTx(amount, from: signer.address, to: to, token: token, options: options, paymasterParams: paymasterParams)
await populateTransaction(&transaction)
let signed = signTransaction(transaction)
Expand Down
62 changes: 39 additions & 23 deletions Sources/ZkSync2/Clients/BaseClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@ public class BaseClient: ZkSyncClient {
}

public func getBalance(address: String, blockNumber: BlockNumber = .latest, token: String?) async throws -> BigUInt {
if token == nil || token == ZkSyncAddresses.EthAddress {
var token = token
if token == nil {
token = ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS
}else if ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS) ||
ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.LEGACY_ETH_ADDRESS){
token = try! await l2TokenAddress(address: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS)
}

if token == ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS {
return try await web3.eth.getBalance(for: EthereumAddress(address)!, onBlock: blockNumber)
}

Expand All @@ -69,10 +77,17 @@ public class BaseClient: ZkSyncClient {
}

public func l2TokenAddress(address: String) async throws -> String {
if address == ZkSyncAddresses.EthAddress {
return address
var address = address
if address == ZkSyncAddresses.LEGACY_ETH_ADDRESS {
address = ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS
}

let baseToken = try await getBaseTokenContractAddress()
if ZkSyncAddresses.isAddressEq(a: baseToken, b: address){
return ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS
}
let bridgeAddress = try await bridgeContracts().l2Erc20DefaultBridge

let bridgeAddress = try await bridgeContracts().l2SharedDefaultBridge
let bridge = web3.contract(Web3Utils.IL2Bridge, at: EthereumAddress(bridgeAddress)!)
let result = try await bridge?.createReadOperation("l2TokenAddress", parameters: [address])?.callContractMethod()["0"] as! EthereumAddress
return result.address
Expand Down Expand Up @@ -273,15 +288,16 @@ public class BaseClient: ZkSyncClient {
}

public func getWithdrawTx(_ amount: BigUInt, from: String, to: String?, token: String? = nil, options: TransactionOption? = nil, paymasterParams: PaymasterParams? = nil) async throws -> CodableTransaction{
let isEthChain = try! await isEthBasedChain()
var token = token != nil && ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.LEGACY_ETH_ADDRESS) ? ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS : token
let isBaseToken = token != nil ? try! await isBaseToken(tokenAddress: token!) : true

if token != nil &&
ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.LEGACY_ETH_ADDRESS) && !isEthChain {
token = try! await l2TokenAddress(address: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS)
} else if token == nil || (isBaseToken){
return try await getWithdrawTx(amount, from: from, to: to, token: token, options: options, paymasterParams: paymasterParams, bridgeAddress: nil)
}

public func getWithdrawTx(_ amount: BigUInt, from: String, to: String?, token: String? = nil, options: TransactionOption? = nil, paymasterParams: PaymasterParams? = nil, bridgeAddress: String? = nil) async throws -> CodableTransaction{
var token = token
if token == nil {
token = ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS
}else if ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS) ||
ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.LEGACY_ETH_ADDRESS){
token = try await l2TokenAddress(address: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS)
}

let to = to ?? from
Expand All @@ -293,7 +309,7 @@ public class BaseClient: ZkSyncClient {
nonce = try await web3.eth.getTransactionCount(for: EthereumAddress(from)!)
}
let prepared = CodableTransaction.createEtherTransaction(from: EthereumAddress(from)!, to: EthereumAddress(to)!, value: amount, nonce: nonce, paymasterParams: paymasterParams)
if isBaseToken {
if ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS) {
if options?.value == nil {
options?.value = amount
}
Expand All @@ -303,8 +319,12 @@ public class BaseClient: ZkSyncClient {
transaction.chainID = try await chainID()
return transaction
}
var bridgeAddress = bridgeAddress
if bridgeAddress == nil{
bridgeAddress = try await bridgeContracts().l2SharedDefaultBridge
}
let bridgeAddresses = try await bridgeContracts()
let bridge = web3.contract(Web3Utils.IL2Bridge, at: EthereumAddress(bridgeAddresses.l2Erc20DefaultBridge), transaction: prepared)
let bridge = web3.contract(Web3Utils.IL2Bridge, at: EthereumAddress(bridgeAddress!), transaction: prepared)
var transaction = (bridge?.createWriteOperation("withdraw", parameters: [to, token!, amount])!.transaction)!
transaction.chainID = try await chainID()
transaction.value = BigUInt.zero
Expand All @@ -318,22 +338,18 @@ public class BaseClient: ZkSyncClient {
}

public func getTransferTx(_ to: String, amount: BigUInt, from:String, token: String? = nil, options: TransactionOption? = nil, paymasterParams: PaymasterParams? = nil) async -> CodableTransaction {
let isEthChain = try! await isEthBasedChain()
var token = token
let isBaseToken = token != nil ? try! await isBaseToken(tokenAddress: token!) : true

if token != nil &&
ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.LEGACY_ETH_ADDRESS) &&
!isEthChain {
token = try! await l2TokenAddress(address: token!)
} else if token == nil || (isBaseToken){
if token == nil {
token = ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS
}else if ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS) ||
ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.LEGACY_ETH_ADDRESS){
token = try! await l2TokenAddress(address: ZkSyncAddresses.ETH_ADDRESS_IN_CONTRACTS)
}

let nonce = try! await web3.eth.getTransactionCount(for: EthereumAddress(from)!)
let prepared = CodableTransaction.createEtherTransaction(from: EthereumAddress(from)!, to: EthereumAddress(to)!, value: amount, nonce: nonce, paymasterParams: paymasterParams)

if isBaseToken{
if ZkSyncAddresses.isAddressEq(a: token!, b: ZkSyncAddresses.L2_BASE_TOKEN_ADDRESS){
return prepared
}
let tokenContract = web3.contract(Web3Utils.IERC20, at: EthereumAddress(token!)!, transaction: prepared)
Expand Down
2 changes: 2 additions & 0 deletions Sources/ZkSync2/Clients/ZkSyncClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ public protocol ZkSyncClient {
func getProof(address: String, keys: [String], l1BatchNumber: BigUInt) async throws -> Proof

func getWithdrawTx(_ amount: BigUInt, from: String, to: String?, token: String?, options: TransactionOption?, paymasterParams: PaymasterParams?) async throws -> CodableTransaction

func getWithdrawTx(_ amount: BigUInt, from: String, to: String?, token: String?, options: TransactionOption?, paymasterParams: PaymasterParams?, bridgeAddress: String?) async throws -> CodableTransaction
// EstimateGasWithdraw estimates the amount of gas required for a withdrawal
// transaction.
func estimateGasWithdraw(_ amount: BigUInt, from: String, to: String?, token: String?, options: TransactionOption?, paymasterParams: PaymasterParams?) async throws -> BigUInt?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,9 +383,9 @@ class ZkSyncWalletIntegrationTests: XCTestCase {
let result = try! await wallet.walletL2.withdraw(amount, to: nil, token: ZkSyncAddresses.EthAddress)
let receipt = await ZkSyncTransactionReceiptProcessor(zkSync: zkSync).waitForTransactionReceipt(hash: result!.hash)
XCTAssertNotNil(receipt)
//let isFinalized = await wallet.walletL1.isWithdrawalFinalized(withdrawHash: result!.hash)
let isFinalized = await wallet.walletL1.isWithdrawalFinalized(withdrawHash: result!.hash)
sleep(10)
//XCTAssertFalse(isFinalized)
XCTAssertFalse(isFinalized)
_ = try! await wallet.walletL1.finalizeWithdrawal(withdrawalHash: result!.hash)

let l2BalanceAfter = await wallet.walletL2.balance()
Expand Down Expand Up @@ -440,8 +440,8 @@ class ZkSyncWalletIntegrationTests: XCTestCase {
let receipt = await ZkSyncTransactionReceiptProcessor(zkSync: zkSync).waitForTransactionReceipt(hash: result!.hash)
XCTAssertNotNil(receipt)
sleep(10)
//let isFinalized = await wallet.walletL1.isWithdrawalFinalized(withdrawHash: result!.hash)
//XCTAssertFalse(isFinalized)
let isFinalized = await wallet.walletL1.isWithdrawalFinalized(withdrawHash: result!.hash)
XCTAssertFalse(isFinalized)
_ = try! await wallet.walletL1.finalizeWithdrawal(withdrawalHash: result!.hash)

let l2BalanceAfter = await wallet.walletL2.balance(token: l2DAI)
Expand Down

0 comments on commit 04b156e

Please sign in to comment.