From 571a69ea3c73ce747b2c7f0822417ff676739c43 Mon Sep 17 00:00:00 2001
From: Dimitri <69167058+dimsome@users.noreply.github.com>
Date: Thu, 27 Jan 2022 19:34:47 +0700
Subject: [PATCH] chore: add stores

---
 .../mainnet/connectors/mstable/events.sol     |   9 +-
 .../mainnet/connectors/mstable/helpers.sol    |  36 +++--
 contracts/mainnet/connectors/mstable/main.sol | 138 ++++++++++++++----
 .../polygon/connectors/mstable/events.sol     |   9 +-
 .../polygon/connectors/mstable/helpers.sol    |  36 +++--
 contracts/polygon/connectors/mstable/main.sol | 138 ++++++++++++++----
 test/mainnet/mstable/mstable.test.ts          |  19 ++-
 test/mainnet/mstable/mstable.utils.ts         |   6 +-
 test/polygon/mstable/mstable.test.ts          |  19 ++-
 test/polygon/mstable/mstable.utils.ts         |   6 +-
 10 files changed, 308 insertions(+), 108 deletions(-)

diff --git a/contracts/mainnet/connectors/mstable/events.sol b/contracts/mainnet/connectors/mstable/events.sol
index 7cabfddc..11497875 100644
--- a/contracts/mainnet/connectors/mstable/events.sol
+++ b/contracts/mainnet/connectors/mstable/events.sol
@@ -1,8 +1,13 @@
 pragma solidity ^0.7.6;
 
 contract Events {
-	event LogDeposit(address token, uint256 amount, address path);
-	event LogWithdraw(address token, uint256 amount, address path);
+	event LogDeposit(address token, uint256 amount, address path, bool stake);
+	event LogWithdraw(
+		address token,
+		uint256 amount,
+		address path,
+		bool unstake
+	);
 	event LogClaimRewards(address token, uint256 amount);
 	event LogSwap(
 		address from,
diff --git a/contracts/mainnet/connectors/mstable/helpers.sol b/contracts/mainnet/connectors/mstable/helpers.sol
index dce9024f..9d569963 100644
--- a/contracts/mainnet/connectors/mstable/helpers.sol
+++ b/contracts/mainnet/connectors/mstable/helpers.sol
@@ -24,6 +24,7 @@ abstract contract Helpers is DSMath, Basic {
 	 * @param _token Address of token to deposit
 	 * @param _amount Amount of token to deposit
 	 * @param _path Path to mint mUSD (only needed for Feeder Pool)
+	 * @param _stake stake token in Vault?
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -31,7 +32,8 @@ abstract contract Helpers is DSMath, Basic {
 	function _deposit(
 		address _token,
 		uint256 _amount,
-		address _path
+		address _path,
+		bool _stake
 	) internal returns (string memory _eventName, bytes memory _eventParam) {
 		// 1. Deposit mUSD to Save
 		approve(TokenInterface(mUsdToken), imUsdToken, _amount);
@@ -39,35 +41,43 @@ abstract contract Helpers is DSMath, Basic {
 			_amount
 		);
 
-		// 2. Stake imUSD to Vault
-		approve(TokenInterface(imUsdToken), imUsdVault, credits);
-		IBoostedSavingsVault(imUsdVault).stake(credits);
-
+		if (_stake) {
+			// 2. Stake imUSD to Vault
+			approve(TokenInterface(imUsdToken), imUsdVault, credits);
+			IBoostedSavingsVault(imUsdVault).stake(credits);
+		}
 		// 3. Log Events
-		_eventName = "LogDeposit(address,uint256,address)";
-		_eventParam = abi.encode(_token, _amount, _path);
+		_eventName = "LogDeposit(address,uint256,address,bool)";
+		_eventParam = abi.encode(_token, _amount, _path, _stake);
 	}
 
 	/**
 	 * @dev Withdraws from Save
 	 * @notice Withdraws token supported by mStable from Save
 	 * @param _credits Credits to withdraw
+	 * @param _unstake unstake from Vault?
 	 * @return amountWithdrawn Amount withdrawn in mUSD
 	 */
 
-	function _withdraw(uint256 _credits)
+	function _withdraw(uint256 _credits, bool _unstake)
 		internal
 		returns (uint256 amountWithdrawn)
 	{
+		uint256 credits;
 		// 1. Withdraw from Vault
-		// approve(TokenInterface(imUsdVault), imUsdToken, _credits);
-		IBoostedSavingsVault(imUsdVault).withdraw(_credits);
+		if (_unstake) {
+			credits = _credits == uint256(-1)
+				? TokenInterface(imUsdVault).balanceOf(address(this))
+				: _credits;
+			IBoostedSavingsVault(imUsdVault).withdraw(credits);
+		}
 
 		// 2. Withdraw from Save
+		credits = _credits == uint256(-1)
+			? TokenInterface(imUsdToken).balanceOf(address(this))
+			: _credits;
 		approve(TokenInterface(imUsdToken), imUsdVault, _credits);
-		amountWithdrawn = ISavingsContractV2(imUsdToken).redeemCredits(
-			_credits
-		);
+		amountWithdrawn = ISavingsContractV2(imUsdToken).redeemCredits(credits);
 	}
 
 	/**
diff --git a/contracts/mainnet/connectors/mstable/main.sol b/contracts/mainnet/connectors/mstable/main.sol
index f42abf42..30107346 100644
--- a/contracts/mainnet/connectors/mstable/main.sol
+++ b/contracts/mainnet/connectors/mstable/main.sol
@@ -22,6 +22,9 @@ abstract contract mStableResolver is Events, Helpers {
 	 * @param _token Address of token to deposit
 	 * @param _amount Amount of token to deposit
 	 * @param _minOut Minimum amount of token to mint/deposit, equal to _amount if mUSD
+	 * @param _stake stake token in Vault?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens deposited
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -29,28 +32,42 @@ abstract contract mStableResolver is Events, Helpers {
 	function deposit(
 		address _token,
 		uint256 _amount,
-		uint256 _minOut
+		uint256 _minOut,
+		bool _stake,
+		uint256 _setId,
+		uint256 _getId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
-		uint256 mintedAmount = _amount;
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_token).balanceOf(address(this))
+			: amount;
+		uint256 mintedAmount;
 		address path;
 
 		// Check if needs to be minted first
 		if (IMasset(mUsdToken).bAssetIndexes(_token) != 0) {
 			// mint first
-			approve(TokenInterface(_token), mUsdToken, _amount);
+			approve(TokenInterface(_token), mUsdToken, amount);
 			mintedAmount = IMasset(mUsdToken).mint(
 				_token,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
 			path = mUsdToken;
 		} else {
-			require(mintedAmount >= _minOut, "mintedAmount < _minOut");
+			require(amount >= _minOut, "mintedAmount < _minOut");
+			mintedAmount = amount;
 			path = imUsdToken;
 		}
 
-		(_eventName, _eventParam) = _deposit(_token, mintedAmount, path);
+		setUint(_setId, mintedAmount);
+		(_eventName, _eventParam) = _deposit(
+			_token,
+			mintedAmount,
+			path,
+			_stake
+		);
 	}
 
 	/**
@@ -60,6 +77,9 @@ abstract contract mStableResolver is Events, Helpers {
 	 * @param _amount Amount of token to deposit
 	 * @param _minOut Minimum amount of token to mint
 	 * @param _path Feeder Pool address for _token
+	 * @param _stake stake token in Vault?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens deposited
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -68,7 +88,10 @@ abstract contract mStableResolver is Events, Helpers {
 		address _token,
 		uint256 _amount,
 		uint256 _minOut,
-		address _path
+		address _path,
+		bool _stake,
+		uint256 _setId,
+		uint256 _getId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
 		require(_path != address(0), "Path must be set");
 		require(
@@ -76,16 +99,27 @@ abstract contract mStableResolver is Events, Helpers {
 			"Token is bAsset"
 		);
 
-		approve(TokenInterface(_token), _path, _amount);
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_token).balanceOf(address(this))
+			: amount;
+
+		approve(TokenInterface(_token), _path, amount);
 		uint256 mintedAmount = IFeederPool(_path).swap(
 			_token,
 			mUsdToken,
-			_amount,
+			amount,
 			_minOut,
 			address(this)
 		);
 
-		(_eventName, _eventParam) = _deposit(_token, mintedAmount, _path);
+		setUint(_setId, mintedAmount);
+		(_eventName, _eventParam) = _deposit(
+			_token,
+			mintedAmount,
+			_path,
+			_stake
+		);
 	}
 
 	/**
@@ -94,6 +128,9 @@ abstract contract mStableResolver is Events, Helpers {
 	 * @param _token Address of token to withdraw
 	 * @param _credits Credits to withdraw
 	 * @param _minOut Minimum amount of token to withdraw
+	 * @param _unstake from the Vault first?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens withdrawn
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -101,9 +138,13 @@ abstract contract mStableResolver is Events, Helpers {
 	function withdraw(
 		address _token,
 		uint256 _credits,
-		uint256 _minOut
+		uint256 _minOut,
+		bool _unstake,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
-		uint256 amountWithdrawn = _withdraw(_credits);
+		uint256 credits = getUint(_getId, _credits);
+		uint256 amountWithdrawn = _withdraw(credits, _unstake);
 
 		// Check if needs to be redeemed
 		if (IMasset(mUsdToken).bAssetIndexes(_token) != 0) {
@@ -117,8 +158,14 @@ abstract contract mStableResolver is Events, Helpers {
 			require(amountWithdrawn >= _minOut, "amountWithdrawn < _minOut");
 		}
 
-		_eventName = "LogWithdraw(address,uint256,address)";
-		_eventParam = abi.encode(mUsdToken, amountWithdrawn, imUsdToken);
+		setUint(_setId, amountWithdrawn);
+		_eventName = "LogWithdraw(address,uint256,address,bool)";
+		_eventParam = abi.encode(
+			mUsdToken,
+			amountWithdrawn,
+			imUsdToken,
+			_unstake
+		);
 	}
 
 	/**
@@ -128,6 +175,9 @@ abstract contract mStableResolver is Events, Helpers {
 	 * @param _credits Credits to withdraw
 	 * @param _minOut Minimum amount of token to mint
 	 * @param _path Feeder Pool address for _token
+	 * @param _unstake from the Vault first?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens withdrawn
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -136,7 +186,10 @@ abstract contract mStableResolver is Events, Helpers {
 		address _token,
 		uint256 _credits,
 		uint256 _minOut,
-		address _path
+		address _path,
+		bool _unstake,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
 		require(_path != address(0), "Path must be set");
 		require(
@@ -144,7 +197,9 @@ abstract contract mStableResolver is Events, Helpers {
 			"Token is bAsset"
 		);
 
-		uint256 amountWithdrawn = _withdraw(_credits);
+		uint256 credits = getUint(_getId, _credits);
+
+		uint256 amountWithdrawn = _withdraw(credits, _unstake);
 
 		approve(TokenInterface(mUsdToken), _path, amountWithdrawn);
 		uint256 amountRedeemed = IFeederPool(_path).swap(
@@ -155,18 +210,22 @@ abstract contract mStableResolver is Events, Helpers {
 			address(this)
 		);
 
-		_eventName = "LogWithdraw(address,uint256,address)";
-		_eventParam = abi.encode(_token, amountRedeemed, _path);
+		setUint(_setId, amountRedeemed);
+
+		_eventName = "LogWithdraw(address,uint256,address,bool)";
+		_eventParam = abi.encode(_token, amountRedeemed, _path, _unstake);
 	}
 
 	/**
 	 * @dev Claims Rewards
 	 * @notice Claims accrued rewards from the Vault
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens withdrawn
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
 
-	function claimRewards()
+	function claimRewards(uint256 _getId, uint256 _setId)
 		external
 		returns (string memory _eventName, bytes memory _eventParam)
 	{
@@ -179,6 +238,8 @@ abstract contract mStableResolver is Events, Helpers {
 
 		uint256 claimedRewardToken = sub(rewardAmountUpdated, rewardAmount);
 
+		setUint(_setId, claimedRewardToken);
+
 		_eventName = "LogClaimRewards(address,uint256)";
 		_eventParam = abi.encode(rewardToken, claimedRewardToken);
 	}
@@ -190,6 +251,8 @@ abstract contract mStableResolver is Events, Helpers {
 	 * @param _output Token address to swap to
 	 * @param _amount Amount of tokens to swap
 	 * @param _minOut Minimum amount of token to mint
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens swapped
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -198,9 +261,15 @@ abstract contract mStableResolver is Events, Helpers {
 		address _input,
 		address _output,
 		uint256 _amount,
-		uint256 _minOut
+		uint256 _minOut,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
-		approve(TokenInterface(_input), mUsdToken, _amount);
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_input).balanceOf(address(this))
+			: amount;
+		approve(TokenInterface(_input), mUsdToken, amount);
 		uint256 amountSwapped;
 
 		// Check the assets and swap accordingly
@@ -208,7 +277,7 @@ abstract contract mStableResolver is Events, Helpers {
 			// bAsset to mUSD => mint
 			amountSwapped = IMasset(mUsdToken).mint(
 				_input,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
@@ -216,7 +285,7 @@ abstract contract mStableResolver is Events, Helpers {
 			// mUSD to bAsset => redeem
 			amountSwapped = IMasset(mUsdToken).redeem(
 				_output,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
@@ -225,14 +294,15 @@ abstract contract mStableResolver is Events, Helpers {
 			amountSwapped = IMasset(mUsdToken).swap(
 				_input,
 				_output,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
 		}
 
+		setUint(_setId, amountSwapped);
 		_eventName = "LogSwap(address,address,uint256,uint256)";
-		_eventParam = abi.encode(_input, _output, _amount, amountSwapped);
+		_eventParam = abi.encode(_input, _output, amount, amountSwapped);
 	}
 
 	/**
@@ -243,6 +313,8 @@ abstract contract mStableResolver is Events, Helpers {
 	 * @param _amount Amount of tokens to swap
 	 * @param _minOut Minimum amount of token to mint
 	 * @param _path Feeder Pool address to use
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens swapped
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -252,24 +324,32 @@ abstract contract mStableResolver is Events, Helpers {
 		address _output,
 		uint256 _amount,
 		uint256 _minOut,
-		address _path
+		address _path,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
 		uint256 amountSwapped;
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_input).balanceOf(address(this))
+			: amount;
 
-		approve(TokenInterface(_input), _path, _amount);
+		approve(TokenInterface(_input), _path, amount);
 
 		// swaps fAsset to mUSD via Feeder Pool
 		// swaps mUSD to fAsset via Feeder Pool
 		amountSwapped = IFeederPool(_path).swap(
 			_input,
 			_output,
-			_amount,
+			amount,
 			_minOut,
 			address(this)
 		);
 
+		setUint(_setId, amountSwapped);
+
 		_eventName = "LogSwap(address,address,uint256,uint256)";
-		_eventParam = abi.encode(_input, _output, _amount, amountSwapped);
+		_eventParam = abi.encode(_input, _output, amount, amountSwapped);
 	}
 }
 
diff --git a/contracts/polygon/connectors/mstable/events.sol b/contracts/polygon/connectors/mstable/events.sol
index dcbbbe68..c463b75d 100644
--- a/contracts/polygon/connectors/mstable/events.sol
+++ b/contracts/polygon/connectors/mstable/events.sol
@@ -1,8 +1,13 @@
 pragma solidity ^0.7.6;
 
 contract Events {
-	event LogDeposit(address token, uint256 amount, address path);
-	event LogWithdraw(address token, uint256 amount, address path);
+	event LogDeposit(address token, uint256 amount, address path, bool stake);
+	event LogWithdraw(
+		address token,
+		uint256 amount,
+		address path,
+		bool unstake
+	);
 	event LogClaimRewards(
 		address token,
 		uint256 amount,
diff --git a/contracts/polygon/connectors/mstable/helpers.sol b/contracts/polygon/connectors/mstable/helpers.sol
index 54e3d0da..d4330fb6 100644
--- a/contracts/polygon/connectors/mstable/helpers.sol
+++ b/contracts/polygon/connectors/mstable/helpers.sol
@@ -24,6 +24,7 @@ abstract contract Helpers is DSMath, Basic {
 	 * @param _token Address of token to deposit
 	 * @param _amount Amount of token to deposit
 	 * @param _path Path to mint mUSD (only needed for Feeder Pool)
+	 * @param _stake stake token in Vault?
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -31,42 +32,51 @@ abstract contract Helpers is DSMath, Basic {
 	function _deposit(
 		address _token,
 		uint256 _amount,
-		address _path
+		address _path,
+		bool _stake
 	) internal returns (string memory _eventName, bytes memory _eventParam) {
 		// 1. Deposit mUSD to Save
 		approve(TokenInterface(mUsdToken), imUsdToken, _amount);
 		uint256 credits = ISavingsContractV2(imUsdToken).depositSavings(
 			_amount
 		);
-
-		// 2. Stake imUSD to Vault
-		approve(TokenInterface(imUsdToken), imUsdVault, credits);
-		IStakingRewardsWithPlatformToken(imUsdVault).stake(credits);
-
+		if (_stake) {
+			// 2. Stake imUSD to Vault
+			approve(TokenInterface(imUsdToken), imUsdVault, credits);
+			IStakingRewardsWithPlatformToken(imUsdVault).stake(credits);
+		}
 		// 3. Log Events
-		_eventName = "LogDeposit(address,uint256,address)";
-		_eventParam = abi.encode(_token, _amount, _path);
+		_eventName = "LogDeposit(address,uint256,address,bool)";
+		_eventParam = abi.encode(_token, _amount, _path, _stake);
 	}
 
 	/**
 	 * @dev Withdraws from Save
 	 * @notice Withdraws token supported by mStable from Save
 	 * @param _credits Credits to withdraw
+	 * @param _unstake unstake from Vault?
 	 * @return amountWithdrawn Amount withdrawn in mUSD
 	 */
 
-	function _withdraw(uint256 _credits)
+	function _withdraw(uint256 _credits, bool _unstake)
 		internal
 		returns (uint256 amountWithdrawn)
 	{
+		uint256 credits;
 		// 1. Withdraw from Vault
-		IStakingRewardsWithPlatformToken(imUsdVault).withdraw(_credits);
+		if (_unstake) {
+			credits = _credits == uint256(-1)
+				? TokenInterface(imUsdVault).balanceOf(address(this))
+				: _credits;
+			IStakingRewardsWithPlatformToken(imUsdVault).withdraw(credits);
+		}
 
 		// 2. Withdraw from Save
+		credits = _credits == uint256(-1)
+			? TokenInterface(imUsdToken).balanceOf(address(this))
+			: _credits;
 		approve(TokenInterface(imUsdToken), imUsdVault, _credits);
-		amountWithdrawn = ISavingsContractV2(imUsdToken).redeemCredits(
-			_credits
-		);
+		amountWithdrawn = ISavingsContractV2(imUsdToken).redeemCredits(credits);
 	}
 
 	/**
diff --git a/contracts/polygon/connectors/mstable/main.sol b/contracts/polygon/connectors/mstable/main.sol
index b247fb4b..2f116322 100644
--- a/contracts/polygon/connectors/mstable/main.sol
+++ b/contracts/polygon/connectors/mstable/main.sol
@@ -21,6 +21,9 @@ abstract contract PmStableResolver is Events, Helpers {
 	 * @param _token Address of token to deposit
 	 * @param _amount Amount of token to deposit
 	 * @param _minOut Minimum amount of token to mint/deposit, equal to _amount if mUSD
+	 * @param _stake stake token in Vault?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens deposited
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -28,28 +31,43 @@ abstract contract PmStableResolver is Events, Helpers {
 	function deposit(
 		address _token,
 		uint256 _amount,
-		uint256 _minOut
+		uint256 _minOut,
+		bool _stake,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
-		uint256 mintedAmount = _amount;
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_token).balanceOf(address(this))
+			: amount;
+		uint256 mintedAmount;
 		address path;
 
 		// Check if needs to be minted first
 		if (IMasset(mUsdToken).bAssetIndexes(_token) != 0) {
 			// mint first
-			approve(TokenInterface(_token), mUsdToken, _amount);
+			approve(TokenInterface(_token), mUsdToken, amount);
 			mintedAmount = IMasset(mUsdToken).mint(
 				_token,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
 			path = mUsdToken;
 		} else {
-			require(mintedAmount >= _minOut, "mintedAmount < _minOut");
+			require(amount >= _minOut, "mintedAmount < _minOut");
+			mintedAmount = amount;
 			path = imUsdToken;
 		}
 
-		(_eventName, _eventParam) = _deposit(_token, mintedAmount, path);
+		setUint(_setId, mintedAmount);
+
+		(_eventName, _eventParam) = _deposit(
+			_token,
+			mintedAmount,
+			path,
+			_stake
+		);
 	}
 
 	/**
@@ -59,6 +77,9 @@ abstract contract PmStableResolver is Events, Helpers {
 	 * @param _amount Amount of token to deposit
 	 * @param _minOut Minimum amount of token to mint
 	 * @param _path Feeder Pool address for _token
+	 * @param _stake stake token in Vault?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens deposited
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -67,7 +88,10 @@ abstract contract PmStableResolver is Events, Helpers {
 		address _token,
 		uint256 _amount,
 		uint256 _minOut,
-		address _path
+		address _path,
+		bool _stake,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
 		require(_path != address(0), "Path must be set");
 		require(
@@ -75,16 +99,27 @@ abstract contract PmStableResolver is Events, Helpers {
 			"Token is bAsset"
 		);
 
-		approve(TokenInterface(_token), _path, _amount);
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_token).balanceOf(address(this))
+			: amount;
+
+		approve(TokenInterface(_token), _path, amount);
 		uint256 mintedAmount = IFeederPool(_path).swap(
 			_token,
 			mUsdToken,
-			_amount,
+			amount,
 			_minOut,
 			address(this)
 		);
 
-		(_eventName, _eventParam) = _deposit(_token, mintedAmount, _path);
+		setUint(_setId, mintedAmount);
+		(_eventName, _eventParam) = _deposit(
+			_token,
+			mintedAmount,
+			_path,
+			_stake
+		);
 	}
 
 	/**
@@ -93,6 +128,9 @@ abstract contract PmStableResolver is Events, Helpers {
 	 * @param _token Address of token to withdraw
 	 * @param _credits Credits to withdraw
 	 * @param _minOut Minimum amount of token to withdraw
+	 * @param _unstake from the Vault first?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens withdrawn
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -100,9 +138,13 @@ abstract contract PmStableResolver is Events, Helpers {
 	function withdraw(
 		address _token,
 		uint256 _credits,
-		uint256 _minOut
+		uint256 _minOut,
+		bool _unstake,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
-		uint256 amountWithdrawn = _withdraw(_credits);
+		uint256 credits = getUint(_getId, _credits);
+		uint256 amountWithdrawn = _withdraw(credits, _unstake);
 
 		// Check if needs to be redeemed
 		if (IMasset(mUsdToken).bAssetIndexes(_token) != 0) {
@@ -116,8 +158,14 @@ abstract contract PmStableResolver is Events, Helpers {
 			require(amountWithdrawn >= _minOut, "amountWithdrawn < _minOut");
 		}
 
-		_eventName = "LogWithdraw(address,uint256,address)";
-		_eventParam = abi.encode(mUsdToken, amountWithdrawn, imUsdToken);
+		setUint(_setId, amountWithdrawn);
+		_eventName = "LogWithdraw(address,uint256,address,bool)";
+		_eventParam = abi.encode(
+			mUsdToken,
+			amountWithdrawn,
+			imUsdToken,
+			_unstake
+		);
 	}
 
 	/**
@@ -127,6 +175,9 @@ abstract contract PmStableResolver is Events, Helpers {
 	 * @param _credits Credits to withdraw
 	 * @param _minOut Minimum amount of token to mint
 	 * @param _path Feeder Pool address for _token
+	 * @param _unstake from the Vault first?
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens withdrawn
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -135,7 +186,10 @@ abstract contract PmStableResolver is Events, Helpers {
 		address _token,
 		uint256 _credits,
 		uint256 _minOut,
-		address _path
+		address _path,
+		bool _unstake,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
 		require(_path != address(0), "Path must be set");
 		require(
@@ -143,7 +197,8 @@ abstract contract PmStableResolver is Events, Helpers {
 			"Token is bAsset"
 		);
 
-		uint256 amountWithdrawn = _withdraw(_credits);
+		uint256 credits = getUint(_getId, _credits);
+		uint256 amountWithdrawn = _withdraw(credits, _unstake);
 
 		approve(TokenInterface(mUsdToken), _path, amountWithdrawn);
 		uint256 amountRedeemed = IFeederPool(_path).swap(
@@ -154,18 +209,21 @@ abstract contract PmStableResolver is Events, Helpers {
 			address(this)
 		);
 
-		_eventName = "LogWithdraw(address,uint256,address)";
-		_eventParam = abi.encode(_token, amountRedeemed, _path);
+		setUint(_setId, amountRedeemed);
+		_eventName = "LogWithdraw(address,uint256,address,bool)";
+		_eventParam = abi.encode(_token, amountRedeemed, _path, _unstake);
 	}
 
 	/**
 	 * @dev Claims Rewards
 	 * @notice Claims accrued rewards from the Vault
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens withdrawn
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
 
-	function claimRewards()
+	function claimRewards(uint256 _getId, uint256 _setId)
 		external
 		returns (string memory _eventName, bytes memory _eventParam)
 	{
@@ -189,6 +247,7 @@ abstract contract PmStableResolver is Events, Helpers {
 			platformAmount
 		);
 
+		setUint(_setId, claimedRewardToken);
 		_eventName = "LogClaimRewards(address,uint256,address,uint256)";
 		_eventParam = abi.encode(
 			rewardToken,
@@ -205,6 +264,8 @@ abstract contract PmStableResolver is Events, Helpers {
 	 * @param _output Token address to swap to
 	 * @param _amount Amount of tokens to swap
 	 * @param _minOut Minimum amount of token to mint
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens swapped
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -213,9 +274,16 @@ abstract contract PmStableResolver is Events, Helpers {
 		address _input,
 		address _output,
 		uint256 _amount,
-		uint256 _minOut
+		uint256 _minOut,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
-		approve(TokenInterface(_input), mUsdToken, _amount);
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_input).balanceOf(address(this))
+			: amount;
+
+		approve(TokenInterface(_input), mUsdToken, amount);
 		uint256 amountSwapped;
 
 		// Check the assets and swap accordingly
@@ -223,7 +291,7 @@ abstract contract PmStableResolver is Events, Helpers {
 			// bAsset to mUSD => mint
 			amountSwapped = IMasset(mUsdToken).mint(
 				_input,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
@@ -231,7 +299,7 @@ abstract contract PmStableResolver is Events, Helpers {
 			// mUSD to bAsset => redeem
 			amountSwapped = IMasset(mUsdToken).redeem(
 				_output,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
@@ -240,14 +308,16 @@ abstract contract PmStableResolver is Events, Helpers {
 			amountSwapped = IMasset(mUsdToken).swap(
 				_input,
 				_output,
-				_amount,
+				amount,
 				_minOut,
 				address(this)
 			);
 		}
 
+		setUint(_setId, amountSwapped);
+
 		_eventName = "LogSwap(address,address,uint256,uint256)";
-		_eventParam = abi.encode(_input, _output, _amount, amountSwapped);
+		_eventParam = abi.encode(_input, _output, amount, amountSwapped);
 	}
 
 	/**
@@ -258,6 +328,8 @@ abstract contract PmStableResolver is Events, Helpers {
 	 * @param _amount Amount of tokens to swap
 	 * @param _minOut Minimum amount of token to mint
 	 * @param _path Feeder Pool address to use
+	 * @param _getId ID to retrieve amt
+	 * @param _setId ID stores the amount of tokens swapped
 	 * @return _eventName Event name
 	 * @return _eventParam Event parameters
 	 */
@@ -267,24 +339,32 @@ abstract contract PmStableResolver is Events, Helpers {
 		address _output,
 		uint256 _amount,
 		uint256 _minOut,
-		address _path
+		address _path,
+		uint256 _getId,
+		uint256 _setId
 	) external returns (string memory _eventName, bytes memory _eventParam) {
 		uint256 amountSwapped;
+		uint256 amount = getUint(_getId, _amount);
+		amount = amount == uint256(-1)
+			? TokenInterface(_input).balanceOf(address(this))
+			: amount;
 
-		approve(TokenInterface(_input), _path, _amount);
+		approve(TokenInterface(_input), _path, amount);
 
 		// swaps fAsset to mUSD via Feeder Pool
 		// swaps mUSD to fAsset via Feeder Pool
 		amountSwapped = IFeederPool(_path).swap(
 			_input,
 			_output,
-			_amount,
+			amount,
 			_minOut,
 			address(this)
 		);
 
+		setUint(_setId, amountSwapped);
+
 		_eventName = "LogSwap(address,address,uint256,uint256)";
-		_eventParam = abi.encode(_input, _output, _amount, amountSwapped);
+		_eventParam = abi.encode(_input, _output, amount, amountSwapped);
 	}
 }
 
diff --git a/test/mainnet/mstable/mstable.test.ts b/test/mainnet/mstable/mstable.test.ts
index 53bb6dfc..8ca09a8c 100644
--- a/test/mainnet/mstable/mstable.test.ts
+++ b/test/mainnet/mstable/mstable.test.ts
@@ -120,32 +120,36 @@ describe("MStable", async () => {
         const depositAmount = simpleToExactAmount(100);
         const minOut = depositAmount;
 
-        await executeAndAssertDeposit("deposit", mUsdToken, depositAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertDeposit("deposit", mUsdToken, depositAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should deposit DAI to Vault successfully (mUSD bAsset)", async () => {
         const depositAmount = simpleToExactAmount(100);
         const minOut = calcMinOut(depositAmount, 0.02);
 
-        await executeAndAssertDeposit("deposit", daiToken, depositAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertDeposit("deposit", daiToken, depositAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should deposit alUSD to Vault successfully (via Feeder Pool)", async () => {
         const depositAmount = simpleToExactAmount(100);
         const minOut = calcMinOut(depositAmount, 0.02);
         const path = getToken("alUSD").feederPool;
 
-        await executeAndAssertDeposit("depositViaSwap", alusdToken, depositAmount, dsaWallet0, wallet0, [minOut, path]);
+        await executeAndAssertDeposit("depositViaSwap", alusdToken, depositAmount, dsaWallet0, wallet0, [
+          minOut,
+          path,
+          true
+        ]);
       });
       it("Should withdraw from Vault to mUSD", async () => {
         const withdrawAmount = simpleToExactAmount(100);
         const minOut = simpleToExactAmount(1);
 
-        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should withdraw from Vault to DAI (mUSD bAsset)", async () => {
         const withdrawAmount = simpleToExactAmount(100);
         const minOut = simpleToExactAmount(1);
 
-        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should withdraw from Vault to alUSD (via Feeder Pool)", async () => {
         const withdrawAmount = simpleToExactAmount(100);
@@ -154,7 +158,8 @@ describe("MStable", async () => {
 
         await executeAndAssertWithdraw("withdrawViaSwap", alusdToken, withdrawAmount, dsaWallet0, wallet0, [
           minOut,
-          path
+          path,
+          true
         ]);
       });
       it("Should claim Rewards", async () => {
@@ -168,7 +173,7 @@ describe("MStable", async () => {
           {
             connector: connectorName,
             method: "claimRewards",
-            args: []
+            args: [0, 0]
           }
         ];
 
diff --git a/test/mainnet/mstable/mstable.utils.ts b/test/mainnet/mstable/mstable.utils.ts
index 2614bff8..88bb21ea 100644
--- a/test/mainnet/mstable/mstable.utils.ts
+++ b/test/mainnet/mstable/mstable.utils.ts
@@ -45,7 +45,7 @@ export const executeAndAssertSwap = async (
     {
       connector: connectorName,
       method,
-      args: [tokenFrom.address, tokenTo.address, swapAmount, 1, ...(args ? args : [])]
+      args: [tokenFrom.address, tokenTo.address, swapAmount, 1, ...(args ? args : []), 0, 0]
     }
   ];
 
@@ -81,7 +81,7 @@ export const executeAndAssertDeposit = async (
     {
       connector: connectorName,
       method,
-      args: [tokenFrom.address, depositAmount, ...(args ? args : [])]
+      args: [tokenFrom.address, depositAmount, ...(args ? args : []), 0, 0]
     }
   ];
 
@@ -120,7 +120,7 @@ export const executeAndAssertWithdraw = async (
     {
       connector: connectorName,
       method,
-      args: [tokenTo.address, withdrawAmount, ...(args ? args : [])]
+      args: [tokenTo.address, withdrawAmount, ...(args ? args : []), 0, 0]
     }
   ];
 
diff --git a/test/polygon/mstable/mstable.test.ts b/test/polygon/mstable/mstable.test.ts
index 2198e288..1015f8dd 100644
--- a/test/polygon/mstable/mstable.test.ts
+++ b/test/polygon/mstable/mstable.test.ts
@@ -120,32 +120,36 @@ describe("MStable", async () => {
         const depositAmount = simpleToExactAmount(100);
         const minOut = depositAmount;
 
-        await executeAndAssertDeposit("deposit", mUsdToken, depositAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertDeposit("deposit", mUsdToken, depositAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should deposit DAI to Vault successfully (mUSD bAsset)", async () => {
         const depositAmount = simpleToExactAmount(100);
         const minOut = calcMinOut(depositAmount, 0.02);
 
-        await executeAndAssertDeposit("deposit", daiToken, depositAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertDeposit("deposit", daiToken, depositAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should deposit FRAX to Vault successfully (via Feeder Pool)", async () => {
         const depositAmount = simpleToExactAmount(100);
         const minOut = calcMinOut(depositAmount, 0.02);
         const path = getToken("FRAX").feederPool;
 
-        await executeAndAssertDeposit("depositViaSwap", fraxToken, depositAmount, dsaWallet0, wallet0, [minOut, path]);
+        await executeAndAssertDeposit("depositViaSwap", fraxToken, depositAmount, dsaWallet0, wallet0, [
+          minOut,
+          path,
+          true
+        ]);
       });
       it("Should withdraw from Vault to mUSD", async () => {
         const withdrawAmount = simpleToExactAmount(100);
         const minOut = simpleToExactAmount(1);
 
-        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should withdraw from Vault to DAI (mUSD bAsset)", async () => {
         const withdrawAmount = simpleToExactAmount(100);
         const minOut = simpleToExactAmount(1);
 
-        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut]);
+        await executeAndAssertWithdraw("withdraw", mUsdToken, withdrawAmount, dsaWallet0, wallet0, [minOut, true]);
       });
       it("Should withdraw from Vault to FRAX (via Feeder Pool)", async () => {
         const withdrawAmount = simpleToExactAmount(100);
@@ -154,7 +158,8 @@ describe("MStable", async () => {
 
         await executeAndAssertWithdraw("withdrawViaSwap", fraxToken, withdrawAmount, dsaWallet0, wallet0, [
           minOut,
-          path
+          path,
+          true
         ]);
       });
       it("Should claim Rewards", async () => {
@@ -168,7 +173,7 @@ describe("MStable", async () => {
           {
             connector: connectorName,
             method: "claimRewards",
-            args: []
+            args: [0, 0]
           }
         ];
 
diff --git a/test/polygon/mstable/mstable.utils.ts b/test/polygon/mstable/mstable.utils.ts
index 2614bff8..88bb21ea 100644
--- a/test/polygon/mstable/mstable.utils.ts
+++ b/test/polygon/mstable/mstable.utils.ts
@@ -45,7 +45,7 @@ export const executeAndAssertSwap = async (
     {
       connector: connectorName,
       method,
-      args: [tokenFrom.address, tokenTo.address, swapAmount, 1, ...(args ? args : [])]
+      args: [tokenFrom.address, tokenTo.address, swapAmount, 1, ...(args ? args : []), 0, 0]
     }
   ];
 
@@ -81,7 +81,7 @@ export const executeAndAssertDeposit = async (
     {
       connector: connectorName,
       method,
-      args: [tokenFrom.address, depositAmount, ...(args ? args : [])]
+      args: [tokenFrom.address, depositAmount, ...(args ? args : []), 0, 0]
     }
   ];
 
@@ -120,7 +120,7 @@ export const executeAndAssertWithdraw = async (
     {
       connector: connectorName,
       method,
-      args: [tokenTo.address, withdrawAmount, ...(args ? args : [])]
+      args: [tokenTo.address, withdrawAmount, ...(args ? args : []), 0, 0]
     }
   ];