← All sample reports
sample-org/contracts/FoundersToken.sol·187 LOC · scanned May 24, 2026, 4:08 PM
1 HIGH2 MED3 LOW4 INFO

Sample report — ERC-20 token launch

A realistic AEDSC report on a typical pre-launch ERC-20 token. 1 HIGH + 2 MED + 3 LOW + 4 INFO. Owner mint without timelock, missing zero-address checks, deprecated SafeMath.

Recommendation

Ship-blocker: the unbounded owner mint must move behind a 48h timelock before mainnet. The unchecked transfer in distribute() can break atomicity if USDT-style tokens are added later. Everything else is hardening.

  1. HIGHF-01 · centralization-risk + own-ruleFoundersToken.sol:112–118

    Owner can mint unlimited supply with no timelock

    The mint() function is callable by owner() at any time with no cap, no timelock, and no event log other than the standard ERC-20 Transfer. A compromised owner key drains holders to zero. This is the highest-impact and most-flagged finding on pre-launch ERC-20s in 2026 — Etherscan auto-flags it on the contract page.

    FoundersToken.solvulnerable
    function mint(address to, uint256 amount) external onlyOwner {
        _mint(to, amount);
    }
    suggested patch drop-in fix
    + uint256 public constant MAX_SUPPLY = 1_000_000_000 ether;
    + ITimelock public immutable timelock;
    - function mint(address to, uint256 amount) external onlyOwner {
    + function mint(address to, uint256 amount) external {
    +     require(msg.sender == address(timelock), "only timelock");
    +     require(totalSupply() + amount <= MAX_SUPPLY, "cap");
          _mint(to, amount);
      }
    Fix: Move mint behind a Timelock (OpenZeppelin's TimelockController, 48h minimum) and cap total supply with a hardcoded MAX_SUPPLY constant. Renounce mint authority after the launch allocation if the tokenomics allow.
    centralization-riskmissing-timelocketherscan-flag
  2. MEDIUMF-02 · unchecked-transferFoundersToken.sol:143

    Unchecked return value on token.transfer in distribute()

    distribute() calls token.transfer(recipient, amount) but discards the boolean return. Standard ERC-20s (USDT, USDC on certain forks) return false rather than reverting on failure. A silent fail leaves the contract in an inconsistent state.

    FoundersToken.solvulnerable
    token.transfer(recipient, amount);
    suggested patch drop-in fix
    - token.transfer(recipient, amount);
    + token.safeTransfer(recipient, amount);
    Fix: Wrap with SafeERC20.safeTransfer or require(token.transfer(...)) explicitly.
    unchecked-transfererc20
  3. MEDIUMF-03 · missing-zero-checkFoundersToken.sol:76

    Missing zero-address check on setTreasury()

    setTreasury(address _treasury) accepts address(0) silently. If called by accident, future fee streams are burned permanently.

    FoundersToken.solvulnerable
    function setTreasury(address _treasury) external onlyOwner {
        treasury = _treasury;
    }
    Fix: Add require(_treasury != address(0), 'zero addr').
    missing-zero-check
  4. LOWF-04 · external-functionFoundersToken.sol:55, 102

    Public function should be external

    Two public functions are never called internally. external is cheaper because args read from calldata.

    FoundersToken.solvulnerable
    function transfer(address to, uint256 amount) public { ... }
    Fix: Change public to external for both functions.
    gas-optimization
  5. LOWF-05 · timestampFoundersToken.sol:163

    Use of block.timestamp in scheduling

    vestingStart uses block.timestamp. Miners can shift this by ±15 seconds. Not exploitable here but flagged for awareness.

    FoundersToken.solvulnerable
    uint256 vestingStart = block.timestamp;
    Fix: Accept for vesting (drift is bounded). Document the ±15s tolerance in the contract NatSpec.
    timestamp
  6. LOWF-06 · pragmaFoundersToken.sol:1

    Floating pragma version

    pragma solidity ^0.8.20 lets a future bug-fix release compile with subtly different behavior. Pin to a single version.

    FoundersToken.solvulnerable
    pragma solidity ^0.8.20;
    Fix: pragma solidity 0.8.24;
    pragma
  7. INFOF-07 · deprecatedFoundersToken.sol:4

    SafeMath imported but unused (Solidity 0.8 has built-in checks)

    SafeMath was needed pre-0.8. On 0.8+, all arithmetic reverts on overflow. The import adds 2 KB of bytecode for nothing.

    FoundersToken.solvulnerable
    import "@openzeppelin/contracts/utils/math/SafeMath.sol";
    Fix: Remove the import.
    deprecated
  8. INFOF-08 · natspec-coverageFoundersToken.sol:various

    No NatSpec on public functions

    Etherscan, RPC indexers, and integrators rely on NatSpec for human-readable transaction summaries. None are present.

    FoundersToken.solvulnerable
    // (no NatSpec on any function)
    Fix: Add /// @notice + /// @param for every external function. Standard pattern: OpenZeppelin's contracts.
    doc
  9. INFOF-09 · event-coverageFoundersToken.sol:44–49

    Constructor sets owner but emits no event

    Setting initial state in the constructor without an OwnershipTransferred event makes off-chain indexing harder.

    FoundersToken.solvulnerable
    owner = msg.sender;
    Fix: Inherit from OpenZeppelin's Ownable (emits the event for you).
    events
  10. INFOF-10 · magic-numberFoundersToken.sol:129

    Magic number 100 for fee basis points

    100 appears in fee logic without a named constant. Risk of confusion with basis-point math.

    FoundersToken.solvulnerable
    fee = amount * 100 / 10000;
    Fix: uint16 public constant FEE_BPS = 100; // 1.00%
    style

Get one of these for your contract.

Free for the first scan. Founder Pro €29/mo with a 7-day free trial unlocks unlimited scans, priority queue, and a human triaging every report — rate locked for life.