Skip to content

Commit

Permalink
fix: Liquidity deposits via addLiquidityAndStake are vulnerable to sa…
Browse files Browse the repository at this point in the history
…ndwich attack (#169)

fix: Liquidity deposits via addLiquidityAndStake are vulnerable to sandwich attacks
  • Loading branch information
andresaiello authored Aug 20, 2024
1 parent a6f3d99 commit 03f8b9a
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ contract RewardDistributor is StakingRewards {
systemContract = SystemContract(systemContract_);
}

function _addLiquidity(uint256 tokenAmountA, uint256 tokenAmountB) internal returns (uint256) {
function _addLiquidity(
uint256 tokenAmountA,
uint256 tokenAmountB,
uint amountAMin,
uint amountBMin
) internal returns (uint256) {
bool transfer = stakingTokenA.transferFrom(msg.sender, address(this), tokenAmountA);
if (!transfer) revert TransferFailed();
bool approve = stakingTokenA.approve(systemContract.uniswapv2Router02Address(), 0);
Expand All @@ -62,8 +67,8 @@ contract RewardDistributor is StakingRewards {
address(stakingTokenB),
tokenAmountA,
tokenAmountB,
0,
0,
amountAMin,
amountBMin,
address(this),
block.timestamp + MAX_DEADLINE
);
Expand Down Expand Up @@ -91,7 +96,12 @@ contract RewardDistributor is StakingRewards {
return (otherTokenReserve * amount) / tokenReserve;
}

function addLiquidityAndStake(address tokenAddress, uint256 amount) external nonReentrant {
function addLiquidityAndStake(
address tokenAddress,
uint256 amount,
uint amountAMin,
uint amountBMin
) external nonReentrant {
if (amount == 0) revert ZeroStakeAmount();
address otherTokenAddress = address(stakingTokenA) == tokenAddress
? address(stakingTokenB)
Expand All @@ -110,7 +120,7 @@ contract RewardDistributor is StakingRewards {

lastDeposit[msg.sender] = block.timestamp;
unlockTokensAt[msg.sender] = type(uint256).max;
uint256 LPTokenAmount = _addLiquidity(amount, otherTokenAmount);
uint256 LPTokenAmount = _addLiquidity(amount, otherTokenAmount, amountAMin, amountBMin);
_stakeFromContract(LPTokenAmount);
}

Expand Down
4 changes: 2 additions & 2 deletions packages/zevm-app-contracts/test/LiquidityIncentives.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ describe("LiquidityIncentives tests", () => {
await ZRC20Contract.connect(signer).approve(rewardDistributorContract.address, amount);
await ZETA_ERC20.connect(signer).approve(rewardDistributorContract.address, zetaNeeded);

return await rewardDistributorContract.connect(signer).addLiquidityAndStake(ZRC20Contract.address, amount);
return await rewardDistributorContract.connect(signer).addLiquidityAndStake(ZRC20Contract.address, amount, 0, 0);
};

const stakeZETA = async (signer: SignerWithAddress, amount: BigNumber) => {
Expand All @@ -54,7 +54,7 @@ describe("LiquidityIncentives tests", () => {
await ZRC20Contract.connect(signer).approve(rewardDistributorContract.address, amount);
await ZETA_ERC20.connect(signer).approve(rewardDistributorContract.address, zetaNeeded);

return await rewardDistributorContract.connect(signer).addLiquidityAndStake(ZETA_ERC20.address, zetaNeeded);
return await rewardDistributorContract.connect(signer).addLiquidityAndStake(ZETA_ERC20.address, zetaNeeded, 0, 0);
};

beforeEach(async () => {
Expand Down
6 changes: 3 additions & 3 deletions packages/zevm-app-contracts/test/MultipleOutput.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ describe("ZetaSwap tests", () => {
zetaMultiOutputContract = (await Factory.deploy(systemContract.address)) as ZetaMultiOutput;
await zetaMultiOutputContract.deployed();

zetaMultiOutputContract.registerDestinationToken(ZRC20Contracts[0].address);
zetaMultiOutputContract.registerDestinationToken(ZRC20Contracts[1].address);
zetaMultiOutputContract.registerDestinationToken(ZRC20Contracts[2].address);
await zetaMultiOutputContract.registerDestinationToken(ZRC20Contracts[0].address);
await zetaMultiOutputContract.registerDestinationToken(ZRC20Contracts[1].address);
await zetaMultiOutputContract.registerDestinationToken(ZRC20Contracts[2].address);
});

describe("ZetaMultiOutput", () => {
Expand Down

0 comments on commit 03f8b9a

Please sign in to comment.