From 0af1c6c9350ec3947ae2d1396ff555f97f84c897 Mon Sep 17 00:00:00 2001 From: spypsy Date: Tue, 24 Mar 2026 13:20:59 +0000 Subject: [PATCH 1/6] fix(bot): A-657 fee juice restart refuel Made-with: Cursor --- .../deploy/DeployAztecL1Contracts.s.sol | 2 +- yarn-project/bot/src/factory.ts | 223 ++++++++++++++++-- 2 files changed, 207 insertions(+), 18 deletions(-) diff --git a/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol b/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol index 97383d84f0d9..23be11dc1397 100644 --- a/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol +++ b/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol @@ -140,7 +140,7 @@ contract DeployAztecL1Contracts is Script, Test { function _maybeDeployFeeAssetHandler() internal { // Deploy on test chains only (when we control the staking asset) if (config.existingTokenAddress() == address(0)) { - _output.feeAssetHandler = new FeeAssetHandler(deployer, address(_output.feeAsset), 1000e18); + _output.feeAssetHandler = new FeeAssetHandler(deployer, address(_output.feeAsset), 10000e18); TestERC20(address(_output.feeAsset)).addMinter(address(_output.feeAssetHandler)); } } diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index c62e3b78a85b..2e24d257efb2 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -15,6 +15,7 @@ import { deriveKeys } from '@aztec/aztec.js/keys'; import { createLogger } from '@aztec/aztec.js/log'; import { waitForL1ToL2MessageReady } from '@aztec/aztec.js/messaging'; import { waitForTx } from '@aztec/aztec.js/node'; +import { getFeeJuiceBalance } from '@aztec/aztec.js/utils'; import { createEthereumChain } from '@aztec/ethereum/chain'; import { createExtendedL1Client } from '@aztec/ethereum/client'; import { RollupContract } from '@aztec/ethereum/contracts'; @@ -39,6 +40,8 @@ import { getBalances, getPrivateBalance, isStandardTokenContract } from './utils const MINT_BALANCE = 1e12; const MIN_BALANCE = 1e3; +const FEE_JUICE_TOP_UP_THRESHOLD = 100n * 10n ** 18n; +const FEE_JUICE_TOP_UP_TARGET = 10_000n * 10n ** 18n; export class BotFactory { private log = createLogger('bot'); @@ -68,7 +71,8 @@ export class BotFactory { }> { const defaultAccountAddress = await this.setupAccount(); const recipient = (await this.wallet.createSchnorrAccount(Fr.random(), Fr.random())).address; - const token = await this.setupToken(defaultAccountAddress); + const token = await this.setupTokenWithOptionalEarlyRefuel(defaultAccountAddress); + await this.ensureFeeJuiceBalance(defaultAccountAddress, token); await this.mintTokens(token, defaultAccountAddress); return { wallet: this.wallet, defaultAccountAddress, token, node: this.aztecNode, recipient }; } @@ -82,7 +86,13 @@ export class BotFactory { node: AztecNode; }> { const defaultAccountAddress = await this.setupAccount(); - const token0 = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotToken0', 'BOT0'); + const token0 = await this.setupTokenContractWithOptionalEarlyRefuel( + defaultAccountAddress, + this.config.tokenSalt, + 'BotToken0', + 'BOT0', + ); + await this.ensureFeeJuiceBalance(defaultAccountAddress, token0); const token1 = await this.setupTokenContract(defaultAccountAddress, this.config.tokenSalt, 'BotToken1', 'BOT1'); const liquidityToken = await this.setupTokenContract( defaultAccountAddress, @@ -258,12 +268,81 @@ export class BotFactory { return accountManager.address; } + /** + * Setup token and refuel first: if the token already exists (restart scenario), + * run ensureFeeJuiceBalance before any step that might need fee juice. When deploying, + * use a bridge claim if balance is below threshold. + */ + private async setupTokenWithOptionalEarlyRefuel(sender: AztecAddress): Promise { + const token = await this.getTokenInstance(sender); + const address = token.address; + const metadata = await this.wallet.getContractMetadata(address); + if (metadata.isContractPublished) { + this.log.info(`Token at ${address.toString()} already deployed, refueling before setup`); + await this.ensureFeeJuiceBalance(sender, token); + } + return this.setupToken(sender, token); + } + + /** + * Setup token0 for AMM with refuel-first behaviour when token already exists. + */ + private async setupTokenContractWithOptionalEarlyRefuel( + deployer: AztecAddress, + contractAddressSalt: Fr, + name: string, + ticker: string, + decimals = 18, + ): Promise { + const deployOpts: DeployOptions = { from: deployer, contractAddressSalt, universalDeploy: true }; + const deploy = TokenContract.deploy(this.wallet, deployer, name, ticker, decimals); + const instance = await deploy.getInstance(deployOpts); + const metadata = await this.wallet.getContractMetadata(instance.address); + if (metadata.isContractPublished) { + this.log.info(`Token ${name} at ${instance.address.toString()} already deployed, refueling before setup`); + const token = TokenContract.at(instance.address, this.wallet); + await this.ensureFeeJuiceBalance(deployer, token); + } + return this.setupTokenContract(deployer, contractAddressSalt, name, ticker, decimals); + } + + private async getTokenInstance(sender: AztecAddress): Promise { + const deployOpts: DeployOptions = { + from: sender, + contractAddressSalt: this.config.tokenSalt, + universalDeploy: true, + }; + if (this.config.contract === SupportedTokenContracts.TokenContract) { + const deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18); + const instance = await deploy.getInstance(deployOpts); + return TokenContract.at(instance.address, this.wallet); + } + if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) { + const tokenSecretKey = Fr.random(); + const tokenPublicKeys = (await deriveKeys(tokenSecretKey)).publicKeys; + const deploy = PrivateTokenContract.deployWithPublicKeys(tokenPublicKeys, this.wallet, MINT_BALANCE, sender); + const instance = await deploy.getInstance({ + ...deployOpts, + skipInstancePublication: true, + skipClassPublication: true, + skipInitialization: false, + }); + return PrivateTokenContract.at(instance.address, this.wallet); + } + throw new Error(`Unsupported token contract type: ${this.config.contract}`); + } + /** * Checks if the token contract is deployed and deploys it if necessary. - * @param wallet - Wallet to deploy the token contract from. - * @returns The TokenContract instance. + * Uses a bridge claim for deploy when balance is below threshold to avoid failing before refuel. + * @param sender - Aztec address to deploy the token contract from. + * @param existingToken - Optional token instance when called from setupTokenWithOptionalEarlyRefuel. + * @returns The TokenContract or PrivateTokenContract instance. */ - private async setupToken(sender: AztecAddress): Promise { + private async setupToken( + sender: AztecAddress, + existingToken?: TokenContract | PrivateTokenContract, + ): Promise { let deploy: DeployMethod; let tokenInstance: ContractInstanceWithAddress | undefined; const deployOpts: DeployOptions = { @@ -300,15 +379,36 @@ export class BotFactory { if (metadata.isContractPublished) { this.log.info(`Token at ${address.toString()} already deployed`); await deploy.register(); + return existingToken ?? token; + } + + this.log.info(`Deploying token contract at ${address.toString()}`); + const balance = await getFeeJuiceBalance(sender, this.aztecNode); + const useClaim = + balance < FEE_JUICE_TOP_UP_THRESHOLD && + this.config.feePaymentMethod === 'fee_juice' && + this.config.l1RpcUrls?.length; + const mnemonicOrPrivateKey = this.config.l1PrivateKey?.getValue() ?? this.config.l1Mnemonic?.getValue(); + + if (useClaim && mnemonicOrPrivateKey) { + const claim = await this.getOrCreateBridgeClaim(sender); + const paymentMethod = new FeeJuicePaymentMethodWithClaim(sender, claim); + const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true, paymentMethod } }); + const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding); + const gasSettings = GasSettings.from({ ...estimatedGas!, maxFeesPerGas, maxPriorityFeesPerGas: GasFees.empty() }); + await this.withNoMinTxsPerBlock(async () => { + const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings, paymentMethod }, wait: NO_WAIT }); + this.log.info(`Sent token deploy tx ${txHash.toString()} (using bridge claim, balance was ${balance})`); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); + await this.store.deleteBridgeClaim(sender); } else { - this.log.info(`Deploying token contract at ${address.toString()}`); const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true } }); const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings: estimatedGas }, wait: NO_WAIT }); this.log.info(`Sent tx for token setup with hash ${txHash.toString()}`, { estimatedGas }); - await this.withNoMinTxsPerBlock(async () => { - await waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); - return token; - }); + await this.withNoMinTxsPerBlock(() => + waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }), + ); } return token; } @@ -482,13 +582,42 @@ export class BotFactory { this.log.info(`Contract ${name} at ${address.toString()} already deployed`); await deploy.register(); } else { - const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true } }); - this.log.info(`Deploying contract ${name} at ${address.toString()}`, { estimatedGas }); - await this.withNoMinTxsPerBlock(async () => { - const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings: estimatedGas }, wait: NO_WAIT }); - this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`); - return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); - }); + const sender = deployOpts.from; + const balance = sender ? await getFeeJuiceBalance(sender, this.aztecNode) : 0n; + const useClaim = + sender && + balance < FEE_JUICE_TOP_UP_THRESHOLD && + this.config.feePaymentMethod === 'fee_juice' && + !!this.config.l1RpcUrls?.length; + const mnemonicOrPrivateKey = this.config.l1PrivateKey?.getValue() ?? this.config.l1Mnemonic?.getValue(); + + if (useClaim && mnemonicOrPrivateKey) { + const claim = await this.getOrCreateBridgeClaim(sender!); + const paymentMethod = new FeeJuicePaymentMethodWithClaim(sender!, claim); + const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true, paymentMethod } }); + const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding); + const gasSettings = GasSettings.from({ + ...estimatedGas!, + maxFeesPerGas, + maxPriorityFeesPerGas: GasFees.empty(), + }); + await this.withNoMinTxsPerBlock(async () => { + const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings, paymentMethod }, wait: NO_WAIT }); + this.log.info( + `Sent contract ${name} deploy tx ${txHash.toString()} (using bridge claim, balance was ${balance})`, + ); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); + await this.store.deleteBridgeClaim(sender!); + } else { + const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true } }); + this.log.info(`Deploying contract ${name} at ${address.toString()}`, { estimatedGas }); + await this.withNoMinTxsPerBlock(async () => { + const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings: estimatedGas }, wait: NO_WAIT }); + this.log.info(`Sent contract ${name} setup tx with hash ${txHash.toString()}`); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); + } } return instance; } @@ -497,6 +626,66 @@ export class BotFactory { * Mints private and public tokens for the sender if their balance is below the minimum. * @param token - Token contract. */ + /** + * Ensures the account has sufficient fee juice by bridging from L1 if balance is below threshold. + * Bridges repeatedly until balance reaches the target (10k FJ). + * Used on startup/restart to top up when the account has run out after previous runs. + */ + private async ensureFeeJuiceBalance( + account: AztecAddress, + token: TokenContract | PrivateTokenContract, + ): Promise { + const { feePaymentMethod, l1RpcUrls } = this.config; + if (feePaymentMethod !== 'fee_juice' || !l1RpcUrls?.length) { + return; + } + const mnemonicOrPrivateKey = this.config.l1PrivateKey?.getValue() ?? this.config.l1Mnemonic?.getValue(); + if (!mnemonicOrPrivateKey) { + return; + } + + let balance = await getFeeJuiceBalance(account, this.aztecNode); + if (balance >= FEE_JUICE_TOP_UP_THRESHOLD) { + this.log.info(`Fee juice balance ${balance} above threshold ${FEE_JUICE_TOP_UP_THRESHOLD}, skipping top-up`); + return; + } + + this.log.info( + `Fee juice balance ${balance} below threshold ${FEE_JUICE_TOP_UP_THRESHOLD}, bridging from L1 until ${FEE_JUICE_TOP_UP_TARGET}`, + ); + const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding); + const minimalInteraction = isStandardTokenContract(token) + ? token.methods.transfer_in_public(account, account, 0n, 0) + : token.methods.transfer(0n, account, account); + + while (balance < FEE_JUICE_TOP_UP_TARGET) { + const claim = await this.bridgeL1FeeJuice(account); + const paymentMethod = new FeeJuicePaymentMethodWithClaim(account, claim); + const { estimatedGas } = await minimalInteraction.simulate({ + from: account, + fee: { estimateGas: true, paymentMethod }, + }); + const gasSettings = GasSettings.from({ + ...estimatedGas!, + maxFeesPerGas, + maxPriorityFeesPerGas: GasFees.empty(), + }); + + await this.withNoMinTxsPerBlock(async () => { + const { txHash } = await minimalInteraction.send({ + from: account, + fee: { gasSettings, paymentMethod }, + wait: NO_WAIT, + }); + this.log.info(`Sent fee juice top-up tx ${txHash.toString()}`); + return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); + }); + balance = await getFeeJuiceBalance(account, this.aztecNode); + this.log.info(`Fee juice balance after top-up: ${balance}`); + } + this.log.info(`Fee juice top-up complete for ${account.toString()}`); + } + private async mintTokens(token: TokenContract | PrivateTokenContract, minter: AztecAddress) { const isStandardToken = isStandardTokenContract(token); let privateBalance = 0n; From 4c8976019493ec8ddadf3d79b6723aebb84f486b Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 25 Mar 2026 14:12:49 +0000 Subject: [PATCH 2/6] forge fmt --- l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol b/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol index 23be11dc1397..08766e8dd237 100644 --- a/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol +++ b/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol @@ -140,7 +140,7 @@ contract DeployAztecL1Contracts is Script, Test { function _maybeDeployFeeAssetHandler() internal { // Deploy on test chains only (when we control the staking asset) if (config.existingTokenAddress() == address(0)) { - _output.feeAssetHandler = new FeeAssetHandler(deployer, address(_output.feeAsset), 10000e18); + _output.feeAssetHandler = new FeeAssetHandler(deployer, address(_output.feeAsset), 10_000e18); TestERC20(address(_output.feeAsset)).addMinter(address(_output.feeAssetHandler)); } } From b4d208155b809c1c148b6f0387502d2b258b7392 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 25 Mar 2026 14:45:50 +0000 Subject: [PATCH 3/6] type fix --- yarn-project/bot/src/factory.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index 7231d2637fed..d6246bc124f6 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -584,7 +584,7 @@ export class BotFactory { this.log.info(`Contract ${name} at ${address.toString()} already deployed`); await deploy.register(); } else { - const sender = deployOpts.from; + const sender = deployOpts.from === NO_FROM ? undefined : deployOpts.from; const balance = sender ? await getFeeJuiceBalance(sender, this.aztecNode) : 0n; const useClaim = sender && From a933c3e29e546f95d4b760f2a4e406f98273ca85 Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 26 Mar 2026 09:47:27 +0000 Subject: [PATCH 4/6] undo amount change --- l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol b/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol index 08766e8dd237..97383d84f0d9 100644 --- a/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol +++ b/l1-contracts/script/deploy/DeployAztecL1Contracts.s.sol @@ -140,7 +140,7 @@ contract DeployAztecL1Contracts is Script, Test { function _maybeDeployFeeAssetHandler() internal { // Deploy on test chains only (when we control the staking asset) if (config.existingTokenAddress() == address(0)) { - _output.feeAssetHandler = new FeeAssetHandler(deployer, address(_output.feeAsset), 10_000e18); + _output.feeAssetHandler = new FeeAssetHandler(deployer, address(_output.feeAsset), 1000e18); TestERC20(address(_output.feeAsset)).addMinter(address(_output.feeAssetHandler)); } } From 69327551027128e9e4c5750646d78cfa79b12433 Mon Sep 17 00:00:00 2001 From: spypsy Date: Wed, 1 Apr 2026 12:30:33 +0000 Subject: [PATCH 5/6] dedup code --- yarn-project/bot/src/factory.ts | 46 ++++----------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index 4974e84c33a9..f5307f0753b5 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -339,7 +339,6 @@ export class BotFactory { existingToken?: TokenContract | PrivateTokenContract, ): Promise { let deploy: DeployMethod; - let tokenInstance: ContractInstanceWithAddress | undefined; const deployOpts: DeployOptions = { from: sender, contractAddressSalt: this.config.tokenSalt, @@ -348,8 +347,8 @@ export class BotFactory { let token: TokenContract | PrivateTokenContract; if (this.config.contract === SupportedTokenContracts.TokenContract) { deploy = TokenContract.deploy(this.wallet, sender, 'BotToken', 'BOT', 18); - tokenInstance = await deploy.getInstance(deployOpts); - token = TokenContract.at(tokenInstance.address, this.wallet); + const instance = await deploy.getInstance(deployOpts); + token = TokenContract.at(instance.address, this.wallet); } else if (this.config.contract === SupportedTokenContracts.PrivateTokenContract) { // Generate keys for the contract since PrivateToken uses SinglePrivateMutable which requires keys const tokenSecretKey = Fr.random(); @@ -360,7 +359,7 @@ export class BotFactory { deployOpts.skipInitialization = false; // Register the contract with the secret key before deployment - tokenInstance = await deploy.getInstance(deployOpts); + const tokenInstance = await deploy.getInstance(deployOpts); token = PrivateTokenContract.at(tokenInstance.address, this.wallet); await this.wallet.registerContract(tokenInstance, PrivateTokenContract.artifact, tokenSecretKey); // The contract constructor initializes private storage vars that need the contract's own nullifier key. @@ -369,43 +368,8 @@ export class BotFactory { throw new Error(`Unsupported token contract type: ${this.config.contract}`); } - const address = tokenInstance?.address ?? (await deploy.getInstance(deployOpts)).address; - const metadata = await this.wallet.getContractMetadata(address); - if (metadata.isContractPublished) { - this.log.info(`Token at ${address.toString()} already deployed`); - await deploy.register(); - return existingToken ?? token; - } - - this.log.info(`Deploying token contract at ${address.toString()}`); - const balance = await getFeeJuiceBalance(sender, this.aztecNode); - const useClaim = - balance < FEE_JUICE_TOP_UP_THRESHOLD && - this.config.feePaymentMethod === 'fee_juice' && - this.config.l1RpcUrls?.length; - const mnemonicOrPrivateKey = this.config.l1PrivateKey?.getValue() ?? this.config.l1Mnemonic?.getValue(); - - if (useClaim && mnemonicOrPrivateKey) { - const claim = await this.getOrCreateBridgeClaim(sender); - const paymentMethod = new FeeJuicePaymentMethodWithClaim(sender, claim); - const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true, paymentMethod } }); - const maxFeesPerGas = (await this.aztecNode.getCurrentMinFees()).mul(1 + this.config.minFeePadding); - const gasSettings = GasSettings.from({ ...estimatedGas!, maxFeesPerGas, maxPriorityFeesPerGas: GasFees.empty() }); - await this.withNoMinTxsPerBlock(async () => { - const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings, paymentMethod }, wait: NO_WAIT }); - this.log.info(`Sent token deploy tx ${txHash.toString()} (using bridge claim, balance was ${balance})`); - return waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }); - }); - await this.store.deleteBridgeClaim(sender); - } else { - const { estimatedGas } = await deploy.simulate({ ...deployOpts, fee: { estimateGas: true } }); - const { txHash } = await deploy.send({ ...deployOpts, fee: { gasSettings: estimatedGas }, wait: NO_WAIT }); - this.log.info(`Sent tx for token setup with hash ${txHash.toString()}`, { estimatedGas }); - await this.withNoMinTxsPerBlock(() => - waitForTx(this.aztecNode, txHash, { timeout: this.config.txMinedWaitSeconds }), - ); - } - return token; + await this.registerOrDeployContract('token', deploy, deployOpts); + return existingToken ?? token; } /** From a656267993f6f60b72ccde8c076b3216482945ca Mon Sep 17 00:00:00 2001 From: spypsy Date: Thu, 2 Apr 2026 13:38:16 +0000 Subject: [PATCH 6/6] laways return token --- yarn-project/bot/src/factory.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index f5307f0753b5..4be39d482dfd 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -276,7 +276,7 @@ export class BotFactory { this.log.info(`Token at ${address.toString()} already deployed, refueling before setup`); await this.ensureFeeJuiceBalance(sender, token); } - return this.setupToken(sender, token); + return this.setupToken(sender); } /** @@ -334,10 +334,7 @@ export class BotFactory { * @param existingToken - Optional token instance when called from setupTokenWithOptionalEarlyRefuel. * @returns The TokenContract or PrivateTokenContract instance. */ - private async setupToken( - sender: AztecAddress, - existingToken?: TokenContract | PrivateTokenContract, - ): Promise { + private async setupToken(sender: AztecAddress): Promise { let deploy: DeployMethod; const deployOpts: DeployOptions = { from: sender, @@ -369,7 +366,7 @@ export class BotFactory { } await this.registerOrDeployContract('token', deploy, deployOpts); - return existingToken ?? token; + return token; } /**