shll-skills 6.0.2 → 6.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -977,10 +977,14 @@ function checkActionRecipientSafety(action, vault) {
977
977
  function policyRejectionHelp(reason, tokenId) {
978
978
  const consoleUrl = agentConsoleUrl(tokenId);
979
979
  const r = reason ?? "";
980
+ if (r.includes("Function not allowed"))
981
+ return { explanation: "The contract method selector is not enabled by the active DeFi policy configuration.", action: "Enable the required protocol pack or selector in Console > Safety, or use a supported transaction path.", consoleUrl };
980
982
  if (r.includes("Approve spender not allowed"))
981
983
  return { explanation: "The DEX router address is not in the approved spender whitelist.", action: "Contact the Agent owner to approve this router, or use a different DEX.", consoleUrl };
982
984
  if (r.includes("Target not allowed"))
983
985
  return { explanation: "The contract address is not in the DeFi target whitelist.", action: "Enable the corresponding DeFi Pack in Console > Safety, or contact the Agent owner.", consoleUrl };
986
+ if (r.includes("Receiver must be vault"))
987
+ return { explanation: "Swap output recipient must be the agent vault address enforced by ReceiverGuard.", action: "Retry with recipient/to set to the vault address, or use a supported flow that routes proceeds back to the vault.", consoleUrl };
984
988
  if (r.includes("Token not in whitelist"))
985
989
  return { explanation: "Token restriction is ON and this token is not whitelisted.", action: `Add the token to the whitelist or disable token restriction at: ${consoleUrl}`, consoleUrl };
986
990
  if (r.includes("Exceeds per-tx limit"))
@@ -1228,13 +1232,18 @@ function ensureRecipientSafe(result) {
1228
1232
  }
1229
1233
  }
1230
1234
  async function validateActionsOrThrow(policyClient, tokenId, actions) {
1231
- for (const action of actions) {
1235
+ for (const [index, action] of actions.entries()) {
1232
1236
  const sim = await policyClient.validate(tokenId, action);
1233
1237
  if (!sim.ok) {
1234
1238
  throw new SkillError(
1235
1239
  "POLICY_REJECTED",
1236
1240
  "Policy rejected transaction",
1237
1241
  {
1242
+ failedActionIndex: index,
1243
+ failedActionTarget: action.target,
1244
+ failedActionSelector: getActionSelector(action),
1245
+ failedActionFunction: getActionFunctionName(action),
1246
+ failedActionValue: action.value.toString(),
1238
1247
  reason: sim.reason,
1239
1248
  ...policyRejectionHelp(sim.reason, tokenId.toString())
1240
1249
  },
@@ -1254,6 +1263,37 @@ async function executeActions(policyClient, tokenId, actions) {
1254
1263
  const result = await policyClient.executeBatch(tokenId, actions, true);
1255
1264
  return { hash: result.hash };
1256
1265
  }
1266
+ function getActionSelector(action) {
1267
+ return action.data && action.data.length >= 10 ? action.data.slice(0, 10) : "0x";
1268
+ }
1269
+ function getActionFunctionName(action) {
1270
+ if (action.data === "0x") {
1271
+ return "nativeTransfer";
1272
+ }
1273
+ const candidates = [
1274
+ ERC20_ABI,
1275
+ WBNB_ABI,
1276
+ VTOKEN_ABI,
1277
+ VBNB_MINT_ABI,
1278
+ SWAP_EXACT_ETH_ABI,
1279
+ SWAP_EXACT_TOKENS_ABI,
1280
+ SWAP_EXACT_TOKENS_FOR_ETH_ABI,
1281
+ SWAP_EXACT_ETH_FOR_TOKENS_FEE_ABI,
1282
+ SWAP_EXACT_TOKENS_FOR_TOKENS_FEE_ABI,
1283
+ SWAP_EXACT_TOKENS_FOR_ETH_FEE_ABI,
1284
+ V3_EXACT_INPUT_SINGLE_ABI,
1285
+ V3_EXACT_INPUT_ABI,
1286
+ FOUR_MEME_V1_ABI,
1287
+ FOUR_MEME_V2_ABI
1288
+ ];
1289
+ for (const abi of candidates) {
1290
+ const decoded = tryDecodeCalldata(abi, action.data);
1291
+ if (decoded?.functionName) {
1292
+ return decoded.functionName;
1293
+ }
1294
+ }
1295
+ return "unknown";
1296
+ }
1257
1297
 
1258
1298
  // src/services/info.ts
1259
1299
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
@@ -1692,25 +1732,6 @@ async function executeSwap(input) {
1692
1732
  args: [minOut, path, vault, deadline]
1693
1733
  })
1694
1734
  });
1695
- } else if (isNativeOut) {
1696
- actions.push({
1697
- target: tokenIn.address,
1698
- value: 0n,
1699
- data: encodeFunctionData2({
1700
- abi: ERC20_ABI,
1701
- functionName: "approve",
1702
- args: [v2Router, amountIn]
1703
- })
1704
- });
1705
- actions.push({
1706
- target: v2Router,
1707
- value: 0n,
1708
- data: encodeFunctionData2({
1709
- abi: SWAP_EXACT_TOKENS_FOR_ETH_ABI,
1710
- functionName: "swapExactTokensForETH",
1711
- args: [amountIn, minOut, path, vault, deadline]
1712
- })
1713
- });
1714
1735
  } else {
1715
1736
  actions.push({
1716
1737
  target: tokenIn.address,
@@ -1725,8 +1746,8 @@ async function executeSwap(input) {
1725
1746
  target: v2Router,
1726
1747
  value: 0n,
1727
1748
  data: encodeFunctionData2({
1728
- abi: SWAP_EXACT_TOKENS_ABI,
1729
- functionName: "swapExactTokensForTokens",
1749
+ abi: SWAP_EXACT_TOKENS_FOR_TOKENS_FEE_ABI,
1750
+ functionName: "swapExactTokensForTokensSupportingFeeOnTransferTokens",
1730
1751
  args: [amountIn, minOut, path, vault, deadline]
1731
1752
  })
1732
1753
  });
package/dist/index.js CHANGED
@@ -979,10 +979,14 @@ function checkActionRecipientSafety(action, vault) {
979
979
  function policyRejectionHelp(reason, tokenId) {
980
980
  const consoleUrl = agentConsoleUrl(tokenId);
981
981
  const r = reason ?? "";
982
+ if (r.includes("Function not allowed"))
983
+ return { explanation: "The contract method selector is not enabled by the active DeFi policy configuration.", action: "Enable the required protocol pack or selector in Console > Safety, or use a supported transaction path.", consoleUrl };
982
984
  if (r.includes("Approve spender not allowed"))
983
985
  return { explanation: "The DEX router address is not in the approved spender whitelist.", action: "Contact the Agent owner to approve this router, or use a different DEX.", consoleUrl };
984
986
  if (r.includes("Target not allowed"))
985
987
  return { explanation: "The contract address is not in the DeFi target whitelist.", action: "Enable the corresponding DeFi Pack in Console > Safety, or contact the Agent owner.", consoleUrl };
988
+ if (r.includes("Receiver must be vault"))
989
+ return { explanation: "Swap output recipient must be the agent vault address enforced by ReceiverGuard.", action: "Retry with recipient/to set to the vault address, or use a supported flow that routes proceeds back to the vault.", consoleUrl };
986
990
  if (r.includes("Token not in whitelist"))
987
991
  return { explanation: "Token restriction is ON and this token is not whitelisted.", action: `Add the token to the whitelist or disable token restriction at: ${consoleUrl}`, consoleUrl };
988
992
  if (r.includes("Exceeds per-tx limit"))
@@ -1249,13 +1253,18 @@ function ensureRecipientSafe(result) {
1249
1253
  }
1250
1254
  }
1251
1255
  async function validateActionsOrThrow(policyClient, tokenId, actions) {
1252
- for (const action of actions) {
1256
+ for (const [index, action] of actions.entries()) {
1253
1257
  const sim = await policyClient.validate(tokenId, action);
1254
1258
  if (!sim.ok) {
1255
1259
  throw new SkillError(
1256
1260
  "POLICY_REJECTED",
1257
1261
  "Policy rejected transaction",
1258
1262
  {
1263
+ failedActionIndex: index,
1264
+ failedActionTarget: action.target,
1265
+ failedActionSelector: getActionSelector(action),
1266
+ failedActionFunction: getActionFunctionName(action),
1267
+ failedActionValue: action.value.toString(),
1259
1268
  reason: sim.reason,
1260
1269
  ...policyRejectionHelp(sim.reason, tokenId.toString())
1261
1270
  },
@@ -1275,6 +1284,37 @@ async function executeActions(policyClient, tokenId, actions) {
1275
1284
  const result = await policyClient.executeBatch(tokenId, actions, true);
1276
1285
  return { hash: result.hash };
1277
1286
  }
1287
+ function getActionSelector(action) {
1288
+ return action.data && action.data.length >= 10 ? action.data.slice(0, 10) : "0x";
1289
+ }
1290
+ function getActionFunctionName(action) {
1291
+ if (action.data === "0x") {
1292
+ return "nativeTransfer";
1293
+ }
1294
+ const candidates = [
1295
+ ERC20_ABI,
1296
+ WBNB_ABI,
1297
+ VTOKEN_ABI,
1298
+ VBNB_MINT_ABI,
1299
+ SWAP_EXACT_ETH_ABI,
1300
+ SWAP_EXACT_TOKENS_ABI,
1301
+ SWAP_EXACT_TOKENS_FOR_ETH_ABI,
1302
+ SWAP_EXACT_ETH_FOR_TOKENS_FEE_ABI,
1303
+ SWAP_EXACT_TOKENS_FOR_TOKENS_FEE_ABI,
1304
+ SWAP_EXACT_TOKENS_FOR_ETH_FEE_ABI,
1305
+ V3_EXACT_INPUT_SINGLE_ABI,
1306
+ V3_EXACT_INPUT_ABI,
1307
+ FOUR_MEME_V1_ABI,
1308
+ FOUR_MEME_V2_ABI
1309
+ ];
1310
+ for (const abi of candidates) {
1311
+ const decoded = tryDecodeCalldata(abi, action.data);
1312
+ if (decoded?.functionName) {
1313
+ return decoded.functionName;
1314
+ }
1315
+ }
1316
+ return "unknown";
1317
+ }
1278
1318
 
1279
1319
  // src/services/info.ts
1280
1320
  var import_viem5 = require("viem");
@@ -1716,25 +1756,6 @@ async function executeSwap(input) {
1716
1756
  args: [minOut, path, vault, deadline]
1717
1757
  })
1718
1758
  });
1719
- } else if (isNativeOut) {
1720
- actions.push({
1721
- target: tokenIn.address,
1722
- value: 0n,
1723
- data: (0, import_viem7.encodeFunctionData)({
1724
- abi: ERC20_ABI,
1725
- functionName: "approve",
1726
- args: [v2Router, amountIn]
1727
- })
1728
- });
1729
- actions.push({
1730
- target: v2Router,
1731
- value: 0n,
1732
- data: (0, import_viem7.encodeFunctionData)({
1733
- abi: SWAP_EXACT_TOKENS_FOR_ETH_ABI,
1734
- functionName: "swapExactTokensForETH",
1735
- args: [amountIn, minOut, path, vault, deadline]
1736
- })
1737
- });
1738
1759
  } else {
1739
1760
  actions.push({
1740
1761
  target: tokenIn.address,
@@ -1749,8 +1770,8 @@ async function executeSwap(input) {
1749
1770
  target: v2Router,
1750
1771
  value: 0n,
1751
1772
  data: (0, import_viem7.encodeFunctionData)({
1752
- abi: SWAP_EXACT_TOKENS_ABI,
1753
- functionName: "swapExactTokensForTokens",
1773
+ abi: SWAP_EXACT_TOKENS_FOR_TOKENS_FEE_ABI,
1774
+ functionName: "swapExactTokensForTokensSupportingFeeOnTransferTokens",
1754
1775
  args: [amountIn, minOut, path, vault, deadline]
1755
1776
  })
1756
1777
  });
package/dist/index.mjs CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  transferFromVault,
28
28
  unwrapWbnb,
29
29
  wrapBnb
30
- } from "./chunk-MPUPO5EJ.mjs";
30
+ } from "./chunk-TH3ENDDM.mjs";
31
31
 
32
32
  // src/index.ts
33
33
  import { Command as Command9 } from "commander";
package/dist/mcp.js CHANGED
@@ -978,10 +978,14 @@ function checkActionRecipientSafety(action, vault) {
978
978
  function policyRejectionHelp(reason, tokenId) {
979
979
  const consoleUrl = agentConsoleUrl(tokenId);
980
980
  const r = reason ?? "";
981
+ if (r.includes("Function not allowed"))
982
+ return { explanation: "The contract method selector is not enabled by the active DeFi policy configuration.", action: "Enable the required protocol pack or selector in Console > Safety, or use a supported transaction path.", consoleUrl };
981
983
  if (r.includes("Approve spender not allowed"))
982
984
  return { explanation: "The DEX router address is not in the approved spender whitelist.", action: "Contact the Agent owner to approve this router, or use a different DEX.", consoleUrl };
983
985
  if (r.includes("Target not allowed"))
984
986
  return { explanation: "The contract address is not in the DeFi target whitelist.", action: "Enable the corresponding DeFi Pack in Console > Safety, or contact the Agent owner.", consoleUrl };
987
+ if (r.includes("Receiver must be vault"))
988
+ return { explanation: "Swap output recipient must be the agent vault address enforced by ReceiverGuard.", action: "Retry with recipient/to set to the vault address, or use a supported flow that routes proceeds back to the vault.", consoleUrl };
985
989
  if (r.includes("Token not in whitelist"))
986
990
  return { explanation: "Token restriction is ON and this token is not whitelisted.", action: `Add the token to the whitelist or disable token restriction at: ${consoleUrl}`, consoleUrl };
987
991
  if (r.includes("Exceeds per-tx limit"))
@@ -1229,13 +1233,18 @@ function ensureRecipientSafe(result) {
1229
1233
  }
1230
1234
  }
1231
1235
  async function validateActionsOrThrow(policyClient, tokenId, actions) {
1232
- for (const action of actions) {
1236
+ for (const [index, action] of actions.entries()) {
1233
1237
  const sim = await policyClient.validate(tokenId, action);
1234
1238
  if (!sim.ok) {
1235
1239
  throw new SkillError(
1236
1240
  "POLICY_REJECTED",
1237
1241
  "Policy rejected transaction",
1238
1242
  {
1243
+ failedActionIndex: index,
1244
+ failedActionTarget: action.target,
1245
+ failedActionSelector: getActionSelector(action),
1246
+ failedActionFunction: getActionFunctionName(action),
1247
+ failedActionValue: action.value.toString(),
1239
1248
  reason: sim.reason,
1240
1249
  ...policyRejectionHelp(sim.reason, tokenId.toString())
1241
1250
  },
@@ -1255,6 +1264,37 @@ async function executeActions(policyClient, tokenId, actions) {
1255
1264
  const result = await policyClient.executeBatch(tokenId, actions, true);
1256
1265
  return { hash: result.hash };
1257
1266
  }
1267
+ function getActionSelector(action) {
1268
+ return action.data && action.data.length >= 10 ? action.data.slice(0, 10) : "0x";
1269
+ }
1270
+ function getActionFunctionName(action) {
1271
+ if (action.data === "0x") {
1272
+ return "nativeTransfer";
1273
+ }
1274
+ const candidates = [
1275
+ ERC20_ABI,
1276
+ WBNB_ABI,
1277
+ VTOKEN_ABI,
1278
+ VBNB_MINT_ABI,
1279
+ SWAP_EXACT_ETH_ABI,
1280
+ SWAP_EXACT_TOKENS_ABI,
1281
+ SWAP_EXACT_TOKENS_FOR_ETH_ABI,
1282
+ SWAP_EXACT_ETH_FOR_TOKENS_FEE_ABI,
1283
+ SWAP_EXACT_TOKENS_FOR_TOKENS_FEE_ABI,
1284
+ SWAP_EXACT_TOKENS_FOR_ETH_FEE_ABI,
1285
+ V3_EXACT_INPUT_SINGLE_ABI,
1286
+ V3_EXACT_INPUT_ABI,
1287
+ FOUR_MEME_V1_ABI,
1288
+ FOUR_MEME_V2_ABI
1289
+ ];
1290
+ for (const abi of candidates) {
1291
+ const decoded = tryDecodeCalldata(abi, action.data);
1292
+ if (decoded?.functionName) {
1293
+ return decoded.functionName;
1294
+ }
1295
+ }
1296
+ return "unknown";
1297
+ }
1258
1298
 
1259
1299
  // src/services/info.ts
1260
1300
  var import_viem5 = require("viem");
@@ -1696,25 +1736,6 @@ async function executeSwap(input) {
1696
1736
  args: [minOut, path, vault, deadline]
1697
1737
  })
1698
1738
  });
1699
- } else if (isNativeOut) {
1700
- actions.push({
1701
- target: tokenIn.address,
1702
- value: 0n,
1703
- data: (0, import_viem7.encodeFunctionData)({
1704
- abi: ERC20_ABI,
1705
- functionName: "approve",
1706
- args: [v2Router, amountIn]
1707
- })
1708
- });
1709
- actions.push({
1710
- target: v2Router,
1711
- value: 0n,
1712
- data: (0, import_viem7.encodeFunctionData)({
1713
- abi: SWAP_EXACT_TOKENS_FOR_ETH_ABI,
1714
- functionName: "swapExactTokensForETH",
1715
- args: [amountIn, minOut, path, vault, deadline]
1716
- })
1717
- });
1718
1739
  } else {
1719
1740
  actions.push({
1720
1741
  target: tokenIn.address,
@@ -1729,8 +1750,8 @@ async function executeSwap(input) {
1729
1750
  target: v2Router,
1730
1751
  value: 0n,
1731
1752
  data: (0, import_viem7.encodeFunctionData)({
1732
- abi: SWAP_EXACT_TOKENS_ABI,
1733
- functionName: "swapExactTokensForTokens",
1753
+ abi: SWAP_EXACT_TOKENS_FOR_TOKENS_FEE_ABI,
1754
+ functionName: "swapExactTokensForTokensSupportingFeeOnTransferTokens",
1734
1755
  args: [amountIn, minOut, path, vault, deadline]
1735
1756
  })
1736
1757
  });
package/dist/mcp.mjs CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  transferFromVault,
27
27
  unwrapWbnb,
28
28
  wrapBnb
29
- } from "./chunk-MPUPO5EJ.mjs";
29
+ } from "./chunk-TH3ENDDM.mjs";
30
30
 
31
31
  // src/mcp.ts
32
32
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shll-skills",
3
- "version": "6.0.2",
3
+ "version": "6.0.3",
4
4
  "description": "SHLL DeFi Agent - CLI + MCP Server for BSC",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -35,4 +35,4 @@
35
35
  "SKILL.md"
36
36
  ],
37
37
  "license": "MIT"
38
- }
38
+ }