feat: handle salt for deterministic deploys (#4528)
## Problem solved
Short description of the bug fixed or feature added
<!-- start pr-codex -->
---
## PR-Codex overview
This PR focuses on adding support for deterministic contract deployment using a salt parameter.
### Detailed summary
- Added support for passing a `salt` parameter for deterministic contract deployment
- Updated functions to handle the `salt` parameter for deterministic deploys
- Modified tests to include deterministic deployment scenarios
> The following files were skipped due to too many changes: `packages/thirdweb/src/extensions/prebuilts/deploy-published.ts`, `packages/thirdweb/src/contract/deployment/deploy-with-abi.ts`, `packages/thirdweb/test/src/abis/proxy.ts`
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
---
|
||||
"thirdweb": minor
|
||||
---
|
||||
|
||||
Handle salt parameter for deterministic deploys of published contracts
|
||||
|
||||
You can now pass a salt parameter to the `deployPublishedContract` function to deploy a contract deterministically.
|
||||
|
||||
```ts
|
||||
const address = await deployPublishedContract({
|
||||
client,
|
||||
chain,
|
||||
account,
|
||||
contractId: "Airdrop",
|
||||
contractParams: {
|
||||
defaultAdmin: "0x...",
|
||||
contractURI: "ipfs://...",
|
||||
},
|
||||
salt: "test", // <--- deterministic deploy
|
||||
});
|
||||
```
|
||||
|
||||
This also works for unpublished contracts, via the `deployContract` function.
|
||||
|
||||
```ts
|
||||
const address = await deployContract({
|
||||
client,
|
||||
chain,
|
||||
account,
|
||||
bytecode: "0x...",
|
||||
abi: contractAbi,
|
||||
constructorParams: {
|
||||
param1: "value1",
|
||||
param2: 123,
|
||||
},
|
||||
salt: "test", // <--- deterministic deploy
|
||||
});
|
||||
```
|
||||
@@ -1,5 +1,10 @@
|
||||
import type { Abi } from "abitype";
|
||||
import { prepareTransaction } from "../../transaction/prepare-transaction.js";
|
||||
import { computeDeploymentInfoFromContractId } from "../../utils/any-evm/compute-published-contract-deploy-info.js";
|
||||
import {
|
||||
computeDeploymentInfoFromBytecode,
|
||||
computeDeploymentInfoFromContractId,
|
||||
} from "../../utils/any-evm/compute-published-contract-deploy-info.js";
|
||||
import type { Hex } from "../../utils/encoding/hex.js";
|
||||
import type { Prettify } from "../../utils/type-utils.js";
|
||||
import type { ClientAndChain } from "../../utils/types.js";
|
||||
import { computeCreate2FactoryAddress } from "./utils/create-2-factory.js";
|
||||
@@ -56,3 +61,31 @@ export function prepareDeterministicDeployTransaction(
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export function prepareDeterministicDeployTransactionFromBytecode(
|
||||
options: ClientAndChain & {
|
||||
abi: Abi;
|
||||
bytecode: Hex;
|
||||
constructorParams?: Record<string, unknown>;
|
||||
salt?: string;
|
||||
},
|
||||
) {
|
||||
const { client, chain } = options;
|
||||
return prepareTransaction({
|
||||
client,
|
||||
chain,
|
||||
to: () =>
|
||||
computeCreate2FactoryAddress({
|
||||
client,
|
||||
chain,
|
||||
}),
|
||||
data: async () => {
|
||||
const infraContractInfo =
|
||||
await computeDeploymentInfoFromBytecode(options);
|
||||
return infraContractInfo.initBytecodeWithsalt;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ export async function deployViaAutoFactory(
|
||||
account,
|
||||
cloneFactoryContract,
|
||||
initializeTransaction,
|
||||
salt,
|
||||
} = options;
|
||||
|
||||
if (isZkSyncChain(chain)) {
|
||||
@@ -79,6 +80,7 @@ export async function deployViaAutoFactory(
|
||||
account,
|
||||
cloneFactoryContract,
|
||||
initializeTransaction,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -87,6 +89,7 @@ export async function deployViaAutoFactory(
|
||||
client,
|
||||
cloneFactoryContract,
|
||||
initializeTransaction,
|
||||
salt,
|
||||
});
|
||||
const receipt = await sendAndConfirmTransaction({
|
||||
transaction: tx,
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import type {
|
||||
AbiConstructor,
|
||||
AbiParameter,
|
||||
AbiParametersToPrimitiveTypes,
|
||||
} from "abitype";
|
||||
import type { Abi, AbiConstructor } from "abitype";
|
||||
import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js";
|
||||
import { prepareTransaction } from "../../transaction/prepare-transaction.js";
|
||||
import { encodeAbiParameters } from "../../utils/abi/encodeAbiParameters.js";
|
||||
import { normalizeFunctionParams } from "../../utils/abi/normalizeFunctionParams.js";
|
||||
import { computeDeploymentAddress } from "../../utils/any-evm/compute-deployment-address.js";
|
||||
import { computeDeploymentInfoFromBytecode } from "../../utils/any-evm/compute-published-contract-deploy-info.js";
|
||||
import { ensureBytecodePrefix } from "../../utils/bytecode/prefix.js";
|
||||
import { concatHex } from "../../utils/encoding/helpers/concat-hex.js";
|
||||
import { type Hex, isHex } from "../../utils/encoding/hex.js";
|
||||
@@ -16,16 +15,11 @@ import type { Account } from "../../wallets/interfaces/wallet.js";
|
||||
/**
|
||||
* @extension DEPLOY
|
||||
*/
|
||||
export type PrepareDirectDeployTransactionOptions<
|
||||
TConstructor extends AbiConstructor,
|
||||
TParams = AbiParametersToPrimitiveTypes<TConstructor["inputs"]>,
|
||||
> = Prettify<
|
||||
export type PrepareDirectDeployTransactionOptions = Prettify<
|
||||
ClientAndChain & {
|
||||
constructorAbi: TConstructor | undefined;
|
||||
abi: Abi;
|
||||
bytecode: Hex;
|
||||
constructorParams: TParams extends readonly AbiParameter[]
|
||||
? TParams
|
||||
: readonly unknown[];
|
||||
constructorParams?: Record<string, unknown>;
|
||||
}
|
||||
>;
|
||||
|
||||
@@ -51,13 +45,16 @@ export type PrepareDirectDeployTransactionOptions<
|
||||
* ```
|
||||
* @extension DEPLOY
|
||||
*/
|
||||
export function prepareDirectDeployTransaction<
|
||||
const TConstructor extends AbiConstructor,
|
||||
>(options: PrepareDirectDeployTransactionOptions<TConstructor>) {
|
||||
export function prepareDirectDeployTransaction(
|
||||
options: PrepareDirectDeployTransactionOptions,
|
||||
) {
|
||||
const bytecode = ensureBytecodePrefix(options.bytecode);
|
||||
if (!isHex(bytecode)) {
|
||||
throw new Error(`Contract bytecode is invalid.\n\n${bytecode}`);
|
||||
}
|
||||
const constructorAbi = options.abi.find(
|
||||
(abi) => abi.type === "constructor",
|
||||
) as AbiConstructor | undefined;
|
||||
// prepare the tx
|
||||
return prepareTransaction({
|
||||
chain: options.chain,
|
||||
@@ -66,8 +63,8 @@ export function prepareDirectDeployTransaction<
|
||||
data: concatHex([
|
||||
bytecode,
|
||||
encodeAbiParameters(
|
||||
options.constructorAbi?.inputs || [], // Leave an empty array if there's no constructor
|
||||
options.constructorParams,
|
||||
constructorAbi?.inputs || [], // Leave an empty array if there's no constructor
|
||||
normalizeFunctionParams(constructorAbi, options.constructorParams),
|
||||
),
|
||||
]),
|
||||
});
|
||||
@@ -85,20 +82,41 @@ export function prepareDirectDeployTransaction<
|
||||
* client,
|
||||
* chain,
|
||||
* bytecode: "0x...",
|
||||
* constructorAbi: {
|
||||
* inputs: [{ type: "uint256", name: "value" }],
|
||||
* type: "constructor",
|
||||
* abi: contractAbi,
|
||||
* constructorParams: {
|
||||
* param1: "value1",
|
||||
* param2: 123,
|
||||
* },
|
||||
* constructorParams: [123],
|
||||
* salt, // passing salt enables deterministic deploys
|
||||
* });
|
||||
* ```
|
||||
* @extension DEPLOY
|
||||
*/
|
||||
export async function deployContract<const TConstructor extends AbiConstructor>(
|
||||
options: PrepareDirectDeployTransactionOptions<TConstructor> & {
|
||||
export async function deployContract(
|
||||
options: PrepareDirectDeployTransactionOptions & {
|
||||
account: Account;
|
||||
salt?: string;
|
||||
},
|
||||
) {
|
||||
if (options.salt !== undefined) {
|
||||
// Deploy with CREATE2 if salt is provided
|
||||
const info = await computeDeploymentInfoFromBytecode(options);
|
||||
sendAndConfirmTransaction({
|
||||
account: options.account,
|
||||
transaction: prepareTransaction({
|
||||
chain: options.chain,
|
||||
client: options.client,
|
||||
to: info.create2FactoryAddress,
|
||||
data: info.initBytecodeWithsalt,
|
||||
}),
|
||||
});
|
||||
return computeDeploymentAddress({
|
||||
bytecode: options.bytecode,
|
||||
encodedArgs: info.encodedArgs,
|
||||
create2FactoryAddress: info.create2FactoryAddress,
|
||||
});
|
||||
}
|
||||
|
||||
const deployTx = prepareDirectDeployTransaction(options);
|
||||
const receipt = await sendAndConfirmTransaction({
|
||||
account: options.account,
|
||||
|
||||
@@ -8,6 +8,7 @@ import { normalizeFunctionParams } from "../../../utils/abi/normalizeFunctionPar
|
||||
import { CONTRACT_DEPLOYER_ADDRESS } from "../../../utils/any-evm/zksync/constants.js";
|
||||
import type { Hex } from "../../../utils/encoding/hex.js";
|
||||
import type { ClientAndChainAndAccount } from "../../../utils/types.js";
|
||||
import { zkDeployContractDeterministic } from "./zkDeployDeterministic.js";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -17,8 +18,14 @@ export async function zkDeployContract(
|
||||
abi: Abi;
|
||||
bytecode: Hex;
|
||||
params?: Record<string, unknown>;
|
||||
salt?: string;
|
||||
},
|
||||
) {
|
||||
if (options.salt !== undefined) {
|
||||
// if a salt is provided, use the deterministic deployer
|
||||
return zkDeployContractDeterministic(options);
|
||||
}
|
||||
|
||||
const data = encodeDeployData({
|
||||
abi: options.abi,
|
||||
bytecode: options.bytecode,
|
||||
|
||||
@@ -48,6 +48,7 @@ export async function zkDeployProxy(
|
||||
_logic: implementationAddress,
|
||||
_data: await encode(options.initializeTransaction),
|
||||
},
|
||||
salt: options.salt,
|
||||
});
|
||||
|
||||
// return address of proxy
|
||||
|
||||
@@ -52,6 +52,7 @@ export type DeployModularContractOptions = Prettify<
|
||||
params: ModularContractParams;
|
||||
modules?: ModuleInstaller[];
|
||||
publisher?: string;
|
||||
salt?: string;
|
||||
}
|
||||
>;
|
||||
|
||||
@@ -97,6 +98,7 @@ export async function deployModularContract(
|
||||
core,
|
||||
params: coreParams,
|
||||
modules = [],
|
||||
salt,
|
||||
} = options;
|
||||
const contractId = getContractId(core);
|
||||
const { cloneFactoryContract, implementationContract } =
|
||||
@@ -147,6 +149,7 @@ export async function deployModularContract(
|
||||
account,
|
||||
cloneFactoryContract,
|
||||
initializeTransaction,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,21 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
||||
expect(address.length).toBe(42);
|
||||
});
|
||||
|
||||
it("should deploy a published direct deploy contract deterministically", async () => {
|
||||
const address = await deployPublishedContract({
|
||||
client: TEST_CLIENT,
|
||||
chain: ANVIL_CHAIN,
|
||||
account: TEST_ACCOUNT_A,
|
||||
contractId: "AccountFactory",
|
||||
contractParams: {
|
||||
defaultAdmin: TEST_ACCOUNT_A.address,
|
||||
entrypoint: ENTRYPOINT_ADDRESS_v0_6,
|
||||
},
|
||||
salt: "test",
|
||||
});
|
||||
expect(address).toBe("0x75fc461544723c0dac7b46256027878e82ddc2cb");
|
||||
});
|
||||
|
||||
it("should deploy a published autofactory contract", async () => {
|
||||
const address = await deployPublishedContract({
|
||||
client: TEST_CLIENT,
|
||||
@@ -41,6 +56,21 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
||||
expect(address.length).toBe(42);
|
||||
});
|
||||
|
||||
it("should deploy a published autofactory contract deterministically", async () => {
|
||||
const address = await deployPublishedContract({
|
||||
client: TEST_CLIENT,
|
||||
chain: ANVIL_CHAIN,
|
||||
account: TEST_ACCOUNT_A,
|
||||
contractId: "Airdrop",
|
||||
contractParams: {
|
||||
defaultAdmin: TEST_ACCOUNT_A.address,
|
||||
contractURI: "",
|
||||
},
|
||||
salt: "test",
|
||||
});
|
||||
expect(address).toBe("0x777151741260F8d4098dD492e45FdB536F442672");
|
||||
});
|
||||
|
||||
// TODO: Replace these tests' live contracts with mocks
|
||||
it("should deploy a published contract with no constructor", async () => {
|
||||
const address = await deployPublishedContract({
|
||||
@@ -65,5 +95,28 @@ describe.runIf(process.env.TW_SECRET_KEY)(
|
||||
expect(address).toBeDefined();
|
||||
expect(address.length).toBe(42);
|
||||
});
|
||||
|
||||
it("should deploy a published contract with no fuzzy params", async () => {
|
||||
const address = await deployPublishedContract({
|
||||
client: TEST_CLIENT,
|
||||
chain: ANVIL_CHAIN,
|
||||
account: TEST_ACCOUNT_A,
|
||||
contractId: "DropERC1155",
|
||||
contractParams: {
|
||||
defaultAdmin: TEST_ACCOUNT_A.address, // defaultAdmin
|
||||
name: "test", // name
|
||||
symbol: "test", // symbol
|
||||
contractURI: "", // contractURI
|
||||
trustedForwarders: [], // trustedForwarders
|
||||
saleRecipient: TEST_ACCOUNT_A.address, // saleRecipient
|
||||
royaltyRecipient: TEST_ACCOUNT_A.address, // royaltyRecipient
|
||||
royaltyBps: 0n, // royaltyBps
|
||||
platformFeeBps: 0n, // platformFeeBps
|
||||
platformFeeRecipient: TEST_ACCOUNT_A.address, // platformFeeRecipient
|
||||
},
|
||||
});
|
||||
expect(address).toBeDefined();
|
||||
expect(address.length).toBe(42);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AbiConstructor, AbiFunction } from "abitype";
|
||||
import type { AbiFunction } from "abitype";
|
||||
import type { Chain } from "../../chains/types.js";
|
||||
import type { ThirdwebClient } from "../../client/client.js";
|
||||
import { type ThirdwebContract, getContract } from "../../contract/contract.js";
|
||||
@@ -31,6 +31,7 @@ export type DeployPublishedContractOptions = {
|
||||
publisher?: string;
|
||||
version?: string;
|
||||
implementationConstructorParams?: Record<string, unknown>;
|
||||
salt?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -64,6 +65,7 @@ export async function deployPublishedContract(
|
||||
publisher,
|
||||
version,
|
||||
implementationConstructorParams,
|
||||
salt,
|
||||
} = options;
|
||||
const deployMetadata = await fetchPublishedContractMetadata({
|
||||
client,
|
||||
@@ -79,6 +81,7 @@ export async function deployPublishedContract(
|
||||
client,
|
||||
initializeParams: contractParams,
|
||||
implementationConstructorParams,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -96,6 +99,7 @@ export type DeployContractfromDeployMetadataOptions = {
|
||||
deployMetadata: FetchDeployMetadataResult;
|
||||
initializeParams?: Record<string, unknown>;
|
||||
}[];
|
||||
salt?: string;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -103,7 +107,7 @@ export type DeployContractfromDeployMetadataOptions = {
|
||||
*/
|
||||
export async function deployContractfromDeployMetadata(
|
||||
options: DeployContractfromDeployMetadataOptions,
|
||||
) {
|
||||
): Promise<string> {
|
||||
const {
|
||||
client,
|
||||
account,
|
||||
@@ -112,6 +116,7 @@ export async function deployContractfromDeployMetadata(
|
||||
deployMetadata,
|
||||
implementationConstructorParams,
|
||||
modules,
|
||||
salt,
|
||||
} = options;
|
||||
switch (deployMetadata?.deployType) {
|
||||
case "standard": {
|
||||
@@ -121,6 +126,7 @@ export async function deployContractfromDeployMetadata(
|
||||
chain,
|
||||
compilerMetadata: deployMetadata,
|
||||
contractParams: initializeParams,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
case "autoFactory": {
|
||||
@@ -157,6 +163,7 @@ export async function deployContractfromDeployMetadata(
|
||||
account,
|
||||
cloneFactoryContract,
|
||||
initializeTransaction,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
case "customFactory": {
|
||||
@@ -185,14 +192,14 @@ export async function deployContractfromDeployMetadata(
|
||||
params: normalizeFunctionParams(method, initializeParams),
|
||||
});
|
||||
// asumption here is that the factory address returns the deployed proxy address
|
||||
const address = simulateTransaction({
|
||||
const address = await simulateTransaction({
|
||||
transaction: deployTx,
|
||||
});
|
||||
await sendAndConfirmTransaction({
|
||||
transaction: deployTx,
|
||||
account,
|
||||
});
|
||||
return address;
|
||||
return address as string;
|
||||
}
|
||||
case undefined: {
|
||||
// Default to standard deployment if none was specified
|
||||
@@ -202,6 +209,7 @@ export async function deployContractfromDeployMetadata(
|
||||
chain,
|
||||
compilerMetadata: deployMetadata,
|
||||
contractParams: initializeParams,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
default:
|
||||
@@ -216,8 +224,10 @@ async function directDeploy(options: {
|
||||
chain: Chain;
|
||||
compilerMetadata: CompilerMetadata;
|
||||
contractParams?: Record<string, unknown>;
|
||||
}) {
|
||||
const { account, client, chain, compilerMetadata, contractParams } = options;
|
||||
salt?: string;
|
||||
}): Promise<string> {
|
||||
const { account, client, chain, compilerMetadata, contractParams, salt } =
|
||||
options;
|
||||
|
||||
if (isZkSyncChain(chain)) {
|
||||
return zkDeployContract({
|
||||
@@ -227,22 +237,21 @@ async function directDeploy(options: {
|
||||
bytecode: compilerMetadata.bytecode,
|
||||
abi: compilerMetadata.abi,
|
||||
params: contractParams,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
|
||||
const { deployContract } = await import(
|
||||
"../../contract/deployment/deploy-with-abi.js"
|
||||
);
|
||||
const constructorAbi = compilerMetadata.abi.find(
|
||||
(i) => i.type === "constructor",
|
||||
) as AbiConstructor | undefined;
|
||||
return deployContract({
|
||||
account,
|
||||
client,
|
||||
chain,
|
||||
bytecode: compilerMetadata.bytecode,
|
||||
constructorAbi,
|
||||
constructorParams: normalizeFunctionParams(constructorAbi, contractParams),
|
||||
abi: compilerMetadata.abi,
|
||||
constructorParams: contractParams,
|
||||
salt,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -322,10 +331,7 @@ async function getInitializeTransaction(options: {
|
||||
chain,
|
||||
address: implementationContract.address,
|
||||
}),
|
||||
method: resolveMethod(
|
||||
metadata.factoryDeploymentData?.implementationInitializerFunction ||
|
||||
"initialize",
|
||||
),
|
||||
method: initializeFunction,
|
||||
params: normalizeFunctionParams(initializeFunction, initializeParams),
|
||||
});
|
||||
return initializeTransaction;
|
||||
|
||||
@@ -35,7 +35,7 @@ describe("sendEip712Transaction", () => {
|
||||
client: TEST_CLIENT,
|
||||
chain: zkSyncSepolia, // TODO make zksync fork chain work
|
||||
account: TEST_ACCOUNT_A,
|
||||
contractId: "DropERC1155",
|
||||
contractId: "DropERC721",
|
||||
contractParams: {
|
||||
defaultAdmin: TEST_ACCOUNT_A.address, // defaultAdmin
|
||||
name: "test", // name
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { AbiConstructor } from "abitype";
|
||||
import type { Abi, AbiConstructor } from "abitype";
|
||||
import type { Chain } from "../../chains/types.js";
|
||||
import type { ThirdwebClient } from "../../client/client.js";
|
||||
import { fetchPublishedContractMetadata } from "../../contract/deployment/publisher.js";
|
||||
import { computeCreate2FactoryAddress } from "../../contract/deployment/utils/create-2-factory.js";
|
||||
import { encodeAbiParameters } from "../abi/encodeAbiParameters.js";
|
||||
import { normalizeFunctionParams } from "../abi/normalizeFunctionParams.js";
|
||||
import { ensureBytecodePrefix } from "../bytecode/prefix.js";
|
||||
import type { Hex } from "../encoding/hex.js";
|
||||
import type { FetchDeployMetadataResult } from "./deploy-metadata.js";
|
||||
import { getInitBytecodeWithSalt } from "./get-init-bytecode-with-salt.js";
|
||||
|
||||
@@ -46,15 +48,33 @@ export async function computeDeploymentInfoFromMetadata(args: {
|
||||
constructorParams?: Record<string, unknown>;
|
||||
salt?: string;
|
||||
}) {
|
||||
const { client, chain, contractMetadata, constructorParams, salt } = args;
|
||||
return computeDeploymentInfoFromBytecode({
|
||||
client: args.client,
|
||||
chain: args.chain,
|
||||
abi: args.contractMetadata.abi,
|
||||
bytecode: args.contractMetadata.bytecode,
|
||||
constructorParams: args.constructorParams,
|
||||
salt: args.salt,
|
||||
});
|
||||
}
|
||||
|
||||
export async function computeDeploymentInfoFromBytecode(args: {
|
||||
client: ThirdwebClient;
|
||||
chain: Chain;
|
||||
abi: Abi;
|
||||
bytecode: Hex;
|
||||
constructorParams?: Record<string, unknown>;
|
||||
salt?: string;
|
||||
}) {
|
||||
const { client, chain, constructorParams, salt } = args;
|
||||
const create2FactoryAddress = await computeCreate2FactoryAddress({
|
||||
client,
|
||||
chain,
|
||||
});
|
||||
const bytecode = contractMetadata.bytecode;
|
||||
const constructorAbi = contractMetadata.abi.find(
|
||||
(abi) => abi.type === "constructor",
|
||||
) as AbiConstructor | undefined;
|
||||
const bytecode = ensureBytecodePrefix(args.bytecode);
|
||||
const constructorAbi = args.abi.find((abi) => abi.type === "constructor") as
|
||||
| AbiConstructor
|
||||
| undefined;
|
||||
const encodedArgs = encodeAbiParameters(
|
||||
constructorAbi?.inputs ?? [],
|
||||
normalizeFunctionParams(constructorAbi, constructorParams),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { AbiConstructor } from "abitype";
|
||||
import type { Abi } from "abitype";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
DUMMY_BYTECODE,
|
||||
@@ -46,8 +46,7 @@ describe("Resolve implementation", async () => {
|
||||
chain: ANVIL_CHAIN,
|
||||
account: TEST_ACCOUNT_A,
|
||||
bytecode: DUMMY_BYTECODE,
|
||||
constructorAbi: {} as AbiConstructor,
|
||||
constructorParams: [],
|
||||
abi: [],
|
||||
});
|
||||
|
||||
const proxyAddress = await deployContract({
|
||||
@@ -55,8 +54,11 @@ describe("Resolve implementation", async () => {
|
||||
chain: ANVIL_CHAIN,
|
||||
account: TEST_ACCOUNT_A,
|
||||
bytecode: ERC1967_PROXY_BYTECODE,
|
||||
constructorAbi: ERC1967_PROXY_CONSTRUCTOR_ABI as AbiConstructor,
|
||||
constructorParams: [implementationAddress, ""],
|
||||
abi: ERC1967_PROXY_CONSTRUCTOR_ABI as Abi,
|
||||
constructorParams: {
|
||||
logic: implementationAddress,
|
||||
data: "",
|
||||
},
|
||||
});
|
||||
|
||||
const proxy = getContract({
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
export const ERC1967_PROXY_BYTECODE =
|
||||
"0x60806040526040516104e13803806104e1833981016040819052610022916102de565b61002e82826000610035565b50506103fb565b61003e83610061565b60008251118061004b5750805b1561005c5761005a83836100a1565b505b505050565b61006a816100cd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100c683836040518060600160405280602781526020016104ba60279139610180565b9392505050565b6001600160a01b0381163b61013f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161019d91906103ac565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b5090925090506101ef868383876101f9565b9695505050505050565b60608315610268578251600003610261576001600160a01b0385163b6102615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610136565b5081610272565b610272838361027a565b949350505050565b81511561028a5781518083602001fd5b8060405162461bcd60e51b815260040161013691906103c8565b634e487b7160e01b600052604160045260246000fd5b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600080604083850312156102f157600080fd5b82516001600160a01b038116811461030857600080fd5b60208401519092506001600160401b038082111561032557600080fd5b818501915085601f83011261033957600080fd5b81518181111561034b5761034b6102a4565b604051601f8201601f19908116603f01168101908382118183101715610373576103736102a4565b8160405282815288602084870101111561038c57600080fd5b61039d8360208301602088016102ba565b80955050505050509250929050565b600082516103be8184602087016102ba565b9190910192915050565b60208152600082518060208401526103e78160408501602087016102ba565b601f01601f19169190910160400192915050565b60b1806104096000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6021565b6058565b565b600060537f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e8080156076573d6000f35b3d6000fdfea264697066735822122078e56a32ce2547a0a7b53ad6597602b4207bd6211f94b4294d5ab7b60e4c0b3f64736f6c63430008170033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564"
|
||||
export const ERC1967_PROXY_CONSTRUCTOR_ABI = {
|
||||
type: "constructor",
|
||||
inputs: [
|
||||
{ name: "_logic", type: "address", internalType: "address" },
|
||||
{ name: "_data", type: "bytes", internalType: "bytes" },
|
||||
],
|
||||
stateMutability: "payable",
|
||||
}
|
||||
"0x60806040526040516104e13803806104e1833981016040819052610022916102de565b61002e82826000610035565b50506103fb565b61003e83610061565b60008251118061004b5750805b1561005c5761005a83836100a1565b505b505050565b61006a816100cd565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606100c683836040518060600160405280602781526020016104ba60279139610180565b9392505050565b6001600160a01b0381163b61013f5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080856001600160a01b03168560405161019d91906103ac565b600060405180830381855af49150503d80600081146101d8576040519150601f19603f3d011682016040523d82523d6000602084013e6101dd565b606091505b5090925090506101ef868383876101f9565b9695505050505050565b60608315610268578251600003610261576001600160a01b0385163b6102615760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610136565b5081610272565b610272838361027a565b949350505050565b81511561028a5781518083602001fd5b8060405162461bcd60e51b815260040161013691906103c8565b634e487b7160e01b600052604160045260246000fd5b60005b838110156102d55781810151838201526020016102bd565b50506000910152565b600080604083850312156102f157600080fd5b82516001600160a01b038116811461030857600080fd5b60208401519092506001600160401b038082111561032557600080fd5b818501915085601f83011261033957600080fd5b81518181111561034b5761034b6102a4565b604051601f8201601f19908116603f01168101908382118183101715610373576103736102a4565b8160405282815288602084870101111561038c57600080fd5b61039d8360208301602088016102ba565b80955050505050509250929050565b600082516103be8184602087016102ba565b9190910192915050565b60208152600082518060208401526103e78160408501602087016102ba565b601f01601f19169190910160400192915050565b60b1806104096000396000f3fe608060405236601057600e6013565b005b600e5b601f601b6021565b6058565b565b600060537f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b905090565b3660008037600080366000845af43d6000803e8080156076573d6000f35b3d6000fdfea264697066735822122078e56a32ce2547a0a7b53ad6597602b4207bd6211f94b4294d5ab7b60e4c0b3f64736f6c63430008170033416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564";
|
||||
export const ERC1967_PROXY_CONSTRUCTOR_ABI = [
|
||||
{
|
||||
type: "constructor",
|
||||
inputs: [
|
||||
{ name: "_logic", type: "address", internalType: "address" },
|
||||
{ name: "_data", type: "bytes", internalType: "bytes" },
|
||||
],
|
||||
stateMutability: "payable",
|
||||
},
|
||||
];
|
||||
|
||||
export const DUMMY_BYTECODE = "0x60ff60005260146000f3" // deploys contract with 0xff bytecode
|
||||
export const DUMMY_BYTECODE = "0x60ff60005260146000f3"; // deploys contract with 0xff bytecode
|
||||
|
||||
Reference in New Issue
Block a user