Skip to content

Commit 680144d

Browse files
committed
Remove invalid require guard on network balance submission
1 parent 9c6cacb commit 680144d

6 files changed

Lines changed: 157 additions & 25 deletions

File tree

contracts/contract/network/RocketNetworkBalances.sol

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ contract RocketNetworkBalances is RocketBase, RocketNetworkBalancesInterface {
2222

2323
// Construct
2424
constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
25-
version = 1;
25+
version = 2;
2626
}
2727

2828
// The block number which balances are current for
@@ -75,8 +75,6 @@ contract RocketNetworkBalances is RocketBase, RocketNetworkBalancesInterface {
7575
// Check block
7676
require(_block < block.number, "Balances can not be submitted for a future block");
7777
require(_block > getBalancesBlock(), "Network balances for an equal or higher block are set");
78-
// Check balances
79-
require(_stakingEth <= _totalEth, "Invalid network balances");
8078
// Get submission keys
8179
bytes32 nodeSubmissionKey = keccak256(abi.encodePacked("network.balances.submitted.node", msg.sender, _block, _totalEth, _stakingEth, _rethSupply));
8280
bytes32 submissionCountKey = keccak256(abi.encodePacked("network.balances.submitted.count", _block, _totalEth, _stakingEth, _rethSupply));
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
pragma solidity 0.7.6;
2+
3+
// SPDX-License-Identifier: GPL-3.0-only
4+
5+
import "@openzeppelin/contracts/math/SafeMath.sol";
6+
7+
import "../../RocketBase.sol";
8+
import "../../../interface/dao/node/RocketDAONodeTrustedInterface.sol";
9+
import "../../../interface/network/RocketNetworkBalancesInterface.sol";
10+
import "../../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNetworkInterface.sol";
11+
12+
// Network balances
13+
14+
contract RocketNetworkBalancesOld is RocketBase, RocketNetworkBalancesInterface {
15+
16+
// Libs
17+
using SafeMath for uint;
18+
19+
// Events
20+
event BalancesSubmitted(address indexed from, uint256 block, uint256 totalEth, uint256 stakingEth, uint256 rethSupply, uint256 time);
21+
event BalancesUpdated(uint256 block, uint256 totalEth, uint256 stakingEth, uint256 rethSupply, uint256 time);
22+
23+
// Construct
24+
constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
25+
version = 1;
26+
}
27+
28+
// The block number which balances are current for
29+
function getBalancesBlock() override public view returns (uint256) {
30+
return getUint(keccak256("network.balances.updated.block"));
31+
}
32+
function setBalancesBlock(uint256 _value) private {
33+
setUint(keccak256("network.balances.updated.block"), _value);
34+
}
35+
36+
// The current RP network total ETH balance
37+
function getTotalETHBalance() override public view returns (uint256) {
38+
return getUint(keccak256("network.balance.total"));
39+
}
40+
function setTotalETHBalance(uint256 _value) private {
41+
setUint(keccak256("network.balance.total"), _value);
42+
}
43+
44+
// The current RP network staking ETH balance
45+
function getStakingETHBalance() override public view returns (uint256) {
46+
return getUint(keccak256("network.balance.staking"));
47+
}
48+
function setStakingETHBalance(uint256 _value) private {
49+
setUint(keccak256("network.balance.staking"), _value);
50+
}
51+
52+
// The current RP network total rETH supply
53+
function getTotalRETHSupply() override external view returns (uint256) {
54+
return getUint(keccak256("network.balance.reth.supply"));
55+
}
56+
function setTotalRETHSupply(uint256 _value) private {
57+
setUint(keccak256("network.balance.reth.supply"), _value);
58+
}
59+
60+
// Get the current RP network ETH utilization rate as a fraction of 1 ETH
61+
// Represents what % of the network's balance is actively earning rewards
62+
function getETHUtilizationRate() override external view returns (uint256) {
63+
uint256 totalEthBalance = getTotalETHBalance();
64+
uint256 stakingEthBalance = getStakingETHBalance();
65+
if (totalEthBalance == 0) { return calcBase; }
66+
return calcBase.mul(stakingEthBalance).div(totalEthBalance);
67+
}
68+
69+
// Submit network balances for a block
70+
// Only accepts calls from trusted (oracle) nodes
71+
function submitBalances(uint256 _block, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) override external onlyLatestContract("rocketNetworkBalances", address(this)) onlyTrustedNode(msg.sender) {
72+
// Check settings
73+
RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));
74+
require(rocketDAOProtocolSettingsNetwork.getSubmitBalancesEnabled(), "Submitting balances is currently disabled");
75+
// Check block
76+
require(_block < block.number, "Balances can not be submitted for a future block");
77+
require(_block > getBalancesBlock(), "Network balances for an equal or higher block are set");
78+
// Check balances
79+
require(_stakingEth <= _totalEth, "Invalid network balances");
80+
// Get submission keys
81+
bytes32 nodeSubmissionKey = keccak256(abi.encodePacked("network.balances.submitted.node", msg.sender, _block, _totalEth, _stakingEth, _rethSupply));
82+
bytes32 submissionCountKey = keccak256(abi.encodePacked("network.balances.submitted.count", _block, _totalEth, _stakingEth, _rethSupply));
83+
// Check & update node submission status
84+
require(!getBool(nodeSubmissionKey), "Duplicate submission from node");
85+
setBool(nodeSubmissionKey, true);
86+
setBool(keccak256(abi.encodePacked("network.balances.submitted.node", msg.sender, _block)), true);
87+
// Increment submission count
88+
uint256 submissionCount = getUint(submissionCountKey).add(1);
89+
setUint(submissionCountKey, submissionCount);
90+
// Emit balances submitted event
91+
emit BalancesSubmitted(msg.sender, _block, _totalEth, _stakingEth, _rethSupply, block.timestamp);
92+
// Check submission count & update network balances
93+
RocketDAONodeTrustedInterface rocketDAONodeTrusted = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));
94+
if (calcBase.mul(submissionCount).div(rocketDAONodeTrusted.getMemberCount()) >= rocketDAOProtocolSettingsNetwork.getNodeConsensusThreshold()) {
95+
updateBalances(_block, _totalEth, _stakingEth, _rethSupply);
96+
}
97+
}
98+
99+
// Executes updateBalances if consensus threshold is reached
100+
function executeUpdateBalances(uint256 _block, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) override external onlyLatestContract("rocketNetworkBalances", address(this)) {
101+
// Check settings
102+
RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));
103+
require(rocketDAOProtocolSettingsNetwork.getSubmitBalancesEnabled(), "Submitting balances is currently disabled");
104+
// Check block
105+
require(_block < block.number, "Balances can not be submitted for a future block");
106+
require(_block > getBalancesBlock(), "Network balances for an equal or higher block are set");
107+
// Check balances
108+
require(_stakingEth <= _totalEth, "Invalid network balances");
109+
// Get submission keys
110+
bytes32 submissionCountKey = keccak256(abi.encodePacked("network.balances.submitted.count", _block, _totalEth, _stakingEth, _rethSupply));
111+
// Get submission count
112+
uint256 submissionCount = getUint(submissionCountKey);
113+
// Check submission count & update network balances
114+
RocketDAONodeTrustedInterface rocketDAONodeTrusted = RocketDAONodeTrustedInterface(getContractAddress("rocketDAONodeTrusted"));
115+
require(calcBase.mul(submissionCount).div(rocketDAONodeTrusted.getMemberCount()) >= rocketDAOProtocolSettingsNetwork.getNodeConsensusThreshold(), "Consensus has not been reached");
116+
updateBalances(_block, _totalEth, _stakingEth, _rethSupply);
117+
}
118+
119+
// Update network balances
120+
function updateBalances(uint256 _block, uint256 _totalEth, uint256 _stakingEth, uint256 _rethSupply) private {
121+
// Update balances
122+
setBalancesBlock(_block);
123+
setTotalETHBalance(_totalEth);
124+
setStakingETHBalance(_stakingEth);
125+
setTotalRETHSupply(_rethSupply);
126+
// Emit balances updated event
127+
emit BalancesUpdated(_block, _totalEth, _stakingEth, _rethSupply, block.timestamp);
128+
}
129+
130+
// Returns the latest block number that oracles should be reporting balances for
131+
function getLatestReportableBlock() override external view returns (uint256) {
132+
// Load contracts
133+
RocketDAOProtocolSettingsNetworkInterface rocketDAOProtocolSettingsNetwork = RocketDAOProtocolSettingsNetworkInterface(getContractAddress("rocketDAOProtocolSettingsNetwork"));
134+
// Get the block balances were lasted updated and the update frequency
135+
uint256 updateFrequency = rocketDAOProtocolSettingsNetwork.getSubmitBalancesFrequency();
136+
// Calculate the last reportable block based on update frequency
137+
return block.number.div(updateFrequency).mul(updateFrequency);
138+
}
139+
}

