Skip to content

Commit

Permalink
[Testing & Devops] bug fixes + unit tests + minor solidity tweaks (#167)
Browse files Browse the repository at this point in the history
* safety redundancy

* llint

* Update RPLVault.sol

* typo

* deployment scripts

* add more impl

* fix tests

* bug fixes

* fix bugs

* security+lint

Update WETHVault.sol

* fix tests

more test

test prep
  • Loading branch information
teddy-nodeset authored May 1, 2024
1 parent 1253529 commit af1ec63
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 269 deletions.
3 changes: 3 additions & 0 deletions contracts/AdminTreasury.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,7 @@ contract AdminTreasury is UpgradeableBase {
_executeInternal(_targets[i], _functionData[i], msg.value);
}
}

// we accept donations
receive() external payable {}
}
2 changes: 1 addition & 1 deletion contracts/Directory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ contract Directory is UUPSUpgradeable, AccessControlUpgradeable {
}

function initialize(Protocol memory newProtocol, address treasury, address admin) public initializer {
require(msg.sender != admin, Constants.INITIALIZATION_ERROR);
// require(msg.sender != admin, Constants.INITIALIZATION_ERROR);
require(
_protocol.whitelist == address(0) && newProtocol.whitelist != address(0),
Constants.INITIALIZATION_ERROR
Expand Down
13 changes: 13 additions & 0 deletions contracts/Testing/Mocks/MockAdminTreasuryV2.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// SPDX License Identifier: GPL v3

pragma solidity 0.8.17;

import '../../AdminTreasury.sol';

contract MockAdminTreasuryV2 is AdminTreasury {

function test() public pure returns(uint256) {
return 69;
}

}
1 change: 1 addition & 0 deletions contracts/Testing/Mocks/MockRETHOracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pragma solidity 0.8.17;
import '../../Interfaces/Oracles/IXRETHOracle.sol';

contract MockRETHOracle is IXRETHOracle {

uint private _yield = 0 ether;

function setTotalYieldAccrued(uint yield) public override {
Expand Down
3 changes: 2 additions & 1 deletion contracts/Tokens/RPLVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ contract RPLVault is UpgradeableBase, ERC4626Upgradeable {
uint256 assets,
uint256 shares
) internal virtual override {
require(caller == receiver, 'caller must be receiver');
if (_directory.isSanctioned(caller, receiver)) {
return;
}
Expand Down Expand Up @@ -221,7 +222,7 @@ contract RPLVault is UpgradeableBase, ERC4626Upgradeable {
SafeERC20.safeTransfer(asset, _to, balance);
OperatorDistributor od = OperatorDistributor(_directory.getOperatorDistributorAddress());
uint256 transferedIn = od.transferRplToVault(shortfall);
console.log("transfering out rpl to vault");
console.log('transfering out rpl to vault');
SafeERC20.safeTransfer(asset, _to, transferedIn);
} else {
SafeERC20.safeTransfer(asset, _to, _amount);
Expand Down
10 changes: 6 additions & 4 deletions contracts/Tokens/WETHVault.sol
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ contract WETHVault is UpgradeableBase, ERC4626Upgradeable {
uint256 assets,
uint256 shares
) internal virtual override nonReentrant {
require(caller == receiver, 'caller must be receiver');
if (_directory.isSanctioned(caller, receiver)) {
return;
}
Expand Down Expand Up @@ -124,6 +125,7 @@ contract WETHVault is UpgradeableBase, ERC4626Upgradeable {
uint256 assets,
uint256 shares
) internal virtual override nonReentrant {
require(caller == receiver, 'caller must be receiver');
if (_directory.isSanctioned(caller, receiver)) {
return;
}
Expand Down Expand Up @@ -175,10 +177,10 @@ contract WETHVault is UpgradeableBase, ERC4626Upgradeable {
function currentIncomeFromRewards() public view returns (uint256) {
unchecked {
FundRouter dp = FundRouter(getDirectory().getDepositPoolAddress());
console.log("WETHVault.currentIncomeFromRewards()");
console.log('WETHVault.currentIncomeFromRewards()');
console.log(gasleft());
console.log("getDirectory()");
console.log("getDirectory().getOperatorDistributorAddress()");
console.log('getDirectory()');
console.log('getDirectory().getOperatorDistributorAddress()');
OperatorDistributor od = OperatorDistributor(getDirectory().getOperatorDistributorAddress());
uint256 tvl = super.totalAssets() + getDistributableYield() + dp.getTvlEth() + od.getTvlEth();

Expand Down Expand Up @@ -221,7 +223,7 @@ contract WETHVault is UpgradeableBase, ERC4626Upgradeable {
return (tvlEth * ethPriceInRpl) / tvlRpl;
}

function getRequiredCollateralAfterDeposit(uint256 deposit) public view returns(uint256) {
function getRequiredCollateralAfterDeposit(uint256 deposit) public view returns (uint256) {
uint256 currentBalance = IERC20(asset()).balanceOf(address(this));
uint256 fullBalance = totalAssets() + deposit;
uint256 requiredBalance = collateralizationRatioBasePoint.mulDiv(fullBalance, 1e5, Math.Rounding.Up);
Expand Down
36 changes: 36 additions & 0 deletions deployments/holeksy_deployment-0.0.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
weth address 0xA220A28A8c7Ae8ab962d8386E2f58acCD046A5d0
oracle address 0xb893bF28507274c425Dbbe80D7aa6b5bd463c966
sanctions address 0x6dCCF43D99821867FfeABFb234e67004965D0492
whitelist deployed to 0xb22be5c52ad10b08610DBf7d330fAB5b5bdF8F2C
vaulted constellation eth deployed to 0x962076740a4acDFCA3a92284C7216fBDB4a25EFe
vaulted constellation rpl deployed to 0x9d8886aF4b2a2E4C2B6386EFA96A23945F944097
Fund Router (Deposit Pool) deployed to 0x6Eea224bE35694390F82d88f63f327711a6eBCa7
operator distributor deployed to 0x1a3a2c99bD7F02Aa39Afc1DDFD94332a5fB22aee
yield distributor deployed to 0x6a558b87e6966210C9209d897c86379d536630f9
price fetcher deployed to 0xD063b49d2529ce52B761A68Ca60817b55C4b3987
admin treasury deployed to 0x5ECCdBCfAD0a140B88348F91D2eE8cF8Ad63Bb26
node account impl for cloning deployed to 0x885FB35fbFF3475484C0f9A1D1bf08FdFAB5b143
node account factory deployed to 0xF0640494859a32b8363073E1bf0A7a351097E06d
verify directory input
whitelistProxy.address 0xb22be5c52ad10b08610DBf7d330fAB5b5bdF8F2C
vCWETHProxy.address 0x962076740a4acDFCA3a92284C7216fBDB4a25EFe
vCRPLProxy.address 0x9d8886aF4b2a2E4C2B6386EFA96A23945F944097
depositPoolProxy.address 0x6Eea224bE35694390F82d88f63f327711a6eBCa7
operatorDistributorProxy.address 0x1a3a2c99bD7F02Aa39Afc1DDFD94332a5fB22aee
nodeAccountFactoryProxy.address 0xF0640494859a32b8363073E1bf0A7a351097E06d
yieldDistributorProxy.address 0x6a558b87e6966210C9209d897c86379d536630f9
oracle 0xb893bF28507274c425Dbbe80D7aa6b5bd463c966
priceFetcherProxy.address 0xD063b49d2529ce52B761A68Ca60817b55C4b3987
rocketStorage 0x594Fb75D3dc2DFa0150Ad03F99F97817747dd4E1
weth 0xA220A28A8c7Ae8ab962d8386E2f58acCD046A5d0
uniswapV3 0x324a0F727B57153A079f09eC9526b56B9E1B04fd
sanctions 0x6dCCF43D99821867FfeABFb234e67004965D0492
Duplicate definition of SanctionViolation (SanctionViolation(address,address), SanctionViolation(address))
Duplicate definition of SanctionViolation (SanctionViolation(address,address), SanctionViolation(address))
directory deployed to 0x8AFBF878b0692c1c2e8a0c8AFfc09f5D78e5e239
directory matches predicted address 0x8afbf878b0692c1c2e8a0c8affc09f5d78e5e239
Duplicate definition of SanctionViolation (SanctionViolation(address,address), SanctionViolation(address))
Duplicate definition of SanctionViolation (SanctionViolation(address,address), SanctionViolation(address))
timelock role set
Duplicate definition of SanctionViolation (SanctionViolation(address,address), SanctionViolation(address))
protocol role set
2 changes: 1 addition & 1 deletion gas-report.txt
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,4 @@
| WhitelistV2 · - · - · 2329709 · 7.8 % · - │
·······················································|·············|·············|·············|···············|··············
| YieldDistributor · - · - · 3087220 · 10.3 % · - │
·------------------------------------------------------|-------------|-------------|-------------|---------------|-------------·
·------------------------------------------------------|-------------|-------------|-------------|---------------|-------------·
189 changes: 5 additions & 184 deletions scripts/dev_setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,73 +6,25 @@ import { getNextContractAddress } from "../test/utils/utils";
import { IXRETHOracle, NodeAccountFactory } from "../typechain-types";
import { expect } from "chai";
import readline from 'readline';
import { generateBytes32Identifier, retryOperation } from "./utils/deployment";
import { fastDeployProtocol, generateBytes32Identifier, retryOperation } from "./utils/deployment";
import { wEth } from "../typechain-types/contracts/Testing";


async function main() {
const predictedNonce = 12;
const [deployer, admin] = await ethers.getSigners();


// Contract identifiers
const contractIdentifiers = {
rocketNodeManager: 'rocketNodeManager',
rocketTokenRPL: 'rocketTokenRPL',
rocketDAOProtocolSettingsNetwork: 'rocketDAOProtocolSettingsNetwork',
rocketStorage: 'rocketStorage',
rocketNodeStaking: 'rocketNodeStaking',
rocketNodeDeposit: 'rocketNodeDeposit'
};

const rpAddresses: { [key: string]: string } = {};

// Generate the bytes32 hashes for each identifier
for (const [name, identifier] of Object.entries(contractIdentifiers)) {
const bytes32Identifier = generateBytes32Identifier(identifier);
console.log(`${name}: ${bytes32Identifier}`);
rpAddresses[name] = bytes32Identifier;
}

const rocketStorage = await ethers.getContractAt('RocketStorage', '0x594Fb75D3dc2DFa0150Ad03F99F97817747dd4E1'); // holesky addr

// Resolve contract addresses
for (const identifier of Object.values(contractIdentifiers)) {
const bytes32Identifier = generateBytes32Identifier(identifier);
const address = await rocketStorage.getAddress(bytes32Identifier);

if (address === ethers.constants.AddressZero) {
throw new Error(`Address not found for identifier ${identifier}`);
}

rpAddresses[identifier] = address;
}
upgrades.silenceWarnings()

console.log("Deploying contracts with the account:", deployer.address);
console.log("Account balance:", (await deployer.getBalance()).toString());

const rplContract = await ethers.getContractAt("contracts/Interfaces/RocketTokenRPLInterface.sol:RocketTokenRPLInterface", rpAddresses['rocketTokenRPL']);
const networkFeesContract = await ethers.getContractAt("contracts/Interfaces/RocketDAOProtocolSettingsNetworkInterface.sol:RocketDAOProtocolSettingsNetworkInterface", rpAddresses['rocketDAOProtocolSettingsNetwork']);
const rockStorageContract = await ethers.getContractAt("RocketStorage", rpAddresses['rocketStorage']);
const rocketNodeManagerContract = await ethers.getContractAt("RocketNodeManagerInterface", rpAddresses['rocketNodeManager']);
const rocketNodeStakingContract = await ethers.getContractAt("RocketNodeStaking", rpAddresses['rocketNodeStaking']);
const rocketNodeDepositContract = await ethers.getContractAt("RocketNodeDeposit", rpAddresses['rocketNodeDeposit']);

console.log("rocketpool contracts of interest")
console.log("rplContract", rplContract.address)
console.log("networkFeesContract", networkFeesContract.address)
console.log("rockStorageContract", rockStorageContract.address)
console.log("rocketNodeManagerContract", rocketNodeManagerContract.address)

upgrades.silenceWarnings();
// deploy weth
const wETH = await retryOperation(async () => {
const WETH = await ethers.getContractFactory("WETH");
const contract = await WETH.deploy();
await contract.deployed();
return contract;
});

// wait for weth deploy to be mined
console.log("weth address", wETH.address)

// deploy mock uniswap v3 pool
const uniswapV3Pool = await retryOperation(async () => {
Expand All @@ -82,88 +34,9 @@ async function main() {
return contract;
});

// wait for uniswap v3 pool deploy to be mined

const directoryAddress = await getNextContractAddress(deployer, predictedNonce - 1)
console.log("predicted directory address", directoryAddress)

const initNonce = await deployer.getTransactionCount();
console.log("init nonce", initNonce)

const whitelist = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("contracts/Whitelist/Whitelist.sol:Whitelist"), [directoryAddress], { 'initializer': 'initializeWhitelist', 'kind': 'uups', 'unsafeAllow': ['constructor'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("whitelist address", whitelist.address);

const vCWETHProxyAbi = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("WETHVault"), [directoryAddress, wETH.address], { 'initializer': 'initializeVault', 'kind': 'uups', 'unsafeAllow': ['constructor', 'delegatecall'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("vCWETHProxyAbi address", vCWETHProxyAbi.address);

const vCWETH = await ethers.getContractAt("WETHVault", vCWETHProxyAbi.address);
console.log("vCWETH address", vCWETH.address)

const vCRPLProxyAbi = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("RPLVault"), [directoryAddress, rplContract.address], { 'initializer': 'initializeVault', 'kind': 'uups', 'unsafeAllow': ['constructor', 'delegatecall'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("vCRPLProxyAbi address", vCRPLProxyAbi.address);

const vCRPL = await ethers.getContractAt("RPLVault", vCRPLProxyAbi.address);
console.log("vCRPL address", vCRPL.address)

const depositPoolProxyAbi = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("FundRouter"), [directoryAddress], { 'initializer': 'initialize', 'kind': 'uups', 'unsafeAllow': ['constructor', 'delegatecall'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("depositPoolProxyAbi address", depositPoolProxyAbi.address);


const depositPool = await ethers.getContractAt("FundRouter", depositPoolProxyAbi.address);
console.log("depositPool address", depositPool.address)

const operatorDistributorProxyAbi = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("OperatorDistributor"), [directoryAddress], { 'initializer': 'initialize', 'kind': 'uups', 'unsafeAllow': ['constructor', 'delegatecall'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("operatorDistributorProxyAbi address", operatorDistributorProxyAbi.address);

// wait for operatorDistributor deploy to be mined
await operatorDistributorProxyAbi.deployTransaction.wait();

const operatorDistributor = await ethers.getContractAt("OperatorDistributor", operatorDistributorProxyAbi.address);
console.log("operatorDistributor address", operatorDistributor.address)

const yieldDistributorProxyAbi = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("YieldDistributor"), [directoryAddress], { 'initializer': 'initialize', 'kind': 'uups', 'unsafeAllow': ['constructor', 'delegatecall'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("yieldDistributorProxyAbi address", yieldDistributorProxyAbi.address);

const yieldDistributor = await ethers.getContractAt("YieldDistributor", yieldDistributorProxyAbi.address);
console.log("yieldDistributor address", yieldDistributor.address)

const oracle = (await (await ethers.getContractFactory("MockRETHOracle")).deploy()) as IXRETHOracle;
console.log("oracle address", oracle.address)

// wait for oracle deploy to be mined
await oracle.deployTransaction.wait();

const priceFetcher = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("PriceFetcher"), [directoryAddress], { 'initializer': 'initialize', 'kind': 'uups', 'unsafeAllow': ['constructor'] });
await deployedProxy.deployed();
return deployedProxy;
});
console.log("priceFetcher address", priceFetcher.address);

const sanctions = await retryOperation(async () => {
const Sanctions = await ethers.getContractFactory("MockSanctions");
const contract = await Sanctions.deploy();
Expand All @@ -172,59 +45,7 @@ async function main() {
});
console.log("sanctions address", sanctions.address);

const NodeAccountFactory = await retryOperation(async () => {
const NodeAccountLogic = await ethers.getContractFactory("NodeAccount");
const NodeAccountLogic = await NodeAccountLogic.deploy();
await NodeAccountLogic.deployed();
const factory = await upgrades.deployProxy(await ethers.getContractFactory("NodeAccountFactory"), [directoryAddress, NodeAccountLogic.address], { 'initializer': 'initializeWithImplementation', 'kind': 'uups', 'unsafeAllow': ['constructor'] });
await factory.deployTransaction.wait();
return factory;
}) as NodeAccountFactory;
console.log("validator factory address", NodeAccountFactory.address);

const directoryProxyAbi = await retryOperation(async () => {
const deployedProxy = await upgrades.deployProxy(await ethers.getContractFactory("Directory"),
[
[
whitelist.address,
vCWETH.address,
vCRPL.address,
depositPool.address,
operatorDistributor.address,
NodeAccountFactory.address,
yieldDistributor.address,
oracle.address,
priceFetcher.address,
rockStorageContract.address,
rocketNodeManagerContract.address,
rocketNodeStakingContract.address,
rocketNodeDepositContract.address,
rplContract.address,
wETH.address,
uniswapV3Pool.address,
sanctions.address,
],
deployer.address,
"0x241E263b40c7Bf458b6b28D86338cf26f7Cc5a57",
], { 'initializer': 'initialize', 'kind': 'uups', 'unsafeAllow': ['constructor'] });
await deployedProxy.deployTransaction.wait();
return deployedProxy;
});
console.log("directoryProxyAbi address", directoryProxyAbi.address);


const finalNonce = await deployer.getTransactionCount();
console.log("final nonce", finalNonce)

const directory = await ethers.getContractAt("Directory", directoryProxyAbi.address);
console.log("directory address", directory.address)

// wait 30 seconds to ensure everything is deployed
console.log("waiting 30 seconds for everything to deploy")
await new Promise(r => setTimeout(r, 30000));

expect(finalNonce - initNonce).to.equal(predictedNonce);
expect(directory.address).to.hexEqual(directoryAddress);
const { directory } = await fastDeployProtocol(deployer, admin, rocketStorage.address, wETH.address, sanctions.address, uniswapV3Pool.address, oracle.address, admin.address, true);

// set adminServer to be ADMIN_SERVER_ROLE
const adminRole = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("ADMIN_SERVER_ROLE"));
Expand Down
Loading

0 comments on commit af1ec63

Please sign in to comment.