From 306f09ffb81fba322f5c8dc1269033289586f5db Mon Sep 17 00:00:00 2001 From: Sarang Parikh Date: Fri, 6 May 2022 20:16:32 +0400 Subject: [PATCH 1/6] ssaf-03 and ssaf-04 --- contracts/base/FuroVesting.sol | 58 +++++++++++++-------------- contracts/interfaces/IFuroVesting.sol | 12 +++--- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/contracts/base/FuroVesting.sol b/contracts/base/FuroVesting.sol index 12b7295..6720b7a 100644 --- a/contracts/base/FuroVesting.sol +++ b/contracts/base/FuroVesting.sol @@ -59,8 +59,8 @@ contract FuroVesting is uint32 cliffDuration, uint32 stepDuration, uint32 steps, - uint128 cliffAmount, - uint128 stepAmount, + uint128 cliffShares, + uint128 stepShares, bool fromBentoBox ) external @@ -73,7 +73,7 @@ contract FuroVesting is address(token), msg.sender, address(this), - cliffAmount + (stepAmount * steps), + cliffShares + (stepShares * steps), fromBentoBox ); @@ -87,8 +87,8 @@ contract FuroVesting is cliffDuration: cliffDuration, stepDuration: stepDuration, steps: steps, - cliffAmount: cliffAmount, - stepAmount: stepAmount, + cliffShares: cliffShares, + stepShares: stepShares, claimed: 0 }); @@ -101,8 +101,8 @@ contract FuroVesting is cliffDuration, stepDuration, steps, - cliffAmount, - stepAmount, + cliffShares, + stepShares, fromBentoBox ); } @@ -135,9 +135,10 @@ contract FuroVesting is function stopVesting(uint256 vestId, bool toBentoBox) external override { Vest memory vest = vests[vestId]; if (vest.owner != msg.sender) revert NotOwner(); - uint256 canClaim = _balanceOf(vest) - vest.claimed; - uint256 returnAmount = (vest.cliffAmount + - (vest.steps * vest.stepAmount)) - canClaim; + uint256 amountVested = _balanceOf(vest); + uint256 canClaim = amountVested - vest.claimed; + uint256 returnShares = (vest.cliffShares + + (vest.steps * vest.stepShares)) - amountVested; _transferToken( address(vest.token), address(this), @@ -150,12 +151,12 @@ contract FuroVesting is address(vest.token), address(this), msg.sender, - returnAmount, + returnShares, toBentoBox ); emit CancelVesting( vestId, - returnAmount, + returnShares, canClaim, vest.token, toBentoBox @@ -192,7 +193,7 @@ contract FuroVesting is passedSinceCliff / vest.stepDuration ); - claimable = vest.cliffAmount + (vest.stepAmount * stepPassed); + claimable = vest.cliffShares + (vest.stepShares * stepPassed); } function updateOwner(uint256 vestId, address newOwner) external override { @@ -206,28 +207,27 @@ contract FuroVesting is address token, address from, address to, - uint256 amount, + uint256 shares, bool fromBentoBox ) internal returns (uint256 depositedShares) { - if (token == wETH && address(this).balance >= amount) { - (, depositedShares) = bentoBox.deposit{value: amount}( - address(0), - from, - to, - amount, - 0 - ); + if ( + token == wETH && + address(this).balance >= + bentoBox.toAmount(address(0), shares, false) + ) { + (, depositedShares) = bentoBox.deposit{ + value: address(this).balance + }(address(0), from, to, address(this).balance, 0); } else { if (fromBentoBox) { - depositedShares = bentoBox.toShare(token, amount, false); - bentoBox.transfer(token, from, to, depositedShares); + bentoBox.transfer(token, from, to, shares); } else { (, depositedShares) = bentoBox.deposit( token, from, to, - amount, - 0 + 0, + shares ); } } @@ -237,13 +237,13 @@ contract FuroVesting is address token, address from, address to, - uint256 amount, + uint256 shares, bool toBentoBox ) internal { if (toBentoBox) { - bentoBox.transfer(token, from, to, amount); + bentoBox.transfer(token, from, to, shares); } else { - bentoBox.withdraw(token, from, to, 0, amount); + bentoBox.withdraw(token, from, to, 0, shares); } } } diff --git a/contracts/interfaces/IFuroVesting.sol b/contracts/interfaces/IFuroVesting.sol index eef2ecb..a833b39 100644 --- a/contracts/interfaces/IFuroVesting.sol +++ b/contracts/interfaces/IFuroVesting.sol @@ -25,8 +25,8 @@ interface IFuroVesting { uint32 cliffDuration, uint32 stepDuration, uint32 steps, - uint128 cliffAmount, - uint128 stepAmount, + uint128 cliffShares, + uint128 stepShares, bool fromBentoBox ) external payable returns (uint256 depositedShares, uint256 vestId); @@ -49,8 +49,8 @@ interface IFuroVesting { uint32 cliffDuration; uint32 stepDuration; uint32 steps; - uint128 cliffAmount; - uint128 stepAmount; + uint128 cliffShares; + uint128 stepShares; uint128 claimed; } @@ -63,8 +63,8 @@ interface IFuroVesting { uint32 cliffDuration, uint32 stepDuration, uint32 steps, - uint128 cliffAmount, - uint128 stepAmount, + uint128 cliffShares, + uint128 stepShares, bool fromBentoBox ); From 27cec8a9e63f63b001463ac7e1a4ee8e0c1d4f6c Mon Sep 17 00:00:00 2001 From: Sarang Parikh Date: Fri, 6 May 2022 20:19:07 +0400 Subject: [PATCH 2/6] ssaf-05 --- contracts/base/FuroVesting.sol | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/base/FuroVesting.sol b/contracts/base/FuroVesting.sol index 6720b7a..f541083 100644 --- a/contracts/base/FuroVesting.sol +++ b/contracts/base/FuroVesting.sol @@ -134,11 +134,16 @@ contract FuroVesting is function stopVesting(uint256 vestId, bool toBentoBox) external override { Vest memory vest = vests[vestId]; + if (vest.owner != msg.sender) revert NotOwner(); + uint256 amountVested = _balanceOf(vest); uint256 canClaim = amountVested - vest.claimed; uint256 returnShares = (vest.cliffShares + (vest.steps * vest.stepShares)) - amountVested; + + delete vests[vestId]; + _transferToken( address(vest.token), address(this), @@ -161,8 +166,6 @@ contract FuroVesting is vest.token, toBentoBox ); - - delete vests[vestId]; } function vestBalance(uint256 vestId) From 5f6ab5596178e473c3d1c925d7d42dfc9343d18c Mon Sep 17 00:00:00 2001 From: Sarang Parikh Date: Fri, 6 May 2022 20:29:22 +0400 Subject: [PATCH 3/6] ssaf-13 --- contracts/base/FuroVesting.sol | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contracts/base/FuroVesting.sol b/contracts/base/FuroVesting.sol index f541083..c7801f3 100644 --- a/contracts/base/FuroVesting.sol +++ b/contracts/base/FuroVesting.sol @@ -20,6 +20,7 @@ contract FuroVesting is // custom errors error InvalidStart(); error NotOwner(); + error InvalidStepSetting(); constructor(IBentoBoxMinimal _bentoBox, address _wETH) { bentoBox = _bentoBox; @@ -69,6 +70,8 @@ contract FuroVesting is returns (uint256 depositedShares, uint256 vestId) { if (start < block.timestamp) revert InvalidStart(); + if(stepDuration == 0 || steps == 0) revert InvalidStepSetting(); + depositedShares = _depositToken( address(token), msg.sender, @@ -117,6 +120,8 @@ contract FuroVesting is if (recipient != msg.sender) revert NotOwner(); uint256 canClaim = _balanceOf(vest) - vest.claimed; + if (canClaim == 0) return; + vest.claimed += uint128(canClaim); _transferToken( From de804703dea3a43f306717f85b74d4a9386bcfb5 Mon Sep 17 00:00:00 2001 From: Sarang Parikh Date: Fri, 6 May 2022 20:38:18 +0400 Subject: [PATCH 4/6] ssaf-22 --- contracts/base/FuroVesting.sol | 12 ++++++------ contracts/interfaces/IFuroVesting.sol | 1 - contracts/utils/BoringBatchable.sol | 1 - test/furo-vest-test.ts | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/contracts/base/FuroVesting.sol b/contracts/base/FuroVesting.sol index c7801f3..c7f8ea2 100644 --- a/contracts/base/FuroVesting.sol +++ b/contracts/base/FuroVesting.sol @@ -7,8 +7,7 @@ import "../interfaces/IFuroVesting.sol"; contract FuroVesting is IFuroVesting, ERC721("Furo Vesting", "FUROVEST"), - BoringBatchable, - BoringOwnable + BoringBatchable { IBentoBoxMinimal public immutable bentoBox; address public immutable wETH; @@ -20,6 +19,7 @@ contract FuroVesting is // custom errors error InvalidStart(); error NotOwner(); + error NotVestReceiver(); error InvalidStepSetting(); constructor(IBentoBoxMinimal _bentoBox, address _wETH) { @@ -70,7 +70,7 @@ contract FuroVesting is returns (uint256 depositedShares, uint256 vestId) { if (start < block.timestamp) revert InvalidStart(); - if(stepDuration == 0 || steps == 0) revert InvalidStepSetting(); + if (stepDuration == 0 || steps == 0) revert InvalidStepSetting(); depositedShares = _depositToken( address(token), @@ -117,7 +117,7 @@ contract FuroVesting is ) external override { Vest storage vest = vests[vestId]; address recipient = ownerOf[vestId]; - if (recipient != msg.sender) revert NotOwner(); + if (recipient != msg.sender) revert NotVestReceiver(); uint256 canClaim = _balanceOf(vest) - vest.claimed; if (canClaim == 0) return; @@ -139,9 +139,9 @@ contract FuroVesting is function stopVesting(uint256 vestId, bool toBentoBox) external override { Vest memory vest = vests[vestId]; - + if (vest.owner != msg.sender) revert NotOwner(); - + uint256 amountVested = _balanceOf(vest); uint256 canClaim = amountVested - vest.claimed; uint256 returnShares = (vest.cliffShares + diff --git a/contracts/interfaces/IFuroVesting.sol b/contracts/interfaces/IFuroVesting.sol index a833b39..11bf8b7 100644 --- a/contracts/interfaces/IFuroVesting.sol +++ b/contracts/interfaces/IFuroVesting.sol @@ -5,7 +5,6 @@ pragma solidity 0.8.10; import "./ITasker.sol"; import "./IBentoBoxMinimal.sol"; import "../utils/BoringBatchable.sol"; -import "../utils/BoringOwnable.sol"; import "@openzeppelin/contracts/utils/math/Math.sol"; import "@rari-capital/solmate/src/tokens/ERC721.sol"; diff --git a/contracts/utils/BoringBatchable.sol b/contracts/utils/BoringBatchable.sol index 6c0effa..e89fac1 100644 --- a/contracts/utils/BoringBatchable.sol +++ b/contracts/utils/BoringBatchable.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.10; -pragma experimental ABIEncoderV2; // solhint-disable avoid-low-level-calls // solhint-disable no-inline-assembly diff --git a/test/furo-vest-test.ts b/test/furo-vest-test.ts index 9539da6..66bfd23 100644 --- a/test/furo-vest-test.ts +++ b/test/furo-vest-test.ts @@ -426,7 +426,7 @@ describe("Withdraw", () => { it("should not allow to withdraw if not owner", async function () { await expect(furoVesting.withdraw(vestId, "0x", false)).to.be.revertedWith( - "NotOwner()" + "NotVestReceiver()" ); }); From 37e335239c60fc6c718712460618654afd3784eb Mon Sep 17 00:00:00 2001 From: Sarang Parikh Date: Wed, 18 May 2022 17:30:39 +0400 Subject: [PATCH 5/6] fix update deposit shares --- contracts/base/FuroStream.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/base/FuroStream.sol b/contracts/base/FuroStream.sol index 110e793..62e05e3 100644 --- a/contracts/base/FuroStream.sol +++ b/contracts/base/FuroStream.sol @@ -134,7 +134,8 @@ contract FuroStream is toBentoBox ); - if (taskData.length != 0 && msg.sender == recipient) ITasker(to).onTaskReceived(taskData); + if (taskData.length != 0 && msg.sender == recipient) + ITasker(to).onTaskReceived(taskData); emit Withdraw( streamId, @@ -250,6 +251,7 @@ contract FuroStream is stream.startTime = uint64(block.timestamp); stream.withdrawnShares = 0; + stream.depositedShares -= uint128(recipientBalance); stream.depositedShares += uint128(depositedShares); stream.endTime += extendTime; From 366f2fe3368c63d799909cbee0dcb087c9b2a3bb Mon Sep 17 00:00:00 2001 From: Sarang Parikh Date: Wed, 18 May 2022 18:44:40 +0400 Subject: [PATCH 6/6] ssrr01 --- contracts/base/FuroStream.sol | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/base/FuroStream.sol b/contracts/base/FuroStream.sol index 62e05e3..505a0f1 100644 --- a/contracts/base/FuroStream.sol +++ b/contracts/base/FuroStream.sol @@ -22,6 +22,7 @@ contract FuroStream is error InvalidEndTime(); error InvalidWithdrawTooMuch(); error NotSender(); + error Overflow(); constructor(IBentoBoxMinimal _bentoBox, address _wETH) { bentoBox = _bentoBox; @@ -247,12 +248,15 @@ contract FuroStream is address recipient = ownerOf[streamId]; - (, uint256 recipientBalance) = _streamBalanceOf(stream); + (uint256 senderBalance, uint256 recipientBalance) = _streamBalanceOf( + stream + ); stream.startTime = uint64(block.timestamp); stream.withdrawnShares = 0; - stream.depositedShares -= uint128(recipientBalance); - stream.depositedShares += uint128(depositedShares); + uint256 newDepositedShares = senderBalance + depositedShares; + if (newDepositedShares > type(uint128).max) revert Overflow(); + stream.depositedShares += uint128(newDepositedShares); stream.endTime += extendTime; _transferToken(