-
Notifications
You must be signed in to change notification settings - Fork 3
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
4 changed files
with
559 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,110 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity 0.8.15; | ||
|
||
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; | ||
|
||
import "../../core/interfaces/IERC677.sol"; | ||
import "../../core/interfaces/IERC677Receiver.sol"; | ||
|
||
/** | ||
* @title Staking Mock | ||
* @dev Mocks contract for testing | ||
*/ | ||
contract StakingMockV1 is IERC677Receiver { | ||
IERC677 public token; | ||
|
||
mapping(address => uint256) public stakedBalances; | ||
address public migration; | ||
|
||
uint256 public baseReward; | ||
uint256 public delegationReward; | ||
|
||
bool public active; | ||
bool public paused; | ||
|
||
constructor(address _token) { | ||
token = IERC677(_token); | ||
active = true; | ||
} | ||
|
||
function onTokenTransfer( | ||
address _sender, | ||
uint256 _value, | ||
bytes calldata | ||
) external { | ||
require(msg.sender == address(token), "has to be token"); | ||
stakedBalances[_sender] += _value; | ||
} | ||
|
||
function getCommunityStakerLimits() external pure returns (uint256, uint256) { | ||
return (10 ether, 7000 ether); | ||
} | ||
|
||
function getOperatorLimits() external pure returns (uint256, uint256) { | ||
return (10 ether, 50000 ether); | ||
} | ||
|
||
function getMaxPoolSize() external pure returns (uint256) { | ||
return 25000000 ether; | ||
} | ||
|
||
function getTotalStakedAmount() external view returns (uint256) { | ||
return token.balanceOf(address(this)); | ||
} | ||
|
||
function setActive(bool _active) external { | ||
active = _active; | ||
} | ||
|
||
function isActive() external view returns (bool) { | ||
return active; | ||
} | ||
|
||
function isOperator(address) external pure returns (bool) { | ||
return true; | ||
} | ||
|
||
function getStake(address staker) external view returns (uint256) { | ||
return stakedBalances[staker]; | ||
} | ||
|
||
function setMigration(address _migration) external { | ||
migration = _migration; | ||
} | ||
|
||
function migrate(bytes calldata) external { | ||
token.transferAndCall(migration, stakedBalances[msg.sender], "0x0"); | ||
} | ||
|
||
function setBaseReward(uint256 _amount) external { | ||
baseReward = _amount; | ||
} | ||
|
||
function getBaseReward(address) external view returns (uint256) { | ||
return baseReward; | ||
} | ||
|
||
function setDelegationReward(uint256 _amount) external { | ||
delegationReward = _amount; | ||
} | ||
|
||
function getDelegationReward(address) external view returns (uint256) { | ||
return delegationReward; | ||
} | ||
|
||
function getMigrationTarget() external view returns (address) { | ||
return migration; | ||
} | ||
|
||
function setPaused(bool _paused) external { | ||
paused = _paused; | ||
} | ||
|
||
function isPaused() external view returns (bool) { | ||
return paused; | ||
} | ||
|
||
function raiseAlert() external { | ||
token.transfer(msg.sender, 100 ether); | ||
} | ||
} |
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,65 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity 0.8.15; | ||
|
||
import "./VaultV1.sol"; | ||
|
||
/** | ||
* @title Operator Vault | ||
* @notice Vault contract for depositing LINK collateral into the Chainlink staking controller as an operator | ||
*/ | ||
contract OperatorVaultV1 is VaultV1 { | ||
using SafeERC20Upgradeable for IERC20Upgradeable; | ||
|
||
address public operator; | ||
|
||
event AlertRaised(); | ||
|
||
/// @custom:oz-upgrades-unsafe-allow constructor | ||
constructor() { | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize( | ||
address _token, | ||
address _vaultController, | ||
address _stakeController, | ||
address _operator | ||
) public reinitializer(2) { | ||
__Vault_init(_token, _vaultController, _stakeController); | ||
operator = _operator; | ||
} | ||
|
||
modifier onlyOperator() { | ||
require(operator == msg.sender, "Operator only"); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice returns the total balance of this contract in the Chainlink staking contract | ||
* @return total balance | ||
*/ | ||
function getTotalDeposits() public view override returns (uint256) { | ||
return | ||
stakeController.getStake(address(this)) + | ||
stakeController.getBaseReward(address(this)) + | ||
stakeController.getDelegationReward(address(this)); | ||
} | ||
|
||
/** | ||
* @notice raises an alert in the Chainlink staking contract | ||
*/ | ||
function raiseAlert() external onlyOperator { | ||
stakeController.raiseAlert(); | ||
token.safeTransfer(vaultController, token.balanceOf(address(this))); | ||
emit AlertRaised(); | ||
} | ||
|
||
/** | ||
* @notice sets the operator address if not already set | ||
* @param _operator operator address | ||
*/ | ||
function setOperator(address _operator) external onlyOwner { | ||
require(operator == address(0), "Operator already set"); | ||
operator = _operator; | ||
} | ||
} |
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,108 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity 0.8.15; | ||
|
||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; | ||
import "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol"; | ||
|
||
import "../../../core/interfaces/IERC677.sol"; | ||
|
||
interface IStakingV1 { | ||
function getCommunityStakerLimits() external view returns (uint256, uint256); | ||
|
||
function getOperatorLimits() external view returns (uint256, uint256); | ||
|
||
function getMaxPoolSize() external view returns (uint256); | ||
|
||
function getTotalStakedAmount() external view returns (uint256); | ||
|
||
function isActive() external view returns (bool); | ||
|
||
function isOperator(address staker) external view returns (bool); | ||
|
||
function getStake(address staker) external view returns (uint256); | ||
|
||
function migrate(bytes calldata data) external; | ||
|
||
function getBaseReward(address staker) external view returns (uint256); | ||
|
||
function getDelegationReward(address staker) external view returns (uint256); | ||
|
||
function getMigrationTarget() external view returns (address); | ||
|
||
function isPaused() external view returns (bool); | ||
|
||
function raiseAlert() external; | ||
} | ||
|
||
/** | ||
* @title Vault | ||
* @notice Base vault contract for depositing LINK collateral into the Chainlink staking controller | ||
*/ | ||
abstract contract VaultV1 is Initializable, UUPSUpgradeable, OwnableUpgradeable { | ||
using SafeERC20Upgradeable for IERC20Upgradeable; | ||
|
||
IERC20Upgradeable public token; | ||
address public vaultController; | ||
IStakingV1 public stakeController; | ||
|
||
uint256[10] private __gap; | ||
|
||
function __Vault_init( | ||
address _token, | ||
address _vaultController, | ||
address _stakeController | ||
) public onlyInitializing { | ||
__Ownable_init(); | ||
__UUPSUpgradeable_init(); | ||
token = IERC20Upgradeable(_token); | ||
vaultController = _vaultController; | ||
stakeController = IStakingV1(_stakeController); | ||
} | ||
|
||
modifier onlyVaultController() { | ||
require(vaultController == msg.sender, "Vault controller only"); | ||
_; | ||
} | ||
|
||
/** | ||
* @notice deposits tokens into the Chainlink staking contract | ||
* @param _amount amount to deposit | ||
*/ | ||
function deposit(uint256 _amount) external onlyVaultController { | ||
token.safeTransferFrom(msg.sender, address(this), _amount); | ||
IERC677(address(token)).transferAndCall(address(stakeController), _amount, "0x00"); | ||
} | ||
|
||
/** | ||
* @notice withdrawals are not yet implemented in this iteration of Chainlink staking | ||
*/ | ||
function withdraw(uint256) external view onlyVaultController { | ||
revert("withdrawals not yet implemented"); | ||
} | ||
|
||
/** | ||
* @notice returns the total balance of this contract in the Chainlink staking contract | ||
* @return total balance | ||
*/ | ||
function getTotalDeposits() public view virtual returns (uint256); | ||
|
||
/** | ||
* @notice returns the principal balance of this contract in the Chainlink staking contract | ||
* @return principal balance | ||
*/ | ||
function getPrincipalDeposits() public view returns (uint256) { | ||
return stakeController.getStake(address(this)); | ||
} | ||
|
||
/** | ||
* @notice migrates the deposited tokens into a new stake controller | ||
*/ | ||
function migrate(bytes calldata data) external onlyVaultController { | ||
stakeController.migrate(data); | ||
stakeController = IStakingV1(stakeController.getMigrationTarget()); | ||
} | ||
|
||
function _authorizeUpgrade(address) internal override onlyOwner {} | ||
} |
Oops, something went wrong.