global-property-implem…
**Role**: Implement global properties into Properties.sol, wire ghost variables into Base.sol, and populate Snapshots.sol. These are checked by the fuzzer…
**Role**: Implement specific (per-handler) properties into Properties.sol and wire ghost updates + snapshot calls + property assertions into handler files.
$ npx -y skills add pashov/skills --agent claude-codeHow it fires
How this agent gets triggered: by you, by Claude, or both.
Context preview
The summary Claude sees to decide when to auto-load this agent.
**Role**: Implement specific (per-handler) properties into Properties.sol and wire ghost updates + snapshot calls + property assertions into handler files.
**Role**: Implement specific (per-handler) properties into Properties.sol and wire ghost updates + snapshot calls + property assertions into handler files.
**Spawn config**: `general-purpose` agent, `model: "{AGENT_MODEL}"` (see SKILL.md "Subagent Model" section — defaults to `sonnet`, `opus` under `--max`). Spawned in parallel with Agent 7A.
---
You implement SPECIFIC properties and wire all ghost/snapshot/property calls into the handler files.
These rules expand on the general property implementation instructions in `property-generation.md` with specifics for the per-handler properties and wiring.
Specific properties are `internal` functions called at the end of relevant handlers. They check postconditions for specific operations.
Every property function you write MUST have its Spec ID as the first thing in its natspec, on its own line, in this exact form:
/// @notice SP-NN: <one-line description>
function property_<name>() internal { ... }The `SP-NN:` token (with the colon) is how `/fizz-convert` and future runs locate the existing implementation of a Spec ID for re-generation or deletion. Without it, automation cannot reconcile the spec with the code. This is a hard requirement, not a style preference.
// ――――――――――――――――――― Specific properties ――――――――――――――――――――
// These properties must hold after specific function calls
// They MUST BE INTERNAL and called at the end of the relevant handlers
function property_depositIncreasesShares() internal {
gt(
stateAfter.vaultTotalSupply,
stateBefore.vaultTotalSupply,
"Deposit did not increase total supply"
);
}
function property_withdrawDecreasesAssets() internal {
lt(
stateAfter.vaultTotalAssets,
stateBefore.vaultTotalAssets,
"Withdraw did not decrease total assets"
);
}
function property_roundTripNoFreeValue(uint256 balanceBefore, uint256 balanceAfter) internal {
lte(
balanceAfter,
balanceBefore,
"Round-trip created free value"
);
}Call specific properties at the END of the handler, AFTER ghost updates and snapshotAfter():
function vault_withdraw_clamped(uint256 assets) public {
// ... clamping logic ...
vault_withdraw(assets);
}
function vault_withdraw(uint256 assets) public asActor {
snapshotBefore();
vm.prank(address(actor));
vault.withdraw(assets);
snapshotAfter();
ghosts.totalWithdrawn += assets;
property_withdrawDecreasesAssets();
}For round-trip and liveness checks that need to execute a multi-step sequence and then revert (no state pollution), implement them as handler-level functions that test the sequence inline:
/// @notice Liveness: every actor with balance > 0 can withdraw
function property_allCanWithdraw() public {
for (uint256 i; i < NUMBER_OF_ACTORS; i++) {
uint256 bal = vault.balanceOf(address(actors[i]));
if (bal > 0) {
vm.prank(address(actors[i]));
try vault.redeem(bal, address(actors[i]), address(actors[i])) {}
catch { t(false, "Liveness: user cannot withdraw"); }
}
}
}Note: Stateless properties are properties that must not pollute state, as they are extreme cases that will make subsequent calls revert. For stateless properties, use `try/catch` patterns or implement them as view-approximations where possible. For true round-trip tests, consider using `FoundryTester.sol` for Foundry-based scenario tests.
For every `SP-*` property:
Match by exact ID. Do NOT renumber, reorder, or rewrite other lines.
Return: `DONE: X specific properties implemented (Y marked [x], Z marked [-] as skipped/TODO). Handler wiring: A handlers updated with ghost updates, B with snapshot calls, C with property assertions.`
AI-powered Solidity security skills — built by Pashov Audit Group. Supported AI Platforms:
Repo: pashov/skills
**Role**: Implement global properties into Properties.sol, wire ghost variables into Base.sol, and populate Snapshots.sol. These are checked by the fuzzer…
**Discovery approach**: Think like an attacker. What would maximize extracted value? What sequence breaks liveness? What edge conditions create exploitable…
**Discovery approach**: For every aggregate/total variable, write a "sum of individual parts = tracked whole" property. This is the #1 bug-finding pattern in…
**Discovery approach**: Auto-detect the protocol type from PROTOCOL_CONTEXT, then apply battle-tested property templates specific to that protocol category.
**Discovery approach**: For every paired operation and conversion function, verify that round-trips don't create value and rounding always favors the protocol.
**Discovery approach**: Map the state machine, verify operation postconditions, check paired-operation symmetry, and ensure entity counts stay consistent.