Skip to content

Commit

Permalink
Merge pull request #17 from Badger-Finance/delegate-snapshot-generic
Browse files Browse the repository at this point in the history
delegate to arbitrary snapshot + function renames
  • Loading branch information
dapp-whisperer authored Aug 25, 2022
2 parents 2f3f678 + 2271eab commit 303ea03
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 7 deletions.
31 changes: 30 additions & 1 deletion contracts/MyStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {IAuraLocker} from "../interfaces/aura/IAuraLocker.sol";
import {IRewardDistributor} from "../interfaces/hiddenhand/IRewardDistributor.sol";
import {IBribesProcessor} from "../interfaces/badger/IBribesProcessor.sol";
import {IWeth} from "../interfaces/weth/IWeth.sol";
import {IDelegateRegistry} from "../interfaces/snapshot/IDelegateRegistry.sol";

/**
* Version 1:
Expand All @@ -27,6 +28,7 @@ import {IWeth} from "../interfaces/weth/IWeth.sol";
* - Introduces bribes redirection paths for certain bribe tokens
* - Introduces the bribe redirection fee and processing
* - Introduces a setter function for the above
* - Introduces snapshot delegation
*/

contract MyStrategy is BaseStrategy, ReentrancyGuardUpgradeable {
Expand All @@ -47,6 +49,8 @@ contract MyStrategy is BaseStrategy, ReentrancyGuardUpgradeable {

IAuraLocker public constant LOCKER = IAuraLocker(0x3Fa73f1E5d8A792C80F426fc8F84FBF7Ce9bBCAC);

IDelegateRegistry public constant SNAPSHOT = IDelegateRegistry(0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446);

IERC20Upgradeable public constant BAL = IERC20Upgradeable(0xba100000625a3754423978a60c9317c58a424e3D);
IERC20Upgradeable public constant WETH = IERC20Upgradeable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
IERC20Upgradeable public constant AURA = IERC20Upgradeable(0xC0c293ce456fF0ED870ADd98a0828Dd4d2903DBF);
Expand Down Expand Up @@ -116,12 +120,25 @@ contract MyStrategy is BaseStrategy, ReentrancyGuardUpgradeable {
/// ===== Extra Functions =====

/// @dev Change Delegation to another address
function manualSetDelegate(address delegate) external {
function setAuraLockerDelegate(address delegate) external {
_onlyGovernance();
// Set delegate is enough as it will clear previous delegate automatically
LOCKER.delegate(delegate);
}

/// @dev Set snapshot delegation for an arbitrary space ID (Can't be used to remove delegation)
function setSnapshotDelegate(bytes32 id, address delegate) external {
_onlyGovernance();
// Set delegate is enough as it will clear previous delegate automatically
SNAPSHOT.setDelegate(id, delegate);
}

/// @dev Clears snapshot delegation for an arbitrary space ID
function clearSnapshotDelegate(bytes32 id) external {
_onlyGovernance();
SNAPSHOT.clearDelegate(id);
}

/// @dev Should we check if the amount requested is more than what we can return on withdrawal?
function setWithdrawalSafetyCheck(bool newWithdrawalSafetyCheck) external {
_onlyGovernance();
Expand Down Expand Up @@ -232,10 +249,22 @@ contract MyStrategy is BaseStrategy, ReentrancyGuardUpgradeable {
return protectedTokens;
}

/// @dev Get aura locker delegate address
function getAuraLockerDelegate() public view returns (address) {
return LOCKER.delegates(address(this));
}

/// @dev Get aura locker delegate address
/// @dev Duplicate of getAuraLockerDelegate() for legacy support
function getDelegate() public view returns (address) {
return LOCKER.delegates(address(this));
}

/// @dev Get snapshot delegation, for a given space ID
function getSnapshotDelegate(bytes32 id) external view returns (address) {
return SNAPSHOT.delegation(address(this), id);
}

/// ===== Internal Core Implementations =====

/// @dev Deposit `_amount` of want, investing it to earn yield
Expand Down
4 changes: 3 additions & 1 deletion interfaces/snapshot/IDelegateRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,7 @@ pragma solidity 0.6.12;
interface IDelegateRegistry {
function setDelegate(bytes32 id, address delegate) external;

function delegation(address, bytes32) external returns (address);
function clearDelegate(bytes32 id) external;

function delegation(address, bytes32) external view returns (address);
}
4 changes: 4 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
interface,
accounts,
chain,
Contract
)
from _setup.config import (
WANT,
Expand Down Expand Up @@ -37,6 +38,9 @@ def deployer():
def user():
return accounts[9]

@pytest.fixture
def delegation_registry():
return Contract.from_explorer("0x469788fE6E9E9681C6ebF3bF78e7Fd26Fc015446")

## Fund the account
@pytest.fixture
Expand Down
4 changes: 2 additions & 2 deletions tests/integration/test_strategy_permissions.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ def test_strategy_action_permissions(
# setWithdrawalSafetyCheck
for actor in actorsToCheck:
if actor == strategy.governance():
strategy.manualSetDelegate(deployer, {"from": actor})
strategy.setAuraLockerDelegate(deployer, {"from": actor})
else:
with brownie.reverts("onlyGovernance"):
strategy.manualSetDelegate(deployer, {"from": actor})
strategy.setAuraLockerDelegate(deployer, {"from": actor})


def test_strategy_pausing_permissions(deployer, vault, strategy, want, keeper):
Expand Down
68 changes: 65 additions & 3 deletions tests/test_custom.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import brownie
from brownie import interface, chain, accounts
from helpers.constants import MaxUint256
from helpers.constants import MaxUint256, AddressZero
from helpers.SnapshotManager import SnapshotManager
from helpers.time import days

Expand Down Expand Up @@ -176,7 +176,10 @@ def test_delegation_was_correct(deployer, vault, strategy, want, governance, ran

chain.sleep(10000 * 13) # Mine so we get some interest

strategy.manualSetDelegate(randomUser, {"from": governance})
strategy.setAuraLockerDelegate(randomUser, {"from": governance})
assert strategy.getAuraLockerDelegate() == randomUser

# Variant maintained for read compatibility
assert strategy.getDelegate() == randomUser


Expand Down Expand Up @@ -230,4 +233,63 @@ def test_cant_take_eth(deployer, strategy):

def test_can_set_slippage(strategy, strategist):
strategy.setAuraBalToBalEthBptMinOutBps(10, {"from": strategist})
assert strategy.auraBalToBalEthBptMinOutBps() == 10
assert strategy.auraBalToBalEthBptMinOutBps() == 10

def test_snapshot_delegation(delegation_registry, strategy, governance, strategist):
target_delegate = "0x14F83fF95D4Ec5E8812DDf42DA1232b0ba1015e6"
CONVEX_SPACE_ID = "0x6376782e65746800000000000000000000000000000000000000000000000000"
BALANCER_SPACE_ID = "0x62616c616e6365722e6574680000000000000000000000000000000000000000"

# No delegates set at the beginning
assert strategy.getSnapshotDelegate(CONVEX_SPACE_ID) == AddressZero
assert strategy.getSnapshotDelegate(BALANCER_SPACE_ID) == AddressZero

# Confirm non-governance address cannot set delegate
with brownie.reverts():
strategy.setSnapshotDelegate(CONVEX_SPACE_ID, target_delegate, {'from': strategist})

with brownie.reverts():
strategy.setSnapshotDelegate(BALANCER_SPACE_ID, target_delegate, {'from': strategist})

# Set both spaces to target delegate
strategy.setSnapshotDelegate(CONVEX_SPACE_ID, target_delegate, {'from': governance})
strategy.setSnapshotDelegate(BALANCER_SPACE_ID, target_delegate, {'from': governance})

# Confirm via strategy getSnapshotDelegate
convex_space_delegate = strategy.getSnapshotDelegate(CONVEX_SPACE_ID)
balancer_space_delegate = strategy.getSnapshotDelegate(BALANCER_SPACE_ID)

assert convex_space_delegate == target_delegate
assert balancer_space_delegate == target_delegate

# Confirm via snapshot registry directly
convex_space_delegate = delegation_registry.delegation(strategy, CONVEX_SPACE_ID)
balancer_space_delegate = delegation_registry.delegation(strategy, BALANCER_SPACE_ID)

assert convex_space_delegate == target_delegate
assert balancer_space_delegate == target_delegate

# Confirm non-governance address cannot clear delegate
with brownie.reverts():
strategy.clearSnapshotDelegate(CONVEX_SPACE_ID, {'from': strategist})

with brownie.reverts():
strategy.clearSnapshotDelegate(BALANCER_SPACE_ID, {'from': strategist})

# Clear delegation for both space IDs
strategy.clearSnapshotDelegate(CONVEX_SPACE_ID, {'from': governance})
strategy.clearSnapshotDelegate(BALANCER_SPACE_ID, {'from': governance})

# Confirm via strategy getSnapshotDelegate
convex_space_delegate = strategy.getSnapshotDelegate(CONVEX_SPACE_ID)
balancer_space_delegate = strategy.getSnapshotDelegate(BALANCER_SPACE_ID)

assert convex_space_delegate == AddressZero
assert balancer_space_delegate == AddressZero

# Confirm via snapshot registry directly
convex_space_delegate = delegation_registry.delegation(strategy, CONVEX_SPACE_ID)
balancer_space_delegate = delegation_registry.delegation(strategy, BALANCER_SPACE_ID)

assert convex_space_delegate == AddressZero
assert balancer_space_delegate == AddressZero

0 comments on commit 303ea03

Please sign in to comment.