Beginner FriendlyFoundryNFT
100 EXP
View results
Submission Details
Severity: medium
Invalid

Initializer function in LoveToken.sol can be called multiple times.

Summary

The initVault function is meant to be called once at the launch of the protocol. However, it can be called as many times as wanted. To fix, create a way to limit the function to only being called once per airdrop and staking vault. Or use OpenZepplein's Initializable.sol. To fix, add boolean state variables originally set to false for both the airdrop and vault contracts. Have these bools set to true once they are called.

Vulnerability Details

/// @notice Called at the launch of the protocol.
/// @notice Will distribute all the supply to Airdrop and Staking Contract.
function initVault(address managerContract) public {
if (msg.sender == airdropVault) {
_mint(airdropVault, 500_000_000 ether);
approve(managerContract, 500_000_000 ether);
emit AirdropInitialized(managerContract);
} else if (msg.sender == stakingVault) {
_mint(stakingVault, 500_000_000 ether);
approve(managerContract, 500_000_000 ether);
emit StakingInitialized(managerContract);
} else revert LoveToken__Unauthorized();
}

Nothing prevents this function from being called multiple times accept for the goodwill of the airdropVault and the stakingVault.

Impact

The initVault() function can be called multiple times to inflate the balance of either the airdropVault or the stakingVault.

function testMultipleinitVault() public {
    soulmate = new Soulmate();
    loveToken = new LoveToken(ISoulmate(address(soulmate)),  address(this), address(this));

    assertEq(0, loveToken.balanceOf(address(this)));
    
    loveToken.initVault(address(this));
    assertEq(500_000_000 ether, loveToken.balanceOf(address(this)));

    loveToken.initVault(address(this));
    assertEq(1_000_000_000 ether, loveToken.balanceOf(address(this)));

    loveToken.initVault(address(this));
    assertEq(1_500_000_000 ether, loveToken.balanceOf(address(this)));
}

Tools Used

Foundry

Recommendations

/// @notice Called at the launch of the protocol.
/// @notice Will distribute all the supply to Airdrop and Staking Contract.
function initVault(address managerContract) public {
    if (msg.sender == airdropVault) {
        require(wasAirdropVaultInit == false, "Airdrop Vault Already Initialized");

        _mint(airdropVault, 500_000_000 ether);
        approve(managerContract, 500_000_000 ether);
        emit AirdropInitialized(managerContract);

        wasAirdropVaultInit = true;

    } else if (msg.sender == stakingVault) {
        require(wasStakingVaultInit == false, "Staking Vault Already Initialized");

        _mint(stakingVault, 500_000_000 ether);
        approve(managerContract, 500_000_000 ether);
        emit StakingInitialized(managerContract);

        wasStakingVaultInit = true;
    } else revert LoveToken__Unauthorized();
}
Updates

Lead Judging Commences

0xnevi Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Other
sungyuk1 Submitter
over 1 year ago
sungyuk1 Submitter
over 1 year ago

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.