-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
545 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.7.0; | ||
pragma experimental ABIEncoderV2; | ||
|
||
import "./MockSwapper.sol"; | ||
import "../connectors/BalPowerIndexConnector.sol"; | ||
|
||
contract MockBalConnector is BalPowerIndexConnector { | ||
event MockWrapperCallback(uint256 withdrawAmount); | ||
event TestMigrate(bytes migrateData); | ||
|
||
MockSwapper immutable swapper; | ||
|
||
constructor( | ||
address _assetManager, | ||
address _staking, | ||
address _underlying, | ||
address _rewardsToken, | ||
address _rewardsMinter, | ||
address _vault, | ||
bytes32 _pId, | ||
address _swapper | ||
) BalPowerIndexConnector(_assetManager, _staking, _underlying, _rewardsToken, _rewardsMinter, _vault, _pId) { | ||
swapper = MockSwapper(_swapper); | ||
} | ||
|
||
function _swapRewardsToUnderlying(uint256 _rewardsAmount) internal override { | ||
swapper.swap(address(REWARDS_TOKEN), address(UNDERLYING), _rewardsAmount); | ||
} | ||
|
||
function getSwapperAddress() public view override returns (address) { | ||
return address(swapper); | ||
} | ||
|
||
function migrate(bytes calldata _migrateData) external virtual override { | ||
emit TestMigrate(_migrateData); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,233 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
pragma solidity ^0.7.0; | ||
|
||
import "@powerpool/balancer-v2-solidity-utils/contracts/openzeppelin/ReentrancyGuard.sol"; | ||
import "@powerpool/balancer-v2-solidity-utils/contracts/openzeppelin/SafeMath.sol"; | ||
import "@powerpool/balancer-v2-solidity-utils/contracts/openzeppelin/EIP712.sol"; | ||
|
||
import "./IBalancerMinter.sol"; | ||
import "./IBalancerToken.sol"; | ||
import "../../interfaces/ILiquidityGauge.sol"; | ||
|
||
contract BalancerMinterMock is ReentrancyGuard, EIP712 { | ||
using SafeMath for uint256; | ||
|
||
IBalancerToken private immutable _token; | ||
|
||
// user -> gauge -> value | ||
mapping(address => mapping(address => uint256)) private _minted; | ||
// minter -> user -> can mint? | ||
mapping(address => mapping(address => bool)) private _allowedMinter; | ||
|
||
// Signature replay attack prevention for each user. | ||
mapping(address => uint256) internal _nextNonce; | ||
|
||
// solhint-disable-next-line var-name-mixedcase | ||
bytes32 private immutable _SET_MINTER_APPROVAL_TYPEHASH = keccak256( | ||
"SetMinterApproval(address minter,bool approval,uint256 nonce,uint256 deadline)" | ||
); | ||
|
||
event MinterApprovalSet(address indexed user, address indexed minter, bool approval); | ||
|
||
constructor(IBalancerToken token) EIP712("Balancer Minter", "1") { | ||
_token = token; | ||
} | ||
|
||
function getDomainSeparator() external view returns (bytes32) { | ||
return _domainSeparatorV4(); | ||
} | ||
|
||
function getNextNonce(address user) external view returns (uint256) { | ||
return _nextNonce[user]; | ||
} | ||
|
||
/** | ||
* @notice Returns the address of the Balancer Governance Token | ||
*/ | ||
function getBalancerToken() external view returns (IERC20) { | ||
return _token; | ||
} | ||
|
||
/** | ||
* @notice Mint everything which belongs to `msg.sender` and send to them | ||
* @param gauge `LiquidityGauge` address to get mintable amount from | ||
*/ | ||
function mint(address gauge) external nonReentrant returns (uint256) { | ||
return _mintFor(gauge, msg.sender); | ||
} | ||
|
||
/** | ||
* @notice Mint everything which belongs to `msg.sender` across multiple gauges | ||
* @param gauges List of `LiquidityGauge` addresses | ||
*/ | ||
function mintMany(address[] calldata gauges) external nonReentrant returns (uint256) { | ||
return _mintForMany(gauges, msg.sender); | ||
} | ||
|
||
/** | ||
* @notice Mint tokens for `user` | ||
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf | ||
* @param gauge `LiquidityGauge` address to get mintable amount from | ||
* @param user Address to mint to | ||
*/ | ||
function mintFor(address gauge, address user) external nonReentrant returns (uint256) { | ||
require(_allowedMinter[msg.sender][user], "Caller not allowed to mint for user"); | ||
return _mintFor(gauge, user); | ||
} | ||
|
||
/** | ||
* @notice Mint tokens for `user` across multiple gauges | ||
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf | ||
* @param gauges List of `LiquidityGauge` addresses | ||
* @param user Address to mint to | ||
*/ | ||
function mintManyFor(address[] calldata gauges, address user) external nonReentrant returns (uint256) { | ||
require(_allowedMinter[msg.sender][user], "Caller not allowed to mint for user"); | ||
return _mintForMany(gauges, user); | ||
} | ||
|
||
/** | ||
* @notice The total number of tokens minted for `user` from `gauge` | ||
*/ | ||
function minted(address user, address gauge) external view returns (uint256) { | ||
return _minted[user][gauge]; | ||
} | ||
|
||
/** | ||
* @notice Whether `minter` is approved to mint tokens for `user` | ||
*/ | ||
function getMinterApproval(address minter, address user) external view returns (bool) { | ||
return _allowedMinter[minter][user]; | ||
} | ||
|
||
/** | ||
* @notice Set whether `minter` is approved to mint tokens on your behalf | ||
*/ | ||
function setMinterApproval(address minter, bool approval) public { | ||
_setMinterApproval(minter, msg.sender, approval); | ||
} | ||
|
||
/** | ||
* @notice Set whether `minter` is approved to mint tokens on behalf of `user`, who has signed a message authorizing | ||
* them. | ||
*/ | ||
function setMinterApprovalWithSignature( | ||
address minter, | ||
bool approval, | ||
address user, | ||
uint256 deadline, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) external { | ||
// solhint-disable-next-line not-rely-on-time | ||
require(deadline > block.timestamp, "Signature expired"); | ||
|
||
uint256 nonce = _nextNonce[user]++; | ||
|
||
bytes32 structHash = keccak256(abi.encode(_SET_MINTER_APPROVAL_TYPEHASH, minter, approval, nonce, deadline)); | ||
bytes32 digest = _hashTypedDataV4(structHash); | ||
|
||
address recoveredAddress = ecrecover(digest, v, r, s); | ||
|
||
// ecrecover returns the zero address on recover failure, so we need to handle that explicitly. | ||
require(recoveredAddress != address(0) && recoveredAddress == user, "Invalid signature"); | ||
|
||
_setMinterApproval(minter, user, approval); | ||
} | ||
|
||
function _setMinterApproval( | ||
address minter, | ||
address user, | ||
bool approval | ||
) private { | ||
_allowedMinter[minter][user] = approval; | ||
emit MinterApprovalSet(user, minter, approval); | ||
} | ||
|
||
// Internal functions | ||
function _updateGauge(address gauge, address user) internal returns (uint256 tokensToMint) { | ||
ILiquidityGauge(gauge).user_checkpoint(user); | ||
uint256 totalMint = ILiquidityGauge(gauge).integrate_fraction(user); | ||
tokensToMint = totalMint.sub(_minted[user][gauge]); | ||
|
||
if (tokensToMint > 0) { | ||
_minted[user][gauge] = totalMint; | ||
} | ||
} | ||
|
||
function _mintFor(address gauge, address user) internal returns (uint256 tokensToMint) { | ||
tokensToMint = _updateGauge(gauge, user); | ||
if (tokensToMint > 0) { | ||
_token.mint(user, tokensToMint); | ||
} | ||
} | ||
|
||
function _mintForMany(address[] calldata gauges, address user) internal returns (uint256 tokensToMint) { | ||
uint256 length = gauges.length; | ||
for (uint256 i = 0; i < length; ++i) { | ||
tokensToMint = tokensToMint.add(_updateGauge(gauges[i], user)); | ||
} | ||
|
||
if (tokensToMint > 0) { | ||
_token.mint(user, tokensToMint); | ||
} | ||
} | ||
|
||
// The below functions are near-duplicates of functions available above. | ||
// They are included for ABI compatibility with snake_casing as used in vyper contracts. | ||
// solhint-disable func-name-mixedcase | ||
|
||
/** | ||
* @notice Whether `minter` is approved to mint tokens for `user` | ||
*/ | ||
function allowed_to_mint_for(address minter, address user) external view returns (bool) { | ||
return _allowedMinter[minter][user]; | ||
} | ||
|
||
/** | ||
* @notice Mint everything which belongs to `msg.sender` across multiple gauges | ||
* @dev This function is not recommended as `mintMany()` is more flexible and gas efficient | ||
* @param gauges List of `LiquidityGauge` addresses | ||
*/ | ||
function mint_many(address[8] calldata gauges) external nonReentrant { | ||
for (uint256 i = 0; i < 8; ++i) { | ||
if (gauges[i] == address(0)) { | ||
break; | ||
} | ||
_mintFor(gauges[i], msg.sender); | ||
} | ||
} | ||
|
||
/** | ||
* @notice Mint tokens for `user` | ||
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf | ||
* @param gauge `LiquidityGauge` address to get mintable amount from | ||
* @param user Address to mint to | ||
*/ | ||
function mint_for(address gauge, address user) external nonReentrant { | ||
if (_allowedMinter[msg.sender][user]) { | ||
_mintFor(gauge, user); | ||
} | ||
} | ||
|
||
/** | ||
* @notice Toggle whether `minter` is approved to mint tokens for `user` | ||
*/ | ||
function toggle_approve_mint(address minter) external { | ||
setMinterApproval(minter, !_allowedMinter[minter][msg.sender]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// SPDX-License-Identifier: GPL-3.0-or-later | ||
// This program is free software: you can redistribute it and/or modify | ||
// it under the terms of the GNU General Public License as published by | ||
// the Free Software Foundation, either version 3 of the License, or | ||
// (at your option) any later version. | ||
|
||
// This program is distributed in the hope that it will be useful, | ||
// but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
// GNU General Public License for more details. | ||
|
||
// You should have received a copy of the GNU General Public License | ||
// along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
pragma solidity ^0.7.0; | ||
|
||
import "./IBalancerTokenAdmin.sol"; | ||
|
||
interface IBalancerMinter { | ||
event Minted(address indexed recipient, address gauge, uint256 minted); | ||
|
||
/** | ||
* @notice Returns the address of the Balancer Governance Token | ||
*/ | ||
function getBalancerToken() external view returns (IERC20); | ||
|
||
/** | ||
* @notice Returns the address of the Balancer Token Admin contract | ||
*/ | ||
function getBalancerTokenAdmin() external view returns (IBalancerTokenAdmin); | ||
|
||
/** | ||
* @notice Mint everything which belongs to `msg.sender` and send to them | ||
* @param gauge `LiquidityGauge` address to get mintable amount from | ||
*/ | ||
function mint(address gauge) external returns (uint256); | ||
|
||
/** | ||
* @notice Mint everything which belongs to `msg.sender` across multiple gauges | ||
* @param gauges List of `LiquidityGauge` addresses | ||
*/ | ||
function mintMany(address[] calldata gauges) external returns (uint256); | ||
|
||
/** | ||
* @notice Mint tokens for `user` | ||
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf | ||
* @param gauge `LiquidityGauge` address to get mintable amount from | ||
* @param user Address to mint to | ||
*/ | ||
function mintFor(address gauge, address user) external returns (uint256); | ||
|
||
/** | ||
* @notice Mint tokens for `user` across multiple gauges | ||
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf | ||
* @param gauges List of `LiquidityGauge` addresses | ||
* @param user Address to mint to | ||
*/ | ||
function mintManyFor(address[] calldata gauges, address user) external returns (uint256); | ||
|
||
/** | ||
* @notice The total number of tokens minted for `user` from `gauge` | ||
*/ | ||
function minted(address user, address gauge) external view returns (uint256); | ||
|
||
/** | ||
* @notice Whether `minter` is approved to mint tokens for `user` | ||
*/ | ||
function getMinterApproval(address minter, address user) external view returns (bool); | ||
|
||
/** | ||
* @notice Set whether `minter` is approved to mint tokens on your behalf | ||
*/ | ||
function setMinterApproval(address minter, bool approval) external; | ||
|
||
/** | ||
* @notice Set whether `minter` is approved to mint tokens on behalf of `user`, who has signed a message authorizing | ||
* them. | ||
*/ | ||
function setMinterApprovalWithSignature( | ||
address minter, | ||
bool approval, | ||
address user, | ||
uint256 deadline, | ||
uint8 v, | ||
bytes32 r, | ||
bytes32 s | ||
) external; | ||
|
||
// The below functions are near-duplicates of functions available above. | ||
// They are included for ABI compatibility with snake_casing as used in vyper contracts. | ||
// solhint-disable func-name-mixedcase | ||
|
||
/** | ||
* @notice Whether `minter` is approved to mint tokens for `user` | ||
*/ | ||
function allowed_to_mint_for(address minter, address user) external view returns (bool); | ||
|
||
/** | ||
* @notice Mint everything which belongs to `msg.sender` across multiple gauges | ||
* @dev This function is not recommended as `mintMany()` is more flexible and gas efficient | ||
* @param gauges List of `LiquidityGauge` addresses | ||
*/ | ||
function mint_many(address[8] calldata gauges) external; | ||
|
||
/** | ||
* @notice Mint tokens for `user` | ||
* @dev Only possible when `msg.sender` has been approved by `user` to mint on their behalf | ||
* @param gauge `LiquidityGauge` address to get mintable amount from | ||
* @param user Address to mint to | ||
*/ | ||
function mint_for(address gauge, address user) external; | ||
|
||
/** | ||
* @notice Toggle whether `minter` is approved to mint tokens for `user` | ||
*/ | ||
function toggle_approve_mint(address minter) external; | ||
} |
Oops, something went wrong.