From 1cbdbe64eed49502f68a3eaf71f4b2db99c62062 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Tue, 13 Feb 2024 19:47:17 +0400 Subject: [PATCH 1/3] feat: add fluid staking contract --- .../connectors/fluid-staking/events.sol | 28 +++++ .../connectors/fluid-staking/helpers.sol | 13 ++ .../connectors/fluid-staking/interface.sol | 9 ++ .../mainnet/connectors/fluid-staking/main.sol | 117 ++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 contracts/mainnet/connectors/fluid-staking/events.sol create mode 100644 contracts/mainnet/connectors/fluid-staking/helpers.sol create mode 100644 contracts/mainnet/connectors/fluid-staking/interface.sol create mode 100644 contracts/mainnet/connectors/fluid-staking/main.sol diff --git a/contracts/mainnet/connectors/fluid-staking/events.sol b/contracts/mainnet/connectors/fluid-staking/events.sol new file mode 100644 index 0000000..f42acd6 --- /dev/null +++ b/contracts/mainnet/connectors/fluid-staking/events.sol @@ -0,0 +1,28 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +contract Events { + + event LogDeposit( + address indexed stakingPool, + uint256 amount, + uint getId, + uint setId + ); + + event LogWithdrawAndClaimedReward( + address indexed stakingPool, + uint256 amount, + uint256 rewardAmt, + uint getId, + uint setIdAmount, + uint setIdReward + ); + + event LogClaimedReward( + address indexed stakingPool, + address indexed rewardToken, + uint256 rewardAmt, + uint setId + ); +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/fluid-staking/helpers.sol b/contracts/mainnet/connectors/fluid-staking/helpers.sol new file mode 100644 index 0000000..e52978a --- /dev/null +++ b/contracts/mainnet/connectors/fluid-staking/helpers.sol @@ -0,0 +1,13 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + + +import { DSMath } from "../../common/math.sol"; +import { Basic } from "../../common/basic.sol"; +import { TokenInterface } from "../../common/interfaces.sol"; +import { IStakingRewards } from "./interface.sol"; + +abstract contract Helpers is DSMath, Basic { + TokenInterface constant internal REWARD_TOKEN = + TokenInterface(0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb); // TODO: Update +} \ No newline at end of file diff --git a/contracts/mainnet/connectors/fluid-staking/interface.sol b/contracts/mainnet/connectors/fluid-staking/interface.sol new file mode 100644 index 0000000..0089962 --- /dev/null +++ b/contracts/mainnet/connectors/fluid-staking/interface.sol @@ -0,0 +1,9 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +interface IStakingRewards { + function stake(uint256 amount) external; + function withdraw(uint256 amount) external; + function getReward() external; + function balanceOf(address account) external view returns(uint256); +} diff --git a/contracts/mainnet/connectors/fluid-staking/main.sol b/contracts/mainnet/connectors/fluid-staking/main.sol new file mode 100644 index 0000000..2725c42 --- /dev/null +++ b/contracts/mainnet/connectors/fluid-staking/main.sol @@ -0,0 +1,117 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +/** + * @title Fluid Staking. + * @dev Stake Fluid for earning rewards. + */ + +import { TokenInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { Helpers } from "./helpers.sol"; +import { Events } from "./events.sol"; +import { IStakingRewards } from "./interface.sol"; + +contract Main is Helpers, Events { + + /** + * @dev Deposit ERC20. + * @notice Deposit Tokens to staking pool. + * @param stakingPool staking pool address. + * @param stakingToken staking token address. + * @param amt staking token amount. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount of staked tokens. + */ + function deposit( + address stakingPool, + address stakingToken, + uint amt, + uint getId, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IStakingRewards stakingContract = IStakingRewards(stakingPool); + TokenInterface stakingTokenContract = TokenInterface(stakingToken); + + _amt = _amt == type(uint256).max + ? stakingTokenContract.balanceOf(address(this)) + : _amt; + + approve(stakingTokenContract, address(stakingContract), _amt); + stakingContract.stake(_amt); + + setUint(setId, _amt); + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(stakingPool, _amt, getId, setId); + } + + /** + * @dev Withdraw ERC20. + * @notice Withdraw Tokens from the staking pool. + * @param stakingPool staking pool address. + * @param stakingToken staking token address. + * @param amt staking token amount. + * @param getId ID to retrieve amount. + * @param setIdAmount ID stores the amount of stake tokens withdrawn. + * @param setIdReward ID stores the amount of reward tokens claimed. + */ + function withdraw( + address stakingPool, + address stakingToken, // TODO: Remove? + uint amt, + uint getId, + uint setIdAmount, + uint setIdReward + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IStakingRewards stakingContract = IStakingRewards(stakingPool); + + _amt = _amt == type(uint256).max + ? stakingContract.balanceOf(address(this)) + : _amt; + + uint intialBal = REWARD_TOKEN.balanceOf(address(this)); + stakingContract.withdraw(_amt); + stakingContract.getReward(); + + uint rewardAmt = REWARD_TOKEN.balanceOf(address(this)) - intialBal; + + setUint(setIdAmount, _amt); + setUint(setIdReward, rewardAmt); + { + _eventName = "LogWithdrawAndClaimedReward(address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(stakingPool, _amt, rewardAmt, getId, setIdAmount, setIdReward); + } + } + + /** + * @dev Claim Reward. + * @notice Claim Pending Rewards of tokens staked. + * @param stakingPool staking pool address. + * @param setId ID stores the amount of reward tokens claimed. + */ + function claimReward( + address stakingPool, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + IStakingRewards stakingContract = IStakingRewards(stakingPool); + + uint intialBal = REWARD_TOKEN.balanceOf(address(this)); + stakingContract.getReward(); + uint finalBal = REWARD_TOKEN.balanceOf(address(this)); + + uint rewardAmt = finalBal - intialBal; + + setUint(setId, rewardAmt); + _eventName = "LogClaimedReward(address,address,uint256,uint256)"; + _eventParam = abi.encode(address(stakingPool), address(REWARD_TOKEN), rewardAmt, setId); + } + +} + +contract connectV2StakeFluid is Main { + string public constant name = "Stake-Fluid-v1.0"; +} \ No newline at end of file From afb457e4c228033778d3c302fe253515d596d45c Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 15 Feb 2024 04:24:42 +0400 Subject: [PATCH 2/3] feat: update mainnet connector --- .../connectors/fluid-staking/helpers.sol | 13 --------- .../connectors/fluid-staking/interface.sol | 4 +++ .../mainnet/connectors/fluid-staking/main.sol | 27 +++++++++---------- 3 files changed, 17 insertions(+), 27 deletions(-) delete mode 100644 contracts/mainnet/connectors/fluid-staking/helpers.sol diff --git a/contracts/mainnet/connectors/fluid-staking/helpers.sol b/contracts/mainnet/connectors/fluid-staking/helpers.sol deleted file mode 100644 index e52978a..0000000 --- a/contracts/mainnet/connectors/fluid-staking/helpers.sol +++ /dev/null @@ -1,13 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.8.2; - - -import { DSMath } from "../../common/math.sol"; -import { Basic } from "../../common/basic.sol"; -import { TokenInterface } from "../../common/interfaces.sol"; -import { IStakingRewards } from "./interface.sol"; - -abstract contract Helpers is DSMath, Basic { - TokenInterface constant internal REWARD_TOKEN = - TokenInterface(0x6f40d4A6237C257fff2dB00FA0510DeEECd303eb); // TODO: Update -} \ No newline at end of file diff --git a/contracts/mainnet/connectors/fluid-staking/interface.sol b/contracts/mainnet/connectors/fluid-staking/interface.sol index 0089962..7323473 100644 --- a/contracts/mainnet/connectors/fluid-staking/interface.sol +++ b/contracts/mainnet/connectors/fluid-staking/interface.sol @@ -1,9 +1,13 @@ //SPDX-License-Identifier: MIT pragma solidity ^0.8.2; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + interface IStakingRewards { function stake(uint256 amount) external; function withdraw(uint256 amount) external; function getReward() external; function balanceOf(address account) external view returns(uint256); + function rewardsToken() external view returns (IERC20); + function stakingToken() external view returns (IERC20); } diff --git a/contracts/mainnet/connectors/fluid-staking/main.sol b/contracts/mainnet/connectors/fluid-staking/main.sol index 2725c42..59d9733 100644 --- a/contracts/mainnet/connectors/fluid-staking/main.sol +++ b/contracts/mainnet/connectors/fluid-staking/main.sol @@ -8,24 +8,23 @@ pragma solidity ^0.8.2; import { TokenInterface } from "../../common/interfaces.sol"; import { Stores } from "../../common/stores.sol"; -import { Helpers } from "./helpers.sol"; +import { Basic } from "../../common/basic.sol"; import { Events } from "./events.sol"; import { IStakingRewards } from "./interface.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -contract Main is Helpers, Events { +contract Main is Basic, Events { /** * @dev Deposit ERC20. * @notice Deposit Tokens to staking pool. * @param stakingPool staking pool address. - * @param stakingToken staking token address. * @param amt staking token amount. * @param getId ID to retrieve amount. * @param setId ID stores the amount of staked tokens. */ function deposit( address stakingPool, - address stakingToken, uint amt, uint getId, uint setId @@ -33,13 +32,13 @@ contract Main is Helpers, Events { uint _amt = getUint(getId, amt); IStakingRewards stakingContract = IStakingRewards(stakingPool); - TokenInterface stakingTokenContract = TokenInterface(stakingToken); + IERC20 stakingTokenContract = stakingContract.stakingToken(); _amt = _amt == type(uint256).max ? stakingTokenContract.balanceOf(address(this)) : _amt; - approve(stakingTokenContract, address(stakingContract), _amt); + approve(TokenInterface(address(stakingTokenContract)), address(stakingContract), _amt); stakingContract.stake(_amt); setUint(setId, _amt); @@ -51,7 +50,6 @@ contract Main is Helpers, Events { * @dev Withdraw ERC20. * @notice Withdraw Tokens from the staking pool. * @param stakingPool staking pool address. - * @param stakingToken staking token address. * @param amt staking token amount. * @param getId ID to retrieve amount. * @param setIdAmount ID stores the amount of stake tokens withdrawn. @@ -59,7 +57,6 @@ contract Main is Helpers, Events { */ function withdraw( address stakingPool, - address stakingToken, // TODO: Remove? uint amt, uint getId, uint setIdAmount, @@ -68,16 +65,17 @@ contract Main is Helpers, Events { uint _amt = getUint(getId, amt); IStakingRewards stakingContract = IStakingRewards(stakingPool); + IERC20 rewardsToken = stakingContract.rewardsToken(); _amt = _amt == type(uint256).max ? stakingContract.balanceOf(address(this)) : _amt; - uint intialBal = REWARD_TOKEN.balanceOf(address(this)); + uint intialBal = rewardsToken.balanceOf(address(this)); stakingContract.withdraw(_amt); stakingContract.getReward(); - uint rewardAmt = REWARD_TOKEN.balanceOf(address(this)) - intialBal; + uint rewardAmt = rewardsToken.balanceOf(address(this)) - intialBal; setUint(setIdAmount, _amt); setUint(setIdReward, rewardAmt); @@ -98,20 +96,21 @@ contract Main is Helpers, Events { uint setId ) external payable returns (string memory _eventName, bytes memory _eventParam) { IStakingRewards stakingContract = IStakingRewards(stakingPool); + IERC20 rewardsToken = stakingContract.rewardsToken(); - uint intialBal = REWARD_TOKEN.balanceOf(address(this)); + uint intialBal = rewardsToken.balanceOf(address(this)); stakingContract.getReward(); - uint finalBal = REWARD_TOKEN.balanceOf(address(this)); + uint finalBal = rewardsToken.balanceOf(address(this)); uint rewardAmt = finalBal - intialBal; setUint(setId, rewardAmt); _eventName = "LogClaimedReward(address,address,uint256,uint256)"; - _eventParam = abi.encode(address(stakingPool), address(REWARD_TOKEN), rewardAmt, setId); + _eventParam = abi.encode(stakingPool, address(rewardsToken), rewardAmt, setId); } } -contract connectV2StakeFluid is Main { +contract ConnectV2StakeFluid is Main { string public constant name = "Stake-Fluid-v1.0"; } \ No newline at end of file From db7b37cd3717b4509196ff56b78be9503f0441d8 Mon Sep 17 00:00:00 2001 From: Shriya Tyagi Date: Thu, 15 Feb 2024 04:25:01 +0400 Subject: [PATCH 3/3] feat: add polygon staking connector --- .../connectors/fluid-staking/events.sol | 28 +++++ .../connectors/fluid-staking/interface.sol | 13 ++ .../polygon/connectors/fluid-staking/main.sol | 116 ++++++++++++++++++ 3 files changed, 157 insertions(+) create mode 100644 contracts/polygon/connectors/fluid-staking/events.sol create mode 100644 contracts/polygon/connectors/fluid-staking/interface.sol create mode 100644 contracts/polygon/connectors/fluid-staking/main.sol diff --git a/contracts/polygon/connectors/fluid-staking/events.sol b/contracts/polygon/connectors/fluid-staking/events.sol new file mode 100644 index 0000000..f42acd6 --- /dev/null +++ b/contracts/polygon/connectors/fluid-staking/events.sol @@ -0,0 +1,28 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +contract Events { + + event LogDeposit( + address indexed stakingPool, + uint256 amount, + uint getId, + uint setId + ); + + event LogWithdrawAndClaimedReward( + address indexed stakingPool, + uint256 amount, + uint256 rewardAmt, + uint getId, + uint setIdAmount, + uint setIdReward + ); + + event LogClaimedReward( + address indexed stakingPool, + address indexed rewardToken, + uint256 rewardAmt, + uint setId + ); +} \ No newline at end of file diff --git a/contracts/polygon/connectors/fluid-staking/interface.sol b/contracts/polygon/connectors/fluid-staking/interface.sol new file mode 100644 index 0000000..7323473 --- /dev/null +++ b/contracts/polygon/connectors/fluid-staking/interface.sol @@ -0,0 +1,13 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +interface IStakingRewards { + function stake(uint256 amount) external; + function withdraw(uint256 amount) external; + function getReward() external; + function balanceOf(address account) external view returns(uint256); + function rewardsToken() external view returns (IERC20); + function stakingToken() external view returns (IERC20); +} diff --git a/contracts/polygon/connectors/fluid-staking/main.sol b/contracts/polygon/connectors/fluid-staking/main.sol new file mode 100644 index 0000000..3242c90 --- /dev/null +++ b/contracts/polygon/connectors/fluid-staking/main.sol @@ -0,0 +1,116 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.2; + +/** + * @title Fluid Staking. + * @dev Stake Fluid for earning rewards. + */ + +import { TokenInterface } from "../../common/interfaces.sol"; +import { Stores } from "../../common/stores.sol"; +import { Basic } from "../../common/basic.sol"; +import { Events } from "./events.sol"; +import { IStakingRewards } from "./interface.sol"; +import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; + +contract Main is Basic, Events { + + /** + * @dev Deposit ERC20. + * @notice Deposit Tokens to staking pool. + * @param stakingPool staking pool address. + * @param amt staking token amount. + * @param getId ID to retrieve amount. + * @param setId ID stores the amount of staked tokens. + */ + function deposit( + address stakingPool, + uint amt, + uint getId, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IStakingRewards stakingContract = IStakingRewards(stakingPool); + IERC20 stakingTokenContract = stakingContract.stakingToken(); + + _amt = _amt == type(uint256).max + ? stakingTokenContract.balanceOf(address(this)) + : _amt; + + approve(TokenInterface(address(stakingTokenContract)), address(stakingContract), _amt); + stakingContract.stake(_amt); + + setUint(setId, _amt); + _eventName = "LogDeposit(address,uint256,uint256,uint256)"; + _eventParam = abi.encode(stakingPool, _amt, getId, setId); + } + + /** + * @dev Withdraw ERC20. + * @notice Withdraw Tokens from the staking pool. + * @param stakingPool staking pool address. + * @param amt staking token amount. + * @param getId ID to retrieve amount. + * @param setIdAmount ID stores the amount of stake tokens withdrawn. + * @param setIdReward ID stores the amount of reward tokens claimed. + */ + function withdraw( + address stakingPool, + uint amt, + uint getId, + uint setIdAmount, + uint setIdReward + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + uint _amt = getUint(getId, amt); + + IStakingRewards stakingContract = IStakingRewards(stakingPool); + IERC20 rewardsToken = stakingContract.rewardsToken(); + + _amt = _amt == type(uint256).max + ? stakingContract.balanceOf(address(this)) + : _amt; + + uint intialBal = rewardsToken.balanceOf(address(this)); + stakingContract.withdraw(_amt); + stakingContract.getReward(); + + uint rewardAmt = rewardsToken.balanceOf(address(this)) - intialBal; + + setUint(setIdAmount, _amt); + setUint(setIdReward, rewardAmt); + { + _eventName = "LogWithdrawAndClaimedReward(address,uint256,uint256,uint256,uint256,uint256)"; + _eventParam = abi.encode(stakingPool, _amt, rewardAmt, getId, setIdAmount, setIdReward); + } + } + + /** + * @dev Claim Reward. + * @notice Claim Pending Rewards of tokens staked. + * @param stakingPool staking pool address. + * @param setId ID stores the amount of reward tokens claimed. + */ + function claimReward( + address stakingPool, + uint setId + ) external payable returns (string memory _eventName, bytes memory _eventParam) { + IStakingRewards stakingContract = IStakingRewards(stakingPool); + IERC20 rewardsToken = stakingContract.rewardsToken(); + + uint intialBal = rewardsToken.balanceOf(address(this)); + stakingContract.getReward(); + uint finalBal = rewardsToken.balanceOf(address(this)); + + uint rewardAmt = finalBal - intialBal; + + setUint(setId, rewardAmt); + _eventName = "LogClaimedReward(address,address,uint256,uint256)"; + _eventParam = abi.encode(stakingPool, address(rewardsToken), rewardAmt, setId); + } + +} + +contract ConnectV2StakeFluidPolygon is Main { + string public constant name = "Stake-Fluid-v1.0"; +} \ No newline at end of file