Improper Free Memory Pointer Management in Inline Assembly Causes Memory Corruption
Under Solidity’s memory model, the free memory pointer stored at slot 0x40 must always point to the next unused memory location. When inline assembly temporarily uses memory starting at the free memory pointer, it is expected to advance or restore this pointer so that subsequent allocations do not overlap.
In the codebase, multiple internal functions load the free memory pointer with mload(0x40) and write temporary data at that location but never update the pointer afterward. This leaves the free memory pointer pointing to already-used memory, allowing later Solidity or assembly allocations to overwrite or be overwritten, leading to silent memory corruption and undefined behavior.
The same pattern appears in _approve, _allowance, _mint, _burn, _spendAllowance, and _balanceOf.
Likelihood:
Occurs during execution paths that call multiple inline-assembly-based internal functions which rely on the free memory pointer and are followed by Solidity-level memory allocations.
Occurs when compiler-generated code or another assembly block allocates memory after one of these functions has written to ptr without advancing 0x40.
Impact:
Silent memory corruption that can alter return values, event payloads, or ABI-encoded data.
Undefined and non-deterministic behavior that may surface only under specific call sequences, making issues hard to detect and debug.
< this test does not work but it shows the kind of bug which can appears >
The following test demonstrates how failing to advance the free memory pointer can corrupt subsequent Solidity memory allocations. A Solidity function allocates memory for strings before and after an inline-assembly call that mismanages 0x40. The second allocation may reuse already-written memory and return corrupted data.
Explanation
The _mint function uses ptr := mload(0x40) for temporary storage but does not advance the pointer. When name() or symbol() is called afterward, Solidity allocates memory starting from the same pointer, potentially overwriting data and returning incorrect results.
This test can fail unpredictably depending on compiler output and execution order, which is characteristic of free-memory-pointer misuse.
Advance the free memory pointer in every function that uses ptr := mload(0x40) for temporary memory, ensuring the pointer always references unused memory.
Example fix for _transfer(address from, address to, uint256 value):
The same adjustment should be applied consistently in _approve, _allowance, _mint, _burn, _spendAllowance, and _balanceOf wherever temporary memory is allocated using the free memory pointer.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.
The contest is complete and the rewards are being distributed.