-
Notifications
You must be signed in to change notification settings - Fork 476
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f30f2b7
commit a9b2b15
Showing
6 changed files
with
278 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
packages/thirdweb/src/contract/deployment/deploy-via-autofactory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import type { SharedDeployOptions } from "./types.js"; | ||
import type { FullPublishMetadata } from "./utils/deploy-metadata.js"; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export async function prepareDeployTransactionViaAutoFactory( | ||
args: SharedDeployOptions & { | ||
extendedMetadata: FullPublishMetadata; | ||
}, | ||
) { | ||
// TODO | ||
console.log(args); | ||
} | ||
86 changes: 86 additions & 0 deletions
86
packages/thirdweb/src/contract/deployment/deploy-via-clone-factory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import type { Abi } from "abitype"; | ||
import type { SharedDeployOptions } from "./types.js"; | ||
import { getContract } from "../contract.js"; | ||
import { prepareContractCall } from "../../transaction/prepare-contract-call.js"; | ||
import { encode } from "../../transaction/actions/encode.js"; | ||
import { keccakId } from "../../utils/any-evm/keccak-id.js"; | ||
import { getRpcClient } from "../../rpc/rpc.js"; | ||
import { eth_blockNumber } from "../../rpc/actions/eth_blockNumber.js"; | ||
import { toHex } from "../../utils/encoding/hex.js"; | ||
|
||
/** | ||
* Prepares a deploy transaction via a proxy factory. | ||
* @param args - The arguments for deploying the contract. | ||
* @example | ||
* ```ts | ||
* import { prepareDeployTransactionViaCloneFactory } from "thirdweb/contract"; | ||
* import { ethereum } from "thirdweb/chains"; | ||
* | ||
* const tx = await prepareDeployTransactionViaCloneFactory({ | ||
* client, | ||
* chain: ethereum, | ||
* factoryAddress: "0x...", | ||
* implementationAddress: "0x...", | ||
* implementationAbi: abi, | ||
* initializerFunction: "initialize", | ||
* initializerArgs: [123, "hello"], | ||
* }); | ||
* ``` | ||
* @returns A prepared deployment transaction ready to be sent. | ||
*/ | ||
export async function prepareDeployTransactionViaCloneFactory( | ||
args: SharedDeployOptions & { | ||
factoryAddress: string; | ||
implementationAddress: string; | ||
implementationAbi: Abi; | ||
initializerFunction: string; | ||
initializerArgs: unknown[]; | ||
saltForProxyDeploy?: string; | ||
}, | ||
) { | ||
const { | ||
client, | ||
chain, | ||
factoryAddress, | ||
implementationAddress, | ||
implementationAbi, | ||
initializerFunction, | ||
initializerArgs, | ||
saltForProxyDeploy, | ||
} = args; | ||
const factory = getContract({ | ||
client, | ||
chain, | ||
address: factoryAddress, | ||
}); | ||
return prepareContractCall({ | ||
contract: factory, | ||
method: | ||
"function deployProxyByImplementation(address _implementation, bytes memory _data, bytes32 _salt) returns (address deployedProxy)", | ||
params: async () => { | ||
const implementation = getContract({ | ||
client, | ||
chain, | ||
address: implementationAddress, | ||
abi: implementationAbi, | ||
}); | ||
const initializerTransaction = prepareContractCall({ | ||
contract: implementation, | ||
method: initializerFunction, | ||
params: initializerArgs, | ||
}); | ||
const rpcRequest = getRpcClient({ | ||
client, | ||
chain, | ||
}); | ||
const blockNumber = await eth_blockNumber(rpcRequest); | ||
const salt = saltForProxyDeploy | ||
? keccakId(saltForProxyDeploy) | ||
: toHex(blockNumber, { | ||
size: 32, | ||
}); | ||
const encoded = await encode(initializerTransaction); | ||
return [implementationAddress, encoded, salt] as const; | ||
}, | ||
}); | ||
} | ||
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
81 changes: 81 additions & 0 deletions
81
packages/thirdweb/src/contract/deployment/utils/fetch-published-contract.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { polygon } from "../../../chains/chain-definitions/polygon.js"; | ||
import type { ThirdwebClient } from "../../../client/client.js"; | ||
import { readContract } from "../../../transaction/read-contract.js"; | ||
import { getContract } from "../../contract.js"; | ||
|
||
const ContractPublisherAddress = "0xf5b896Ddb5146D5dA77efF4efBb3Eae36E300808"; // Polygon only | ||
export const THIRDWEB_DEPLOYER = "0xdd99b75f095d0c4d5112aCe938e4e6ed962fb024"; | ||
|
||
/** | ||
* @internal | ||
*/ | ||
export async function fetchPublishedContract(args: { | ||
client: ThirdwebClient; | ||
contractId: string; | ||
publisherAddress?: string; | ||
}) { | ||
const { client, publisherAddress, contractId } = args; | ||
const contractPublisher = getContract({ | ||
client, | ||
chain: polygon, | ||
address: ContractPublisherAddress, | ||
}); | ||
// TODO support mutliple contract versions | ||
return readContract({ | ||
contract: contractPublisher, | ||
method: GET_PUBLISHED_CONTRACT_ABI, | ||
params: [publisherAddress || THIRDWEB_DEPLOYER, contractId], | ||
}); | ||
} | ||
|
||
const GET_PUBLISHED_CONTRACT_ABI = { | ||
inputs: [ | ||
{ | ||
internalType: "address", | ||
name: "_publisher", | ||
type: "address", | ||
}, | ||
{ | ||
internalType: "string", | ||
name: "_contractId", | ||
type: "string", | ||
}, | ||
], | ||
name: "getPublishedContract", | ||
outputs: [ | ||
{ | ||
components: [ | ||
{ | ||
internalType: "string", | ||
name: "contractId", | ||
type: "string", | ||
}, | ||
{ | ||
internalType: "uint256", | ||
name: "publishTimestamp", | ||
type: "uint256", | ||
}, | ||
{ | ||
internalType: "string", | ||
name: "publishMetadataUri", | ||
type: "string", | ||
}, | ||
{ | ||
internalType: "bytes32", | ||
name: "bytecodeHash", | ||
type: "bytes32", | ||
}, | ||
{ | ||
internalType: "address", | ||
name: "implementation", | ||
type: "address", | ||
}, | ||
], | ||
internalType: "struct IContractPublisher.CustomContractInstance", | ||
name: "published", | ||
type: "tuple", | ||
}, | ||
], | ||
stateMutability: "view", | ||
type: "function", | ||
} as const; | ||
71 changes: 71 additions & 0 deletions
71
packages/thirdweb/src/contract/deployment/utils/predict-published-contract-address.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import type { AbiConstructor } from "abitype"; | ||
import type { ThirdwebClient } from "../../../client/client.js"; | ||
import { getInitBytecodeWithSalt } from "../../../utils/any-evm/get-init-bytecode-with-salt.js"; | ||
import { fetchDeployMetadata } from "./deploy-metadata.js"; | ||
import { fetchPublishedContract } from "./fetch-published-contract.js"; | ||
import { encodeAbiParameters } from "viem"; | ||
import { computeDeploymentAddress } from "../../../utils/any-evm/compute-deployment-address.js"; | ||
import { getCreate2FactoryAddress } from "../../../utils/any-evm/create-2-factory.js"; | ||
import type { Chain } from "../../../chains/types.js"; | ||
|
||
/** | ||
* Predicts the implementation address of any published contract | ||
* @param args - The arguments for predicting the address of a published contract. | ||
* @param args.client - The Thirdweb client. | ||
* @param args.chain - The chain to predict the address on. | ||
* @param args.contractId - The ID of the contract to predict the address of. | ||
* @param args.constructorParams - The parameters for the contract constructor. | ||
* @example | ||
* ```ts | ||
* import { predictPublishedContractAddress } from "thirdweb/contract"; | ||
* | ||
* const address = await predictPublishedContractAddress({ | ||
* client, | ||
* chain, | ||
* contractId, | ||
* constructorParams, | ||
* }); | ||
* ``` | ||
* @returns A promise that resolves to the predicted address of the contract. | ||
*/ | ||
export async function predictPublishedContractAddress(args: { | ||
client: ThirdwebClient; | ||
chain: Chain; | ||
contractId: string; | ||
constructorParams: unknown[]; // TODO automate contract params from known inputs | ||
}): Promise<string> { | ||
const { client, chain, contractId, constructorParams } = args; | ||
const contractModel = await fetchPublishedContract({ | ||
client, | ||
contractId, | ||
}); | ||
const [{ compilerMetadata }, create2FactoryAddress] = await Promise.all([ | ||
fetchDeployMetadata({ | ||
client, | ||
uri: contractModel.publishMetadataUri, | ||
}), | ||
getCreate2FactoryAddress({ | ||
client, | ||
chain, | ||
}), | ||
]); | ||
const bytecode = compilerMetadata.bytecode; | ||
const constructorAbi = | ||
(compilerMetadata.abi.find( | ||
(abi) => abi.type === "constructor", | ||
) as AbiConstructor) || []; | ||
const encodedArgs = encodeAbiParameters( | ||
constructorAbi.inputs, | ||
constructorParams, | ||
); | ||
const initBytecodeWithsalt = getInitBytecodeWithSalt({ | ||
bytecode, | ||
encodedArgs, | ||
}); | ||
return computeDeploymentAddress({ | ||
bytecode, | ||
encodedArgs, | ||
create2FactoryAddress, | ||
salt: initBytecodeWithsalt, | ||
}); | ||
} | ||
Check warning on line 71 in packages/thirdweb/src/contract/deployment/utils/predict-published-contract-address.ts
|