From d72c1480f99f3e61e7170753a789944fcfe64670 Mon Sep 17 00:00:00 2001
From: Thrilok Kumar <thrilok2000@gmail.com>
Date: Sun, 13 Jun 2021 16:49:33 +0530
Subject: [PATCH] Added guni factory

---
 .../uniswap_v3_erc20_staking/events.sol       |  27 ++++
 .../uniswap_v3_erc20_staking/helpers.sol      |  17 +++
 .../uniswap_v3_erc20_staking/interface.sol    |  20 +++
 .../uniswap_v3_erc20_staking/main.sol         | 117 ++++++++++++++++++
 4 files changed, 181 insertions(+)
 create mode 100644 contracts/mainnet/connectors/uniswap_v3_erc20_staking/events.sol
 create mode 100644 contracts/mainnet/connectors/uniswap_v3_erc20_staking/helpers.sol
 create mode 100644 contracts/mainnet/connectors/uniswap_v3_erc20_staking/interface.sol
 create mode 100644 contracts/mainnet/connectors/uniswap_v3_erc20_staking/main.sol

diff --git a/contracts/mainnet/connectors/uniswap_v3_erc20_staking/events.sol b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/events.sol
new file mode 100644
index 00000000..4e75acd1
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/events.sol
@@ -0,0 +1,27 @@
+pragma solidity ^0.7.0;
+
+contract Events {
+
+  event LogDeposit(
+    address indexed stakingToken,
+    uint256 amount,
+    uint getId,
+    uint setId
+  );
+
+  event LogWithdrawAndClaimedReward(
+    address indexed stakingToken,
+    uint256 amount,
+    uint256 rewardAmt,
+    uint getId,
+    uint setIdAmount,
+    uint setIdReward
+  );
+
+  event LogClaimedReward(
+    address indexed rewardToken,
+    uint256 rewardAmt,
+    uint setId
+  );
+
+}
\ No newline at end of file
diff --git a/contracts/mainnet/connectors/uniswap_v3_erc20_staking/helpers.sol b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/helpers.sol
new file mode 100644
index 00000000..e083fe94
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/helpers.sol
@@ -0,0 +1,17 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+
+import { DSMath } from "../../common/math.sol";
+import { Basic } from "../../common/basic.sol";
+import { TokenInterface } from "../../common/interfaces.sol";
+import { IStakingRewards, IStakingRewardsFactory } from "./interface.sol";
+
+abstract contract Helpers is DSMath, Basic {
+
+  IStakingRewardsFactory constant internal stakingRewardsFactory = 
+    IStakingRewardsFactory(address(0)); // TODO
+
+  TokenInterface constant internal rewardToken = TokenInterface(address(0)); // TODO
+
+}
\ No newline at end of file
diff --git a/contracts/mainnet/connectors/uniswap_v3_erc20_staking/interface.sol b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/interface.sol
new file mode 100644
index 00000000..78e732a6
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/interface.sol
@@ -0,0 +1,20 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+interface IStakingRewards {
+  function stake(uint256 amount) external;
+  function withdraw(uint256 amount) external;
+  function getReward() external;
+  function balanceOf(address) external view returns(uint);
+}
+
+interface IStakingRewardsFactory {
+
+  struct StakingRewardsInfo {
+    address stakingRewards;
+    uint rewardAmount;
+  }
+
+  function stakingRewardsInfoByStakingToken(address) external view returns(StakingRewardsInfo memory);
+
+}
\ No newline at end of file
diff --git a/contracts/mainnet/connectors/uniswap_v3_erc20_staking/main.sol b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/main.sol
new file mode 100644
index 00000000..ecb4ea2c
--- /dev/null
+++ b/contracts/mainnet/connectors/uniswap_v3_erc20_staking/main.sol
@@ -0,0 +1,117 @@
+pragma solidity ^0.7.0;
+pragma experimental ABIEncoderV2;
+
+/**
+ * @title G-UNI Staking.
+ * @dev Stake G-UNI 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, IStakingRewardsFactory } from "./interface.sol";
+
+contract Main is Helpers, Events {
+
+  /**
+    * @dev Deposit ERC20.
+    * @notice Deposit Tokens to staking pool.
+    * @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 stakingToken,
+    uint amt,
+    uint getId,
+    uint setId
+  ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+    uint _amt = getUint(getId, amt);
+    
+    IStakingRewardsFactory.StakingRewardsInfo memory stakingRewardsInfo =
+      stakingRewardsFactory.stakingRewardsInfoByStakingToken(stakingToken);
+
+    IStakingRewards stakingContract = IStakingRewards(stakingRewardsInfo.stakingRewards);
+    TokenInterface stakingTokenContract = TokenInterface(stakingToken);
+
+    _amt = _amt == uint(-1) ? stakingTokenContract.balanceOf(address(this)) : _amt;
+
+    stakingTokenContract.approve(address(stakingContract), _amt);
+    stakingContract.stake(_amt);
+
+    setUint(setId, _amt);
+    _eventName = "LogDeposit(address,uint256,uint256,uint256)";
+    _eventParam = abi.encode(address(stakingToken), _amt, getId, setId);
+  }
+
+  /**
+    * @dev Withdraw ERC20.
+    * @notice Withdraw Tokens from the staking pool.
+    * @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 stakingToken,
+    uint amt,
+    uint getId,
+    uint setIdAmount,
+    uint setIdReward
+  ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+    uint _amt = getUint(getId, amt);
+
+    IStakingRewardsFactory.StakingRewardsInfo memory stakingRewardsInfo =
+      stakingRewardsFactory.stakingRewardsInfoByStakingToken(stakingToken);
+
+    IStakingRewards stakingContract = IStakingRewards(stakingRewardsInfo.stakingRewards);
+
+    _amt = _amt == uint(-1) ? stakingContract.balanceOf(address(this)) : _amt;
+    uint intialBal = rewardToken.balanceOf(address(this));
+    stakingContract.withdraw(_amt);
+    stakingContract.getReward();
+
+    uint rewardAmt = sub(rewardToken.balanceOf(address(this)), intialBal);
+
+    setUint(setIdAmount, _amt);
+    setUint(setIdReward, rewardAmt);
+    {
+    _eventName = "LogWithdrawAndClaimedReward(address,uint256,uint256,uint256,uint256,uint256)";
+    _eventParam = abi.encode(address(stakingToken), _amt, rewardAmt, getId, setIdAmount, setIdReward);
+    }
+  }
+
+  /**
+    * @dev Claim Reward.
+    * @notice Claim Pending Rewards of tokens staked.
+    * @param stakingToken staking token address.
+    * @param setId ID stores the amount of reward tokens claimed.
+  */
+  function claimReward(
+    address stakingToken,
+    uint setId
+  ) external payable returns (string memory _eventName, bytes memory _eventParam) {
+    IStakingRewardsFactory.StakingRewardsInfo memory stakingRewardsInfo =
+      stakingRewardsFactory.stakingRewardsInfoByStakingToken(stakingToken);
+
+    IStakingRewards stakingContract = IStakingRewards(stakingRewardsInfo.stakingRewards);
+
+    uint intialBal = rewardToken.balanceOf(address(this));
+    stakingContract.getReward();
+    uint finalBal = rewardToken.balanceOf(address(this));
+
+    uint rewardAmt = sub(finalBal, intialBal);
+
+    setUint(setId, rewardAmt);
+    _eventName = "LogClaimedReward(address,uint256,uint256)";
+    _eventParam = abi.encode(address(rewardToken), rewardAmt, setId);
+  }
+
+}
+
+contract connectV2StakeGUNI is Main {
+    string public constant name = "Stake-G-UNI-v1.0";
+}
\ No newline at end of file