Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
0x-r4bbit committed Jan 24, 2025
1 parent 1294b76 commit e812c3d
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 14 deletions.
7 changes: 4 additions & 3 deletions script/DeployRewardsStreamerMP.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ pragma solidity ^0.8.26;

import { BaseScript } from "./Base.s.sol";
import { DeploymentConfig } from "./DeploymentConfig.s.sol";
import { IStakeManager } from "../src/interfaces/IStakeManager.sol";
import { IStakeManagerProxy } from "../src/interfaces/IStakeManagerProxy.sol";
import { StakeManagerProxy } from "../src/StakeManagerProxy.sol";
import { TransparentProxy } from "../src/TransparentProxy.sol";
import { RewardsStreamerMP } from "../src/RewardsStreamerMP.sol";
import { StakeVault } from "../src/StakeVault.sol";

Expand All @@ -17,11 +18,11 @@ contract DeployRewardsStreamerMPScript is BaseScript {

vm.startBroadcast(deployer);
address impl = address(new RewardsStreamerMP());
address proxy = address(new StakeManagerProxy(impl, initializeData));
address proxy = address(new TransparentProxy(impl, initializeData));
vm.stopBroadcast();

RewardsStreamerMP stakeManager = RewardsStreamerMP(proxy);
StakeVault tempVault = new StakeVault(address(this), IStakeManagerProxy(proxy));
StakeVault tempVault = new StakeVault(IStakeManager(stakeManager).STAKING_TOKEN());
bytes32 vaultCodeHash = address(tempVault).codehash;

vm.startBroadcast(deployer);
Expand Down
20 changes: 20 additions & 0 deletions script/DeployVaultFactory.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import { BaseScript } from "./Base.s.sol";
import { DeploymentConfig } from "./DeploymentConfig.s.sol";
import { VaultFactory } from "../src/VaultFactory.sol";

contract DeployVaultFactoryScript is BaseScript {
function run() public returns (VaultFactory, DeploymentConfig) {
DeploymentConfig deploymentConfig = new DeploymentConfig(broadcaster);
(address deployer,) = deploymentConfig.activeNetworkConfig();

address stakeManager = vm.envOr({ name: "STAKE_MANAGER_ADDRESS", defaultValue: address(0) });
vm.startBroadcast(deployer);
VaultFactory vaultFactory = new VaultFactory(deployer, stakeManager);
vm.stopBroadcast();

return (vaultFactory, deploymentConfig);
}
}
19 changes: 19 additions & 0 deletions script/DeployXPToken.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import { BaseScript } from "./Base.s.sol";
import { DeploymentConfig } from "./DeploymentConfig.s.sol";
import { XPToken } from "../src/XPToken.sol";

contract DeployXPTokenScript is BaseScript {
function run() public returns (XPToken, DeploymentConfig) {
DeploymentConfig deploymentConfig = new DeploymentConfig(broadcaster);
(address deployer,) = deploymentConfig.activeNetworkConfig();

vm.startBroadcast(deployer);
XPToken xpToken = new XPToken();
vm.stopBroadcast();

return (xpToken, deploymentConfig);
}
}
23 changes: 16 additions & 7 deletions src/StakeVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

pragma solidity ^0.8.26;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
// import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IStakeManagerProxy } from "./interfaces/IStakeManagerProxy.sol";
import { IStakeVault } from "./interfaces/IStakeVault.sol";
Expand All @@ -13,7 +15,7 @@ import { IStakeVault } from "./interfaces/IStakeVault.sol";
* @notice A contract to secure user stakes and manage staking with IStakeManager.
* @dev This contract is owned by the user and allows staking, unstaking, and withdrawing tokens.
*/
contract StakeVault is IStakeVault, Ownable {
contract StakeVault is IStakeVault, Initializable, OwnableUpgradeable {
error StakeVault__NotEnoughAvailableBalance();
error StakeVault__InvalidDestinationAddress();
error StakeVault__UpdateNotAvailable();
Expand Down Expand Up @@ -55,13 +57,20 @@ contract StakeVault is IStakeVault, Ownable {

/**
* @notice Initializes the contract with the owner, staked token, and stake manager.
*/
constructor(IERC20 token) {
STAKING_TOKEN = token;
_disableInitializers();
}

/**
* @param _owner The address of the owner.
* @param _stakeManager The address of the StakeManager contract.
*/
constructor(address _owner, IStakeManagerProxy _stakeManager) Ownable(_owner) {
STAKING_TOKEN = _stakeManager.STAKING_TOKEN();
stakeManager = _stakeManager;
stakeManagerImplementationAddress = _stakeManager.implementation();
function initialize(address _owner, address _stakeManager) public initializer {
__Ownable_init(_owner);
stakeManager = IStakeManagerProxy(_stakeManager);
stakeManagerImplementationAddress = stakeManager.implementation();
}

/**
Expand All @@ -82,7 +91,7 @@ contract StakeVault is IStakeVault, Ownable {
/**
* @notice Returns the address of the current owner.
*/
function owner() public view override(Ownable, IStakeVault) returns (address) {
function owner() public view override(OwnableUpgradeable, IStakeVault) returns (address) {
return super.owner();
}

Expand Down
13 changes: 13 additions & 0 deletions src/TransparentProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract TransparentProxy is ERC1967Proxy {
constructor(address _implementation, bytes memory _data) ERC1967Proxy(_implementation, _data) { }

function implementation() external view returns (address) {
return _implementation();
}
}

69 changes: 69 additions & 0 deletions src/VaultFactory.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.26;

import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol";
import { IStakeManagerProxy } from "./interfaces/IStakeManagerProxy.sol";
import { IStakeVaultClone } from "./interfaces/IStakeVaultClone.sol";
import { StakeVault } from "./StakeVault.sol";

/**
* @title VaultFactory
* @author 0x-r4bbit
*
* This contract is reponsible for creating staking vaults for users.
* A user of the staking protocol is able to create multiple vaults to facilitate
* different strategies. For example, a user may want to create a vault for
* a long-term lock period, while also creating a vault that has no lock period
* at all.
*
* @notice This contract is used by users to create staking vaults.
* @dev This contract will be deployed by Status, making Status the owner of the contract.
* @dev A contract address for a `StakeManager` has to be provided to create this contract.
* @dev Reverts with {VaultFactory__InvalidStakeManagerAddress} if the provided
* `StakeManager` address is zero.
* @dev The `StakeManager` contract address can be changed by the owner.
*/
contract VaultFactory is Ownable {
error VaultFactory__InvalidStakeManagerAddress();

event VaultCreated(address indexed vault, address indexed owner);
event StakeManagerAddressChanged(address indexed newStakeManagerAddress);

/// @dev Address of the `StakeManager` contract instance.
IStakeManagerProxy public stakeManager;
address public vaultImplementation;

/// @param _stakeManager Address of the `StakeManager` contract instance.
constructor(address _owner, address _stakeManager) Ownable(_owner) {
if (_stakeManager == address(0)) {
revert VaultFactory__InvalidStakeManagerAddress();
}
stakeManager = IStakeManagerProxy(_stakeManager);
vaultImplementation = address(new StakeVault(stakeManager.STAKING_TOKEN()));
}

/// @notice Sets the `StakeManager` contract address.
/// @dev Only the owner can call this function.
/// @dev Reverts if the provided `StakeManager` address is zero.
/// @dev Emits a {StakeManagerAddressChanged} event.
/// @param _stakeManager Address of the `StakeManager` contract instance.
function setStakeManager(address _stakeManager) external onlyOwner {
if (_stakeManager == address(0) || _stakeManager == address(stakeManager)) {
revert VaultFactory__InvalidStakeManagerAddress();
}
stakeManager = IStakeManagerProxy(_stakeManager);
emit StakeManagerAddressChanged(_stakeManager);
}

/// @notice Creates an instance of a `StakeVault` contract.
/// @dev Anyone can call this function.
/// @dev Emits a {VaultCreated} event.
function createVault() external returns (StakeVault) {
StakeVault clone = StakeVault(Clones.clone(vaultImplementation));
clone.initialize(msg.sender, address(stakeManager));
emit VaultCreated(address(clone), msg.sender);
return clone;
}
}
5 changes: 2 additions & 3 deletions src/interfaces/IStakeManagerProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.26;

import { IStakeManager } from "./IStakeManager.sol";
import { ITransparentProxy } from "./ITransparentProxy.sol";

interface IStakeManagerProxy is IStakeManager {
function implementation() external view returns (address);
}
interface IStakeManagerProxy is IStakeManager, ITransparentProxy {}
8 changes: 8 additions & 0 deletions src/interfaces/IStakeVaultClone.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import { IStakeVault } from "./IStakeVault.sol";
import { ITransparentProxy } from "./ITransparentProxy.sol";

interface IStakeVaultClone is IStakeVault, ITransparentProxy {}

7 changes: 7 additions & 0 deletions src/interfaces/ITransparentProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

interface ITransparentProxy {
function implementation() external view returns (address);
}

1 change: 0 additions & 1 deletion test/RewardsStreamerMP.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils
import { RewardsStreamerMP } from "../src/RewardsStreamerMP.sol";
import { StakeVault } from "../src/StakeVault.sol";
import { IStakeManagerProxy } from "../src/interfaces/IStakeManagerProxy.sol";
import { StakeManagerProxy } from "../src/StakeManagerProxy.sol";
import { MockToken } from "./mocks/MockToken.sol";
import { StackOverflowStakeManager } from "./mocks/StackOverflowStakeManager.sol";

Expand Down

0 comments on commit e812c3d

Please sign in to comment.