@nodeset/contracts
Version:
Protocol for accessing NodeSet's Constellation Ethereum staking network
481 lines (434 loc) • 24.8 kB
JavaScript
/*** Dependencies ********************/
import { RocketStorage } from '../_utils/artifacts';
const hre = require('hardhat');
const pako = require('pako');
const fs = require('fs');
const Web3 = require('web3');
/*** Utility Methods *****************/
// Compress / decompress ABIs
function compressABI(abi) {
return Buffer.from(pako.deflate(JSON.stringify(abi))).toString('base64');
}
function decompressABI(abi) {
return JSON.parse(pako.inflate(Buffer.from(abi, 'base64'), { to: 'string' }));
}
// Load ABI files and parse
function loadABI(abiFilePath) {
return JSON.parse(fs.readFileSync(abiFilePath));
}
/*** Contracts ***********************/
// Storage
const rocketStorage = artifacts.require('RocketStorage.sol');
// Network contracts
const contracts = {
// Vault
rocketVault: artifacts.require('RocketVault.sol'),
// Tokens
rocketTokenRPLFixedSupply: artifacts.require('RocketTokenDummyRPL.sol'),
rocketTokenRETH: artifacts.require('RocketTokenRETH.sol'),
rocketTokenRPL: artifacts.require('RocketTokenRPL.sol'),
// Auction
rocketAuctionManager: artifacts.require('RocketAuctionManager.sol'),
// Deposit
rocketDepositPool: artifacts.require('RocketDepositPool.sol'),
// Minipool
rocketMinipoolDelegate: artifacts.require('RocketMinipoolDelegate.sol'),
rocketMinipoolManager: artifacts.require('RocketMinipoolManagerOld.sol'),
rocketMinipoolQueue: artifacts.require('RocketMinipoolQueue.sol'),
rocketMinipoolPenalty: artifacts.require('RocketMinipoolPenalty.sol'),
// Network
rocketNetworkBalances: artifacts.require('RocketNetworkBalancesOld.sol'),
rocketNetworkFees: artifacts.require('RocketNetworkFees.sol'),
rocketNetworkPrices: artifacts.require('RocketNetworkPricesOld.sol'),
rocketNetworkPenalties: artifacts.require('RocketNetworkPenalties.sol'),
// Rewards
rocketRewardsPool: artifacts.require('RocketRewardsPoolOld.sol'),
rocketClaimDAO: artifacts.require('RocketClaimDAOOld.sol'),
// Node
rocketNodeDeposit: artifacts.require('RocketNodeDepositOld.sol'),
rocketNodeManager: artifacts.require('RocketNodeManagerOld.sol'),
rocketNodeStaking: artifacts.require('RocketNodeStakingOld.sol'),
// DAOs
rocketDAOProposal: artifacts.require('RocketDAOProposal.sol'),
rocketDAONodeTrusted: artifacts.require('RocketDAONodeTrusted.sol'),
rocketDAONodeTrustedProposals: artifacts.require('RocketDAONodeTrustedProposals.sol'),
rocketDAONodeTrustedActions: artifacts.require('RocketDAONodeTrustedActions.sol'),
rocketDAONodeTrustedUpgrade: artifacts.require('RocketDAONodeTrustedUpgrade.sol'),
rocketDAONodeTrustedSettingsMembers: artifacts.require('RocketDAONodeTrustedSettingsMembers.sol'),
rocketDAONodeTrustedSettingsProposals: artifacts.require('RocketDAONodeTrustedSettingsProposals.sol'),
rocketDAONodeTrustedSettingsMinipool: artifacts.require('RocketDAONodeTrustedSettingsMinipool.sol'),
rocketDAOProtocol: artifacts.require('RocketDAOProtocolOld.sol'),
rocketDAOProtocolProposals: artifacts.require('RocketDAOProtocolProposalsOld.sol'),
rocketDAOProtocolActions: artifacts.require('RocketDAOProtocolActions.sol'),
rocketDAOProtocolSettingsInflation: artifacts.require('RocketDAOProtocolSettingsInflationOld.sol'),
rocketDAOProtocolSettingsRewards: artifacts.require('RocketDAOProtocolSettingsRewardsOld.sol'),
rocketDAOProtocolSettingsAuction: artifacts.require('RocketDAOProtocolSettingsAuctionOld.sol'),
rocketDAOProtocolSettingsNode: artifacts.require('RocketDAOProtocolSettingsNode.sol'),
rocketDAOProtocolSettingsNetwork: artifacts.require('RocketDAOProtocolSettingsNetworkOld.sol'),
rocketDAOProtocolSettingsDeposit: artifacts.require('RocketDAOProtocolSettingsDepositOld.sol'),
rocketDAOProtocolSettingsMinipool: artifacts.require('RocketDAOProtocolSettingsMinipoolOld.sol'),
// v1.1
rocketMerkleDistributorMainnet: artifacts.require('RocketMerkleDistributorMainnet.sol'),
rocketDAONodeTrustedSettingsRewards: artifacts.require('RocketDAONodeTrustedSettingsRewards.sol'),
rocketSmoothingPool: artifacts.require('RocketSmoothingPool.sol'),
rocketNodeDistributorFactory: artifacts.require('RocketNodeDistributorFactory.sol'),
rocketNodeDistributorDelegate: artifacts.require('RocketNodeDistributorDelegate.sol'),
rocketMinipoolFactory: artifacts.require('RocketMinipoolFactory.sol'),
// v1.2
rocketMinipoolBase: artifacts.require('RocketMinipoolBase.sol'),
rocketMinipoolBondReducer: artifacts.require('RocketMinipoolBondReducer.sol'),
// v1.3
rocketNetworkSnapshots: artifacts.require('RocketNetworkSnapshots.sol'),
rocketNetworkVoting: artifacts.require('RocketNetworkVoting.sol'),
rocketDAOProtocolSettingsProposals: artifacts.require('RocketDAOProtocolSettingsProposals.sol'),
rocketDAOProtocolVerifier: artifacts.require('RocketDAOProtocolVerifier.sol'),
rocketDAOSecurity: artifacts.require('RocketDAOSecurity.sol'),
rocketDAOSecurityActions: artifacts.require('RocketDAOSecurityActions.sol'),
rocketDAOSecurityProposals: artifacts.require('RocketDAOSecurityProposals.sol'),
rocketDAOProtocolSettingsSecurity: artifacts.require('RocketDAOProtocolSettingsSecurity.sol'),
rocketDAOProtocolProposal: artifacts.require('RocketDAOProtocolProposal.sol'),
rocketDAOProtocolNew: artifacts.require('RocketDAOProtocol.sol'),
rocketDAOProtocolProposalsNew: artifacts.require('RocketDAOProtocolProposals.sol'),
rocketNetworkPricesNew: artifacts.require('RocketNetworkPrices.sol'),
rocketNodeDepositNew: artifacts.require('RocketNodeDeposit.sol'),
rocketNodeManagerNew: artifacts.require('RocketNodeManager.sol'),
rocketNodeStakingNew: artifacts.require('RocketNodeStaking.sol'),
rocketClaimDAONew: artifacts.require('RocketClaimDAO.sol'),
rocketDAOProtocolSettingsRewardsNew: artifacts.require('RocketDAOProtocolSettingsRewards.sol'),
rocketMinipoolManagerNew: artifacts.require('RocketMinipoolManager.sol'),
rocketRewardsPoolNew: artifacts.require('RocketRewardsPool.sol'),
rocketNetworkBalancesNew: artifacts.require('RocketNetworkBalances.sol'),
rocketDAOProtocolSettingsNetworkNew: artifacts.require('RocketDAOProtocolSettingsNetwork.sol'),
rocketDAOProtocolSettingsAuctionNew: artifacts.require('RocketDAOProtocolSettingsAuction.sol'),
rocketDAOProtocolSettingsDepositNew: artifacts.require('RocketDAOProtocolSettingsDeposit.sol'),
rocketDAOProtocolSettingsInflationNew: artifacts.require('RocketDAOProtocolSettingsInflation.sol'),
rocketDAOProtocolSettingsMinipoolNew: artifacts.require('RocketDAOProtocolSettingsMinipool.sol'),
rocketUpgradeOneDotThree: artifacts.require('RocketUpgradeOneDotThree.sol'),
// Utils
addressQueueStorage: artifacts.require('AddressQueueStorage.sol'),
addressSetStorage: artifacts.require('AddressSetStorage.sol'),
};
// Development helper contracts
const revertOnTransfer = artifacts.require('RevertOnTransfer.sol');
const rocketNodeDepositLEB4 = artifacts.require('RocketNodeDepositLEB4.sol');
// Instance contract ABIs
const abis = {
// Minipool
rocketMinipool: [artifacts.require('RocketMinipoolDelegate.sol'), artifacts.require('RocketMinipoolBase.sol')],
};
// Construct ABI for rocketMinipool
const rocketMinipoolAbi = []
.concat(artifacts.require('RocketMinipoolDelegate.sol').abi)
.concat(artifacts.require('RocketMinipoolBase.sol').abi)
.filter(i => i.type !== 'fallback' && i.type !== 'receive');
rocketMinipoolAbi.push({ stateMutability: 'payable', type: 'fallback' });
rocketMinipoolAbi.push({ stateMutability: 'payable', type: 'receive' });
/*** Deployment **********************/
// Deploy Rocket Pool
export async function deployRocketPool() {
// Set our web3 provider
const network = hre.network;
let $web3 = new Web3(network.provider);
// Accounts
let accounts = await $web3.eth.getAccounts(function (error, result) {
if (error != null) {
console.log(error);
console.log("Error retrieving accounts.'");
}
return result;
});
console.log(`Using network: ${network.name}`);
console.log(`Deploying from: ${accounts[0]}`)
console.log('\n');
const casperDepositABI = loadABI('./contracts/Testing/Rocketpool/contract/casper/compiled/Deposit.abi');
// Live deployment
if (network.name === 'live') {
// Casper live contract address
let casperDepositAddress = '0x00000000219ab540356cBB839Cbe05303d7705Fa';
contracts.casperDeposit = {
address: casperDepositAddress,
abi: casperDepositABI,
precompiled: true
};
// Add our live RPL token address in place
contracts.rocketTokenRPLFixedSupply.address = '0xb4efd85c19999d84251304bda99e90b92300bd93';
}
// Goerli test network
else if (network.name === 'goerli') {
// Casper deposit contract details
const casperDepositAddress = '0xff50ed3d0ec03ac01d4c79aad74928bff48a7b2b'; // Prater
contracts.casperDeposit = {
address: casperDepositAddress,
abi: casperDepositABI,
precompiled: true
};
}
// Test network deployment
else {
// Precompiled - Casper Deposit Contract
const casperDeposit = new $web3.eth.Contract(casperDepositABI, null, {
from: accounts[0],
gasPrice: '20000000000' // 20 gwei
});
// Create the contract now
const casperDepositContract = await casperDeposit.deploy(
// Casper deployment
{
data: fs.readFileSync('./contracts/Testing/Rocketpool/contract/casper/compiled/Deposit.bin').toString()
}).send({
from: accounts[0],
gas: 8000000,
gasPrice: '20000000000'
});
// Set the Casper deposit address
let casperDepositAddress = casperDepositContract._address;
// Store it in storage
contracts.casperDeposit = {
address: casperDepositAddress,
abi: casperDepositABI,
precompiled: true
};
}
// Deploy rocketStorage first - has to be done in this order so that the following contracts already know the storage address
const rs = await rocketStorage.new();
rocketStorage.setAsDeployed(rs);
const rsTx = await $web3.eth.getTransactionReceipt(rs.transactionHash);
const deployBlock = rsTx.blockNumber;
// Update the storage with the new addresses
let rocketStorageInstance = await rocketStorage.deployed();
// Deploy other contracts - have to be inside an async loop
const deployContracts = async function () {
for (let contract in contracts) {
// Only deploy if it hasn't been deployed already like a precompiled
let instance
if (!contracts[contract].hasOwnProperty('precompiled')) {
switch (contract) {
// New RPL contract - pass storage address & existing RPL contract address
case 'rocketTokenRPL':
instance = await contracts[contract].new(rocketStorageInstance.address, (await contracts.rocketTokenRPLFixedSupply.deployed()).address);
contracts[contract].setAsDeployed(instance);
break;
// Contracts with no constructor args
case 'rocketMinipoolDelegate':
case 'rocketNodeDistributorDelegate':
case 'rocketMinipoolBase':
instance = await contracts[contract].new();
contracts[contract].setAsDeployed(instance);
break;
// Upgrade contract
case 'rocketUpgradeOneDotThree':
const upgrader = await contracts[contract].new(rocketStorageInstance.address);
contracts[contract].setAsDeployed(upgrader);
const args = [
[
(await contracts.rocketDAOProtocolNew.deployed()).address,
(await contracts.rocketDAOProtocolProposalsNew.deployed()).address,
(await contracts.rocketNetworkPricesNew.deployed()).address,
(await contracts.rocketNodeDepositNew.deployed()).address,
(await contracts.rocketNodeManagerNew.deployed()).address,
(await contracts.rocketNodeStakingNew.deployed()).address,
(await contracts.rocketClaimDAONew.deployed()).address,
(await contracts.rocketDAOProtocolSettingsRewardsNew.deployed()).address,
(await contracts.rocketMinipoolManagerNew.deployed()).address,
(await contracts.rocketRewardsPoolNew.deployed()).address,
(await contracts.rocketNetworkBalancesNew.deployed()).address,
(await contracts.rocketDAOProtocolSettingsNetworkNew.deployed()).address,
(await contracts.rocketDAOProtocolSettingsAuctionNew.deployed()).address,
(await contracts.rocketDAOProtocolSettingsDepositNew.deployed()).address,
(await contracts.rocketDAOProtocolSettingsInflationNew.deployed()).address,
(await contracts.rocketDAOProtocolSettingsMinipoolNew.deployed()).address,
(await contracts.rocketDAOProtocolVerifier.deployed()).address,
(await contracts.rocketDAOProtocolSettingsProposals.deployed()).address,
(await contracts.rocketDAOProtocolSettingsSecurity.deployed()).address,
(await contracts.rocketDAOSecurity.deployed()).address,
(await contracts.rocketDAOSecurityActions.deployed()).address,
(await contracts.rocketDAOSecurityProposals.deployed()).address,
(await contracts.rocketNetworkSnapshots.deployed()).address,
(await contracts.rocketNetworkVoting.deployed()).address,
(await contracts.rocketDAOProtocolProposal.deployed()).address,
],
[
compressABI(contracts.rocketDAOProtocolNew.abi),
compressABI(contracts.rocketDAOProtocolProposalsNew.abi),
compressABI(contracts.rocketNetworkPricesNew.abi),
compressABI(contracts.rocketNodeDepositNew.abi),
compressABI(contracts.rocketNodeManagerNew.abi),
compressABI(contracts.rocketNodeStakingNew.abi),
compressABI(contracts.rocketClaimDAONew.abi),
compressABI(contracts.rocketDAOProtocolSettingsRewardsNew.abi),
compressABI(contracts.rocketMinipoolManagerNew.abi),
compressABI(contracts.rocketRewardsPoolNew.abi),
compressABI(contracts.rocketNetworkBalancesNew.abi),
compressABI(contracts.rocketDAOProtocolSettingsNetworkNew.abi),
compressABI(contracts.rocketDAOProtocolSettingsAuctionNew.abi),
compressABI(contracts.rocketDAOProtocolSettingsDepositNew.abi),
compressABI(contracts.rocketDAOProtocolSettingsInflationNew.abi),
compressABI(contracts.rocketDAOProtocolSettingsMinipoolNew.abi),
compressABI(contracts.rocketDAOProtocolVerifier.abi),
compressABI(contracts.rocketDAOProtocolSettingsProposals.abi),
compressABI(contracts.rocketDAOProtocolSettingsSecurity.abi),
compressABI(contracts.rocketDAOSecurity.abi),
compressABI(contracts.rocketDAOSecurityActions.abi),
compressABI(contracts.rocketDAOSecurityProposals.abi),
compressABI(contracts.rocketNetworkSnapshots.abi),
compressABI(contracts.rocketNetworkVoting.abi),
compressABI(contracts.rocketDAOProtocolProposal.abi),
],
]
await upgrader.set(...args)
break;
// All other contracts - pass storage address
default:
if (contract === 'rocketStorage') {
instance = await contracts[contract].new();
} else {
instance = await contracts[contract].new(rocketStorageInstance.address);
}
contracts[contract].setAsDeployed(instance);
// Slight hack to allow gas optimisation using immutable addresses for non-upgradable contracts
if (contract === 'rocketVault' || contract === 'rocketTokenRETH') {
await rocketStorageInstance.setAddress(
$web3.utils.soliditySha3('contract.address', contract),
(await contracts[contract].deployed()).address
);
}
break;
}
}
}
};
// Run it
await deployContracts();
// Register all other contracts with storage and store their abi
const addContracts = async function () {
// Log RocketStorage
console.log('\x1b[31m%s\x1b[0m:', ' Set Storage Address');
console.log(' ' + (await rocketStorage.deployed()).address);
// Add Rocket Storage to deployed contracts
contracts.rocketStorage = artifacts.require('RocketStorage.sol');
// Now process the rest
for (let contract in contracts) {
if (contracts.hasOwnProperty(contract)) {
switch (contract) {
// Ignore contracts that will be upgraded later
case 'rocketDAOProtocolNew':
case 'rocketDAOProtocolProposalsNew':
case 'rocketNetworkPricesNew':
case 'rocketNodeDepositNew':
case 'rocketNodeManagerNew':
case 'rocketNodeStakingNew':
case 'rocketClaimDAONew':
case 'rocketDAOProtocolSettingsRewardsNew':
case 'rocketMinipoolManagerNew':
case 'rocketRewardsPoolNew':
case 'rocketNetworkBalancesNew':
case 'rocketDAOProtocolSettingsNetworkNew':
case 'rocketDAOProtocolSettingsAuctionNew':
case 'rocketDAOProtocolSettingsDepositNew':
case 'rocketDAOProtocolSettingsInflationNew':
case 'rocketDAOProtocolSettingsMinipoolNew':
case 'rocketDAOProtocolVerifier':
case 'rocketDAOProtocolSettingsProposals':
case 'rocketDAOProtocolSettingsSecurity':
case 'rocketDAOSecurity':
case 'rocketDAOSecurityActions':
case 'rocketDAOSecurityProposals':
case 'rocketNetworkSnapshots':
case 'rocketNetworkVoting':
case 'rocketDAOProtocolProposal':
break;
default:
const address = contract === 'casperDeposit' ? contracts[contract].address : (await contracts[contract].deployed()).address;
// Log it
console.log('\x1b[31m%s\x1b[0m:', ' Set Storage ' + contract + ' Address');
console.log(' ' + address);
// Register the contract address as part of the network
await rocketStorageInstance.setBool(
$web3.utils.soliditySha3('contract.exists', address),
true
);
// Register the contract's name by address
await rocketStorageInstance.setString(
$web3.utils.soliditySha3('contract.name', address),
contract
);
// Register the contract's address by name (rocketVault and rocketTokenRETH addresses already stored)
if (!(contract === 'rocketVault' || contract === 'rocketTokenRETH')) {
await rocketStorageInstance.setAddress(
$web3.utils.soliditySha3('contract.address', contract),
address
);
}
// Compress and store the ABI by name
await rocketStorageInstance.setString(
$web3.utils.soliditySha3('contract.abi', contract),
compressABI(contracts[contract].abi)
);
break;
}
}
}
};
// Register ABI-only contracts
const addABIs = async function () {
for (let contract in abis) {
if (abis.hasOwnProperty(contract)) {
console.log('\x1b[31m%s\x1b[0m:', ' Set Storage ABI');
console.log(' ' + contract);
if (Array.isArray(abis[contract])) {
// Merge ABIs from multiple artifacts
let combinedAbi = [];
for (const artifact of abis[contract]) {
combinedAbi = combinedAbi.concat(artifact.abi);
}
// Compress and store the ABI
await rocketStorageInstance.setString(
$web3.utils.soliditySha3('contract.abi', contract),
compressABI(combinedAbi)
);
} else {
// Compress and store the ABI
await rocketStorageInstance.setString(
$web3.utils.soliditySha3('contract.abi', contract),
compressABI(abis[contract].abi)
);
}
}
}
};
// Run it
console.log('\x1b[34m%s\x1b[0m', ' Deploy Contracts');
console.log('\x1b[34m%s\x1b[0m', ' ******************************************');
await addContracts();
console.log('\n');
console.log('\x1b[34m%s\x1b[0m', ' Set ABI Only Storage');
console.log('\x1b[34m%s\x1b[0m', ' ******************************************');
await addABIs();
// Store deployed block
console.log('\n');
console.log('Setting deploy.block to ' + deployBlock);
await rocketStorageInstance.setUint(
$web3.utils.soliditySha3('deploy.block'),
deployBlock
);
// Disable direct access to storage now
await rocketStorageInstance.setDeployedStatus();
if (await rocketStorageInstance.getDeployedStatus() !== true) throw 'Storage Access Not Locked Down!!';
// Log it
console.log('\n');
console.log('\x1b[32m%s\x1b[0m', ' Storage Direct Access For Owner Removed... Lets begin! :)');
console.log('\n');
// Deploy development help contracts
if (network.name !== 'live' && network.name !== 'goerli') {
let instance = await revertOnTransfer.new();
revertOnTransfer.setAsDeployed(instance);
instance = await rocketNodeDepositLEB4.new(rocketStorageInstance.address);
rocketNodeDepositLEB4.setAsDeployed(instance);
}
// Perform upgrade if we are not running in test environment
console.log('Executing upgrade to v1.3')
const RocketUpgradeOneDotThree = artifacts.require('RocketUpgradeOneDotThree')
const rocketUpgradeOneDotThree = await RocketUpgradeOneDotThree.deployed();
await rocketUpgradeOneDotThree.execute({ from: accounts[0] });
return rs;
};