Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fees and rewards views #18

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
26 changes: 26 additions & 0 deletions script/FoldCaptiveStaking.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.19;

import "forge-std/Script.sol";
import "src/FoldCaptiveStaking.sol";

contract FoldCaptiveStakingScript is Script {
INonfungiblePositionManager public positionManager =
INonfungiblePositionManager(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
IUniswapV3Pool public pool = IUniswapV3Pool(0x5eCEf3b72Cb00DBD8396EBAEC66E0f87E9596e97);
WETH public weth = WETH(payable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2));
ERC20 public fold = ERC20(0xd084944d3c05CD115C09d072B9F44bA3E0E45921);


function run() public {
vm.startBroadcast();
FoldCaptiveStaking foldCaptiveStaking =
new FoldCaptiveStaking(address(positionManager), address(pool), address(weth), address(fold));

fold.transfer(address(foldCaptiveStaking), 1_000_000);
weth.transfer(address(foldCaptiveStaking), 1_000_000);

foldCaptiveStaking.initialize();
vm.stopBroadcast();
}
}
10 changes: 10 additions & 0 deletions script/deploy-fork.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

source .env

forge script script/FoldCaptiveStaking.s.sol:FoldCaptiveStakingScript \
--chain-id $CHAIN_ID \
--fork-url $RPC_MAINNET \
--broadcast \
--private-key $PRIVATE_KEY \
-vvv
12 changes: 12 additions & 0 deletions script/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

source .env

forge script script/FoldCaptiveStaking.s.sol:FoldCaptiveStakingScript \
--chain-id 1 \
--rpc-url $RPC_MAINNET \
--broadcast \
--private-key $PRIVATE_KEY \
--verify \
--etherscan-api-key $ETHERSCAN_API_KEY \
-vvv
35 changes: 24 additions & 11 deletions src/FoldCaptiveStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,7 @@ contract FoldCaptiveStaking is Owned(msg.sender) {
function compound() public isInitialized {
collectPositionFees();

uint256 fee0Owed = (token0FeesPerLiquidity - balances[msg.sender].token0FeeDebt) * balances[msg.sender].amount
/ liquidityUnderManagement;
uint256 fee1Owed = (token1FeesPerLiquidity - balances[msg.sender].token1FeeDebt) * balances[msg.sender].amount
/ liquidityUnderManagement;
(uint256 fee0Owed, uint256 fee1Owed) = owedFees();

INonfungiblePositionManager.IncreaseLiquidityParams memory params = INonfungiblePositionManager
.IncreaseLiquidityParams({
Expand All @@ -243,14 +240,23 @@ contract FoldCaptiveStaking is Owned(msg.sender) {
emit Compounded(msg.sender, liquidity, fee0Owed, fee1Owed);
}

/// @notice User-specific function to view fees owed on the singular position
function owedFees() public view returns (uint256, uint256) {
uint256 fee0Owed = ((token0FeesPerLiquidity -
balances[msg.sender].token0FeeDebt) * balances[msg.sender].amount) /
liquidityUnderManagement;
uint256 fee1Owed = ((token1FeesPerLiquidity -
balances[msg.sender].token1FeeDebt) * balances[msg.sender].amount) /
liquidityUnderManagement;

return (fee0Owed, fee1Owed);
}

/// @notice User-specific function to collect fees on the singular position
function collectFees() public isInitialized {
collectPositionFees();

uint256 fee0Owed = (token0FeesPerLiquidity - balances[msg.sender].token0FeeDebt) * balances[msg.sender].amount
/ liquidityUnderManagement;
uint256 fee1Owed = (token1FeesPerLiquidity - balances[msg.sender].token1FeeDebt) * balances[msg.sender].amount
/ liquidityUnderManagement;
(uint256 fee0Owed, uint256 fee1Owed) = owedFees();

token0.transfer(msg.sender, fee0Owed);
token1.transfer(msg.sender, fee1Owed);
Expand All @@ -261,10 +267,16 @@ contract FoldCaptiveStaking is Owned(msg.sender) {
emit FeesCollected(msg.sender, fee0Owed, fee1Owed);
}

/// @notice User-specific function to view rewards owed on the singular position
function owedRewards() public view returns (uint256) {
return
((rewardsPerLiquidity - balances[msg.sender].rewardDebt) *
balances[msg.sender].amount) / liquidityUnderManagement;
}

/// @notice User-specific Rewards for Protocol Rewards
function collectRewards() public isInitialized {
uint256 rewardsOwed = (rewardsPerLiquidity - balances[msg.sender].rewardDebt) * balances[msg.sender].amount
/ liquidityUnderManagement;
uint256 rewardsOwed = owedRewards();

WETH9.transfer(msg.sender, rewardsOwed);

Expand Down Expand Up @@ -373,7 +385,8 @@ contract FoldCaptiveStaking is Owned(msg.sender) {
amount1Max: uint128(amount1)
});

(uint256 amount0Collected, uint256 amount1Collected) = positionManager.collect(collectParams);
(uint256 amount0Collected, uint256 amount1Collected) = positionManager
.collect(collectParams);

if (amount0Collected != amount0 || amount1Collected != amount1) {
revert WithdrawFailed();
Expand Down
36 changes: 36 additions & 0 deletions test/UnitTests.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,42 @@ contract UnitTests is BaseCaptiveTest {
assertEq(amount, liq / 4);
}

/// @dev Ensure that owed fees are returned correctly.
function testOwedFees() public {
testAddLiquidity();
uint256 owedReards = foldCaptiveStaking.owedRewards();
(uint256 amount, uint256 rewardDebt, , ) = foldCaptiveStaking.balances(
User01
);
uint256 rewardOwedCheck = ((foldCaptiveStaking.rewardsPerLiquidity() -
rewardDebt) * amount) /
foldCaptiveStaking.liquidityUnderManagement();

assertEq(rewardOwedCheck, owedReards);
}

/// @dev Ensure that owed fees are returned correctly.
function testOwedRewards() public {
testAddLiquidity();
(uint256 fee0Owed, uint256 fee1Owed) = foldCaptiveStaking.owedFees();
(
uint256 amount,
,
uint256 token0FeeDebt,
uint256 token1FeeDebt
) = foldCaptiveStaking.balances(User01);
uint256 fee0OwedCheck = ((foldCaptiveStaking.token0FeesPerLiquidity() -
token0FeeDebt) * amount) /
foldCaptiveStaking.liquidityUnderManagement();

uint256 fee1OwedCheck = ((foldCaptiveStaking.token1FeesPerLiquidity() -
token1FeeDebt) * amount) /
foldCaptiveStaking.liquidityUnderManagement();

assertEq(fee0OwedCheck, fee0Owed);
assertEq(fee1OwedCheck, fee1Owed);
}

/// @dev Ensure fees are accrued correctly and distributed proportionately.
function testFeesAccrue() public {
testAddLiquidity();
Expand Down