zksync-web3
Advanced tools
Comparing version 0.15.5 to 0.16.0-beta.0
@@ -138,2 +138,3 @@ import { BigNumber, BigNumberish, BytesLike, ethers } from "ethers"; | ||
getAllBalances(): Promise<BalancesMap>; | ||
getDeploymentNonce(): Promise<BigNumber>; | ||
getL2BridgeContracts(): Promise<{ | ||
@@ -140,0 +141,0 @@ erc20: import("../typechain").IL2Bridge; |
@@ -200,3 +200,10 @@ "use strict"; | ||
let refundRecipient = (_j = tx.refundRecipient) !== null && _j !== void 0 ? _j : ethers_1.ethers.constants.AddressZero; | ||
const args = [to, token, amount, tx.l2GasLimit, tx.gasPerPubdataByte, refundRecipient]; | ||
const args = [ | ||
to, | ||
token, | ||
amount, | ||
tx.l2GasLimit, | ||
tx.gasPerPubdataByte, | ||
refundRecipient, | ||
]; | ||
(_k = overrides.value) !== null && _k !== void 0 ? _k : (overrides.value = baseCost.add(operatorTip)); | ||
@@ -328,3 +335,3 @@ await (0, utils_1.checkBaseCost)(baseCost, overrides.value); | ||
async finalizeWithdrawal(withdrawalHash, index = 0, overrides) { | ||
const { l1BatchNumber, l2MessageIndex, l2TxNumberInBlock, message, sender, proof, } = await this.finalizeWithdrawalParams(withdrawalHash, index); | ||
const { l1BatchNumber, l2MessageIndex, l2TxNumberInBlock, message, sender, proof } = await this.finalizeWithdrawalParams(withdrawalHash, index); | ||
if ((0, utils_1.isETH)(sender)) { | ||
@@ -365,4 +372,3 @@ const withdrawTo = ethers_1.ethers.utils.hexDataSlice(message, 4, 24); | ||
const receipt = await this._providerL2().getTransactionReceipt(ethers_1.ethers.utils.hexlify(depositHash)); | ||
const successL2ToL1LogIndex = receipt.l2ToL1Logs.findIndex((l2ToL1log) => l2ToL1log.sender == utils_1.BOOTLOADER_FORMAL_ADDRESS && | ||
l2ToL1log.key == depositHash); | ||
const successL2ToL1LogIndex = receipt.l2ToL1Logs.findIndex((l2ToL1log) => l2ToL1log.sender == utils_1.BOOTLOADER_FORMAL_ADDRESS && l2ToL1log.key == depositHash); | ||
const successL2ToL1Log = receipt.l2ToL1Logs[successL2ToL1LogIndex]; | ||
@@ -433,2 +439,5 @@ if (successL2ToL1Log.value != ethers_1.ethers.constants.HashZero) { | ||
} | ||
async getDeploymentNonce() { | ||
return await typechain_1.INonceHolderFactory.connect(utils_1.NONCE_HOLDER_ADDRESS, this._signerL2()).getDeploymentNonce(await this.getAddress()); | ||
} | ||
async getL2BridgeContracts() { | ||
@@ -435,0 +444,0 @@ const addresses = await this._providerL2().getDefaultBridgeAddresses(); |
@@ -11,4 +11,39 @@ import { Wallet } from "./wallet"; | ||
private encodeCalldata; | ||
protected checkOverrides(overrides: ethers.PayableOverrides): void; | ||
getDeployTransaction(...args: any[]): ethers.providers.TransactionRequest; | ||
/** | ||
* Deploys a new contract or account instance on the Ethereum blockchain. | ||
* | ||
* @async | ||
* @param {...Array<any>} args - Constructor arguments for the contract followed by optional | ||
* {@link ethers.PayableOverrides|overrides}. When deploying with CREATE2 opcode slat must be present in overrides. | ||
* | ||
* | ||
* @example | ||
* // Deploy with constructor arguments only using CREATE opcode | ||
* const deployedContract = await contractFactory.deploy(arg1, arg2, ...); | ||
* | ||
* // Deploy with constructor arguments, and factory dependencies using CREATE opcode | ||
* const deployedContractWithSaltAndDeps = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* factoryDeps: ['0x...'] | ||
* } | ||
* }); | ||
* | ||
* // Deploy with constructor arguments and custom salt using CREATE2 opcode | ||
* const deployedContractWithSalt = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* salt: '0x...' | ||
* } | ||
* }); | ||
* | ||
* // Deploy with constructor arguments, custom salt, and factory dependencies using CREATE2 opcode | ||
* const deployedContractWithSaltAndDeps = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* salt: '0x...', | ||
* factoryDeps: ['0x...'] | ||
* } | ||
* }); | ||
*/ | ||
deploy(...args: Array<any>): Promise<Contract>; | ||
} |
@@ -7,2 +7,3 @@ "use strict"; | ||
const types_1 = require("./types"); | ||
const bytes_1 = require("@ethersproject/bytes"); | ||
var ethers_2 = require("ethers"); | ||
@@ -16,17 +17,16 @@ Object.defineProperty(exports, "Contract", { enumerable: true, get: function () { return ethers_2.Contract; } }); | ||
encodeCalldata(salt, bytecodeHash, constructorCalldata) { | ||
if (this.deploymentType == "create") { | ||
return utils_1.CONTRACT_DEPLOYER.encodeFunctionData("create", [ | ||
salt, | ||
bytecodeHash, | ||
constructorCalldata, | ||
]); | ||
const contractDeploymentArgs = [salt, bytecodeHash, constructorCalldata]; | ||
const accountDeploymentArgs = [...contractDeploymentArgs, types_1.AccountAbstractionVersion.Version1]; | ||
if (this.deploymentType === "create") { | ||
return utils_1.CONTRACT_DEPLOYER.encodeFunctionData("create", [...contractDeploymentArgs]); | ||
} | ||
else if (this.deploymentType == "createAccount") { | ||
return utils_1.CONTRACT_DEPLOYER.encodeFunctionData("createAccount", [ | ||
salt, | ||
bytecodeHash, | ||
constructorCalldata, | ||
types_1.AccountAbstractionVersion.Version1, | ||
]); | ||
else if (this.deploymentType === "createAccount") { | ||
return utils_1.CONTRACT_DEPLOYER.encodeFunctionData("createAccount", [...accountDeploymentArgs]); | ||
} | ||
else if (this.deploymentType === "create2") { | ||
return utils_1.CONTRACT_DEPLOYER.encodeFunctionData("create2", [...contractDeploymentArgs]); | ||
} | ||
else if (this.deploymentType === "create2Account") { | ||
return utils_1.CONTRACT_DEPLOYER.encodeFunctionData("create2Account", [...accountDeploymentArgs]); | ||
} | ||
else { | ||
@@ -36,29 +36,92 @@ throw new Error(`Unsupported deployment type ${this.deploymentType}`); | ||
} | ||
checkOverrides(overrides) { | ||
if (this.deploymentType === "create2" || this.deploymentType === "create2Account") { | ||
if (!overrides.customData || !overrides.customData.salt) { | ||
throw new Error("Salt is required for CREATE2 deployment."); | ||
} | ||
if (!overrides.customData.salt.startsWith("0x") || overrides.customData.salt.length !== 66) { | ||
throw new Error("Invalid salt provided."); | ||
} | ||
} | ||
if (overrides.customData && | ||
overrides.customData.factoryDeps && | ||
!Array.isArray(overrides.customData.factoryDeps)) { | ||
throw new Error("Invalid 'factoryDeps' format. It should be an array of bytecodes."); | ||
} | ||
} | ||
getDeployTransaction(...args) { | ||
var _a, _b, _c; | ||
var _d, _e; | ||
// TODO (SMA-1585): Users should be able to provide the salt. | ||
let salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; | ||
var _a, _b, _c, _d, _e, _f; | ||
var _g, _h, _j; | ||
let constructorArgs; | ||
let overrides = { | ||
customData: { factoryDeps: [], salt: utils_1.ZERO_HASH }, | ||
}; | ||
// The overrides will be popped out in this call: | ||
const txRequest = super.getDeployTransaction(...args); | ||
// Removing overrides | ||
if (this.interface.deploy.inputs.length + 1 == args.length) { | ||
args.pop(); | ||
constructorArgs = args.slice(0, args.length - 1); | ||
overrides = args[args.length - 1]; | ||
(_a = overrides.customData) !== null && _a !== void 0 ? _a : (overrides.customData = {}); | ||
(_b = (_g = overrides.customData).salt) !== null && _b !== void 0 ? _b : (_g.salt = utils_1.ZERO_HASH); | ||
this.checkOverrides(overrides); | ||
overrides.customData.factoryDeps = ((_c = overrides.customData.factoryDeps) !== null && _c !== void 0 ? _c : []).map(normalizeBytecode); | ||
} | ||
// Salt argument is not used, so we provide a placeholder value. | ||
else { | ||
constructorArgs = args; | ||
} | ||
const bytecodeHash = (0, utils_1.hashBytecode)(this.bytecode); | ||
const constructorCalldata = ethers_1.utils.arrayify(this.interface.encodeDeploy(args)); | ||
const deployCalldata = this.encodeCalldata(salt, bytecodeHash, constructorCalldata); | ||
txRequest.type = utils_1.EIP712_TX_TYPE; | ||
txRequest.to = utils_1.CONTRACT_DEPLOYER_ADDRESS; | ||
txRequest.data = deployCalldata; | ||
(_a = txRequest.customData) !== null && _a !== void 0 ? _a : (txRequest.customData = {}); | ||
(_b = (_d = txRequest.customData).factoryDeps) !== null && _b !== void 0 ? _b : (_d.factoryDeps = []); | ||
(_c = (_e = txRequest.customData).gasPerPubdata) !== null && _c !== void 0 ? _c : (_e.gasPerPubdata = utils_1.DEFAULT_GAS_PER_PUBDATA_LIMIT); | ||
const constructorCalldata = ethers_1.utils.arrayify(this.interface.encodeDeploy(constructorArgs)); | ||
const deployCalldata = this.encodeCalldata(overrides.customData.salt, bytecodeHash, constructorCalldata); | ||
// salt is no longer used and should not be present in customData of EIP712 transaction | ||
if (txRequest.customData && txRequest.customData.salt) | ||
delete txRequest.customData.salt; | ||
const tx = { | ||
...txRequest, | ||
to: utils_1.CONTRACT_DEPLOYER_ADDRESS, | ||
data: deployCalldata, | ||
type: utils_1.EIP712_TX_TYPE, | ||
}; | ||
(_d = tx.customData) !== null && _d !== void 0 ? _d : (tx.customData = {}); | ||
(_e = (_h = tx.customData).factoryDeps) !== null && _e !== void 0 ? _e : (_h.factoryDeps = overrides.customData.factoryDeps || []); | ||
(_f = (_j = tx.customData).gasPerPubdata) !== null && _f !== void 0 ? _f : (_j.gasPerPubdata = utils_1.DEFAULT_GAS_PER_PUBDATA_LIMIT); | ||
// The number of factory deps is relatively low, so it is efficient enough. | ||
if (!txRequest.customData.factoryDeps.includes(this.bytecode)) { | ||
txRequest.customData.factoryDeps.push(this.bytecode); | ||
if (!tx.customData || !tx.customData.factoryDeps.includes(this.bytecode)) { | ||
tx.customData.factoryDeps.push(this.bytecode); | ||
} | ||
return txRequest; | ||
return tx; | ||
} | ||
/** | ||
* Deploys a new contract or account instance on the Ethereum blockchain. | ||
* | ||
* @async | ||
* @param {...Array<any>} args - Constructor arguments for the contract followed by optional | ||
* {@link ethers.PayableOverrides|overrides}. When deploying with CREATE2 opcode slat must be present in overrides. | ||
* | ||
* | ||
* @example | ||
* // Deploy with constructor arguments only using CREATE opcode | ||
* const deployedContract = await contractFactory.deploy(arg1, arg2, ...); | ||
* | ||
* // Deploy with constructor arguments, and factory dependencies using CREATE opcode | ||
* const deployedContractWithSaltAndDeps = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* factoryDeps: ['0x...'] | ||
* } | ||
* }); | ||
* | ||
* // Deploy with constructor arguments and custom salt using CREATE2 opcode | ||
* const deployedContractWithSalt = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* salt: '0x...' | ||
* } | ||
* }); | ||
* | ||
* // Deploy with constructor arguments, custom salt, and factory dependencies using CREATE2 opcode | ||
* const deployedContractWithSaltAndDeps = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* salt: '0x...', | ||
* factoryDeps: ['0x...'] | ||
* } | ||
* }); | ||
*/ | ||
async deploy(...args) { | ||
@@ -74,1 +137,26 @@ const contract = await super.deploy(...args); | ||
exports.ContractFactory = ContractFactory; | ||
function normalizeBytecode(bytecode) { | ||
let bytecodeHex = null; | ||
if (typeof bytecode === "string") { | ||
bytecodeHex = bytecode; | ||
} | ||
else if ((0, bytes_1.isBytes)(bytecode)) { | ||
bytecodeHex = (0, bytes_1.hexlify)(bytecode); | ||
} | ||
else if (bytecode && typeof bytecode.object === "string") { | ||
// Allow the bytecode object from the Solidity compiler | ||
bytecodeHex = bytecode.object; | ||
} | ||
else { | ||
// Crash in the next verification step | ||
bytecodeHex = "!"; | ||
} | ||
// Make sure it is 0x prefixed | ||
if (bytecodeHex.substring(0, 2) !== "0x") { | ||
bytecodeHex = "0x" + bytecodeHex; | ||
} | ||
// Make sure the final result is valid bytecode | ||
if (!(0, bytes_1.isHexString)(bytecodeHex) || bytecodeHex.length % 2) { | ||
throw new Error("invalid bytecode"); | ||
} | ||
} |
import { BigNumber, BigNumberish, BytesLike, ethers, providers, utils } from "ethers"; | ||
import { ExternalProvider } from "@ethersproject/providers"; | ||
import { ConnectionInfo } from "@ethersproject/web"; | ||
import { Address, BalancesMap, BatchDetails, Block, BlockDetails, BlockTag, BlockWithTransactions, ContractAccountInfo, EventFilter, Log, MessageProof, PriorityOpResponse, Token, TransactionDetails, TransactionReceipt, TransactionRequest, TransactionResponse, TransactionStatus } from "./types"; | ||
import { Address, BalancesMap, BatchDetails, Block, BlockDetails, BlockTag, BlockWithTransactions, ContractAccountInfo, EventFilter, Log, MessageProof, PriorityOpResponse, Token, TransactionDetails, TransactionReceipt, TransactionRequest, TransactionResponse, TransactionStatus, Fee } from "./types"; | ||
import { Signer } from "./signer"; | ||
@@ -29,2 +29,3 @@ import Formatter = providers.Formatter; | ||
estimateGasL1(transaction: utils.Deferrable<TransactionRequest>): Promise<BigNumber>; | ||
estimateFee(transaction: TransactionRequest): Promise<Fee>; | ||
getGasPrice(token?: Address): Promise<BigNumber>; | ||
@@ -31,0 +32,0 @@ constructor(url?: ConnectionInfo | string, network?: ethers.providers.Networkish); |
@@ -96,4 +96,3 @@ "use strict"; | ||
if (receipt.blockNumber == null && | ||
!(receipt.status != null && | ||
ethers_1.BigNumber.from(receipt.status).isZero())) { | ||
!(receipt.status != null && ethers_1.BigNumber.from(receipt.status).isZero())) { | ||
return null; | ||
@@ -151,4 +150,3 @@ } | ||
this._emitted["b:" + log.blockHash] = log.blockNumber; | ||
this._emitted["t:" + log.transactionHash] = | ||
log.blockNumber; | ||
this._emitted["t:" + log.transactionHash] = log.blockNumber; | ||
this.emit(filter, log); | ||
@@ -265,4 +263,3 @@ }); | ||
defaultFormatter.formats.block.l1BatchTimestamp = Formatter.allowNull(number); | ||
defaultFormatter.formats.blockWithTransactions.l1BatchNumber = | ||
Formatter.allowNull(number); | ||
defaultFormatter.formats.blockWithTransactions.l1BatchNumber = Formatter.allowNull(number); | ||
defaultFormatter.formats.blockWithTransactions.l1BatchTimestamp = | ||
@@ -396,2 +393,5 @@ Formatter.allowNull(number); | ||
} | ||
async estimateFee(transaction) { | ||
return await this.send("zks_estimateFee", [transaction]); | ||
} | ||
async getGasPrice(token) { | ||
@@ -398,0 +398,0 @@ const params = token ? [token] : []; |
@@ -39,2 +39,3 @@ import { ethers } from "ethers"; | ||
getAllBalances(): Promise<import("./types").BalancesMap>; | ||
getDeploymentNonce(): Promise<ethers.BigNumber>; | ||
getL2BridgeContracts(): Promise<{ | ||
@@ -210,2 +211,3 @@ erc20: import("../typechain").IL2Bridge; | ||
getAllBalances(): Promise<import("./types").BalancesMap>; | ||
getDeploymentNonce(): Promise<ethers.BigNumber>; | ||
getL2BridgeContracts(): Promise<{ | ||
@@ -212,0 +214,0 @@ erc20: import("../typechain").IL2Bridge; |
@@ -47,4 +47,3 @@ "use strict"; | ||
maxPriorityFeePerGas, | ||
paymaster: ((_g = (_f = transaction.customData) === null || _f === void 0 ? void 0 : _f.paymasterParams) === null || _g === void 0 ? void 0 : _g.paymaster) || | ||
ethers_1.ethers.constants.AddressZero, | ||
paymaster: ((_g = (_f = transaction.customData) === null || _f === void 0 ? void 0 : _f.paymasterParams) === null || _g === void 0 ? void 0 : _g.paymaster) || ethers_1.ethers.constants.AddressZero, | ||
nonce: transaction.nonce, | ||
@@ -51,0 +50,0 @@ value: transaction.value, |
@@ -38,3 +38,3 @@ import { BytesLike, BigNumberish, providers, BigNumber } from "ethers"; | ||
export type BlockTag = number | string | 'committed' | 'finalized' | 'latest' | 'earliest' | 'pending'; | ||
export type DeploymentType = "create" | "createAccount"; | ||
export type DeploymentType = "create" | "createAccount" | "create2" | "create2Account"; | ||
export interface Token { | ||
@@ -49,2 +49,8 @@ l1Address: Address; | ||
} | ||
export interface Fee { | ||
readonly gasLimit: bigint; | ||
readonly gasPerPubdataLimit: bigint; | ||
readonly maxPriorityFeePerGas: bigint; | ||
readonly maxFeePerGas: bigint; | ||
} | ||
export interface MessageProof { | ||
@@ -51,0 +57,0 @@ id: number; |
@@ -7,3 +7,2 @@ import { utils, ethers, BigNumber, BigNumberish, BytesLike } from "ethers"; | ||
export * from "./paymaster-utils"; | ||
export declare const ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; | ||
export declare const ZKSYNC_MAIN_ABI: utils.Interface; | ||
@@ -16,2 +15,5 @@ export declare const CONTRACT_DEPLOYER: utils.Interface; | ||
export declare const L2_BRIDGE_ABI: utils.Interface; | ||
export declare const NONCE_HOLDER_ABI: utils.Interface; | ||
export declare const PAYMASTER_FLOW_ABI: utils.Interface; | ||
export declare const ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; | ||
export declare const BOOTLOADER_FORMAL_ADDRESS = "0x0000000000000000000000000000000000008001"; | ||
@@ -21,2 +23,4 @@ export declare const CONTRACT_DEPLOYER_ADDRESS = "0x0000000000000000000000000000000000008006"; | ||
export declare const L2_ETH_TOKEN_ADDRESS = "0x000000000000000000000000000000000000800a"; | ||
export declare const NONCE_HOLDER_ADDRESS = "0x0000000000000000000000000000000000008003"; | ||
export declare const ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; | ||
export declare const L1_TO_L2_ALIAS_OFFSET = "0x1111000000000000000000000000000000001111"; | ||
@@ -23,0 +27,0 @@ export declare const EIP1271_MAGIC_VALUE = "0x1626ba7e"; |
@@ -17,3 +17,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.estimateCustomBridgeDepositL2Gas = exports.scaleGasLimit = exports.estimateDefaultBridgeDepositL2Gas = exports.isTypedDataSignatureCorrect = exports.isMessageSignatureCorrect = exports.getERC20BridgeCalldata = exports.getERC20DefaultBridgeData = exports.undoL1ToL2Alias = exports.applyL1ToL2Alias = exports.getL2HashFromPriorityOp = exports.parseTransaction = exports.hashBytecode = exports.serialize = exports.checkBaseCost = exports.createAddress = exports.create2Address = exports.getDeployedContracts = exports.getHashedL2ToL1Msg = exports.layer1TxDefaults = exports.sleep = exports.isETH = exports.REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT = exports.DEFAULT_GAS_PER_PUBDATA_LIMIT = exports.L1_RECOMMENDED_MIN_ETH_DEPOSIT_GAS_LIMIT = exports.L1_RECOMMENDED_MIN_ERC20_DEPOSIT_GAS_LIMIT = exports.L1_FEE_ESTIMATION_COEF_DENOMINATOR = exports.L1_FEE_ESTIMATION_COEF_NUMERATOR = exports.MAX_BYTECODE_LEN_BYTES = exports.PRIORITY_OPERATION_L2_TX_TYPE = exports.EIP712_TX_TYPE = exports.EIP1271_MAGIC_VALUE = exports.L1_TO_L2_ALIAS_OFFSET = exports.L2_ETH_TOKEN_ADDRESS = exports.L1_MESSENGER_ADDRESS = exports.CONTRACT_DEPLOYER_ADDRESS = exports.BOOTLOADER_FORMAL_ADDRESS = exports.L2_BRIDGE_ABI = exports.L1_BRIDGE_ABI = exports.IERC1271 = exports.IERC20 = exports.L1_MESSENGER = exports.CONTRACT_DEPLOYER = exports.ZKSYNC_MAIN_ABI = exports.ETH_ADDRESS = void 0; | ||
exports.estimateCustomBridgeDepositL2Gas = exports.scaleGasLimit = exports.estimateDefaultBridgeDepositL2Gas = exports.isTypedDataSignatureCorrect = exports.isMessageSignatureCorrect = exports.getERC20BridgeCalldata = exports.getERC20DefaultBridgeData = exports.undoL1ToL2Alias = exports.applyL1ToL2Alias = exports.getL2HashFromPriorityOp = exports.parseTransaction = exports.hashBytecode = exports.serialize = exports.checkBaseCost = exports.createAddress = exports.create2Address = exports.getDeployedContracts = exports.getHashedL2ToL1Msg = exports.layer1TxDefaults = exports.sleep = exports.isETH = exports.REQUIRED_L1_TO_L2_GAS_PER_PUBDATA_LIMIT = exports.DEFAULT_GAS_PER_PUBDATA_LIMIT = exports.L1_RECOMMENDED_MIN_ETH_DEPOSIT_GAS_LIMIT = exports.L1_RECOMMENDED_MIN_ERC20_DEPOSIT_GAS_LIMIT = exports.L1_FEE_ESTIMATION_COEF_DENOMINATOR = exports.L1_FEE_ESTIMATION_COEF_NUMERATOR = exports.MAX_BYTECODE_LEN_BYTES = exports.PRIORITY_OPERATION_L2_TX_TYPE = exports.EIP712_TX_TYPE = exports.EIP1271_MAGIC_VALUE = exports.L1_TO_L2_ALIAS_OFFSET = exports.ZERO_HASH = exports.NONCE_HOLDER_ADDRESS = exports.L2_ETH_TOKEN_ADDRESS = exports.L1_MESSENGER_ADDRESS = exports.CONTRACT_DEPLOYER_ADDRESS = exports.BOOTLOADER_FORMAL_ADDRESS = exports.ETH_ADDRESS = exports.PAYMASTER_FLOW_ABI = exports.NONCE_HOLDER_ABI = exports.L2_BRIDGE_ABI = exports.L1_BRIDGE_ABI = exports.IERC1271 = exports.IERC20 = exports.L1_MESSENGER = exports.CONTRACT_DEPLOYER = exports.ZKSYNC_MAIN_ABI = void 0; | ||
const ethers_1 = require("ethers"); | ||
@@ -25,3 +25,2 @@ const types_1 = require("./types"); | ||
__exportStar(require("./paymaster-utils"), exports); | ||
exports.ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; | ||
exports.ZKSYNC_MAIN_ABI = new ethers_1.utils.Interface(require("../abi/IZkSync.json").abi); | ||
@@ -34,2 +33,5 @@ exports.CONTRACT_DEPLOYER = new ethers_1.utils.Interface(require("../abi/ContractDeployer.json").abi); | ||
exports.L2_BRIDGE_ABI = new ethers_1.utils.Interface(require("../abi/IL2Bridge.json").abi); | ||
exports.NONCE_HOLDER_ABI = new ethers_1.utils.Interface(require("../abi/INonceHolder.json").abi); | ||
exports.PAYMASTER_FLOW_ABI = new ethers_1.utils.Interface(require("../abi/IPaymasterFlow.json").abi); | ||
exports.ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; | ||
exports.BOOTLOADER_FORMAL_ADDRESS = "0x0000000000000000000000000000000000008001"; | ||
@@ -39,2 +41,4 @@ exports.CONTRACT_DEPLOYER_ADDRESS = "0x0000000000000000000000000000000000008006"; | ||
exports.L2_ETH_TOKEN_ADDRESS = "0x000000000000000000000000000000000000800a"; | ||
exports.NONCE_HOLDER_ADDRESS = "0x0000000000000000000000000000000000008003"; | ||
exports.ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; | ||
exports.L1_TO_L2_ALIAS_OFFSET = "0x1111000000000000000000000000000000001111"; | ||
@@ -287,5 +291,3 @@ exports.EIP1271_MAGIC_VALUE = "0x1626ba7e"; | ||
} | ||
if (ethSignature.v !== 0 && | ||
ethSignature.v !== 1 && | ||
!transaction.customData.customSignature) { | ||
if (ethSignature.v !== 0 && ethSignature.v !== 1 && !transaction.customData.customSignature) { | ||
throw new Error("Failed to parse signature"); | ||
@@ -304,4 +306,3 @@ } | ||
var _a; | ||
if (((_a = transaction === null || transaction === void 0 ? void 0 : transaction.customData) === null || _a === void 0 ? void 0 : _a.customSignature) && | ||
transaction.customData.customSignature.length) { | ||
if (((_a = transaction === null || transaction === void 0 ? void 0 : transaction.customData) === null || _a === void 0 ? void 0 : _a.customSignature) && transaction.customData.customSignature.length) { | ||
return ethers_1.ethers.utils.arrayify(transaction.customData.customSignature); | ||
@@ -471,5 +472,3 @@ } | ||
function scaleGasLimit(gasLimit) { | ||
return gasLimit | ||
.mul(exports.L1_FEE_ESTIMATION_COEF_NUMERATOR) | ||
.div(exports.L1_FEE_ESTIMATION_COEF_DENOMINATOR); | ||
return gasLimit.mul(exports.L1_FEE_ESTIMATION_COEF_NUMERATOR).div(exports.L1_FEE_ESTIMATION_COEF_DENOMINATOR); | ||
} | ||
@@ -476,0 +475,0 @@ exports.scaleGasLimit = scaleGasLimit; |
@@ -12,2 +12,3 @@ import { EIP712Signer } from "./signer"; | ||
getAllBalances(): Promise<import("./types").BalancesMap>; | ||
getDeploymentNonce(): Promise<ethers.BigNumber>; | ||
getL2BridgeContracts(): Promise<{ | ||
@@ -14,0 +15,0 @@ erc20: import("../typechain").IL2Bridge; |
@@ -262,3 +262,3 @@ /* Autogenerated file. Do not edit manually. */ | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -476,3 +476,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -662,3 +662,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -867,3 +867,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -1044,3 +1044,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -1047,0 +1047,0 @@ bytecodeHash: BytesLike; |
@@ -19,3 +19,5 @@ export { ContractDeployerFactory } from './ContractDeployerFactory'; | ||
export type { IPaymasterFlow } from './IPaymasterFlow'; | ||
export { INonceHolderFactory } from './INonceHolderFactory'; | ||
export type { INonceHolder } from './INonceHolder'; | ||
export { IZkSyncFactory } from './IZkSyncFactory'; | ||
export type { IZkSync } from './IZkSync'; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.IZkSyncFactory = exports.IPaymasterFlowFactory = exports.IL2BridgeFactory = exports.IL1MessengerFactory = exports.IL1BridgeFactory = exports.IEthTokenFactory = exports.IERC1271Factory = exports.IERC20Factory = exports.IAllowListFactory = exports.ContractDeployerFactory = void 0; | ||
exports.IZkSyncFactory = exports.INonceHolderFactory = exports.IPaymasterFlowFactory = exports.IL2BridgeFactory = exports.IL1MessengerFactory = exports.IL1BridgeFactory = exports.IEthTokenFactory = exports.IERC1271Factory = exports.IERC20Factory = exports.IAllowListFactory = exports.ContractDeployerFactory = void 0; | ||
var ContractDeployerFactory_1 = require("./ContractDeployerFactory"); | ||
@@ -22,3 +22,5 @@ Object.defineProperty(exports, "ContractDeployerFactory", { enumerable: true, get: function () { return ContractDeployerFactory_1.ContractDeployerFactory; } }); | ||
Object.defineProperty(exports, "IPaymasterFlowFactory", { enumerable: true, get: function () { return IPaymasterFlowFactory_1.IPaymasterFlowFactory; } }); | ||
var INonceHolderFactory_1 = require("./INonceHolderFactory"); | ||
Object.defineProperty(exports, "INonceHolderFactory", { enumerable: true, get: function () { return INonceHolderFactory_1.INonceHolderFactory; } }); | ||
var IZkSyncFactory_1 = require("./IZkSyncFactory"); | ||
Object.defineProperty(exports, "IZkSyncFactory", { enumerable: true, get: function () { return IZkSyncFactory_1.IZkSyncFactory; } }); |
{ | ||
"name": "zksync-web3", | ||
"version": "0.15.5", | ||
"version": "0.16.0-beta.0", | ||
"main": "build/src/index.js", | ||
@@ -5,0 +5,0 @@ "types": "build/src/index.d.ts", |
# 🚀 zksync-web3 JavaScript SDK 🚀 | ||
In order to provide easy access to all the features of zkSync Era, the `zksync-web3` JavaScript SDK was created, | ||
@@ -16,3 +15,2 @@ which is made in a way that has an interface very similar to those of [ethers](https://docs.ethers.io/v5/). In | ||
🔗 For a detailed walkthrough, refer to the [official documentation](https://era.zksync.io/docs/api/js/). | ||
@@ -24,12 +22,12 @@ | ||
- `Provider` provides connection to the zkSync Era blockchain, which allows querying the blockchain state, such as account, block or transaction details, | ||
querying event logs or evaluating read-only code using call. Additionally, the client facilitates writing to the blockchain by sending | ||
transactions. | ||
- `Wallet` wraps all operations that interact with an account. An account generally has a private key, which can be used to sign a variety of | ||
types of payloads. It provides easy usage of the most common features. | ||
- `Provider` provides connection to the zkSync Era blockchain, which allows querying the blockchain state, such as account, block or transaction details, | ||
querying event logs or evaluating read-only code using call. Additionally, the client facilitates writing to the blockchain by sending | ||
transactions. | ||
- `Wallet` wraps all operations that interact with an account. An account generally has a private key, which can be used to sign a variety of | ||
types of payloads. It provides easy usage of the most common features. | ||
## 🛠 Prerequisites | ||
- `node: >= 14.20.0` ([installation guide](https://nodejs.org/en/download/package-manager)) | ||
- `ethers: ~5.7.0` | ||
- `node: >= 14.20.0` ([installation guide](https://nodejs.org/en/download/package-manager)) | ||
- `ethers: ~5.7.0` | ||
@@ -82,6 +80,6 @@ ## 📥 Installation & Setup | ||
### Transfer funds | ||
Transfer funds among accounts on L2 network. | ||
```ts | ||
@@ -91,5 +89,5 @@ const receiver = Wallet.createRandom(); | ||
const transfer = await wallet.transfer({ | ||
to: receiver, | ||
token: utils.ETH_ADDRESS, | ||
amount: ethers.utils.parseEther("1.0"), | ||
to: receiver, | ||
token: utils.ETH_ADDRESS, | ||
amount: ethers.utils.parseEther("1.0"), | ||
}); | ||
@@ -101,6 +99,7 @@ ``` | ||
Transfer funds from L1 to L2 network. | ||
```ts | ||
const deposit = await wallet.deposit({ | ||
token: utils.ETH_ADDRESS, | ||
amount: ethers.utils.parseEther("1.0"), | ||
token: utils.ETH_ADDRESS, | ||
amount: ethers.utils.parseEther("1.0"), | ||
}); | ||
@@ -112,6 +111,7 @@ ``` | ||
Transfer funds from L2 to L1 network. | ||
```ts | ||
const withdrawal = await wallet.withdraw({ | ||
token: utils.ETH_ADDRESS, | ||
amount: ethers.utils.parseEther("1.0"), | ||
token: utils.ETH_ADDRESS, | ||
amount: ethers.utils.parseEther("1.0"), | ||
}); | ||
@@ -118,0 +118,0 @@ ``` |
@@ -7,2 +7,3 @@ import { BigNumber, BigNumberish, BytesLike, ethers } from "ethers"; | ||
IZkSyncFactory, | ||
INonceHolderFactory, | ||
} from "../typechain"; | ||
@@ -35,2 +36,3 @@ import { Provider } from "./provider"; | ||
undoL1ToL2Alias, | ||
NONCE_HOLDER_ADDRESS, | ||
} from "./utils"; | ||
@@ -72,6 +74,3 @@ | ||
async getBalanceL1( | ||
token?: Address, | ||
blockTag?: ethers.providers.BlockTag, | ||
): Promise<BigNumber> { | ||
async getBalanceL1(token?: Address, blockTag?: ethers.providers.BlockTag): Promise<BigNumber> { | ||
token ??= ETH_ADDRESS; | ||
@@ -209,5 +208,3 @@ if (isETH(token)) { | ||
try { | ||
l2WethToken = await bridgeContracts.weth.l2TokenAddress( | ||
transaction.token, | ||
); | ||
l2WethToken = await bridgeContracts.weth.l2TokenAddress(transaction.token); | ||
} catch (e) {} | ||
@@ -224,6 +221,3 @@ // If the token is Wrapped Ether, use its bridge. | ||
// We only request the allowance if the current one is not enough. | ||
const allowance = await this.getAllowanceL1( | ||
transaction.token, | ||
bridgeAddress, | ||
); | ||
const allowance = await this.getAllowanceL1(transaction.token, bridgeAddress); | ||
if (allowance.lt(transaction.amount)) { | ||
@@ -291,5 +285,3 @@ const approveTx = await this.approveERC20( | ||
if (transaction.bridgeAddress != null) { | ||
bridgeContracts.erc20 = bridgeContracts.erc20.attach( | ||
transaction.bridgeAddress, | ||
); | ||
bridgeContracts.erc20 = bridgeContracts.erc20.attach(transaction.bridgeAddress); | ||
} | ||
@@ -359,10 +351,10 @@ | ||
let refundRecipient = tx.refundRecipient ?? ethers.constants.AddressZero; | ||
const args: [ | ||
Address, | ||
Address, | ||
BigNumberish, | ||
BigNumberish, | ||
BigNumberish, | ||
Address, | ||
] = [to, token, amount, tx.l2GasLimit, tx.gasPerPubdataByte, refundRecipient]; | ||
const args: [Address, Address, BigNumberish, BigNumberish, BigNumberish, Address] = [ | ||
to, | ||
token, | ||
amount, | ||
tx.l2GasLimit, | ||
tx.gasPerPubdataByte, | ||
refundRecipient, | ||
]; | ||
@@ -458,4 +450,3 @@ overrides.value ??= baseCost.add(operatorTip); | ||
.add(baseCost); | ||
const formattedRecommendedBalance = | ||
ethers.utils.formatEther(recommendedETHBalance); | ||
const formattedRecommendedBalance = ethers.utils.formatEther(recommendedETHBalance); | ||
throw new Error( | ||
@@ -504,5 +495,3 @@ `Not enough balance for deposit. Under the provided gas price, the recommended balance to perform a deposit is ${formattedRecommendedBalance} ETH`, | ||
fullCost.maxFeePerGas = BigNumber.from(await tx.overrides.maxFeePerGas); | ||
fullCost.maxPriorityFeePerGas = BigNumber.from( | ||
await tx.overrides.maxPriorityFeePerGas, | ||
); | ||
fullCost.maxPriorityFeePerGas = BigNumber.from(await tx.overrides.maxPriorityFeePerGas); | ||
} | ||
@@ -544,6 +533,3 @@ | ||
const { log, l1BatchTxId } = await this._getWithdrawalLog(withdrawalHash, index); | ||
const { l2ToL1LogIndex } = await this._getWithdrawalL2ToL1Log( | ||
withdrawalHash, | ||
index, | ||
); | ||
const { l2ToL1LogIndex } = await this._getWithdrawalL2ToL1Log(withdrawalHash, index); | ||
const sender = ethers.utils.hexDataSlice(log.topics[1], 12); | ||
@@ -567,10 +553,4 @@ const proof = await this._providerL2().getLogProof(withdrawalHash, l2ToL1LogIndex); | ||
) { | ||
const { | ||
l1BatchNumber, | ||
l2MessageIndex, | ||
l2TxNumberInBlock, | ||
message, | ||
sender, | ||
proof, | ||
} = await this.finalizeWithdrawalParams(withdrawalHash, index); | ||
const { l1BatchNumber, l2MessageIndex, l2TxNumberInBlock, message, sender, proof } = | ||
await this.finalizeWithdrawalParams(withdrawalHash, index); | ||
@@ -607,6 +587,3 @@ if (isETH(sender)) { | ||
const l2Bridge = IL2BridgeFactory.connect(sender, this._providerL2()); | ||
const l1Bridge = IL1BridgeFactory.connect( | ||
await l2Bridge.l1Bridge(), | ||
this._signerL1(), | ||
); | ||
const l1Bridge = IL1BridgeFactory.connect(await l2Bridge.l1Bridge(), this._signerL1()); | ||
return await l1Bridge.finalizeWithdrawal( | ||
@@ -624,6 +601,3 @@ l1BatchNumber, | ||
const { log } = await this._getWithdrawalLog(withdrawalHash, index); | ||
const { l2ToL1LogIndex } = await this._getWithdrawalL2ToL1Log( | ||
withdrawalHash, | ||
index, | ||
); | ||
const { l2ToL1LogIndex } = await this._getWithdrawalL2ToL1Log(withdrawalHash, index); | ||
const sender = ethers.utils.hexDataSlice(log.topics[1], 12); | ||
@@ -643,6 +617,3 @@ // `getLogProof` is called not to get proof but | ||
const l2Bridge = IL2BridgeFactory.connect(sender, this._providerL2()); | ||
const l1Bridge = IL1BridgeFactory.connect( | ||
await l2Bridge.l1Bridge(), | ||
this._providerL1(), | ||
); | ||
const l1Bridge = IL1BridgeFactory.connect(await l2Bridge.l1Bridge(), this._providerL1()); | ||
@@ -658,4 +629,3 @@ return await l1Bridge.isWithdrawalFinalized(log.l1BatchNumber, proof.id); | ||
(l2ToL1log) => | ||
l2ToL1log.sender == BOOTLOADER_FORMAL_ADDRESS && | ||
l2ToL1log.key == depositHash, | ||
l2ToL1log.sender == BOOTLOADER_FORMAL_ADDRESS && l2ToL1log.key == depositHash, | ||
); | ||
@@ -667,5 +637,3 @@ const successL2ToL1Log = receipt.l2ToL1Logs[successL2ToL1LogIndex]; | ||
const tx = await this._providerL2().getTransaction( | ||
ethers.utils.hexlify(depositHash), | ||
); | ||
const tx = await this._providerL2().getTransaction(ethers.utils.hexlify(depositHash)); | ||
@@ -681,6 +649,3 @@ // Undo the aliasing, since the Mailbox contract set it as for contract address. | ||
const proof = await this._providerL2().getLogProof( | ||
depositHash, | ||
successL2ToL1LogIndex, | ||
); | ||
const proof = await this._providerL2().getLogProof(depositHash, successL2ToL1LogIndex); | ||
return await l1Bridge.claimFailedDeposit( | ||
@@ -806,7 +771,3 @@ calldata["_l1Sender"], | ||
async getBalance(token?: Address, blockTag: BlockTag = "committed") { | ||
return await this._providerL2().getBalance( | ||
await this.getAddress(), | ||
blockTag, | ||
token, | ||
); | ||
return await this._providerL2().getBalance(await this.getAddress(), blockTag, token); | ||
} | ||
@@ -818,2 +779,9 @@ | ||
async getDeploymentNonce(): Promise<BigNumber> { | ||
return await INonceHolderFactory.connect( | ||
NONCE_HOLDER_ADDRESS, | ||
this._signerL2(), | ||
).getDeploymentNonce(await this.getAddress()); | ||
} | ||
async getL2BridgeContracts() { | ||
@@ -820,0 +788,0 @@ const addresses = await this._providerL2().getDefaultBridgeAddresses(); |
@@ -11,4 +11,6 @@ import { Wallet } from "./wallet"; | ||
DEFAULT_GAS_PER_PUBDATA_LIMIT, | ||
ZERO_HASH, | ||
} from "./utils"; | ||
import { AccountAbstractionVersion, DeploymentType } from "./types"; | ||
import { hexlify, isBytes, isHexString } from "@ethersproject/bytes"; | ||
export { Contract } from "ethers"; | ||
@@ -34,16 +36,13 @@ | ||
constructorCalldata: BytesLike, | ||
) { | ||
if (this.deploymentType == "create") { | ||
return CONTRACT_DEPLOYER.encodeFunctionData("create", [ | ||
salt, | ||
bytecodeHash, | ||
constructorCalldata, | ||
]); | ||
} else if (this.deploymentType == "createAccount") { | ||
return CONTRACT_DEPLOYER.encodeFunctionData("createAccount", [ | ||
salt, | ||
bytecodeHash, | ||
constructorCalldata, | ||
AccountAbstractionVersion.Version1, | ||
]); | ||
): string { | ||
const contractDeploymentArgs = [salt, bytecodeHash, constructorCalldata]; | ||
const accountDeploymentArgs = [...contractDeploymentArgs, AccountAbstractionVersion.Version1]; | ||
if (this.deploymentType === "create") { | ||
return CONTRACT_DEPLOYER.encodeFunctionData("create", [...contractDeploymentArgs]); | ||
} else if (this.deploymentType === "createAccount") { | ||
return CONTRACT_DEPLOYER.encodeFunctionData("createAccount", [...accountDeploymentArgs]); | ||
} else if (this.deploymentType === "create2") { | ||
return CONTRACT_DEPLOYER.encodeFunctionData("create2", [...contractDeploymentArgs]); | ||
} else if (this.deploymentType === "create2Account") { | ||
return CONTRACT_DEPLOYER.encodeFunctionData("create2Account", [...accountDeploymentArgs]); | ||
} else { | ||
@@ -54,33 +53,106 @@ throw new Error(`Unsupported deployment type ${this.deploymentType}`); | ||
protected checkOverrides(overrides: ethers.PayableOverrides) { | ||
if (this.deploymentType === "create2" || this.deploymentType === "create2Account") { | ||
if (!overrides.customData || !overrides.customData.salt) { | ||
throw new Error("Salt is required for CREATE2 deployment."); | ||
} | ||
if (!overrides.customData.salt.startsWith("0x") || overrides.customData.salt.length !== 66) { | ||
throw new Error("Invalid salt provided."); | ||
} | ||
} | ||
if ( | ||
overrides.customData && | ||
overrides.customData.factoryDeps && | ||
!Array.isArray(overrides.customData.factoryDeps) | ||
) { | ||
throw new Error("Invalid 'factoryDeps' format. It should be an array of bytecodes."); | ||
} | ||
} | ||
override getDeployTransaction(...args: any[]): ethers.providers.TransactionRequest { | ||
// TODO (SMA-1585): Users should be able to provide the salt. | ||
let salt = "0x0000000000000000000000000000000000000000000000000000000000000000"; | ||
let constructorArgs: any[]; | ||
let overrides: ethers.Overrides = { | ||
customData: { factoryDeps: [], salt: ZERO_HASH }, | ||
}; | ||
// The overrides will be popped out in this call: | ||
const txRequest = super.getDeployTransaction(...args); | ||
// Removing overrides | ||
if (this.interface.deploy.inputs.length + 1 == args.length) { | ||
args.pop(); | ||
constructorArgs = args.slice(0, args.length - 1); | ||
overrides = args[args.length - 1] as ethers.PayableOverrides; | ||
overrides.customData ??= {}; | ||
overrides.customData.salt ??= ZERO_HASH; | ||
this.checkOverrides(overrides); | ||
overrides.customData.factoryDeps = (overrides.customData.factoryDeps ?? []).map( | ||
normalizeBytecode, | ||
); | ||
} else { | ||
constructorArgs = args; | ||
} | ||
// Salt argument is not used, so we provide a placeholder value. | ||
const bytecodeHash = hashBytecode(this.bytecode); | ||
const constructorCalldata = utils.arrayify(this.interface.encodeDeploy(args)); | ||
const constructorCalldata = utils.arrayify(this.interface.encodeDeploy(constructorArgs)); | ||
const deployCalldata = this.encodeCalldata( | ||
overrides.customData.salt, | ||
bytecodeHash, | ||
constructorCalldata, | ||
); | ||
const deployCalldata = this.encodeCalldata(salt, bytecodeHash, constructorCalldata); | ||
// salt is no longer used and should not be present in customData of EIP712 transaction | ||
if (txRequest.customData && txRequest.customData.salt) delete txRequest.customData.salt; | ||
const tx = { | ||
...txRequest, | ||
to: CONTRACT_DEPLOYER_ADDRESS, | ||
data: deployCalldata, | ||
type: EIP712_TX_TYPE, | ||
}; | ||
txRequest.type = EIP712_TX_TYPE; | ||
txRequest.to = CONTRACT_DEPLOYER_ADDRESS; | ||
txRequest.data = deployCalldata; | ||
txRequest.customData ??= {}; | ||
txRequest.customData.factoryDeps ??= []; | ||
txRequest.customData.gasPerPubdata ??= DEFAULT_GAS_PER_PUBDATA_LIMIT; | ||
tx.customData ??= {}; | ||
tx.customData.factoryDeps ??= overrides.customData.factoryDeps || []; | ||
tx.customData.gasPerPubdata ??= DEFAULT_GAS_PER_PUBDATA_LIMIT; | ||
// The number of factory deps is relatively low, so it is efficient enough. | ||
if (!txRequest.customData.factoryDeps.includes(this.bytecode)) { | ||
txRequest.customData.factoryDeps.push(this.bytecode); | ||
if (!tx.customData || !tx.customData.factoryDeps.includes(this.bytecode)) { | ||
tx.customData.factoryDeps.push(this.bytecode); | ||
} | ||
return txRequest; | ||
return tx; | ||
} | ||
/** | ||
* Deploys a new contract or account instance on the Ethereum blockchain. | ||
* | ||
* @async | ||
* @param {...Array<any>} args - Constructor arguments for the contract followed by optional | ||
* {@link ethers.PayableOverrides|overrides}. When deploying with CREATE2 opcode slat must be present in overrides. | ||
* | ||
* | ||
* @example | ||
* // Deploy with constructor arguments only using CREATE opcode | ||
* const deployedContract = await contractFactory.deploy(arg1, arg2, ...); | ||
* | ||
* // Deploy with constructor arguments, and factory dependencies using CREATE opcode | ||
* const deployedContractWithSaltAndDeps = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* factoryDeps: ['0x...'] | ||
* } | ||
* }); | ||
* | ||
* // Deploy with constructor arguments and custom salt using CREATE2 opcode | ||
* const deployedContractWithSalt = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* salt: '0x...' | ||
* } | ||
* }); | ||
* | ||
* // Deploy with constructor arguments, custom salt, and factory dependencies using CREATE2 opcode | ||
* const deployedContractWithSaltAndDeps = await contractFactory.deploy(arg1, arg2, ..., { | ||
* customData: { | ||
* salt: '0x...', | ||
* factoryDeps: ['0x...'] | ||
* } | ||
* }); | ||
*/ | ||
override async deploy(...args: Array<any>): Promise<Contract> { | ||
@@ -108,1 +180,27 @@ const contract = await super.deploy(...args); | ||
} | ||
function normalizeBytecode(bytecode: BytesLike | { object: string }) { | ||
let bytecodeHex: string = null; | ||
if (typeof bytecode === "string") { | ||
bytecodeHex = bytecode; | ||
} else if (isBytes(bytecode)) { | ||
bytecodeHex = hexlify(bytecode); | ||
} else if (bytecode && typeof bytecode.object === "string") { | ||
// Allow the bytecode object from the Solidity compiler | ||
bytecodeHex = (<any>bytecode).object; | ||
} else { | ||
// Crash in the next verification step | ||
bytecodeHex = "!"; | ||
} | ||
// Make sure it is 0x prefixed | ||
if (bytecodeHex.substring(0, 2) !== "0x") { | ||
bytecodeHex = "0x" + bytecodeHex; | ||
} | ||
// Make sure the final result is valid bytecode | ||
if (!isHexString(bytecodeHex) || bytecodeHex.length % 2) { | ||
throw new Error("invalid bytecode"); | ||
} | ||
} |
@@ -11,9 +11,5 @@ import { BytesLike, ethers } from "ethers"; | ||
export const IPaymasterFlow = new ethers.utils.Interface( | ||
require("../abi/IPaymasterFlow.json").abi, | ||
); | ||
export const IPaymasterFlow = new ethers.utils.Interface(require("../abi/IPaymasterFlow.json").abi); | ||
export function getApprovalBasedPaymasterInput( | ||
paymasterInput: ApprovalBasedPaymasterInput, | ||
): BytesLike { | ||
export function getApprovalBasedPaymasterInput(paymasterInput: ApprovalBasedPaymasterInput): BytesLike { | ||
return IPaymasterFlow.encodeFunctionData("approvalBased", [ | ||
@@ -20,0 +16,0 @@ paymasterInput.token, |
@@ -1,10 +0,2 @@ | ||
import { | ||
BigNumber, | ||
BigNumberish, | ||
BytesLike, | ||
Contract, | ||
ethers, | ||
providers, | ||
utils, | ||
} from "ethers"; | ||
import { BigNumber, BigNumberish, BytesLike, Contract, ethers, providers, utils } from "ethers"; | ||
import { ExternalProvider } from "@ethersproject/providers"; | ||
@@ -32,2 +24,3 @@ import { ConnectionInfo, poll } from "@ethersproject/web"; | ||
TransactionStatus, | ||
Fee | ||
} from "./types"; | ||
@@ -158,6 +151,3 @@ import { | ||
receipt.blockNumber == null && | ||
!( | ||
receipt.status != null && | ||
BigNumber.from(receipt.status).isZero() | ||
) | ||
!(receipt.status != null && BigNumber.from(receipt.status).isZero()) | ||
) { | ||
@@ -228,4 +218,3 @@ return null; | ||
this._emitted["b:" + log.blockHash] = log.blockNumber; | ||
this._emitted["t:" + log.transactionHash] = | ||
log.blockNumber; | ||
this._emitted["t:" + log.transactionHash] = log.blockNumber; | ||
@@ -376,4 +365,3 @@ this.emit(filter, log); | ||
defaultFormatter.formats.block.l1BatchTimestamp = Formatter.allowNull(number); | ||
defaultFormatter.formats.blockWithTransactions.l1BatchNumber = | ||
Formatter.allowNull(number); | ||
defaultFormatter.formats.blockWithTransactions.l1BatchNumber = Formatter.allowNull(number); | ||
defaultFormatter.formats.blockWithTransactions.l1BatchTimestamp = | ||
@@ -481,5 +469,3 @@ Formatter.allowNull(number); | ||
override async estimateGas( | ||
transaction: utils.Deferrable<TransactionRequest>, | ||
): Promise<BigNumber> { | ||
override async estimateGas(transaction: utils.Deferrable<TransactionRequest>): Promise<BigNumber> { | ||
await this.getNetwork(); | ||
@@ -501,5 +487,3 @@ const params = await utils.resolveProperties({ | ||
async estimateGasL1( | ||
transaction: utils.Deferrable<TransactionRequest>, | ||
): Promise<BigNumber> { | ||
async estimateGasL1(transaction: utils.Deferrable<TransactionRequest>): Promise<BigNumber> { | ||
await this.getNetwork(); | ||
@@ -523,2 +507,6 @@ const params = await utils.resolveProperties({ | ||
async estimateFee(transaction: TransactionRequest): Promise<Fee> { | ||
return await this.send("zks_estimateFee", [transaction]); | ||
} | ||
override async getGasPrice(token?: Address): Promise<BigNumber> { | ||
@@ -763,5 +751,3 @@ const params = token ? [token] : []; | ||
override async getLogs( | ||
filter: EventFilter | Promise<EventFilter> = {}, | ||
): Promise<Array<Log>> { | ||
override async getLogs(filter: EventFilter | Promise<EventFilter> = {}): Promise<Array<Log>> { | ||
filter = await filter; | ||
@@ -779,4 +765,3 @@ const logs = await this.send("eth_getLogs", [this._prepareFilter(filter)]); | ||
...filter, | ||
fromBlock: | ||
filter.fromBlock == null ? null : this.formatter.blockTag(filter.fromBlock), | ||
fromBlock: filter.fromBlock == null ? null : this.formatter.blockTag(filter.fromBlock), | ||
toBlock: filter.fromBlock == null ? null : this.formatter.blockTag(filter.toBlock), | ||
@@ -820,5 +805,3 @@ }; | ||
override async getTransaction( | ||
hash: string | Promise<string>, | ||
): Promise<TransactionResponse> { | ||
override async getTransaction(hash: string | Promise<string>): Promise<TransactionResponse> { | ||
hash = await hash; | ||
@@ -829,5 +812,3 @@ const tx = await super.getTransaction(hash); | ||
override async sendTransaction( | ||
transaction: string | Promise<string>, | ||
): Promise<TransactionResponse> { | ||
override async sendTransaction(transaction: string | Promise<string>): Promise<TransactionResponse> { | ||
return (await super.sendTransaction(transaction)) as TransactionResponse; | ||
@@ -870,7 +851,3 @@ } | ||
async getContractAccountInfo(address: Address): Promise<ContractAccountInfo> { | ||
const deployerContract = new Contract( | ||
CONTRACT_DEPLOYER_ADDRESS, | ||
CONTRACT_DEPLOYER, | ||
this, | ||
); | ||
const deployerContract = new Contract(CONTRACT_DEPLOYER_ADDRESS, CONTRACT_DEPLOYER, this); | ||
const data = await deployerContract.getAccountInfo(address); | ||
@@ -929,4 +906,3 @@ | ||
let path = | ||
provider.host || provider.path || (provider.isMetaMask ? "metamask" : "eip-1193:"); | ||
let path = provider.host || provider.path || (provider.isMetaMask ? "metamask" : "eip-1193:"); | ||
super(path, network); | ||
@@ -933,0 +909,0 @@ this.provider = provider; |
import { ethers } from "ethers"; | ||
import { Provider } from "./provider"; | ||
import { | ||
DEFAULT_GAS_PER_PUBDATA_LIMIT, | ||
EIP712_TX_TYPE, | ||
hashBytecode, | ||
serialize, | ||
} from "./utils"; | ||
import { DEFAULT_GAS_PER_PUBDATA_LIMIT, EIP712_TX_TYPE, hashBytecode, serialize } from "./utils"; | ||
import { BlockTag, Signature, TransactionRequest, TransactionResponse } from "./types"; | ||
@@ -59,9 +54,7 @@ import { TypedDataDomain, TypedDataSigner } from "@ethersproject/abstract-signer"; | ||
paymaster: | ||
transaction.customData?.paymasterParams?.paymaster || | ||
ethers.constants.AddressZero, | ||
transaction.customData?.paymasterParams?.paymaster || ethers.constants.AddressZero, | ||
nonce: transaction.nonce, | ||
value: transaction.value, | ||
data: transaction.data, | ||
factoryDeps: | ||
transaction.customData?.factoryDeps?.map((dep) => hashBytecode(dep)) || [], | ||
factoryDeps: transaction.customData?.factoryDeps?.map((dep) => hashBytecode(dep)) || [], | ||
paymasterInput: transaction.customData?.paymasterParams?.paymasterInput || "0x", | ||
@@ -88,7 +81,3 @@ }; | ||
}; | ||
return TypedDataEncoder.hash( | ||
domain, | ||
eip712Types, | ||
EIP712Signer.getSignInput(transaction), | ||
); | ||
return TypedDataEncoder.hash(domain, eip712Types, EIP712Signer.getSignInput(transaction)); | ||
} | ||
@@ -127,5 +116,3 @@ } | ||
override async sendTransaction( | ||
transaction: TransactionRequest, | ||
): Promise<TransactionResponse> { | ||
override async sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> { | ||
if (transaction.customData == null && transaction.type == null) { | ||
@@ -216,5 +203,3 @@ // use legacy txs by default | ||
override async sendTransaction( | ||
transaction: TransactionRequest, | ||
): Promise<TransactionResponse> { | ||
override async sendTransaction(transaction: TransactionRequest): Promise<TransactionResponse> { | ||
if (transaction.customData == null && transaction.type == null) { | ||
@@ -221,0 +206,0 @@ // use legacy txs by default |
@@ -58,4 +58,3 @@ import { BytesLike, BigNumberish, providers, BigNumber } from "ethers"; | ||
// TODO (SMA-1585): Support create2 variants. | ||
export type DeploymentType = "create" | "createAccount"; | ||
export type DeploymentType = "create" | "createAccount" | "create2" | "create2Account"; | ||
@@ -72,2 +71,9 @@ export interface Token { | ||
export interface Fee { | ||
readonly gasLimit: bigint; | ||
readonly gasPerPubdataLimit: bigint; | ||
readonly maxPriorityFeePerGas: bigint; | ||
readonly maxFeePerGas: bigint; | ||
} | ||
export interface MessageProof { | ||
@@ -74,0 +80,0 @@ id: number; |
@@ -20,8 +20,4 @@ import { utils, ethers, BigNumber, BigNumberish, BytesLike } from "ethers"; | ||
export const ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; | ||
export const ZKSYNC_MAIN_ABI = new utils.Interface(require("../abi/IZkSync.json").abi); | ||
export const CONTRACT_DEPLOYER = new utils.Interface( | ||
require("../abi/ContractDeployer.json").abi, | ||
); | ||
export const CONTRACT_DEPLOYER = new utils.Interface(require("../abi/ContractDeployer.json").abi); | ||
export const L1_MESSENGER = new utils.Interface(require("../abi/IL1Messenger.json").abi); | ||
@@ -32,3 +28,6 @@ export const IERC20 = new utils.Interface(require("../abi/IERC20.json").abi); | ||
export const L2_BRIDGE_ABI = new utils.Interface(require("../abi/IL2Bridge.json").abi); | ||
export const NONCE_HOLDER_ABI = new utils.Interface(require("../abi/INonceHolder.json").abi); | ||
export const PAYMASTER_FLOW_ABI = new utils.Interface(require("../abi/IPaymasterFlow.json").abi); | ||
export const ETH_ADDRESS = "0x0000000000000000000000000000000000000000"; | ||
export const BOOTLOADER_FORMAL_ADDRESS = "0x0000000000000000000000000000000000008001"; | ||
@@ -38,3 +37,6 @@ export const CONTRACT_DEPLOYER_ADDRESS = "0x0000000000000000000000000000000000008006"; | ||
export const L2_ETH_TOKEN_ADDRESS = "0x000000000000000000000000000000000000800a"; | ||
export const NONCE_HOLDER_ADDRESS = "0x0000000000000000000000000000000000008003"; | ||
export const ZERO_HASH = "0x0000000000000000000000000000000000000000000000000000000000000000"; | ||
export const L1_TO_L2_ALIAS_OFFSET = "0x1111000000000000000000000000000000001111"; | ||
@@ -96,5 +98,3 @@ | ||
export function getDeployedContracts( | ||
receipt: ethers.providers.TransactionReceipt, | ||
): DeploymentInfo[] { | ||
export function getDeployedContracts(receipt: ethers.providers.TransactionReceipt): DeploymentInfo[] { | ||
const addressBytesLen = 40; | ||
@@ -171,11 +171,5 @@ const deployedContracts = receipt.logs | ||
export function serialize( | ||
transaction: ethers.providers.TransactionRequest, | ||
signature?: SignatureLike, | ||
) { | ||
export function serialize(transaction: ethers.providers.TransactionRequest, signature?: SignatureLike) { | ||
if (transaction.customData == null && transaction.type != EIP712_TX_TYPE) { | ||
return utils.serializeTransaction( | ||
transaction as ethers.PopulatedTransaction, | ||
signature, | ||
); | ||
return utils.serializeTransaction(transaction as ethers.PopulatedTransaction, signature); | ||
} | ||
@@ -195,5 +189,3 @@ if (!transaction.chainId) { | ||
if (!transaction.from) { | ||
throw new Error( | ||
"Explicitly providing `from` field is reqiured for EIP712 transactions", | ||
); | ||
throw new Error("Explicitly providing `from` field is reqiured for EIP712 transactions"); | ||
} | ||
@@ -231,5 +223,3 @@ const from = transaction.from; | ||
// Add meta | ||
fields.push( | ||
formatNumber(meta.gasPerPubdata || DEFAULT_GAS_PER_PUBDATA_LIMIT, "gasPerPubdata"), | ||
); | ||
fields.push(formatNumber(meta.gasPerPubdata || DEFAULT_GAS_PER_PUBDATA_LIMIT, "gasPerPubdata")); | ||
fields.push((meta.factoryDeps ?? []).map((dep) => utils.hexlify(dep))); | ||
@@ -358,7 +348,3 @@ | ||
if ( | ||
ethSignature.v !== 0 && | ||
ethSignature.v !== 1 && | ||
!transaction.customData.customSignature | ||
) { | ||
if (ethSignature.v !== 0 && ethSignature.v !== 1 && !transaction.customData.customSignature) { | ||
throw new Error("Failed to parse signature"); | ||
@@ -379,6 +365,3 @@ } | ||
function getSignature(transaction: any, ethSignature?: EthereumSignature): Uint8Array { | ||
if ( | ||
transaction?.customData?.customSignature && | ||
transaction.customData.customSignature.length | ||
) { | ||
if (transaction?.customData?.customSignature && transaction.customData.customSignature.length) { | ||
return ethers.utils.arrayify(transaction.customData.customSignature); | ||
@@ -490,7 +473,3 @@ } | ||
// letting our SDK have functionality to verify signatures. | ||
function isECDSASignatureCorrect( | ||
address: string, | ||
msgHash: string, | ||
signature: SignatureLike, | ||
): boolean { | ||
function isECDSASignatureCorrect(address: string, msgHash: string, signature: SignatureLike): boolean { | ||
try { | ||
@@ -626,5 +605,3 @@ return address == ethers.utils.recoverAddress(msgHash, signature); | ||
export function scaleGasLimit(gasLimit: BigNumber): BigNumber { | ||
return gasLimit | ||
.mul(L1_FEE_ESTIMATION_COEF_NUMERATOR) | ||
.div(L1_FEE_ESTIMATION_COEF_DENOMINATOR); | ||
return gasLimit.mul(L1_FEE_ESTIMATION_COEF_NUMERATOR).div(L1_FEE_ESTIMATION_COEF_DENOMINATOR); | ||
} | ||
@@ -631,0 +608,0 @@ |
@@ -88,5 +88,3 @@ import { EIP712Signer } from "./signer"; | ||
override async populateTransaction( | ||
transaction: TransactionRequest, | ||
): Promise<TransactionRequest> { | ||
override async populateTransaction(transaction: TransactionRequest): Promise<TransactionRequest> { | ||
if (transaction.type == null && transaction.customData == null) { | ||
@@ -93,0 +91,0 @@ // use legacy txs by default |
@@ -262,3 +262,3 @@ /* Autogenerated file. Do not edit manually. */ | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -476,3 +476,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -662,3 +662,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -867,3 +867,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -1044,3 +1044,3 @@ bytecodeHash: BytesLike; | ||
"forceDeployOnAddress((bytes32,address,bool,uint256,bytes),address)"( | ||
"forceDeployOnAddress(tuple,address)"( | ||
_deployment: { | ||
@@ -1047,0 +1047,0 @@ bytecodeHash: BytesLike; |
@@ -19,4 +19,6 @@ export {ContractDeployerFactory} from './ContractDeployerFactory'; | ||
export type {IPaymasterFlow} from './IPaymasterFlow'; | ||
export {INonceHolderFactory} from './INonceHolderFactory'; | ||
export type {INonceHolder} from './INonceHolder'; | ||
export {IZkSyncFactory} from './IZkSyncFactory'; | ||
export type {IZkSync} from './IZkSync'; | ||
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1160027
114
37913