Skip to content

Latest commit

 

History

History
77 lines (53 loc) · 3.09 KB

File metadata and controls

77 lines (53 loc) · 3.09 KB

Hidden Fossilized Dragonfly

High

create() is vulnerable to front running

Summary

The create function allows users to create vaults with specific parameters

function create(string memory _name, string memory _symbol, address _asset, uint96 _salt)
        external
        returns (address _vault)
    {

These values are visible on the mempool and could be front-run by malicious actors.

Root Cause

https://github.com/sherlock-audit/2025-01-peapods-finance/blob/main/contracts/contracts/LendingAssetVaultFactory.sol#L20

The vulnerability arises due to the predictable nature of the salt parameter _salt used in the CREATE2 address computation. Since _salt is directly supplied by the caller and the function does not rely or use any dynamic, unpredictable factors (e.g., block.timestamp, or msg.sender an attacker can front run transactions to create() with exact parameters and higher gas fees ultimately now in control of the vault.

function _getFullSalt(uint96 _salt) internal view returns (uint256) {
        return uint256(uint160(address(this))) + _salt;
    }

Attack Path

  1. Alice wants to deploy a vault using parameters Doge dog 0xAddressOfDogeToken 234678889
  2. Attacker sees Alice's transaction on the mempool
  3. Attacker sends a transaction with the exact same parameters (Doge dog 0xAddressOfDogeToken 234678889)
  4. Attacker now owns vault address

Impact

Front running transactions to create can lead to various security risks

  • Funds Loss – If users expect a vault at a known address, the attacker could deploy a malicious vault with selfdestruct functionality , call selfdestruct() replace deployed vault with malicious code which can be used to drain user funds.
  • Stealing Alice’s Vault Name & Symbol – The attacker can deploy a vault with the same branding(name and symbol), misleading users.
  • DOS: Locking Out Legitimate Users – If Alice intended to launch a vault at a specific CREATE2 address, she is now locked out of that address.

PoC

   function testcreateFrontRunning() public {
        address attacker = address(0x2);
        string memory VAULT_NAME = "Doge Vault";   //Alice wants to create Doge Vault.
        string memory VAULT_SYMBOL = "DOGE";
        uint96 SALT = 6;

        asset.transfer(attacker, 10000 * 10 ** 18);
        
        address expectedVault = factory.getNewCaFromParams(VAULT_NAME, VAULT_SYMBOL, address(asset), SALT);

        // Attacker front-runs the deployment
        vm.startPrank(attacker);
        asset.approve(address(factory), 1000);
        address attackerVault = factory.create(VAULT_NAME, VAULT_SYMBOL, address(asset), SALT);
        vm.stopPrank();

        vm.startPrank(user);
        vm.expectRevert();  //user can no longer create vault due to collision error.
        factory.create(VAULT_NAME, VAULT_SYMBOL, address(asset), SALT);
        vm.stopPrank();
        assert(attackerVault == expectedVault );
        
    }

Mitigation

Update _getFullSalt() to use a dynamic factors during computation of _salt such as block.timestamp or msg.sender