Presale is a complete mini-protocol for managing the launch of a new ERC20 token, FlyToken. It allows users to buy tokens before they are listed on a DEX, across 3 phases with different prices and time limits, fee and blacklist mechanisms, with secure ETH/USD price conversion via Chainlink. It integrates several smart contracts (Presale, FlyToken, MockAggregator, MockTreasury) working together, everything fully covered by unit, fuzzing, invariant, and mainnet-fork tests on Arbitrum One.
- πͺ New ERC20 Token: FlyToken is minted and allocated for sale during the presale.
- πͺ Buy with Stablecoins: purchase FlyToken using USDT or USDC.
- β‘ Buy with ETH: ETH payments are automatically converted to USD using Chainlink oracles.
- π Chainlink oracle: data feed USDT/ETH price.
- π Phased Presale: configurable supply, price, and duration for each phase.
- π« Blacklist Mechanism: owner can restrict malicious addresses.
- π‘οΈ Claim Period: users claim tokens after the presale ends.
- πΈ Fee System: protocol collects fees in both ERC20 and ETH.
- π Fee Withdrawal: only the owner can withdraw accumulated fees (ERC20 or ETH) after the presale ends.
- π Emergency Withdraw: owner can rescue tokens or ETH if needed.
- πͺ SafeERC20: all token transfers use
SafeERC20to handle non-standard ERC20 implementations safely - π Access Control:
onlyOwnermodifier restricts privileged functions (blacklist,withdrawFees,emergencyWithdraw, etc.) - π‘οΈ Reentrancy Protection: critical functions (
buyWithTokens,buyWithETH,claimTokens,withdrawFees) are protected with OpenZeppelinβsReentrancyGuard - π’ Event Logging: all state mutations emit events (
TokensBought,ETHBought,TokensClaimed,FeeWithdrawn, etc.) for transparency and off-chain monitoring - π§© CEI Pattern: all external functions follow the Checks-Effects-Interactions pattern to minimize vulnerabilities
- π Chainlink Oracle: secure ETH/USD price feed integration prevents manipulation of ETH payments
- π§ͺ Testing: complete unit tests, fuzzing test, and mocks ensure robustness
- π Forked Mainnet Testing: validated on Arbitrum One with real USDT, USDC, and Chainlink feeds
Complete suite test using Foundry, with forked Arbitrum RPC for integration and two mock contracts (MockAggregator.sol for the Chainlink price feed and MockTreasury.sol for ETH/stablecoin receiving).
The suite includes happy paths, negative paths, edge cases, and fuzzing tests to ensure robustness.
- β
buyWithTokens()β happy path, invalid token, zero amount, blacklist, presale inactive, max supply, phase changes - β
buyWithETH()β happy path, zero amount, blacklist, presale inactive, oracle integration, max supply - β
claimTokens()β happy path, before claim period, nothing to claim, double claim - β
blacklist()/unBlacklist()β owner only, reverts for non-owners - β
withdrawFees()β ERC20 and ETH fees, reverts if not owner or before claim period - β
emergencyWithdrawTokens()β owner only, reverts for non-owners - β
emergencyWithdrawETH()β owner only, reverts for non-owners - β Fuzzing tests for token and ETH purchases
Run tests with:
forge test --fork-url https://arb1.arbitrum.io/rpc --vvvv --match-test test_buyWithTokens- βοΈ Solidity (
^0.8.24) β smart contract programming language - π§ͺ Foundry β framework for development, testing, fuzzing, invariants and deployment
- π OpenZeppelin Contracts β
ERC20,Ownable,ReentrancyGuard,SafeERC20 - π Chainlink Oracles β secure ETH/USD price feed integration
- π Arbitrum One β mainnet fork for realistic testing with live USDT, USDC and Chainlink feeds
- π οΈ Mocks β custom
MockAggregatorandMockTreasurycontracts for local testing
This project is licensed under the MIT License.