generated from yearn/brownie-strategy-mix
-
Notifications
You must be signed in to change notification settings - Fork 3
16slim/ve angle #6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
16slim
wants to merge
45
commits into
master
Choose a base branch
from
16slim/ve-angle
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
45 commits
Select commit
Hold shift + click to select a range
fe6844d
feat: initial version of central veAngle voter
16slim 7a07c62
fix: changes necessary in tests to make them pass with central veAngle
16slim 0be3adf
feat: lock and increase amount locked
16slim e35f803
feat: add 2nd harvest
16slim c863f46
fix: remove percentLock
16slim 3676450
fix: remove percentLock setter
16slim 64c75d7
fix: set governance to ychad in constructors
16slim 649c309
fix: remove .address and rename voter fixtures
16slim f189c10
fix: remove treasury check for strategy proxy
16slim f389c7e
feat: add two-step process to set governance
16slim 46571e0
fix: naming convention for proxy, setProxy
16slim d0140f0
feat: changed prepareMigration logic to convert back to want
16slim a9ff880
chore: rebase onto most recent security-approved master
charlesndalton 4096176
fix: fix multiple strategies using stablemaster
16slim 31ff372
chore: fix translation errors
16slim 9db840c
fix: remove debugging event
16slim 88f18fd
feat: add whitelister interface to test lock
16slim 618637b
feat: test lock & release veAngle
16slim 15ce260
chore: remove debugging make
16slim de4174d
fix: remove approveStrategy as it's included in fixture
16slim 5072669
chore: removed unused deposit and approve
16slim 06b0dae
chore: remove unnecessary approve
16slim aa72c39
fix: change test to check voter proxy instead of treasury
16slim 2435759
feat: add boolean to approve and whitelist voter
16slim a6aa5d6
fix: fix _withdrawSome()
16slim cdbe6c4
chore: remove .py tests
16slim 915b8a4
fix: remove unused cursor variable
16slim dfc900d
chore: rename angle to angleToken
16slim 16f7e42
feat: check allowance function
16slim 432873a
fix: remove token parameter from claimRewards
16slim 8c607ed
chore: rename deposit to stake
16slim ada3a34
fix: typo in _withdrawSome
16slim 8fb4d14
chore: remove comment and add space
16slim d7571d9
feat: save gas approving angle from voter
16slim f4e0c73
chore: rename balanceOf to balanceOfSTakedSanToken
16slim 8c63ff1
feat: add access control to lock() function
16slim 528a4c4
fix: replace fro withdrawAll in strategy
16slim 8ba167e
fix: necessary changes for access control lock to pass
16slim c848384
feat: Angle rewards stay in voter and not in proxy
16slim 542f347
fix: hardcode unlock time and remove access control to locl
16slim 748466f
fix: include force harvest trigger fix
16slim 5c3038e
chore: remove unused imports
16slim ea48325
feat: add revert message to safeExecute
16slim cf81296
feat: clean migration process
16slim 6937fad
feat: include message error in safeExecute
16slim File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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,181 @@ | ||
| // SPDX-License-Identifier: AGPL-3.0 | ||
| pragma solidity ^0.8.12; | ||
| pragma experimental ABIEncoderV2; | ||
|
|
||
| import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | ||
| import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
| import {Address} from "@openzeppelin/contracts/utils/Address.sol"; | ||
|
|
||
| import {YearnAngleVoter} from "./YearnAngleVoter.sol"; | ||
|
|
||
| import "./interfaces/curve/ICurve.sol"; | ||
| import "./interfaces/Angle/IStableMaster.sol"; | ||
| import "./interfaces/Angle/IAngleGauge.sol"; | ||
| import "./interfaces/Uniswap/IUniV2.sol"; | ||
|
|
||
| library SafeVoter { | ||
| function safeExecute( | ||
| YearnAngleVoter voter, | ||
| address to, | ||
| uint256 value, | ||
| bytes memory data | ||
| ) internal { | ||
| (bool success, bytes memory result) = voter.execute(to, value, data); | ||
| require(success, string(result)); | ||
| } | ||
| } | ||
|
|
||
| contract AngleStrategyVoterProxy { | ||
| using SafeVoter for YearnAngleVoter; | ||
| using SafeERC20 for IERC20; | ||
| using Address for address; | ||
|
|
||
| YearnAngleVoter public yearnAngleVoter; | ||
| address public constant angleToken = address(0x31429d1856aD1377A8A0079410B297e1a9e214c2); | ||
|
|
||
| uint256 public constant UNLOCK_TIME = 4 * 365 * 24 * 60 * 60; | ||
|
|
||
| // gauge => strategies | ||
| mapping(address => address) public strategies; | ||
| mapping(address => bool) public voters; | ||
| address public governance; | ||
|
|
||
| constructor(address _voter) public { | ||
| governance = address(0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52); | ||
| yearnAngleVoter = YearnAngleVoter(_voter); | ||
| } | ||
|
|
||
| function setGovernance(address _governance) external { | ||
| require(msg.sender == governance, "!governance"); | ||
| governance = _governance; | ||
| } | ||
|
|
||
| function approveStrategy(address _gauge, address _strategy) external { | ||
| require(msg.sender == governance, "!governance"); | ||
| strategies[_gauge] = _strategy; | ||
| } | ||
|
|
||
| function revokeStrategy(address _gauge) external { | ||
| require(msg.sender == governance, "!governance"); | ||
| strategies[_gauge] = address(0); | ||
| } | ||
|
|
||
| function approveVoter(address _voter) external { | ||
| require(msg.sender == governance, "!governance"); | ||
| voters[_voter] = true; | ||
| } | ||
|
|
||
| function revokeVoter(address _voter) external { | ||
| require(msg.sender == governance, "!governance"); | ||
| voters[_voter] = false; | ||
| } | ||
|
|
||
| function lock(uint256 amount) external { | ||
| if (amount > 0 && amount <= IERC20(angleToken).balanceOf(address(yearnAngleVoter))) { | ||
| yearnAngleVoter.createLock(amount, block.timestamp + UNLOCK_TIME); | ||
| } | ||
| } | ||
|
|
||
| function increaseAmount(uint256 amount) external { | ||
| if (amount > 0 && amount <= IERC20(angleToken).balanceOf(address(yearnAngleVoter))) { | ||
| yearnAngleVoter.increaseAmount(amount); | ||
| } | ||
| } | ||
|
|
||
| function vote(address _gauge, uint256 _amount) public { | ||
| require(voters[msg.sender], "!voter"); | ||
| yearnAngleVoter.safeExecute(_gauge, 0, abi.encodeWithSignature("vote_for_gauge_weights(address,uint256)", _gauge, _amount)); | ||
| } | ||
|
|
||
| function withdraw( | ||
| address _gauge, | ||
| address _token, | ||
| uint256 _amount | ||
| ) public returns (uint256) { | ||
| require(strategies[_gauge] == msg.sender, "!strategy"); | ||
| uint256 _balance = IERC20(_token).balanceOf(address(yearnAngleVoter)); | ||
| yearnAngleVoter.safeExecute(_gauge, 0, abi.encodeWithSignature("withdraw(uint256)", _amount)); | ||
| _balance = IERC20(_token).balanceOf(address(yearnAngleVoter)) - _balance; | ||
| yearnAngleVoter.safeExecute(_token, 0, abi.encodeWithSignature("transfer(address,uint256)", msg.sender, _balance)); | ||
charlesndalton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return _balance; | ||
| } | ||
|
|
||
| function withdrawFromStableMaster(address stableMaster, uint256 amount, | ||
| address poolManager, address token, address gauge) external { | ||
16slim marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| require(strategies[gauge] == msg.sender, "!strategy"); | ||
|
|
||
| IERC20(token).safeTransfer(address(yearnAngleVoter), amount); | ||
|
|
||
| yearnAngleVoter.safeExecute(stableMaster, 0, abi.encodeWithSignature( | ||
| "withdraw(uint256,address,address,address)", | ||
| amount, | ||
| address(yearnAngleVoter), | ||
| msg.sender, | ||
| poolManager | ||
| )); | ||
| } | ||
|
|
||
| function balanceOfStakedSanToken(address _gauge) public view returns (uint256) { | ||
| return IERC20(_gauge).balanceOf(address(yearnAngleVoter)); | ||
| } | ||
|
|
||
| function withdrawAll(address _gauge, address _token) external returns (uint256) { | ||
charlesndalton marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| require(strategies[_gauge] == msg.sender, "!strategy"); | ||
| return withdraw(_gauge, _token, balanceOfStakedSanToken(_gauge)); | ||
| } | ||
|
|
||
| function stake(address gauge, uint256 amount, address token) external { | ||
| require(strategies[gauge] == msg.sender, "!strategy"); | ||
|
|
||
| _checkAllowance(token, gauge, amount); | ||
|
|
||
| yearnAngleVoter.safeExecute(gauge, 0, abi.encodeWithSignature( | ||
| "deposit(uint256)", | ||
| amount | ||
| )); | ||
| } | ||
|
|
||
| function depositToStableMaster(address stableMaster, uint256 amount, | ||
| address poolManager, address token, address gauge) external { | ||
| require(strategies[gauge] == msg.sender, "!strategy"); | ||
|
|
||
| IERC20(token).safeTransfer(address(yearnAngleVoter), amount); | ||
|
|
||
| _checkAllowance(token, stableMaster, amount); | ||
|
|
||
| yearnAngleVoter.safeExecute(stableMaster, 0, abi.encodeWithSignature( | ||
| "deposit(uint256,address,address)", | ||
| amount, | ||
| address(yearnAngleVoter), | ||
| poolManager | ||
| )); | ||
| } | ||
|
|
||
| function claimRewards(address _gauge) external { | ||
| require(strategies[_gauge] == msg.sender, "!strategy"); | ||
| yearnAngleVoter.safeExecute( | ||
| _gauge, | ||
| 0, | ||
| abi.encodeWithSelector( | ||
| IAngleGauge.claim_rewards.selector | ||
| ) | ||
| ); | ||
| address _token = address(angleToken); | ||
| yearnAngleVoter.safeExecute(_token, 0, abi.encodeWithSignature("transfer(address,uint256)", msg.sender, IERC20(_token).balanceOf(address(yearnAngleVoter)))); | ||
| } | ||
|
|
||
| function balanceOfSanToken(address sanToken) public view returns (uint256) { | ||
| return IERC20(sanToken).balanceOf(address(yearnAngleVoter)); | ||
| } | ||
|
|
||
| function _checkAllowance( | ||
| address _token, | ||
| address _contract, | ||
| uint256 _amount | ||
| ) internal { | ||
| if (IERC20(_token).allowance(address(yearnAngleVoter), _contract) < _amount) { | ||
| yearnAngleVoter.safeExecute(_token, 0, abi.encodeWithSignature("approve(address,uint256)", _contract, 0)); | ||
| yearnAngleVoter.safeExecute(_token, 0, abi.encodeWithSignature("approve(address,uint256)", _contract, _amount)); | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.