|
| 1 | +import type { AbiConstructor } from "abitype"; |
| 2 | +import { getContract } from "src/contract/contract.js"; |
| 3 | +import { getDeployedInfraContractFromMetadata } from "src/contract/deployment/utils/infra.js"; |
| 4 | +import { computeDeployAddress } from "src/extensions/tokens/__generated__/ContractFactory/read/computeDeployAddress.js"; |
| 5 | +import { computeProxyAddress } from "src/extensions/tokens/__generated__/ContractFactory/read/computeProxyAddress.js"; |
| 6 | +import { encodeAbiParameters } from "src/utils/abi/encodeAbiParameters.js"; |
| 7 | +import { normalizeFunctionParams } from "src/utils/abi/normalizeFunctionParams.js"; |
| 8 | +import { |
| 9 | + fetchBytecodeFromCompilerMetadata, |
| 10 | + fetchDeployMetadata, |
| 11 | +} from "src/utils/any-evm/deploy-metadata.js"; |
| 12 | +import { isContractDeployed } from "src/utils/bytecode/is-contract-deployed.js"; |
| 13 | +import { padHex, toHex } from "src/utils/encoding/hex.js"; |
| 14 | +import { withCache } from "src/utils/promise/withCache.js"; |
1 | 15 | import type { ClientAndChain } from "../utils/types.js"; |
| 16 | +import { |
| 17 | + CONTRACT_DEPLOY, |
| 18 | + CONTRACT_FACTORY_DEPLOY_URL, |
| 19 | + ENTRYPOINT_DEPLOY_URL, |
| 20 | + MANAGER_ADDRESS, |
| 21 | + OWNER_ADDRESS, |
| 22 | + PROXY_DEPLOY, |
| 23 | +} from "./constants.js"; |
2 | 24 |
|
3 | 25 | export async function getDeployedEntrypointERC20(options: ClientAndChain) { |
4 | | - // TODO (1): get the create2 factory address |
5 | | - // TODO (2): get the bootstrap contract factory address from the create2 factory |
6 | | - // TODO (3): get the entrypoint contract addresses using contract factory OR predict it using the contract factory address |
7 | | - throw new Error("Asset factory deployment is not deployed yet."); |
| 26 | + const cacheKey = `${options.chain.id}-${ENTRYPOINT_DEPLOY_URL}`; |
| 27 | + |
| 28 | + return withCache( |
| 29 | + async () => { |
| 30 | + // 1. Get deployed contract factory |
| 31 | + const contractFactory = await getDeployedContractFactory(options); |
| 32 | + |
| 33 | + if (!contractFactory) { |
| 34 | + throw new Error( |
| 35 | + `Contract factory not found on chain: ${options.chain.id}`, |
| 36 | + ); |
| 37 | + } |
| 38 | + |
| 39 | + // 2. Fetch metadata and encode args for entrypoint implementation |
| 40 | + const contractMetadata = await fetchDeployMetadata({ |
| 41 | + client: options.client, |
| 42 | + uri: ENTRYPOINT_DEPLOY_URL, |
| 43 | + }); |
| 44 | + const bytecode = await fetchBytecodeFromCompilerMetadata({ |
| 45 | + chain: options.chain, |
| 46 | + client: options.client, |
| 47 | + compilerMetadata: contractMetadata, |
| 48 | + }); |
| 49 | + const constructorAbi = contractMetadata.abi.find( |
| 50 | + (abi) => abi.type === "constructor", |
| 51 | + ) as AbiConstructor | undefined; |
| 52 | + const encodedArgs = encodeAbiParameters( |
| 53 | + constructorAbi?.inputs ?? [], |
| 54 | + normalizeFunctionParams(constructorAbi, {}), |
| 55 | + ); |
| 56 | + |
| 57 | + // 3. Compute entrypoint implementation address |
| 58 | + const entrypointImplAddress = await computeDeployAddress({ |
| 59 | + contract: contractFactory, |
| 60 | + deployType: CONTRACT_DEPLOY.CREATE2, |
| 61 | + bytecode, |
| 62 | + constructorArgs: encodedArgs, |
| 63 | + salt: padHex(toHex("ERC20_ENTRYPOINT:1"), { size: 32 }), |
| 64 | + }); |
| 65 | + |
| 66 | + // 4. Compute entrypoint proxy address |
| 67 | + const entrypointProxyAddress = await computeProxyAddress({ |
| 68 | + contract: contractFactory, |
| 69 | + implementation: entrypointImplAddress, |
| 70 | + data: "0x", |
| 71 | + salt: padHex(toHex("ERC20_ENTRYPOINT_PROXY:1"), { size: 32 }), |
| 72 | + deployType: PROXY_DEPLOY.ERC1967, |
| 73 | + }); |
| 74 | + const entrypointProxy = getContract({ |
| 75 | + ...options, |
| 76 | + address: entrypointProxyAddress, |
| 77 | + }); |
| 78 | + |
| 79 | + const isDeployed = await isContractDeployed(entrypointProxy); |
| 80 | + |
| 81 | + if (!isDeployed) { |
| 82 | + throw new Error( |
| 83 | + `Entrypoint is not deployed yet on chain: ${options.chain.id}`, |
| 84 | + ); |
| 85 | + } |
| 86 | + |
| 87 | + return entrypointProxy; |
| 88 | + }, |
| 89 | + { |
| 90 | + cacheKey, |
| 91 | + cacheTime: 24 * 60 * 60 * 1000, // 1 day |
| 92 | + }, |
| 93 | + ); |
| 94 | +} |
| 95 | + |
| 96 | +async function getDeployedContractFactory(options: ClientAndChain) { |
| 97 | + const cacheKey = `${options.chain.id}-${CONTRACT_FACTORY_DEPLOY_URL}`; |
| 98 | + return withCache( |
| 99 | + async () => { |
| 100 | + const contractMetadata = await fetchDeployMetadata({ |
| 101 | + client: options.client, |
| 102 | + uri: CONTRACT_FACTORY_DEPLOY_URL, |
| 103 | + }); |
| 104 | + |
| 105 | + return getDeployedInfraContractFromMetadata({ |
| 106 | + chain: options.chain, |
| 107 | + client: options.client, |
| 108 | + constructorParams: { |
| 109 | + owner: OWNER_ADDRESS, |
| 110 | + manager: MANAGER_ADDRESS, |
| 111 | + }, |
| 112 | + contractMetadata, |
| 113 | + salt: "THIRDWEB_CONTRACT_FACTORY:1", |
| 114 | + }); |
| 115 | + }, |
| 116 | + { |
| 117 | + cacheKey, |
| 118 | + cacheTime: 24 * 60 * 60 * 1000, // 1 day |
| 119 | + }, |
| 120 | + ); |
8 | 121 | } |
0 commit comments