contracts/contract/upgrade/RocketUpgradeOneDotTwo.sol

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ contract RocketUpgradeOneDotTwo is RocketBase {
4040
address public newRocketDAONodeTrustedSettingsMinipool;
4141
address public newRocketNodeManager;
4242
address public newRocketDAOProtocolSettingsNode;
43+
address public newRocketNetworkBalances;
4344
address public rocketMinipoolBase;
4445
address public rocketMinipoolBondReducer;
4546

@@ -59,8 +60,10 @@ contract RocketUpgradeOneDotTwo is RocketBase {
5960
string public newRocketDAONodeTrustedSettingsMinipoolAbi;
6061
string public newRocketNodeManagerAbi;
6162
string public newRocketDAOProtocolSettingsNodeAbi;
63+
string public newRocketNetworkBalancesAbi;
6264
string public rocketMinipoolBaseAbi;
6365
string public rocketMinipoolBondReducerAbi;
66+
string public rocketNetworkBalancesAbi;
6467

6568
string public newRocketMinipoolAbi;
6669

@@ -104,8 +107,9 @@ contract RocketUpgradeOneDotTwo is RocketBase {
104107
newRocketDAONodeTrustedSettingsMinipool = _addresses[12];
105108
newRocketNodeManager = _addresses[13];
106109
newRocketDAOProtocolSettingsNode = _addresses[14];
107-
rocketMinipoolBase = _addresses[15];
108-
rocketMinipoolBondReducer = _addresses[16];
110+
newRocketNetworkBalances = _addresses[15];
111+
rocketMinipoolBase = _addresses[16];
112+
rocketMinipoolBondReducer = _addresses[17];
109113

110114
// Set ABIs
111115
newRocketNodeDepositAbi = _abis[0];
@@ -123,10 +127,11 @@ contract RocketUpgradeOneDotTwo is RocketBase {
123127
newRocketDAONodeTrustedSettingsMinipoolAbi = _abis[12];
124128
newRocketNodeManagerAbi = _abis[13];
125129
newRocketDAOProtocolSettingsNodeAbi = _abis[14];
126-
rocketMinipoolBaseAbi = _abis[15];
127-
rocketMinipoolBondReducerAbi = _abis[16];
130+
newRocketNetworkBalancesAbi = _abis[15];
131+
rocketMinipoolBaseAbi = _abis[16];
132+
rocketMinipoolBondReducerAbi = _abis[17];
128133

129-
newRocketMinipoolAbi = _abis[17];
134+
newRocketMinipoolAbi = _abis[18];
130135
}
131136

132137
function setInterval(uint256 _interval, uint256 _block) external {
@@ -166,6 +171,7 @@ contract RocketUpgradeOneDotTwo is RocketBase {
166171
_upgradeContract("rocketDAONodeTrustedSettingsMinipool", newRocketDAONodeTrustedSettingsMinipool, newRocketDAONodeTrustedSettingsMinipoolAbi);
167172
_upgradeContract("rocketNodeManager", newRocketNodeManager, newRocketNodeManagerAbi);
168173
_upgradeContract("rocketDAOProtocolSettingsNode", newRocketDAOProtocolSettingsNode, newRocketDAOProtocolSettingsNodeAbi);
174+
_upgradeContract("rocketNetworkBalances", newRocketNetworkBalances, newRocketNetworkBalancesAbi);
169175

170176
// Add new contracts
171177
_addContract("rocketMinipoolBase", rocketMinipoolBase, rocketMinipoolBaseAbi);

test/_helpers/deployment.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const contracts = {
4949
rocketMinipoolStatus: artifacts.require('RocketMinipoolStatus.sol'),
5050
rocketMinipoolPenalty: artifacts.require('RocketMinipoolPenalty.sol'),
5151
// Network
52-
rocketNetworkBalances: artifacts.require('RocketNetworkBalances.sol'),
52+
rocketNetworkBalances: artifacts.require('RocketNetworkBalancesOld.sol'),
5353
rocketNetworkFees: artifacts.require('RocketNetworkFeesOld.sol'),
5454
rocketNetworkPrices: artifacts.require('RocketNetworkPricesOld.sol'),
5555
rocketNetworkPenalties: artifacts.require('RocketNetworkPenalties.sol'),
@@ -104,6 +104,7 @@ const contracts = {
104104
rocketNodeManagerNew: artifacts.require('RocketNodeManager.sol'),
105105
rocketDAOProtocolSettingsNodeNew: artifacts.require('RocketDAOProtocolSettingsNode.sol'),
106106
rocketMinipoolBondReducer: artifacts.require('RocketMinipoolBondReducer.sol'),
107+
rocketNetworkBalancesNew: artifacts.require('RocketNetworkBalances.sol'),
107108
rocketUpgradeOneDotTwo: artifacts.require('RocketUpgradeOneDotTwo.sol'),
108109
// Utils
109110
addressQueueStorage: artifacts.require('AddressQueueStorage.sol'),
@@ -260,6 +261,7 @@ export async function deployRocketPool() {
260261
(await contracts.rocketDAONodeTrustedSettingsMinipoolNew.deployed()).address,
261262
(await contracts.rocketNodeManagerNew.deployed()).address,
262263
(await contracts.rocketDAOProtocolSettingsNodeNew.deployed()).address,
264+
(await contracts.rocketNetworkBalancesNew.deployed()).address,
263265
(await contracts.rocketMinipoolBase.deployed()).address,
264266
(await contracts.rocketMinipoolBondReducer.deployed()).address,
265267
],
@@ -280,6 +282,7 @@ export async function deployRocketPool() {
280282
compressABI(contracts.rocketDAONodeTrustedSettingsMinipoolNew.abi),
281283
compressABI(contracts.rocketNodeManagerNew.abi),
282284
compressABI(contracts.rocketDAOProtocolSettingsNodeNew.abi),
285+
compressABI(contracts.rocketNetworkBalancesNew.abi),
283286
compressABI(contracts.rocketMinipoolBase.abi),
284287
compressABI(contracts.rocketMinipoolBondReducer.abi),
285288
compressABI(rocketMinipoolAbi),
@@ -335,6 +338,7 @@ export async function deployRocketPool() {
335338
case 'rocketDAONodeTrustedSettingsMinipoolNew':
336339
case 'rocketNodeManagerNew':
337340
case 'rocketDAOProtocolSettingsNodeNew':
341+
case 'rocketNetworkBalancesNew':
338342
case 'rocketMinipoolBase':
339343
case 'rocketMinipoolBondReducer':
340344
break;

test/_utils/artifacts.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export const RocketMinipoolStatus = artifacts.require('RocketMinipoolStatus.sol'
2626
export const RocketMinipoolPenalty = artifacts.require('RocketMinipoolPenalty.sol');
2727
export const RocketMinipoolManager = artifacts.require('RocketMinipoolManager.sol');
2828
export const RocketMinipoolManagerOld = artifacts.require('RocketMinipoolManagerOld.sol');
29+
export const RocketNetworkBalancesOld = artifacts.require('RocketNetworkBalancesOld.sol');
2930
export const RocketNetworkBalances = artifacts.require('RocketNetworkBalances.sol');
3031
export const RocketNetworkPenalties = artifacts.require('RocketNetworkPenalties.sol');
3132
export const RocketNetworkFees = artifacts.require('RocketNetworkFees.sol');

test/network/network-balances-tests.js

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -191,22 +191,6 @@ export default function() {
191191
});
192192

193193

194-
it(printTitle('trusted nodes', 'cannot submit invalid network balances'), async () => {
195-
196-
// Set parameters
197-
let block = 1;
198-
let totalBalance = '9'.ether;
199-
let stakingBalance = '10'.ether;
200-
let rethSupply = '8'.ether;
201-
202-
// Submit balances for block
203-
await shouldRevert(submitBalances(block, totalBalance, stakingBalance, rethSupply, {
204-
from: trustedNode1,
205-
}), 'Submitted invalid balances');
206-
207-
});
208-
209-
210194
it(printTitle('trusted nodes', 'cannot submit the same network balances twice'), async () => {
211195

212196
// Set parameters

0 commit comments

Comments
 (0)