What's actually enforced in code
Trading-enabled gate
Before enableTrading() is called, only fee-excluded addresses (the owner, the token contract itself) can send or receive $SNOWBALL. That's the window for seeding PancakeSwap liquidity without a bot front-running the first block of public trading. The switch is one-way: it cannot be turned back off.
Reentrancy guard, proven with a malicious mock
swapAndBurn is wrapped in OpenZeppelin's ReentrancyGuard. The test suite includes a token whose burn() tries to call feeRouter.swapAndBurn() again mid-call (test/mocks/MaliciousToken.sol). The outer call reverts, proving the guard actually holds rather than just trusting the library.
Slippage bound: what it protects against, and what it doesn't
Every swap leg fetches a live quote via router.getAmountsOut() and requires the actual output land within maxSlippageBps (3% default, owner-capped at 20%) of that quote.
This is not full sandwich-attack protection
swapAndBurn is also gated (below): keep it owner/keeper-only until the pool has real depth, and submit calls through a private/MEV-protected RPC once it's opened up.Why swapAndBurn isn't permissionless from day one
onlyKeeperOrOwner restricts swapAndBurn to the owner or a designated keeper address while permissionlessSwaps is false (the default). The owner opens it up later via setPermissionlessSwaps(true) once the pool has enough depth that the slippage bound above is a meaningful protection rather than a formality.
Ownership
All three contracts use OpenZeppelin's Ownable2Step: transferring ownership requires the new owner to explicitly accept, so a mistyped address can't accidentally lock the contracts forever.