Skip to content

Commit

Permalink
feat: mBPT deposit into Balancer mBPT Gauge
Browse files Browse the repository at this point in the history
  • Loading branch information
naddison36 committed Apr 11, 2022
1 parent 17b65af commit d0d50bd
Show file tree
Hide file tree
Showing 13 changed files with 215 additions and 129 deletions.
7 changes: 1 addition & 6 deletions contracts/governance/staking/GamifiedToken.sol
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity 0.8.6;

import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { ContextUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
import { SafeCastExtended } from "../../shared/SafeCastExtended.sol";
import { ILockedERC20 } from "./interfaces/ILockedERC20.sol";
import { HeadlessStakingRewards } from "../../rewards/staking/HeadlessStakingRewards.sol";
Expand All @@ -25,8 +23,6 @@ import "./deps/GamifiedTokenStructs.sol";
**/
abstract contract GamifiedToken is
ILockedERC20,
Initializable,
ContextUpgradeable,
HeadlessStakingRewards
{
/// @notice name of this token (ERC20)
Expand Down Expand Up @@ -74,8 +70,7 @@ abstract contract GamifiedToken is
bytes32 _nameArg,
bytes32 _symbolArg,
address _rewardsDistributorArg
) internal initializer {
__Context_init_unchained();
) internal {
_name = _nameArg;
_symbol = _symbolArg;
HeadlessStakingRewards._initialize(_rewardsDistributorArg);
Expand Down
5 changes: 1 addition & 4 deletions contracts/governance/staking/GamifiedVotingToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import { ECDSAUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol";
import { GamifiedToken } from "./GamifiedToken.sol";
import { IGovernanceHook } from "./interfaces/IGovernanceHook.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";

/**
* @title GamifiedVotingToken
Expand All @@ -22,7 +21,7 @@ import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/I
* - Move totalSupply checkpoints to `afterTokenTransfer`
* - Add _governanceHook hook
*/
abstract contract GamifiedVotingToken is Initializable, GamifiedToken {
abstract contract GamifiedVotingToken is GamifiedToken {
struct Checkpoint {
uint32 fromBlock;
uint224 votes;
Expand Down Expand Up @@ -61,8 +60,6 @@ abstract contract GamifiedVotingToken is Initializable, GamifiedToken {
bool _hasPriceCoeff
) GamifiedToken(_nexus, _rewardsToken, _questManager, _hasPriceCoeff) {}

function __GamifiedVotingToken_init() internal initializer {}

/**
* @dev
*/
Expand Down
51 changes: 33 additions & 18 deletions contracts/governance/staking/StakedToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
bytes32 _nameArg,
bytes32 _symbolArg,
address _rewardsDistributorArg
) public initializer {
) public {
__GamifiedToken_init(_nameArg, _symbolArg, _rewardsDistributorArg);
_initializeReentrancyGuard();
safetyData = SafetyData({ collateralisationRatio: 1e18, slashingPercentage: 0 });
Expand All @@ -106,7 +106,7 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
* @dev Only the recollateralisation module, as specified in the mStable Nexus, can execute this
*/
modifier onlyRecollateralisationModule() {
require(_msgSender() == _recollateraliser(), "Only Recollateralisation Module");
require(_msgSender() == _recollateraliser(), "Only Recollateralisation");
_;
}

Expand All @@ -119,7 +119,7 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
}

function _onlyBeforeRecollateralisation() internal view {
require(safetyData.collateralisationRatio == 1e18, "Only while fully collateralised");
require(safetyData.collateralisationRatio == 1e18, "Only while collateralised");
}

/**
Expand All @@ -133,7 +133,7 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {

function _assertNotContract() internal view {
if (_msgSender() != tx.origin) {
require(whitelistedWrappers[_msgSender()], "Not a whitelisted contract");
require(whitelistedWrappers[_msgSender()], "Not whitelisted");
}
}

Expand Down Expand Up @@ -172,17 +172,27 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
}

/**
* @dev Transfers tokens from sender before calling `_settleStake`
* @dev Transfers an `_amount` of staked tokens from sender to this staking contract
* before calling `_settleStake`.
* Can be overridden if the tokens are held elsewhere. eg in the Balancer Pool Gauge.
*/
function _transferAndStake(
uint256 _amount,
address _delegatee,
bool _exitCooldown
) internal {
) internal virtual {
STAKED_TOKEN.safeTransferFrom(_msgSender(), address(this), _amount);
_settleStake(_amount, _delegatee, _exitCooldown);
}

/**
* @dev Gets the total number of staked tokens in this staking contract. eg MTA or mBPT.
* Can be overridden if the tokens are held elsewhere. eg in the Balancer Pool Gauge.
*/
function _balanceOfStakedTokens() internal virtual view returns (uint256 stakedTokens) {
stakedTokens = STAKED_TOKEN.balanceOf(address(this));
}

/**
* @dev Internal stake fn. Can only be called by whitelisted contracts/EOAs and only before a recollateralisation event.
* NOTE - Assumes tokens have already been transferred
Expand Down Expand Up @@ -260,10 +270,7 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
// 1. If recollateralisation has occured, the contract is finished and we can skip all checks
_burnRaw(_msgSender(), _amount, false, true);
// 2. Return a proportionate amount of tokens, based on the collateralisation ratio
STAKED_TOKEN.safeTransfer(
_recipient,
(_amount * safetyData.collateralisationRatio) / 1e18
);
_transferStakedTokens(_recipient, (_amount * safetyData.collateralisationRatio) / 1e18);
emit Withdraw(_msgSender(), _recipient, _amount);
} else {
// 1. If no recollateralisation has occured, the user must be within their UNSTAKE_WINDOW period in order to withdraw
Expand Down Expand Up @@ -303,13 +310,24 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
_burnRaw(_msgSender(), totalWithdraw, exitCooldown, false);
// Log any redemption fee to the rewards contract
_notifyAdditionalReward(totalWithdraw - userWithdrawal);
// Finally transfer tokens back to recipient
STAKED_TOKEN.safeTransfer(_recipient, userWithdrawal);
// Finally transfer staked tokens back to recipient
_transferStakedTokens(_recipient, userWithdrawal);

emit Withdraw(_msgSender(), _recipient, _amount);
}
}

/**
* @dev Transfers an `amount` of staked tokens to the `recipient`. eg MTA or mBPT.
* Can be overridden if the tokens are held elsewhere. eg in the Balancer Pool Gauge.
*/
function _transferStakedTokens(
address _recipient,
uint256 amount
) internal virtual {
STAKED_TOKEN.safeTransfer(_recipient, amount);
}

/**
* @dev Enters a cooldown period, after which (and before the unstake window elapses) a user will be able
* to withdraw part or all of their staked tokens. Note, during this period, a users voting power is significantly reduced.
Expand Down Expand Up @@ -365,11 +383,8 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
// 1. Change collateralisation rate
safetyData.collateralisationRatio = 1e18 - safetyData.slashingPercentage;
// 2. Take slashing percentage
uint256 balance = STAKED_TOKEN.balanceOf(address(this));
STAKED_TOKEN.safeTransfer(
_recollateraliser(),
(balance * safetyData.slashingPercentage) / 1e18
);
uint256 balance = _balanceOfStakedTokens();
_transferStakedTokens(_recollateraliser(), (balance * safetyData.slashingPercentage) / 1e18);
// 3. No functions should work anymore because the colRatio has changed
emit Recollateralised();
}
Expand All @@ -384,7 +399,7 @@ contract StakedToken is GamifiedVotingToken, InitializableReentrancyGuard {
onlyGovernor
onlyBeforeRecollateralisation
{
require(_newRate <= 5e17, "Cannot exceed 50%");
require(_newRate <= 5e17, "> 50%");

safetyData.slashingPercentage = SafeCast.toUint128(_newRate);

Expand Down
Loading

0 comments on commit d0d50bd

Please sign in to comment.