The BeatToken contract has no maximum supply limits or minting rate controls, allowing the festival contract to mint unlimited tokens and potentially cause severe inflation.
function mint(address to, uint256 amount) external {
require(msg.sender == festivalContract, "Only_Festival_Mint");
@> _mint(to, amount);
@>
@>
}
function burnFrom(address from, uint256 amount) external {
require(msg.sender == festivalContract, "Only_Festival_Burn");
@> _burn(from, amount);
}
function testUnlimitedMinting() public {
vm.startPrank(address(festival));
uint256 excessiveAmount = type(uint256).max / 2;
beatToken.mint(attacker, excessiveAmount);
assert(beatToken.balanceOf(attacker) == excessiveAmount);
assert(beatToken.totalSupply() == excessiveAmount);
vm.stopPrank();
vm.startPrank(address(festival));
for(uint i = 0; i < 1000; i++) {
beatToken.mint(address(uint160(i + 1000)), 1000000 ether);
}
assert(beatToken.totalSupply() > 1000000000 ether);
vm.stopPrank();
}
+ uint256 public constant MAX_TOTAL_SUPPLY = 100_000_000 ether; // 100M tokens max
+ uint256 public constant MAX_MINT_PER_TX = 10_000 ether; // Per transaction limit
+ mapping(address => uint256) public dailyMinted; // Rate limiting
+ mapping(address => uint256) public lastMintDay; // Rate limiting
function mint(address to, uint256 amount) external {
require(msg.sender == festivalContract, "Only_Festival_Mint");
+ require(to != address(0), "Cannot mint to zero address");
+ require(amount > 0, "Amount must be greater than 0");
+ require(amount <= MAX_MINT_PER_TX, "Exceeds per-transaction limit");
+ require(totalSupply() + amount <= MAX_TOTAL_SUPPLY, "Exceeds maximum supply");
+
+ // Daily rate limiting per recipient
+ uint256 currentDay = block.timestamp / 1 days;
+ if (lastMintDay[to] < currentDay) {
+ dailyMinted[to] = 0;
+ lastMintDay[to] = currentDay;
+ }
+ require(dailyMinted[to] + amount <= MAX_MINT_PER_TX * 10, "Daily mint limit exceeded");
+ dailyMinted[to] += amount;
_mint(to, amount);
+ emit TokensMinted(to, amount, totalSupply());
}
+ function burnFrom(address from, uint256 amount) external {
+ require(msg.sender == festivalContract, "Only_Festival_Burn");
+ require(amount > 0, "Amount must be greater than 0");
+ require(balanceOf(from) >= amount, "Insufficient balance to burn");
+
_burn(from, amount);
+ emit TokensBurned(from, amount, totalSupply());
+ }
+ event TokensMinted(address indexed to, uint256 amount, uint256 newTotalSupply);
+ event TokensBurned(address indexed from, uint256 amount, uint256 newTotalSupply);