编译器
0.8.18+commit.87f61d96
文件 1 的 23:AddressSetStorageInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface AddressSetStorageInterface {
function getCount(bytes32 _key) external view returns (uint);
function getItem(bytes32 _key, uint _index) external view returns (address);
function getIndexOf(bytes32 _key, address _value) external view returns (int);
function addItem(bytes32 _key, address _value) external;
function removeItem(bytes32 _key, address _value) external;
}
文件 2 的 23:IERC20.sol
pragma solidity >0.5.0 <0.9.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 3 的 23:IERC20Burnable.sol
import "./IERC20.sol";
pragma solidity >0.5.0 <0.9.0;
interface IERC20Burnable is IERC20 {
function burn(uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
}
文件 4 的 23:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 5 的 23:MinipoolDeposit.sol
pragma solidity >0.5.0 <0.9.0;
enum MinipoolDeposit {
None,
Full,
Half,
Empty,
Variable
}
文件 6 的 23:MinipoolDetails.sol
pragma solidity >0.5.0 <0.9.0;
import "./MinipoolDeposit.sol";
import "./MinipoolStatus.sol";
struct MinipoolDetails {
bool exists;
address minipoolAddress;
bytes pubkey;
MinipoolStatus status;
uint256 statusBlock;
uint256 statusTime;
bool finalised;
MinipoolDeposit depositType;
uint256 nodeFee;
uint256 nodeDepositBalance;
bool nodeDepositAssigned;
uint256 userDepositBalance;
bool userDepositAssigned;
uint256 userDepositAssignedTime;
bool useLatestDelegate;
address delegate;
address previousDelegate;
address effectiveDelegate;
uint256 penaltyCount;
uint256 penaltyRate;
address nodeAddress;
}
文件 7 的 23:MinipoolStatus.sol
pragma solidity >0.5.0 <0.9.0;
enum MinipoolStatus {
Initialised,
Prelaunch,
Staking,
Withdrawable,
Dissolved
}
文件 8 的 23:NodeDetails.sol
pragma solidity >0.5.0 <0.9.0;
struct NodeDetails {
bool exists;
uint256 registrationTime;
string timezoneLocation;
bool feeDistributorInitialised;
address feeDistributorAddress;
uint256 rewardNetwork;
uint256 rplStake;
uint256 effectiveRPLStake;
uint256 minimumRPLStake;
uint256 maximumRPLStake;
uint256 ethMatched;
uint256 ethMatchedLimit;
uint256 minipoolCount;
uint256 balanceETH;
uint256 balanceRETH;
uint256 balanceRPL;
uint256 balanceOldRPL;
uint256 depositCreditBalance;
uint256 distributorBalanceUserETH;
uint256 distributorBalanceNodeETH;
address withdrawalAddress;
address pendingWithdrawalAddress;
bool smoothingPoolRegistrationState;
uint256 smoothingPoolRegistrationChanged;
address nodeAddress;
}
文件 9 的 23:RocketBase.sol
pragma solidity >0.5.0 <0.9.0;
import "../interface/RocketStorageInterface.sol";
abstract contract RocketBase {
uint256 constant calcBase = 1 ether;
uint8 public version;
RocketStorageInterface rocketStorage = RocketStorageInterface(address(0));
modifier onlyLatestNetworkContract() {
require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract");
_;
}
modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract");
_;
}
modifier onlyRegisteredNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
_;
}
modifier onlyTrustedNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node");
_;
}
modifier onlyRegisteredMinipool(address _minipoolAddress) {
require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool");
_;
}
modifier onlyGuardian() {
require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian");
_;
}
constructor(RocketStorageInterface _rocketStorageAddress) {
rocketStorage = RocketStorageInterface(_rocketStorageAddress);
}
function getContractAddress(string memory _contractName) internal view returns (address) {
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
require(contractAddress != address(0x0), "Contract not found");
return contractAddress;
}
function getContractAddressUnsafe(string memory _contractName) internal view returns (address) {
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
return contractAddress;
}
function getContractName(address _contractAddress) internal view returns (string memory) {
string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress)));
require(bytes(contractName).length > 0, "Contract not found");
return contractName;
}
function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
if (_returnData.length < 68) return "Transaction reverted silently";
assembly {
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string));
}
function getAddress(bytes32 _key) internal view returns (address) { return rocketStorage.getAddress(_key); }
function getUint(bytes32 _key) internal view returns (uint) { return rocketStorage.getUint(_key); }
function getString(bytes32 _key) internal view returns (string memory) { return rocketStorage.getString(_key); }
function getBytes(bytes32 _key) internal view returns (bytes memory) { return rocketStorage.getBytes(_key); }
function getBool(bytes32 _key) internal view returns (bool) { return rocketStorage.getBool(_key); }
function getInt(bytes32 _key) internal view returns (int) { return rocketStorage.getInt(_key); }
function getBytes32(bytes32 _key) internal view returns (bytes32) { return rocketStorage.getBytes32(_key); }
function setAddress(bytes32 _key, address _value) internal { rocketStorage.setAddress(_key, _value); }
function setUint(bytes32 _key, uint _value) internal { rocketStorage.setUint(_key, _value); }
function setString(bytes32 _key, string memory _value) internal { rocketStorage.setString(_key, _value); }
function setBytes(bytes32 _key, bytes memory _value) internal { rocketStorage.setBytes(_key, _value); }
function setBool(bytes32 _key, bool _value) internal { rocketStorage.setBool(_key, _value); }
function setInt(bytes32 _key, int _value) internal { rocketStorage.setInt(_key, _value); }
function setBytes32(bytes32 _key, bytes32 _value) internal { rocketStorage.setBytes32(_key, _value); }
function deleteAddress(bytes32 _key) internal { rocketStorage.deleteAddress(_key); }
function deleteUint(bytes32 _key) internal { rocketStorage.deleteUint(_key); }
function deleteString(bytes32 _key) internal { rocketStorage.deleteString(_key); }
function deleteBytes(bytes32 _key) internal { rocketStorage.deleteBytes(_key); }
function deleteBool(bytes32 _key) internal { rocketStorage.deleteBool(_key); }
function deleteInt(bytes32 _key) internal { rocketStorage.deleteInt(_key); }
function deleteBytes32(bytes32 _key) internal { rocketStorage.deleteBytes32(_key); }
function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); }
function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); }
}
文件 10 的 23:RocketDAOProtocolSettingsMinipoolInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../../../types/MinipoolDeposit.sol";
interface RocketDAOProtocolSettingsMinipoolInterface {
function getLaunchBalance() external view returns (uint256);
function getPreLaunchValue() external pure returns (uint256);
function getDepositUserAmount(MinipoolDeposit _depositType) external view returns (uint256);
function getFullDepositUserAmount() external view returns (uint256);
function getHalfDepositUserAmount() external view returns (uint256);
function getVariableDepositAmount() external view returns (uint256);
function getSubmitWithdrawableEnabled() external view returns (bool);
function getBondReductionEnabled() external view returns (bool);
function getLaunchTimeout() external view returns (uint256);
function getMaximumCount() external view returns (uint256);
function isWithinUserDistributeWindow(uint256 _time) external view returns (bool);
function hasUserDistributeWindowPassed(uint256 _time) external view returns (bool);
function getUserDistributeWindowStart() external view returns (uint256);
function getUserDistributeWindowLength() external view returns (uint256);
}
文件 11 的 23:RocketDAOProtocolSettingsNodeInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketDAOProtocolSettingsNodeInterface {
function getRegistrationEnabled() external view returns (bool);
function getSmoothingPoolRegistrationEnabled() external view returns (bool);
function getDepositEnabled() external view returns (bool);
function getVacantMinipoolsEnabled() external view returns (bool);
function getMinimumPerMinipoolStake() external view returns (uint256);
function getMaximumPerMinipoolStake() external view returns (uint256);
function getMaximumStakeForVotingPower() external view returns (uint256);
}
文件 12 的 23:RocketDAOProtocolSettingsRewardsInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketDAOProtocolSettingsRewardsInterface {
function setSettingRewardsClaimers(uint256 _trustedNodePercent, uint256 _protocolPercent, uint256 _nodePercent) external;
function getRewardsClaimerPerc(string memory _contractName) external view returns (uint256);
function getRewardsClaimersPerc() external view returns (uint256 _trustedNodePercent, uint256 _protocolPercent, uint256 _nodePercent);
function getRewardsClaimersTrustedNodePerc() external view returns (uint256);
function getRewardsClaimersProtocolPerc() external view returns (uint256);
function getRewardsClaimersNodePerc() external view returns (uint256);
function getRewardsClaimersTimeUpdated() external view returns (uint256);
function getRewardsClaimIntervalPeriods() external view returns (uint256);
function getRewardsClaimIntervalTime() external view returns (uint256);
}
文件 13 的 23:RocketMinipoolInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolStatus.sol";
import "../RocketStorageInterface.sol";
interface RocketMinipoolInterface {
function version() external view returns (uint8);
function initialise(address _nodeAddress) external;
function getStatus() external view returns (MinipoolStatus);
function getFinalised() external view returns (bool);
function getStatusBlock() external view returns (uint256);
function getStatusTime() external view returns (uint256);
function getScrubVoted(address _member) external view returns (bool);
function getDepositType() external view returns (MinipoolDeposit);
function getNodeAddress() external view returns (address);
function getNodeFee() external view returns (uint256);
function getNodeDepositBalance() external view returns (uint256);
function getNodeRefundBalance() external view returns (uint256);
function getNodeDepositAssigned() external view returns (bool);
function getPreLaunchValue() external view returns (uint256);
function getNodeTopUpValue() external view returns (uint256);
function getVacant() external view returns (bool);
function getPreMigrationBalance() external view returns (uint256);
function getUserDistributed() external view returns (bool);
function getUserDepositBalance() external view returns (uint256);
function getUserDepositAssigned() external view returns (bool);
function getUserDepositAssignedTime() external view returns (uint256);
function getTotalScrubVotes() external view returns (uint256);
function calculateNodeShare(uint256 _balance) external view returns (uint256);
function calculateUserShare(uint256 _balance) external view returns (uint256);
function preDeposit(uint256 _bondingValue, bytes calldata _validatorPubkey, bytes calldata _validatorSignature, bytes32 _depositDataRoot) external payable;
function deposit() external payable;
function userDeposit() external payable;
function distributeBalance(bool _rewardsOnly) external;
function beginUserDistribute() external;
function userDistributeAllowed() external view returns (bool);
function refund() external;
function slash() external;
function finalise() external;
function canStake() external view returns (bool);
function canPromote() external view returns (bool);
function stake(bytes calldata _validatorSignature, bytes32 _depositDataRoot) external;
function prepareVacancy(uint256 _bondAmount, uint256 _currentBalance) external;
function promote() external;
function dissolve() external;
function close() external;
function voteScrub() external;
function reduceBondAmount() external;
}
文件 14 的 23:RocketMinipoolManagerInterface.sol
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
import "../../types/MinipoolDeposit.sol";
import "../../types/MinipoolDetails.sol";
import "./RocketMinipoolInterface.sol";
interface RocketMinipoolManagerInterface {
function getMinipoolCount() external view returns (uint256);
function getStakingMinipoolCount() external view returns (uint256);
function getFinalisedMinipoolCount() external view returns (uint256);
function getActiveMinipoolCount() external view returns (uint256);
function getMinipoolRPLSlashed(address _minipoolAddress) external view returns (bool);
function getMinipoolCountPerStatus(uint256 offset, uint256 limit) external view returns (uint256, uint256, uint256, uint256, uint256);
function getPrelaunchMinipools(uint256 offset, uint256 limit) external view returns (address[] memory);
function getMinipoolAt(uint256 _index) external view returns (address);
function getNodeMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeActiveMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeFinalisedMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeStakingMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeStakingMinipoolCountBySize(address _nodeAddress, uint256 _depositSize) external view returns (uint256);
function getNodeMinipoolAt(address _nodeAddress, uint256 _index) external view returns (address);
function getNodeValidatingMinipoolCount(address _nodeAddress) external view returns (uint256);
function getNodeValidatingMinipoolAt(address _nodeAddress, uint256 _index) external view returns (address);
function getMinipoolByPubkey(bytes calldata _pubkey) external view returns (address);
function getMinipoolExists(address _minipoolAddress) external view returns (bool);
function getMinipoolDestroyed(address _minipoolAddress) external view returns (bool);
function getMinipoolPubkey(address _minipoolAddress) external view returns (bytes memory);
function updateNodeStakingMinipoolCount(uint256 _previousBond, uint256 _newBond, uint256 _previousFee, uint256 _newFee) external;
function getMinipoolWithdrawalCredentials(address _minipoolAddress) external pure returns (bytes memory);
function createMinipool(address _nodeAddress, uint256 _salt) external returns (RocketMinipoolInterface);
function createVacantMinipool(address _nodeAddress, uint256 _salt, bytes calldata _validatorPubkey, uint256 _bondAmount, uint256 _currentBalance) external returns (RocketMinipoolInterface);
function removeVacantMinipool() external;
function getVacantMinipoolCount() external view returns (uint256);
function getVacantMinipoolAt(uint256 _index) external view returns (address);
function destroyMinipool() external;
function incrementNodeStakingMinipoolCount(address _nodeAddress) external;
function decrementNodeStakingMinipoolCount(address _nodeAddress) external;
function tryDistribute(address _nodeAddress) external;
function incrementNodeFinalisedMinipoolCount(address _nodeAddress) external;
function setMinipoolPubkey(bytes calldata _pubkey) external;
function getMinipoolDepositType(address _minipoolAddress) external view returns (MinipoolDeposit);
}
文件 15 的 23:RocketNetworkPricesInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketNetworkPricesInterface {
function getPricesBlock() external view returns (uint256);
function getRPLPrice() external view returns (uint256);
function submitPrices(uint256 _block, uint256 _slotTimestamp, uint256 _rplPrice) external;
function executeUpdatePrices(uint256 _block, uint256 _slotTimestamp, uint256 _rplPrice) external;
}
文件 16 的 23:RocketNetworkSnapshots.sol
pragma solidity 0.8.18;
import "@openzeppelin4/contracts/utils/math/Math.sol";
import "../RocketBase.sol";
import "../../interface/network/RocketNetworkSnapshotsInterface.sol";
contract RocketNetworkSnapshots is RocketBase, RocketNetworkSnapshotsInterface {
constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
version = 1;
if (!rocketStorage.getDeployedStatus()) {
_insert(keccak256("network.prices.rpl"), 0.01 ether);
_insert(keccak256("node.voting.power.stake.maximum"), 1.5 ether);
}
}
function push(bytes32 _key, uint224 _value) onlyLatestContract("rocketNetworkSnapshots", address(this)) onlyLatestNetworkContract external {
_insert(_key, _value);
}
function length(bytes32 _key) public view returns (uint256) {
return rocketStorage.getUint(keccak256(abi.encodePacked("snapshot.length", _key)));
}
function latest(bytes32 _key) external view returns (bool, uint32, uint224) {
uint256 len = length(_key);
if (len == 0) {
return (false, 0, 0);
}
Checkpoint224 memory checkpoint = _load(_key, len - 1);
return (true, checkpoint._block, checkpoint._value);
}
function latestBlock(bytes32 _key) external view returns (uint32) {
uint256 len = length(_key);
return len == 0 ? 0 : _blockAt(_key, len - 1);
}
function latestValue(bytes32 _key) external view returns (uint224) {
uint256 len = length(_key);
return len == 0 ? 0 : _valueAt(_key, len - 1);
}
function lookup(bytes32 _key, uint32 _block) external view returns (uint224) {
uint256 len = length(_key);
uint256 pos = _binaryLookup(_key, _block, 0, len);
return pos == 0 ? 0 : _valueAt(_key, pos - 1);
}
function lookupRecent(bytes32 _key, uint32 _block, uint256 _recency) external view returns (uint224) {
uint256 len = length(_key);
uint256 low = 0;
uint256 high = len;
if (len > 5 && len > _recency) {
uint256 mid = len - _recency;
if (_block < _blockAt(_key, mid)) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _binaryLookup(_key, _block, low, high);
return pos == 0 ? 0 : _valueAt(_key, pos - 1);
}
function _insert(bytes32 _key, uint224 _value) private {
uint32 blockNumber = uint32(block.number);
uint256 pos = length(_key);
if (pos > 0) {
Checkpoint224 memory last = _load(_key, pos - 1);
require (last._block <= blockNumber, "Unordered snapshot insertion");
if (last._block == blockNumber) {
last._value = _value;
_set(_key, pos - 1, last);
} else {
_push(_key, Checkpoint224({_block: blockNumber, _value: _value}));
}
} else {
_push(_key, Checkpoint224({_block: blockNumber, _value: _value}));
}
}
function _binaryLookup(
bytes32 _key,
uint32 _block,
uint256 _low,
uint256 _high
) private view returns (uint256) {
while (_low < _high) {
uint256 mid = Math.average(_low, _high);
if (_blockAt(_key, mid) > _block) {
_high = mid;
} else {
_low = mid + 1;
}
}
return _high;
}
function _load(bytes32 _key, uint256 _pos) private view returns (Checkpoint224 memory) {
bytes32 key = bytes32(uint256(_key) + _pos);
bytes32 raw = rocketStorage.getBytes32(key);
Checkpoint224 memory result;
result._block = uint32(uint256(raw) >> 224);
result._value = uint224(uint256(raw));
return result;
}
function _blockAt(bytes32 _key, uint256 _pos) private view returns (uint32) {
bytes32 key = bytes32(uint256(_key) + _pos);
bytes32 raw = rocketStorage.getBytes32(key);
return uint32(uint256(raw) >> 224);
}
function _valueAt(bytes32 _key, uint256 _pos) private view returns (uint224) {
bytes32 key = bytes32(uint256(_key) + _pos);
bytes32 raw = rocketStorage.getBytes32(key);
return uint224(uint256(raw));
}
function _push(bytes32 _key, Checkpoint224 memory _item) private {
bytes32 lengthKey = keccak256(abi.encodePacked("snapshot.length", _key));
uint256 snapshotLength = rocketStorage.getUint(lengthKey);
bytes32 key = bytes32(uint256(_key) + snapshotLength);
rocketStorage.setUint(lengthKey, snapshotLength + 1);
rocketStorage.setBytes32(key, _encode(_item));
}
function _set(bytes32 _key, uint256 _pos, Checkpoint224 memory _item) private {
bytes32 key = bytes32(uint256(_key) + _pos);
rocketStorage.setBytes32(key, _encode(_item));
}
function _encode(Checkpoint224 memory _item) private pure returns (bytes32) {
return bytes32(
uint256(_item._block) << 224 | uint256(_item._value)
);
}
}
文件 17 的 23:RocketNetworkSnapshotsInterface.sol
pragma solidity >0.5.0 <0.9.0;
struct Checkpoint224 {
uint32 _block;
uint224 _value;
}
interface RocketNetworkSnapshotsInterface {
function push(bytes32 _key, uint224 _value) external;
function length(bytes32 _key) external view returns (uint256);
function latest(bytes32 _key) external view returns (bool, uint32, uint224);
function latestBlock(bytes32 _key) external view returns (uint32);
function latestValue(bytes32 _key) external view returns (uint224);
function lookup(bytes32 _key, uint32 _block) external view returns (uint224);
function lookupRecent(bytes32 _key, uint32 _block, uint256 _recency) external view returns (uint224);
}
文件 18 的 23:RocketNetworkVotingInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketNetworkVotingInterface {
function initialiseVotingFor(address _nodeAddress) external;
function initialiseVoting() external;
function initialiseVotingWithDelegate(address _delegate) external;
function getVotingInitialised(address _nodeAddress) external view returns (bool);
function getNodeCount(uint32 _block) external view returns (uint256);
function getVotingPower(address _nodeAddress, uint32 _block) external view returns (uint256);
function setDelegate(address _newDelegate) external;
function getDelegate(address _nodeAddress, uint32 _block) external view returns (address);
function getCurrentDelegate(address _nodeAddress) external view returns (address);
}
文件 19 的 23:RocketNodeManagerInterface.sol
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
import "../../types/NodeDetails.sol";
interface RocketNodeManagerInterface {
struct TimezoneCount {
string timezone;
uint256 count;
}
function getNodeCount() external view returns (uint256);
function getNodeCountPerTimezone(uint256 offset, uint256 limit) external view returns (TimezoneCount[] memory);
function getNodeAt(uint256 _index) external view returns (address);
function getNodeExists(address _nodeAddress) external view returns (bool);
function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodeRPLWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodeRPLWithdrawalAddressIsSet(address _nodeAddress) external view returns (bool);
function unsetRPLWithdrawalAddress(address _nodeAddress) external;
function setRPLWithdrawalAddress(address _nodeAddress, address _newRPLWithdrawalAddress, bool _confirm) external;
function confirmRPLWithdrawalAddress(address _nodeAddress) external;
function getNodePendingRPLWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodeTimezoneLocation(address _nodeAddress) external view returns (string memory);
function registerNode(string calldata _timezoneLocation) external;
function getNodeRegistrationTime(address _nodeAddress) external view returns (uint256);
function setTimezoneLocation(string calldata _timezoneLocation) external;
function setRewardNetwork(address _nodeAddress, uint256 network) external;
function getRewardNetwork(address _nodeAddress) external view returns (uint256);
function getFeeDistributorInitialised(address _nodeAddress) external view returns (bool);
function initialiseFeeDistributor() external;
function getAverageNodeFee(address _nodeAddress) external view returns (uint256);
function setSmoothingPoolRegistrationState(bool _state) external;
function getSmoothingPoolRegistrationState(address _nodeAddress) external returns (bool);
function getSmoothingPoolRegistrationChanged(address _nodeAddress) external returns (uint256);
function getSmoothingPoolRegisteredNodeCount(uint256 _offset, uint256 _limit) external view returns (uint256);
function getNodeDetails(address _nodeAddress) external view returns (NodeDetails memory);
function getNodeAddresses(uint256 _offset, uint256 _limit) external view returns (address[] memory);
}
文件 20 的 23:RocketNodeStaking.sol
pragma solidity 0.8.18;
import "../../interface/util/IERC20.sol";
import "../RocketBase.sol";
import "../../interface/minipool/RocketMinipoolManagerInterface.sol";
import "../../interface/network/RocketNetworkPricesInterface.sol";
import "../../interface/node/RocketNodeStakingInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsRewardsInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsMinipoolInterface.sol";
import "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
import "../../interface/RocketVaultInterface.sol";
import "../../interface/util/AddressSetStorageInterface.sol";
import "../../interface/network/RocketNetworkSnapshotsInterface.sol";
import "../network/RocketNetworkSnapshots.sol";
import "../../interface/node/RocketNodeManagerInterface.sol";
import "../../interface/network/RocketNetworkVotingInterface.sol";
contract RocketNodeStaking is RocketBase, RocketNodeStakingInterface {
bytes32 immutable internal totalKey;
event RPLStaked(address indexed from, uint256 amount, uint256 time);
event RPLWithdrawn(address indexed to, uint256 amount, uint256 time);
event RPLSlashed(address indexed node, uint256 amount, uint256 ethValue, uint256 time);
event StakeRPLForAllowed(address indexed node, address indexed caller, bool allowed, uint256 time);
event RPLLockingAllowed(address indexed node, bool allowed, uint256 time);
event RPLLocked(address indexed from, uint256 amount, uint256 time);
event RPLUnlocked(address indexed from, uint256 amount, uint256 time);
event RPLTransferred(address indexed from, address indexed to, uint256 amount, uint256 time);
event RPLBurned(address indexed from, uint256 amount, uint256 time);
modifier onlyRPLWithdrawalAddressOrNode(address _nodeAddress) {
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
require(msg.sender == rplWithdrawalAddress, "Must be called from RPL withdrawal address");
} else {
require(msg.sender == _nodeAddress, "Must be called from node address");
}
_;
}
constructor(RocketStorageInterface _rocketStorageAddress) RocketBase(_rocketStorageAddress) {
version = 6;
totalKey = keccak256(abi.encodePacked("rpl.staked.total.amount"));
}
function getTotalRPLStake() override external view returns (uint256) {
return getUint(totalKey);
}
function increaseTotalRPLStake(uint256 _amount) private {
addUint(totalKey, _amount);
}
function decreaseTotalRPLStake(uint256 _amount) private {
subUint(totalKey, _amount);
}
function getNodeRPLStake(address _nodeAddress) override public view returns (uint256) {
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
(bool exists,, uint224 value) = rocketNetworkSnapshots.latest(key);
uint256 stake = uint256(value);
if (!exists){
stake = getUint(key);
}
return stake;
}
function increaseNodeRPLStake(address _nodeAddress, uint256 _amount) private {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
(bool exists,, uint224 value) = rocketNetworkSnapshots.latest(key);
if (!exists){
value = uint224(getUint(key));
}
rocketNetworkSnapshots.push(key, value + uint224(_amount));
}
function decreaseNodeRPLStake(address _nodeAddress, uint256 _amount) private {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
(bool exists,, uint224 value) = rocketNetworkSnapshots.latest(key);
if (!exists){
value = uint224(getUint(key));
}
rocketNetworkSnapshots.push(key, value - uint224(_amount));
}
function getNodeETHMatched(address _nodeAddress) override public view returns (uint256) {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("eth.matched.node.amount", _nodeAddress));
(bool exists, , uint224 value) = rocketNetworkSnapshots.latest(key);
if (exists) {
return value;
} else {
uint256 ethMatched = getUint(key);
if (ethMatched > 0) {
return ethMatched;
} else {
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
return rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress) * 16 ether;
}
}
}
function getNodeETHProvided(address _nodeAddress) override public view returns (uint256) {
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
uint256 activeMinipoolCount = rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress);
uint256 ethMatched = getNodeETHMatched(_nodeAddress);
if (ethMatched > 0) {
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
uint256 totalEthStaked = activeMinipoolCount * launchAmount;
return totalEthStaked - ethMatched;
} else {
return activeMinipoolCount * 16 ether;
}
}
function getNodeETHCollateralisationRatio(address _nodeAddress) override public view returns (uint256) {
uint256 ethMatched = getNodeETHMatched(_nodeAddress);
if (ethMatched == 0) {
return calcBase * 2;
} else {
RocketDAOProtocolSettingsMinipoolInterface rocketDAOProtocolSettingsMinipool = RocketDAOProtocolSettingsMinipoolInterface(getContractAddress("rocketDAOProtocolSettingsMinipool"));
uint256 launchAmount = rocketDAOProtocolSettingsMinipool.getLaunchBalance();
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
uint256 totalEthStaked = rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress) * launchAmount;
return (totalEthStaked * calcBase) / (totalEthStaked - ethMatched);
}
}
function getNodeRPLStakedTime(address _nodeAddress) override public view returns (uint256) {
return getUint(keccak256(abi.encodePacked("rpl.staked.node.time", _nodeAddress)));
}
function setNodeRPLStakedTime(address _nodeAddress, uint256 _time) private {
setUint(keccak256(abi.encodePacked("rpl.staked.node.time", _nodeAddress)), _time);
}
function getNodeEffectiveRPLStake(address _nodeAddress) override public view returns (uint256) {
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
uint256 rplStake = getNodeRPLStake(_nodeAddress);
uint256 matchedETH = getNodeETHMatched(_nodeAddress);
uint256 providedETH = getNodeETHProvided(_nodeAddress);
uint256 rplPrice = rocketNetworkPrices.getRPLPrice();
uint256 maximumStakePercent = rocketDAOProtocolSettingsNode.getMaximumPerMinipoolStake();
uint256 maximumStake = providedETH * maximumStakePercent / rplPrice;
if (rplStake > maximumStake) {
return maximumStake;
}
uint256 minimumStakePercent = rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake();
uint256 minimumStake = matchedETH * minimumStakePercent / rplPrice;
if (rplStake < minimumStake) {
return 0;
}
return rplStake;
}
function getNodeMinimumRPLStake(address _nodeAddress) override external view returns (uint256) {
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
uint256 minimumStakePercent = rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake();
uint256 matchedETH = getNodeETHMatched(_nodeAddress);
return matchedETH * minimumStakePercent / rocketNetworkPrices.getRPLPrice();
}
function getNodeMaximumRPLStake(address _nodeAddress) override public view returns (uint256) {
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
uint256 maximumStakePercent = rocketDAOProtocolSettingsNode.getMaximumPerMinipoolStake();
uint256 providedETH = getNodeETHProvided(_nodeAddress);
return providedETH * maximumStakePercent / rocketNetworkPrices.getRPLPrice();
}
function getNodeETHMatchedLimit(address _nodeAddress) override external view returns (uint256) {
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
uint256 minimumStakePercent = rocketDAOProtocolSettingsNode.getMinimumPerMinipoolStake();
if (minimumStakePercent == 0) {
return type(uint256).max;
}
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
return getNodeRPLStake(_nodeAddress) *rocketNetworkPrices.getRPLPrice() / minimumStakePercent;
}
function getRPLLockingAllowed(address _nodeAddress) external view returns (bool) {
return getBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress)));
}
function stakeRPL(uint256 _amount) override external {
stakeRPLFor(msg.sender, _amount);
}
function stakeRPLFor(address _nodeAddress, uint256 _amount) override public onlyLatestContract("rocketNodeStaking", address(this)) onlyRegisteredNode(_nodeAddress) {
if (msg.sender != getAddress(keccak256(abi.encodePacked("contract.address", "rocketMerkleDistributorMainnet")))) {
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
bool fromNode = false;
if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
fromNode = msg.sender == rplWithdrawalAddress;
} else {
address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
fromNode = (msg.sender == _nodeAddress) || (msg.sender == withdrawalAddress);
}
if (!fromNode) {
require(getBool(keccak256(abi.encodePacked("node.stake.for.allowed", _nodeAddress, msg.sender))), "Not allowed to stake for");
}
}
_stakeRPL(_nodeAddress, _amount);
}
function setRPLLockingAllowed(address _nodeAddress, bool _allowed) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyRPLWithdrawalAddressOrNode(_nodeAddress) {
setBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress)), _allowed);
emit RPLLockingAllowed(_nodeAddress, _allowed, block.timestamp);
}
function setStakeRPLForAllowed(address _caller, bool _allowed) override external {
setStakeRPLForAllowed(msg.sender, _caller, _allowed);
}
function setStakeRPLForAllowed(address _nodeAddress, address _caller, bool _allowed) override public onlyLatestContract("rocketNodeStaking", address(this)) onlyRPLWithdrawalAddressOrNode(_nodeAddress) {
setBool(keccak256(abi.encodePacked("node.stake.for.allowed", _nodeAddress, _caller)), _allowed);
emit StakeRPLForAllowed(_nodeAddress, _caller, _allowed, block.timestamp);
}
function _stakeRPL(address _nodeAddress, uint256 _amount) internal {
RocketNetworkVotingInterface rocketNetworkVoting = RocketNetworkVotingInterface(getContractAddress("rocketNetworkVoting"));
rocketNetworkVoting.initialiseVotingFor(_nodeAddress);
address rplTokenAddress = getContractAddress("rocketTokenRPL");
address rocketVaultAddress = getContractAddress("rocketVault");
IERC20 rplToken = IERC20(rplTokenAddress);
RocketVaultInterface rocketVault = RocketVaultInterface(rocketVaultAddress);
require(rplToken.transferFrom(msg.sender, address(this), _amount), "Could not transfer RPL to staking contract");
require(rplToken.approve(rocketVaultAddress, _amount), "Could not approve vault RPL deposit");
rocketVault.depositToken("rocketNodeStaking", rplToken, _amount);
increaseTotalRPLStake(_amount);
increaseNodeRPLStake(_nodeAddress, _amount);
setNodeRPLStakedTime(_nodeAddress, block.timestamp);
emit RPLStaked(_nodeAddress, _amount, block.timestamp);
}
function getNodeRPLLocked(address _nodeAddress) override public view returns (uint256) {
return getUint(keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress)));
}
function lockRPL(address _nodeAddress, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() {
require(getBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress))), "Node is not allowed to lock RPL");
uint256 rplStake = getNodeRPLStake(_nodeAddress);
bytes32 lockedStakeKey = keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress));
uint256 lockedStake = getUint(lockedStakeKey);
require(rplStake - lockedStake >= _amount, "Not enough staked RPL");
setUint(lockedStakeKey, lockedStake + _amount);
emit RPLLocked(_nodeAddress, _amount, block.timestamp);
}
function unlockRPL(address _nodeAddress, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() {
bytes32 lockedStakeKey = keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress));
uint256 lockedStake = getUint(lockedStakeKey);
require(_amount <= lockedStake, "Not enough locked RPL");
setUint(lockedStakeKey, lockedStake - _amount);
emit RPLUnlocked(_nodeAddress, _amount, block.timestamp);
}
function transferRPL(address _from, address _to, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() onlyRegisteredNode(_from) {
require(getNodeRPLStake(_from) >= _amount, "Sender has insufficient RPL");
decreaseNodeRPLStake(_from, _amount);
increaseNodeRPLStake(_to, _amount);
emit RPLTransferred(_from, _to, _amount, block.timestamp);
}
function burnRPL(address _from, uint256 _amount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyLatestNetworkContract() onlyRegisteredNode(_from) {
require(getNodeRPLStake(_from) >= _amount, "Node has insufficient RPL");
decreaseTotalRPLStake(_amount);
decreaseNodeRPLStake(_from, _amount);
IERC20Burnable rplToken = IERC20Burnable(getContractAddress("rocketTokenRPL"));
RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
rocketVault.withdrawToken(address(this), rplToken, _amount);
rplToken.burn(_amount);
emit RPLBurned(_from, _amount, block.timestamp);
}
function withdrawRPL(uint256 _amount) override external {
withdrawRPL(msg.sender, _amount);
}
function withdrawRPL(address _nodeAddress, uint256 _amount) override public onlyLatestContract("rocketNodeStaking", address(this)) {
require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
require(msg.sender == rplWithdrawalAddress, "Invalid caller");
} else {
address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
require(msg.sender == _nodeAddress || msg.sender == withdrawalAddress, "Invalid caller");
}
RocketDAOProtocolSettingsRewardsInterface rocketDAOProtocolSettingsRewards = RocketDAOProtocolSettingsRewardsInterface(getContractAddress("rocketDAOProtocolSettingsRewards"));
RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
require(block.timestamp - getNodeRPLStakedTime(_nodeAddress) >= rocketDAOProtocolSettingsRewards.getRewardsClaimIntervalTime(), "The withdrawal cooldown period has not passed");
uint256 rplStake = getNodeRPLStake(_nodeAddress);
uint256 lockedStake = getNodeRPLLocked(_nodeAddress);
require(rplStake - lockedStake >= _amount, "Withdrawal amount exceeds node's staked RPL balance");
require(rplStake - _amount >= getNodeMaximumRPLStake(_nodeAddress) + lockedStake, "Node's staked RPL balance after withdrawal is less than required balance");
decreaseTotalRPLStake(_amount);
decreaseNodeRPLStake(_nodeAddress, _amount);
rocketVault.withdrawToken(rplWithdrawalAddress, IERC20(getContractAddress("rocketTokenRPL")), _amount);
emit RPLWithdrawn(_nodeAddress, _amount, block.timestamp);
}
function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) override external onlyLatestContract("rocketNodeStaking", address(this)) onlyRegisteredMinipool(msg.sender) {
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
RocketVaultInterface rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
uint256 rplSlashAmount = calcBase * _ethSlashAmount / rocketNetworkPrices.getRPLPrice();
uint256 rplStake = getNodeRPLStake(_nodeAddress);
if (rplSlashAmount > rplStake) { rplSlashAmount = rplStake; }
if(rplSlashAmount > 0) rocketVault.transferToken("rocketAuctionManager", IERC20(getContractAddress("rocketTokenRPL")), rplSlashAmount);
decreaseTotalRPLStake(rplSlashAmount);
decreaseNodeRPLStake(_nodeAddress, rplSlashAmount);
setBool(keccak256(abi.encodePacked("minipool.rpl.slashed", msg.sender)), true);
emit RPLSlashed(_nodeAddress, rplSlashAmount, _ethSlashAmount, block.timestamp);
}
}
文件 21 的 23:RocketNodeStakingInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketNodeStakingInterface {
function getTotalRPLStake() external view returns (uint256);
function getNodeRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeETHMatched(address _nodeAddress) external view returns (uint256);
function getNodeETHProvided(address _nodeAddress) external view returns (uint256);
function getNodeETHCollateralisationRatio(address _nodeAddress) external view returns (uint256);
function getNodeRPLStakedTime(address _nodeAddress) external view returns (uint256);
function getNodeEffectiveRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeMinimumRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeMaximumRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeETHMatchedLimit(address _nodeAddress) external view returns (uint256);
function getRPLLockingAllowed(address _nodeAddress) external view returns (bool);
function stakeRPL(uint256 _amount) external;
function stakeRPLFor(address _nodeAddress, uint256 _amount) external;
function setRPLLockingAllowed(address _nodeAddress, bool _allowed) external;
function setStakeRPLForAllowed(address _caller, bool _allowed) external;
function setStakeRPLForAllowed(address _nodeAddress, address _caller, bool _allowed) external;
function getNodeRPLLocked(address _nodeAddress) external view returns (uint256);
function lockRPL(address _nodeAddress, uint256 _amount) external;
function unlockRPL(address _nodeAddress, uint256 _amount) external;
function transferRPL(address _from, address _to, uint256 _amount) external;
function burnRPL(address _from, uint256 _amount) external;
function withdrawRPL(uint256 _amount) external;
function withdrawRPL(address _nodeAddress, uint256 _amount) external;
function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) external;
}
文件 22 的 23:RocketStorageInterface.sol
pragma solidity >0.5.0 <0.9.0;
interface RocketStorageInterface {
function getDeployedStatus() external view returns (bool);
function getGuardian() external view returns(address);
function setGuardian(address _newAddress) external;
function confirmGuardian() external;
function getAddress(bytes32 _key) external view returns (address);
function getUint(bytes32 _key) external view returns (uint);
function getString(bytes32 _key) external view returns (string memory);
function getBytes(bytes32 _key) external view returns (bytes memory);
function getBool(bytes32 _key) external view returns (bool);
function getInt(bytes32 _key) external view returns (int);
function getBytes32(bytes32 _key) external view returns (bytes32);
function setAddress(bytes32 _key, address _value) external;
function setUint(bytes32 _key, uint _value) external;
function setString(bytes32 _key, string calldata _value) external;
function setBytes(bytes32 _key, bytes calldata _value) external;
function setBool(bytes32 _key, bool _value) external;
function setInt(bytes32 _key, int _value) external;
function setBytes32(bytes32 _key, bytes32 _value) external;
function deleteAddress(bytes32 _key) external;
function deleteUint(bytes32 _key) external;
function deleteString(bytes32 _key) external;
function deleteBytes(bytes32 _key) external;
function deleteBool(bytes32 _key) external;
function deleteInt(bytes32 _key) external;
function deleteBytes32(bytes32 _key) external;
function addUint(bytes32 _key, uint256 _amount) external;
function subUint(bytes32 _key, uint256 _amount) external;
function getNodeWithdrawalAddress(address _nodeAddress) external view returns (address);
function getNodePendingWithdrawalAddress(address _nodeAddress) external view returns (address);
function setWithdrawalAddress(address _nodeAddress, address _newWithdrawalAddress, bool _confirm) external;
function confirmWithdrawalAddress(address _nodeAddress) external;
}
文件 23 的 23:RocketVaultInterface.sol
pragma solidity >0.5.0 <0.9.0;
import "./util/IERC20Burnable.sol";
interface RocketVaultInterface {
function balanceOf(string memory _networkContractName) external view returns (uint256);
function depositEther() external payable;
function withdrawEther(uint256 _amount) external;
function depositToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) external;
function withdrawToken(address _withdrawalAddress, IERC20 _tokenAddress, uint256 _amount) external;
function balanceOfToken(string memory _networkContractName, IERC20 _tokenAddress) external view returns (uint256);
function transferToken(string memory _networkContractName, IERC20 _tokenAddress, uint256 _amount) external;
function burnToken(IERC20Burnable _tokenAddress, uint256 _amount) external;
}
{
"compilationTarget": {
"contracts/contract/node/RocketNodeStaking.sol": "RocketNodeStaking"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 15000
},
"remappings": []
}
[{"inputs":[{"internalType":"contract RocketStorageInterface","name":"_rocketStorageAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLLockingAllowed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethValue","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLSlashed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLStaked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLUnlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"StakeRPLForAllowed","type":"event"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeETHCollateralisationRatio","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeETHMatched","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeETHMatchedLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeETHProvided","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeEffectiveRPLStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMaximumRPLStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMinimumRPLStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeRPLLocked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeRPLStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeRPLStakedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getRPLLockingAllowed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRPLStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"lockRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setRPLLockingAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_caller","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setStakeRPLForAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"address","name":"_caller","type":"address"},{"internalType":"bool","name":"_allowed","type":"bool"}],"name":"setStakeRPLForAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_ethSlashAmount","type":"uint256"}],"name":"slashRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeRPLFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unlockRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"withdrawRPL","outputs":[],"stateMutability":"nonpayable","type":"function"}]