基于 SOC 职业分类
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/mingdw/sapmall --skill solidity-development-patterns命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
Propagate new fields through the 5-file chain when modifying sys_chain_network table.
Synchronize frontend TypeScript types with backend Go API changes. Ensures all 4 files in the chain are updated when adding/modifying fields.
Migrate Font Awesome and Ant Design Icons to Lucide React across all frontend apps.
| name | solidity-development-patterns |
| description | Common Solidity/Hardhat patterns and pitfalls for Sapphire Mall smart contracts. |
Maximum 3 indexed parameters per event.超过编译报错 More than 3 indexed arguments for event.
// ✅ Correct (3 indexed max)
event PaymentPaid(
bytes32 indexed intentId,
address indexed buyer,
uint256 amount
);
// ❌ Incorrect (4 indexed)
event PaymentPaid(
bytes32 indexed intentId,
address indexed buyer,
address indexed seller,
uint256 amount
);
@openzeppelin/contracts-upgradeable@^5.6.1 no longer exports utils/ReentrancyGuardUpgradeable.sol.
Solution: Use custom reentrancy guard or non-upgradeable ReentrancyGuard.
// Before (OZ v4)
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
// After (OZ v5)
// Option 1: Custom guard
modifier nonReentrant() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
// Option 2: Non-upgradeable
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
.call()Solidity forbids .call() in view functions. Use .staticcall():
// ❌ Incorrect
function getTokenBalance(address token) public view returns (uint256) {
(bool success, bytes memory data) = token.call(
abi.encodeWithSignature("balanceOf(address)", address(this))
);
// ...
}
// ✅ Correct
function getTokenBalance(address token) public view returns (uint256) {
(bool success, bytes memory data) = token.staticcall(
abi.encodeWithSignature("balanceOf(address)", address(this))
);
// ...
}
_disableInitializers() Blocks TestingContracts with _disableInitializers() in constructor cannot call initialize() on implementation.
Error: 0xf92ee8a9 = InvalidInitialization()
Solution for tests: Use hardhat_setStorageAt RPC to reset initialized slot.
// OZ v5 uses ERC-7201 namespaced storage
// Slot: 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00
await network.provider.send("hardhat_setStorageAt", [
contractAddress,
"0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00",
"0x0000000000000000000000000000000000000000000000000000000000000000",
]);
string indexed params stored as keccak256 hashes — original string cannot be recovered.
// Original string not in logs
event OrderCreated(string indexed intentId, address buyer);
// intentId in logs = keccak256("order-123")
Solution: Match against database records by comparing hashes.
indexed for filtering (max 3)indexed for log filteringbytes32 for IDs instead of string (gas efficient)npx tsx --test instead of toolboxcontract/