From be20384a3f1a11a9c426e71fd713fc85c09a0521 Mon Sep 17 00:00:00 2001 From: Sasha Mitchell Date: Sat, 8 Aug 2026 09:38:33 +0700 Subject: [PATCH] fix(vaultsfyi): bind execute_step network to wallet chain Reject execute_step when args.network differs from the wallet chain, mirroring the existing claim_rewards guard so agents cannot fetch and send wrong-network vault calldata on the connected wallet. --- .../vaultsfyi/vaultsfyiActionProvider.test.ts | 35 +++++++++++++++++++ .../vaultsfyi/vaultsfyiActionProvider.ts | 7 ++++ 2 files changed, 42 insertions(+) diff --git a/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.test.ts b/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.test.ts index 43ed1a8d9..2fef26dd2 100644 --- a/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.test.ts +++ b/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.test.ts @@ -291,6 +291,7 @@ describe("VaultsfyiActionProvider", () => { getNetwork: jest.fn().mockReturnValue({ protocolFamily: "evm", networkId: "test-network", + chainId: "1", }), nativeTransfer: jest.fn(), readContract: jest.fn(() => Promise.resolve(18)), // token decimals @@ -461,6 +462,40 @@ describe("VaultsfyiActionProvider", () => { "Failed to execute step: some more info", ); }); + + it("should reject when args.network does not match the wallet chain", async () => { + const args = { + vaultAddress: "0x123", + assetAddress: "0x456", + network: "base", + amount: 1n, + action: "deposit", + } as const; + mockedFetch.mockClear(); + expect(await provider.executeStep(mockWalletProvider, args)).toBe( + "Error: You're trying to execute a step on a different network. Agent network is mainnet.", + ); + expect(mockedFetch).not.toHaveBeenCalled(); + expect(mockWalletProvider.sendTransaction).not.toHaveBeenCalled(); + }); + + it("should reject when the wallet network is missing a chainId", async () => { + mockWalletProvider.getNetwork.mockReturnValue({ + protocolFamily: "evm", + networkId: "test-network", + }); + const args = { + vaultAddress: "0x123", + assetAddress: "0x456", + network: "mainnet", + amount: 1n, + action: "deposit", + } as const; + mockedFetch.mockClear(); + expect(await provider.executeStep(mockWalletProvider, args)).toBe("Invalid network"); + expect(mockedFetch).not.toHaveBeenCalled(); + expect(mockWalletProvider.sendTransaction).not.toHaveBeenCalled(); + }); }); describe("user_idle_assets action", () => { diff --git a/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.ts b/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.ts index 5f27a66d2..56ea92adb 100644 --- a/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.ts +++ b/typescript/agentkit/src/action-providers/vaultsfyi/vaultsfyiActionProvider.ts @@ -282,6 +282,13 @@ export class VaultsfyiActionProvider extends ActionProvider { wallet: EvmWalletProvider, args: z.infer, ): Promise { + const chainId = wallet.getNetwork().chainId; + if (!chainId) return "Invalid network"; + const networkName = getNetworkNameFromChainId(chainId); + if (!networkName) return "Invalid network"; + if (args.network !== networkName) { + return `Error: You're trying to execute a step on a different network. Agent network is ${networkName}.`; + } try { const sdk = getVaultsSdk(this.apiKey); const amount = args.amount === "all" ? 0 : args.amount;