-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit introduces a first version of a `VaultFactory` that later will be extended to be capable of instantiating reward vaults and possible keep track of vault instances per owner. As a first step, this implementation comes with a `createVault()` function which takes care of creating vaults. Because `VaultFactory` also knows about `StakeManager` it can derive the manager's address and stake token from it when creating vaults, allowing the API to be without arguments. Partially addresses #37
- Loading branch information
Showing
6 changed files
with
163 additions
and
14 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 |
---|---|---|
@@ -1,18 +1,24 @@ | ||
CreateVaultTest:testDeployment() (gas: 9774) | ||
CreateVaultTest:test_createVault() (gas: 650992) | ||
ExecuteAccountTest:testDeployment() (gas: 26400) | ||
ExecuteAccountTest:test_RevertWhen_InvalidLimitEpoch() (gas: 982104) | ||
ExecuteAccountTest:test_RevertWhen_InvalidLimitEpoch() (gas: 991602) | ||
LeaveTest:testDeployment() (gas: 26172) | ||
LeaveTest:test_RevertWhen_NoPendingMigration() (gas: 670554) | ||
LeaveTest:test_RevertWhen_NoPendingMigration() (gas: 678051) | ||
LeaveTest:test_RevertWhen_SenderIsNotVault() (gas: 10562) | ||
LockTest:testDeployment() (gas: 26400) | ||
LockTest:test_RevertWhen_DecreasingLockTime() (gas: 985034) | ||
LockTest:test_RevertWhen_DecreasingLockTime() (gas: 994528) | ||
LockTest:test_RevertWhen_SenderIsNotVault() (gas: 10607) | ||
MigrateTest:testDeployment() (gas: 26172) | ||
MigrateTest:test_RevertWhen_NoPendingMigration() (gas: 670393) | ||
MigrateTest:test_RevertWhen_NoPendingMigration() (gas: 677890) | ||
MigrateTest:test_RevertWhen_SenderIsNotVault() (gas: 10629) | ||
SetStakeManagerTest:testDeployment() (gas: 9774) | ||
SetStakeManagerTest:test_RevertWhen_InvalidStakeManagerAddress() (gas: 20481) | ||
SetStakeManagerTest:test_SetStakeManager() (gas: 19869) | ||
StakeManagerTest:testDeployment() (gas: 26172) | ||
StakeTest:testDeployment() (gas: 26172) | ||
StakeTest:test_RevertWhen_SenderIsNotVault() (gas: 10638) | ||
StakedTokenTest:testStakeToken() (gas: 7638) | ||
UnstakeTest:testDeployment() (gas: 26355) | ||
UnstakeTest:test_RevertWhen_FundsLocked() (gas: 981497) | ||
UnstakeTest:test_RevertWhen_SenderIsNotVault() (gas: 10609) | ||
UnstakeTest:test_RevertWhen_FundsLocked() (gas: 990991) | ||
UnstakeTest:test_RevertWhen_SenderIsNotVault() (gas: 10609) | ||
VaultFactoryTest:testDeployment() (gas: 9774) |
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,64 @@ | ||
// SPDX-License-Identifier: MIT | ||
|
||
pragma solidity ^0.8.18; | ||
|
||
import { Ownable2Step } from "@openzeppelin/contracts/access/Ownable2Step.sol"; | ||
import { StakeManager } from "./StakeManager.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 Ownable2Step { | ||
error VaultFactory__InvalidStakeManagerAddress(); | ||
|
||
event VaultCreated(address indexed vault, address indexed owner); | ||
event StakeManagerAddressChanged(address indexed newStakeManagerAddress); | ||
|
||
/// @dev Address of the `StakeManager` contract instance. | ||
StakeManager public stakeManager; | ||
|
||
/// @param _stakeManager Address of the `StakeManager` contract instance. | ||
constructor(address _stakeManager) { | ||
if (_stakeManager == address(0)) { | ||
revert VaultFactory__InvalidStakeManagerAddress(); | ||
} | ||
stakeManager = StakeManager(_stakeManager); | ||
} | ||
|
||
/// @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 = StakeManager(_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 vault = new StakeVault(msg.sender, stakeManager.stakedToken(), stakeManager); | ||
emit VaultCreated(address(vault), msg.sender); | ||
return vault; | ||
} | ||
} |
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
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
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
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,74 @@ | ||
// SPDX-License-Identifier: UNLICENSED | ||
pragma solidity ^0.8.19; | ||
|
||
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; | ||
|
||
import { Test } from "forge-std/Test.sol"; | ||
import { Deploy } from "../script/Deploy.s.sol"; | ||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol"; | ||
|
||
import { StakeManager } from "../contracts/StakeManager.sol"; | ||
import { StakeVault } from "../contracts/StakeVault.sol"; | ||
import { VaultFactory } from "../contracts/VaultFactory.sol"; | ||
|
||
contract VaultFactoryTest is Test { | ||
DeploymentConfig internal deploymentConfig; | ||
|
||
StakeManager internal stakeManager; | ||
|
||
VaultFactory internal vaultFactory; | ||
|
||
address internal deployer; | ||
|
||
address internal stakedToken; | ||
|
||
address internal testUser = makeAddr("testUser"); | ||
|
||
function setUp() public virtual { | ||
Deploy deployment = new Deploy(); | ||
(vaultFactory, stakeManager, deploymentConfig) = deployment.run(); | ||
(deployer, stakedToken) = deploymentConfig.activeNetworkConfig(); | ||
} | ||
|
||
function testDeployment() public { | ||
assertEq(address(vaultFactory.stakeManager()), address(stakeManager)); | ||
} | ||
} | ||
|
||
contract SetStakeManagerTest is VaultFactoryTest { | ||
function setUp() public override { | ||
VaultFactoryTest.setUp(); | ||
} | ||
|
||
function test_RevertWhen_InvalidStakeManagerAddress() public { | ||
vm.startPrank(deployer); | ||
vm.expectRevert(VaultFactory.VaultFactory__InvalidStakeManagerAddress.selector); | ||
vaultFactory.setStakeManager(address(0)); | ||
|
||
vm.expectRevert(VaultFactory.VaultFactory__InvalidStakeManagerAddress.selector); | ||
vaultFactory.setStakeManager(address(stakeManager)); | ||
} | ||
|
||
function test_SetStakeManager() public { | ||
vm.prank(deployer); | ||
vaultFactory.setStakeManager(address(this)); | ||
assertEq(address(vaultFactory.stakeManager()), address(this)); | ||
} | ||
} | ||
|
||
contract CreateVaultTest is VaultFactoryTest { | ||
event VaultCreated(address indexed vault, address indexed owner); | ||
|
||
function setUp() public override { | ||
VaultFactoryTest.setUp(); | ||
} | ||
|
||
function test_createVault() public { | ||
vm.prank(testUser); | ||
vm.expectEmit(false, false, false, false); | ||
emit VaultCreated(makeAddr("some address"), testUser); | ||
StakeVault vault = vaultFactory.createVault(); | ||
assertEq(vault.owner(), testUser); | ||
assertEq(address(vault.stakedToken()), address(stakedToken)); | ||
} | ||
} |