11import type { Abi , AbiConstructor } from "abitype" ;
2+ import { parseEventLogs } from "../../event/actions/parse-logs.js" ;
3+ import { FN_SELECTOR } from "../../extensions/stylus/__generated__/IStylusConstructor/write/stylus_constructor.js" ;
4+ import { contractDeployedEvent } from "../../extensions/stylus/__generated__/IStylusDeployer/events/ContractDeployed.js" ;
5+ import { deploy } from "../../extensions/stylus/__generated__/IStylusDeployer/write/deploy.js" ;
26import { activateStylusContract } from "../../extensions/stylus/write/activateStylusContract.js" ;
7+ import { eth_blockNumber } from "../../rpc/actions/eth_blockNumber.js" ;
8+ import { getRpcClient } from "../../rpc/rpc.js" ;
39import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js" ;
410import { sendTransaction } from "../../transaction/actions/send-transaction.js" ;
511import { prepareTransaction } from "../../transaction/prepare-transaction.js" ;
@@ -11,7 +17,7 @@ import { isZkSyncChain } from "../../utils/any-evm/zksync/isZkSyncChain.js";
1117import { isContractDeployed } from "../../utils/bytecode/is-contract-deployed.js" ;
1218import { ensureBytecodePrefix } from "../../utils/bytecode/prefix.js" ;
1319import { concatHex } from "../../utils/encoding/helpers/concat-hex.js" ;
14- import { type Hex , isHex } from "../../utils/encoding/hex.js" ;
20+ import { type Hex , isHex , toHex } from "../../utils/encoding/hex.js" ;
1521import type { Prettify } from "../../utils/type-utils.js" ;
1622import type { ClientAndChain } from "../../utils/types.js" ;
1723import type { Account } from "../../wallets/interfaces/wallet.js" ;
@@ -171,6 +177,58 @@ export async function deployContract(
171177 to : info . create2FactoryAddress ,
172178 } ) ,
173179 } ) ;
180+ } else if ( options . isStylus && options . constructorParams ) {
181+ const STYLUS_DEPLOYER = "0xCeCbA2F1dC234F70Dd89f2041029807F8D03A990" ;
182+ const stylusDeployer = getContract ( {
183+ address : STYLUS_DEPLOYER ,
184+ chain : options . chain ,
185+ client : options . client ,
186+ } ) ;
187+
188+ const constructorAbi = options . abi . find (
189+ ( abi ) => abi . type === "constructor" ,
190+ ) as AbiConstructor | undefined ;
191+ const constructorCalldata = ( FN_SELECTOR +
192+ encodeAbiParameters (
193+ constructorAbi ?. inputs || [ ] , // Leave an empty array if there's no constructor
194+ normalizeFunctionParams (
195+ constructorAbi ,
196+ options . constructorParams ,
197+ ) . slice ( 2 ) ,
198+ ) ) as `${typeof FN_SELECTOR } ${string } `;
199+
200+ const rpcRequest = getRpcClient ( {
201+ ...options ,
202+ } ) ;
203+ const blockNumber = await eth_blockNumber ( rpcRequest ) ;
204+ const salt = toHex ( blockNumber , {
205+ size : 32 ,
206+ } ) ;
207+
208+ const deployTx = deploy ( {
209+ bytecode : options . bytecode ,
210+ contract : stylusDeployer ,
211+ initData : constructorCalldata ,
212+ initValue : 0n ,
213+ salt,
214+ } ) ;
215+
216+ const receipt = await sendAndConfirmTransaction ( {
217+ account : options . account ,
218+ transaction : deployTx ,
219+ } ) ;
220+
221+ const deployEvent = contractDeployedEvent ( ) ;
222+ const decodedEvent = parseEventLogs ( {
223+ events : [ deployEvent ] ,
224+ logs : receipt . logs ,
225+ } ) ;
226+ if ( decodedEvent . length === 0 || ! decodedEvent [ 0 ] ) {
227+ throw new Error (
228+ `No ContractDeployed event found in transaction: ${ receipt . transactionHash } ` ,
229+ ) ;
230+ }
231+ address = decodedEvent [ 0 ] ?. args . deployedContract ;
174232 } else {
175233 const deployTx = prepareDirectDeployTransaction ( options ) ;
176234 const receipt = await sendAndConfirmTransaction ( {
@@ -180,7 +238,7 @@ export async function deployContract(
180238 address = receipt . contractAddress ;
181239 if ( ! address ) {
182240 throw new Error (
183- `Could not find deployed contract address in transaction: ${ receipt . transactionHash } ` ,
241+ `Could not find deployed contract address in transaction: $receipt.transactionHash` ,
184242 ) ;
185243 }
186244 }
0 commit comments