Skip to content

Commit

Permalink
Add initialize to Keeper, VaultsRegistry
Browse files Browse the repository at this point in the history
  • Loading branch information
tsudmi committed Oct 11, 2023
1 parent 8ae9330 commit 8f0a83e
Show file tree
Hide file tree
Showing 27 changed files with 267 additions and 71 deletions.
10 changes: 5 additions & 5 deletions abi/Errors.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,11 @@
"name": "InvalidHealthFactor",
"type": "error"
},
{
"inputs": [],
"name": "InvalidInitialHarvest",
"type": "error"
},
{
"inputs": [],
"name": "InvalidLiqBonusPercent",
Expand Down Expand Up @@ -184,11 +189,6 @@
"name": "MaxOraclesExceeded",
"type": "error"
},
{
"inputs": [],
"name": "NegativeAssetsDelta",
"type": "error"
},
{
"inputs": [],
"name": "NotCollateralized",
Expand Down
13 changes: 13 additions & 0 deletions abi/IKeeper.json
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_owner",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down
13 changes: 13 additions & 0 deletions abi/IVaultsRegistry.json
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_owner",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
Expand Down
6 changes: 5 additions & 1 deletion contracts/interfaces/IKeeper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ import {IKeeperRewards} from './IKeeperRewards.sol';
* @notice Defines the interface for the Keeper contract
*/
interface IKeeper is IKeeperOracles, IKeeperRewards, IKeeperValidators {

/**
* @notice Initializes the Keeper contract. Can only be called once.
* @param _owner The address of the owner
*/
function initialize(address _owner) external;
}
6 changes: 6 additions & 0 deletions contracts/interfaces/IVaultsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,10 @@ interface IVaultsRegistry {
* @param factory The address of the factory to remove from the whitelist
*/
function removeFactory(address factory) external;

/**
* @notice Function for initializing the registry. Can only be called once during the deployment.
* @param _owner The address of the owner of the contract
*/
function initialize(address _owner) external;
}
13 changes: 13 additions & 0 deletions contracts/keeper/Keeper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import {IKeeper} from '../interfaces/IKeeper.sol';
import {KeeperValidators} from './KeeperValidators.sol';
import {KeeperRewards} from './KeeperRewards.sol';
import {KeeperOracles} from './KeeperOracles.sol';
import {Errors} from '../libraries/Errors.sol';

/**
* @title Keeper
* @author StakeWise
* @notice Defines the functionality for updating Vaults' rewards and approving validators registrations
*/
contract Keeper is KeeperOracles, KeeperRewards, KeeperValidators, IKeeper {
bool private _initialized;

/**
* @dev Constructor
* @param sharedMevEscrow The address of the shared MEV escrow contract
Expand All @@ -37,4 +40,14 @@ contract Keeper is KeeperOracles, KeeperRewards, KeeperValidators, IKeeper {
KeeperRewards(sharedMevEscrow, vaultsRegistry, osToken, _rewardsDelay, maxAvgRewardPerSecond)
KeeperValidators(validatorsRegistry)
{}

/// @inheritdoc IKeeper
function initialize(address _owner) external override onlyOwner {
if (_owner == address(0)) revert Errors.ZeroAddress();
if (_initialized) revert Errors.AccessDenied();

// transfer ownership
_transferOwnership(_owner);
_initialized = true;
}
}
2 changes: 1 addition & 1 deletion contracts/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,6 @@ library Errors {
error InvalidCheckpointIndex();
error InvalidCheckpointValue();
error MaxOraclesExceeded();
error NegativeAssetsDelta();
error InvalidInitialHarvest();
error ClaimTooEarly();
}
3 changes: 1 addition & 2 deletions contracts/misc/CumulativeMerkleDrop.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@ contract CumulativeMerkleDrop is Ownable2Step, ICumulativeMerkleDrop {
* @param _owner The address of the owner of the contract
* @param _token The address of the token contract
*/
constructor(address _owner, address _token) Ownable(msg.sender) {
_transferOwnership(_owner);
constructor(address _owner, address _token) Ownable(_owner) {
token = IERC20(_token);
}

Expand Down
4 changes: 4 additions & 0 deletions contracts/osToken/OsToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ contract OsToken is ERC20, Ownable2Step, IOsToken {
* @param _keeper The address of the Keeper contract
* @param _checker The address of the OsTokenChecker contract
* @param _treasury The address of the DAO treasury
* @param _owner The address of the owner of the contract
* @param _feePercent The fee percent applied on the rewards
* @param _capacity The amount after which the osToken stops accepting deposits
* @param _name The name of the ERC20 token
Expand All @@ -60,18 +61,21 @@ contract OsToken is ERC20, Ownable2Step, IOsToken {
address _keeper,
address _checker,
address _treasury,
address _owner,
uint16 _feePercent,
uint256 _capacity,
string memory _name,
string memory _symbol
) ERC20(_name, _symbol) Ownable(msg.sender) {
if (_owner == address(0)) revert Errors.ZeroAddress();
keeper = _keeper;
checker = _checker;
_lastUpdateTimestamp = uint64(block.timestamp);

setCapacity(_capacity);
setTreasury(_treasury);
setFeePercent(_feePercent);
_transferOwnership(_owner);
}

/// @inheritdoc IERC20
Expand Down
12 changes: 12 additions & 0 deletions contracts/vaults/VaultsRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ contract VaultsRegistry is Ownable2Step, IVaultsRegistry {
/// @inheritdoc IVaultsRegistry
mapping(address => bool) public override vaultImpls;

bool private _initialized;

/**
* @dev Constructor
*/
Expand Down Expand Up @@ -61,4 +63,14 @@ contract VaultsRegistry is Ownable2Step, IVaultsRegistry {
factories[factory] = false;
emit FactoryRemoved(factory);
}

/// @inheritdoc IVaultsRegistry
function initialize(address _owner) external override onlyOwner {
if (_owner == address(0)) revert Errors.ZeroAddress();
if (_initialized) revert Errors.AccessDenied();

// transfer ownership
_transferOwnership(_owner);
_initialized = true;
}
}
10 changes: 7 additions & 3 deletions contracts/vaults/ethereum/EthGenesisVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,9 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault {
// it's the first harvest, deduct rewards accumulated so far in legacy pool
totalAssetsDelta -= SafeCast.toInt256(_rewardEthToken.totalRewards());
// the first state update must be with positive delta
if (totalAssetsDelta < 0) revert Errors.NegativeAssetsDelta();
if (_poolEscrow.owner() != address(this) || totalAssetsDelta < 0) {
revert Errors.InvalidInitialHarvest();
}
}

// fetch total assets controlled by legacy pool
Expand Down Expand Up @@ -153,7 +155,9 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault {

/// @inheritdoc IEthGenesisVault
function migrate(address receiver, uint256 assets) external override returns (uint256 shares) {
if (msg.sender != address(_rewardEthToken)) revert Errors.AccessDenied();
if (msg.sender != address(_rewardEthToken) || _poolEscrow.owner() != address(this)) {
revert Errors.AccessDenied();
}

_checkCollateralized();
_checkHarvested();
Expand Down Expand Up @@ -184,7 +188,7 @@ contract EthGenesisVault is Initializable, EthVault, IEthGenesisVault {
address receiver,
uint256 assets
) internal virtual override(VaultEnterExit, VaultEthStaking) {
_pullAssets();
if (assets > super._vaultAssets()) _pullAssets();
return super._transferVaultAssets(receiver, assets);
}

Expand Down
2 changes: 2 additions & 0 deletions helpers/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const NETWORKS: {
governor: '0xFF2B6d2d5c205b99E2e6f607B6aFA3127B9957B6',
validatorsRegistry: '0xff50ed3d0ec03aC01D4C79aAd74928BFF48a7b2b',
securityDeposit: 1000000000,
exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours

// Keeper
oracles: [
Expand Down Expand Up @@ -65,6 +66,7 @@ export const NETWORKS: {
governor: '0x144a98cb1CdBb23610501fE6108858D9B7D24934',
validatorsRegistry: '0x00000000219ab540356cBB839Cbe05303d7705Fa',
securityDeposit: 1000000000,
exitedAssetsClaimDelay: 24 * 60 * 60, // 24 hours

// Keeper
oracles: [], // TODO: update with oracles' addresses
Expand Down
1 change: 1 addition & 0 deletions helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ export type NetworkConfig = {
governor: string
validatorsRegistry: string
securityDeposit: BigNumberish
exitedAssetsClaimDelay: number

// Keeper
oracles: string[]
Expand Down
2 changes: 1 addition & 1 deletion helpers/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { HardhatRuntimeEnvironment } from 'hardhat/types/runtime'

export async function deployContract(tx: any): Promise<Contract> {
const result = await tx
await result.deployTransaction.wait()
await result.waitForDeployment()
return result
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stakewise/v3-core",
"version": "0.1.0",
"version": "1.0.0",
"description": "Liquid staking protocol for Ethereum",
"main": "index.js",
"scripts": {
Expand Down
47 changes: 31 additions & 16 deletions tasks/eth-full-deploy-local.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
RewardSplitter__factory,
RewardSplitterFactory__factory,
CumulativeMerkleDrop__factory,
OsTokenChecker__factory,
} from '../typechain-types'
import { deployContract } from '../helpers/utils'
import { NetworkConfig, Networks } from '../helpers/types'
Expand Down Expand Up @@ -55,15 +56,22 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ
const sharedMevEscrowAddress = await sharedMevEscrow.getAddress()
console.log('SharedMevEscrow deployed at', sharedMevEscrowAddress)

const osTokenChecker = await deployContract(
new OsTokenChecker__factory(deployer).deploy(vaultsRegistryAddress)
)
const osTokenCheckerAddress = await osTokenChecker.getAddress()
console.log('OsTokenChecker deployed at', osTokenCheckerAddress)

const keeperCalculatedAddress = ethers.getCreateAddress({
from: deployer.address,
nonce: (await ethers.provider.getTransactionCount(deployer.address)) + 1,
})
const osToken = await deployContract(
new OsToken__factory(deployer).deploy(
keeperCalculatedAddress,
vaultsRegistryAddress,
osTokenCheckerAddress,
treasury.address,
governor.address,
goerliConfig.osTokenFeePercent,
goerliConfig.osTokenCapacity,
goerliConfig.osTokenName,
Expand Down Expand Up @@ -107,7 +115,8 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ
ltvPercent: goerliConfig.ltvPercent,
})
)
console.log('OsTokenConfig deployed at', osTokenConfig.address)
const osTokenConfigAddress = await osTokenConfig.getAddress()
console.log('OsTokenConfig deployed at', osTokenConfigAddress)

const factories: string[] = []
for (const vaultType of ['EthVault', 'EthPrivVault', 'EthErc20Vault', 'EthPrivErc20Vault']) {
Expand All @@ -119,8 +128,9 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ
vaultsRegistryAddress,
validatorsRegistryAddress,
osTokenAddress,
osTokenConfig.address,
osTokenConfigAddress,
sharedMevEscrowAddress,
goerliConfig.exitedAssetsClaimDelay,
],
})) as string
console.log(`${vaultType} implementation deployed at`, vaultImpl)
Expand All @@ -134,15 +144,16 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ
await vaultsRegistry.addFactory(ethVaultFactoryAddress)
console.log(`Added ${vaultType}Factory to VaultsRegistry`)

await osToken.setVaultImplementation(vaultImpl, true)
console.log(`Added ${vaultType} implementation to OsToken`)
await vaultsRegistry.addVaultImpl(vaultImpl)
console.log(`Added ${vaultType} implementation to VaultsRegistry`)
factories.push(ethVaultFactoryAddress)
}

const priceFeed = await deployContract(
new PriceFeed__factory(deployer).deploy(osTokenAddress, goerliConfig.priceFeedDescription)
)
console.log('PriceFeed deployed at', priceFeed.address)
const priceFeedAddress = await priceFeed.getAddress()
console.log('PriceFeed deployed at', priceFeedAddress)

const rewardSplitterImpl = await deployContract(new RewardSplitter__factory(deployer).deploy())
const rewardSplitterImplAddress = await rewardSplitterImpl.getAddress()
Expand All @@ -151,27 +162,30 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ
const rewardSplitterFactory = await deployContract(
new RewardSplitterFactory__factory(deployer).deploy(rewardSplitterImplAddress)
)
console.log('RewardSplitterFactory deployed at', rewardSplitterFactory.address)
const rewardSplitterFactoryAddress = await rewardSplitterFactory.getAddress()
console.log('RewardSplitterFactory deployed at', rewardSplitterFactoryAddress)

const cumulativeMerkleDrop = await deployContract(
new CumulativeMerkleDrop__factory(deployer).deploy(
goerliConfig.liquidityCommittee,
goerliConfig.swiseToken
)
)
console.log('CumulativeMerkleDrop deployed at', cumulativeMerkleDrop.address)
const cumulativeMerkleDropAddress = await cumulativeMerkleDrop.getAddress()
console.log('CumulativeMerkleDrop deployed at', cumulativeMerkleDropAddress)

// pass ownership to governor
await vaultsRegistry.transferOwnership(governor.address)
await keeper.transferOwnership(governor.address)
await osToken.transferOwnership(governor.address)
console.log('Ownership transferred to governor')

// accept ownership from governor
await Keeper__factory.connect(keeperAddress, governor).acceptOwnership()
await OsToken__factory.connect(osTokenAddress, governor).acceptOwnership()
await VaultsRegistry__factory.connect(vaultsRegistryAddress, governor).acceptOwnership()
console.log('Ownership accepted from governor')
// transfer ownership to governor
await vaultsRegistry.initialize(governor.address)
console.log('VaultsRegistry ownership transferred to', governor.address)

await keeper.initialize(governor.address)
console.log('Keeper ownership transferred to', governor.address)

// Save the addresses
const addresses = {
Expand All @@ -183,9 +197,10 @@ task('eth-full-deploy-local', 'deploys StakeWise V3 for Ethereum to local networ
EthPrivErc20VaultFactory: factories[3],
SharedMevEscrow: sharedMevEscrowAddress,
OsToken: osTokenAddress,
OsTokenConfig: osTokenConfig.address,
PriceFeed: priceFeed.address,
RewardSplitterFactory: rewardSplitterFactory.address,
OsTokenConfig: osTokenConfigAddress,
OsTokenChecker: osTokenCheckerAddress,
PriceFeed: priceFeedAddress,
RewardSplitterFactory: rewardSplitterFactoryAddress,
}
const json = JSON.stringify(addresses, null, 2)
const fileName = `${DEPLOYMENTS_DIR}/${networkName}.json`
Expand Down
Loading

0 comments on commit 8f0a83e

Please sign in to comment.