Skip to content
Open
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 44 additions & 3 deletions contracts/finance/VestingWallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,36 @@ contract VestingWallet is Context, Ownable {
* @dev Calculates the amount of ether that has already vested. Default implementation is a linear vesting curve.
*/
function vestedAmount(uint64 timestamp) public view virtual returns (uint256) {
return _vestingSchedule(address(this).balance + released(), timestamp);
uint256 balance = address(this).balance;
uint256 releasedAmount = released();

// Check for overflow and cap at type(uint256).max
uint256 totalAllocation = balance;
if (totalAllocation <= type(uint256).max - releasedAmount) {
totalAllocation += releasedAmount;
} else {
totalAllocation = type(uint256).max;
}

return _vestingSchedule(totalAllocation, timestamp);
}

/**
* @dev Calculates the amount of tokens that has already vested. Default implementation is a linear vesting curve.
*/
function vestedAmount(address token, uint64 timestamp) public view virtual returns (uint256) {
return _vestingSchedule(IERC20(token).balanceOf(address(this)) + released(token), timestamp);
uint256 balance = IERC20(token).balanceOf(address(this));
uint256 releasedAmount = released(token);

// Check for overflow and cap at type(uint256).max
uint256 totalAllocation = balance;
if (totalAllocation <= type(uint256).max - releasedAmount) {
totalAllocation += releasedAmount;
} else {
totalAllocation = type(uint256).max;
}

return _vestingSchedule(totalAllocation, timestamp);
}

/**
Expand All @@ -153,7 +175,26 @@ contract VestingWallet is Context, Ownable {
} else if (timestamp >= end()) {
return totalAllocation;
} else {
return (totalAllocation * (timestamp - start())) / duration();
uint256 timeElapsed = timestamp - start();
uint256 durationValue = duration();

// Handle edge case where timeElapsed is 0
if (timeElapsed == 0) {
return 0;
}

// Check for overflow in multiplication
if (totalAllocation <= type(uint256).max / timeElapsed) {
return (totalAllocation * timeElapsed) / durationValue;
} else {
// If multiplication would overflow, use a different approach
// Calculate the ratio first to avoid overflow
return
(totalAllocation / durationValue) *
timeElapsed +
((totalAllocation % durationValue) * timeElapsed) /
durationValue;
}
}
}
}
Loading