Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 122 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Stake RPL For | 24552614 | 3 mins ago | IN | 0 ETH | 0.00036804 | ||||
| Stake RPL For | 24550643 | 6 hrs ago | IN | 0 ETH | 0.00000832 | ||||
| Set Stake RPL Fo... | 24550523 | 7 hrs ago | IN | 0 ETH | 0.00000391 | ||||
| Unstake Legacy R... | 24550228 | 8 hrs ago | IN | 0 ETH | 0.00002366 | ||||
| Unstake Legacy R... | 24550216 | 8 hrs ago | IN | 0 ETH | 0.00002555 | ||||
| Stake RPL For | 24549600 | 10 hrs ago | IN | 0 ETH | 0.00003596 | ||||
| Stake RPL For | 24549585 | 10 hrs ago | IN | 0 ETH | 0.00004045 | ||||
| Stake RPL For | 24549555 | 10 hrs ago | IN | 0 ETH | 0.00004173 | ||||
| Unstake Legacy R... | 24546932 | 19 hrs ago | IN | 0 ETH | 0.00051344 | ||||
| Unstake Legacy R... | 24546636 | 20 hrs ago | IN | 0 ETH | 0.00001433 | ||||
| Stake RPL | 24546112 | 21 hrs ago | IN | 0 ETH | 0.0004733 | ||||
| Unstake Legacy R... | 24545920 | 22 hrs ago | IN | 0 ETH | 0.00001342 | ||||
| Unstake Legacy R... | 24544919 | 25 hrs ago | IN | 0 ETH | 0.00001442 | ||||
| Unstake RPL For | 24544862 | 26 hrs ago | IN | 0 ETH | 0.00045028 | ||||
| Unstake Legacy R... | 24543876 | 29 hrs ago | IN | 0 ETH | 0.00002581 | ||||
| Stake RPL | 24543876 | 29 hrs ago | IN | 0 ETH | 0.00036524 | ||||
| Unstake Legacy R... | 24543682 | 29 hrs ago | IN | 0 ETH | 0.00003064 | ||||
| Unstake Legacy R... | 24541622 | 36 hrs ago | IN | 0 ETH | 0.00006095 | ||||
| Stake RPL | 24541321 | 37 hrs ago | IN | 0 ETH | 0.00001276 | ||||
| Stake RPL | 24540496 | 40 hrs ago | IN | 0 ETH | 0.00001145 | ||||
| Stake RPL | 24540470 | 40 hrs ago | IN | 0 ETH | 0.00001325 | ||||
| Stake RPL | 24539440 | 44 hrs ago | IN | 0 ETH | 0.00047238 | ||||
| Stake RPL | 24538850 | 46 hrs ago | IN | 0 ETH | 0.00000865 | ||||
| Unstake Legacy R... | 24538210 | 2 days ago | IN | 0 ETH | 0.00003616 | ||||
| Stake RPL | 24537843 | 2 days ago | IN | 0 ETH | 0.0003715 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
RocketNodeStaking
Compiler Version
v0.8.30+commit.73712a01
Contract Source Code (Solidity Standard Json-Input format)
/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.30;
import {RocketStorageInterface} from "../../interface/RocketStorageInterface.sol";
import {RocketVaultInterface} from "../../interface/RocketVaultInterface.sol";
import {RocketDAOProtocolSettingsNodeInterface} from "../../interface/dao/protocol/settings/RocketDAOProtocolSettingsNodeInterface.sol";
import {RocketMinipoolManagerInterface} from "../../interface/minipool/RocketMinipoolManagerInterface.sol";
import {RocketNetworkPricesInterface} from "../../interface/network/RocketNetworkPricesInterface.sol";
import {RocketNetworkSnapshotsInterface} from "../../interface/network/RocketNetworkSnapshotsInterface.sol";
import {RocketNodeManagerInterface} from "../../interface/node/RocketNodeManagerInterface.sol";
import {RocketNodeStakingInterface} from "../../interface/node/RocketNodeStakingInterface.sol";
import {RocketTokenRPLInterface} from "../../interface/token/RocketTokenRPLInterface.sol";
import {IERC20} from "../../interface/util/IERC20.sol";
import {IERC20Burnable} from "../../interface/util/IERC20Burnable.sol";
import {RocketBase} from "../RocketBase.sol";
/// @notice Handles staking of RPL by node operators
contract RocketNodeStaking is RocketBase, RocketNodeStakingInterface {
// Immutables
bytes32 immutable internal totalKey;
bytes32 immutable internal totalMegapoolKey;
RocketTokenRPLInterface immutable internal rplToken;
RocketVaultInterface immutable internal rocketVault;
// Events
event RPLStaked(address indexed node, address from, uint256 amount, uint256 time);
event RPLStaked(address indexed from, uint256 amount, uint256 time);
event RPLUnstaked(address indexed from, uint256 amount, uint256 time);
event RPLLegacyUnstaked(address indexed to, 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);
/// @dev Reverts if not being called from a node or their RPL withdrawal address
modifier onlyRPLWithdrawalAddressOrNode(address _nodeAddress) {
// Check that the call is coming from RPL withdrawal address (or node if unset)
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 = 7;
// Precompute keys
totalKey = keccak256(abi.encodePacked("rpl.staked.total.amount"));
totalMegapoolKey = keccak256(abi.encodePacked("rpl.megapool.staked.total.amount"));
// Store immutable contract references
rplToken = RocketTokenRPLInterface(getContractAddress("rocketTokenRPL"));
rocketVault = RocketVaultInterface(getContractAddress("rocketVault"));
}
/// @notice Returns the total quantity of RPL staked on the network
function getTotalStakedRPL() override public view returns (uint256) {
return getUint(totalKey);
}
/// @notice Returns the total quantity of "Megapool Staked RPL" on the network
function getTotalMegapoolStakedRPL() override public view returns (uint256) {
return getUint(totalMegapoolKey);
}
/// @notice Returns the total amount of "Legacy Staked RPL" in the protocol
function getTotalLegacyStakedRPL() override external view returns (uint256) {
return getTotalStakedRPL() - getTotalMegapoolStakedRPL();
}
/// @notice Returns the total amount of RPL staked by a node operator (both legacy and megapool staked RPL)
/// @param _nodeAddress The address of the node operator to query
function getNodeStakedRPL(address _nodeAddress) override public view returns (uint256) {
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
(,, uint224 value) = rocketNetworkSnapshots.latest(key);
return uint256(value);
}
/// @notice Returns the amount of legacy staked RPL for a node operator
/// @notice _nodeAddress Address of the node operator to query
function getNodeLegacyStakedRPL(address _nodeAddress) override public view returns (uint256) {
bytes32 migratedKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.migrated", _nodeAddress));
if (getBool(migratedKey)) {
bytes32 legacyKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.amount", _nodeAddress));
return getUint(legacyKey);
}
return getNodeStakedRPL(_nodeAddress);
}
/// @notice Returns the amount of megapool staked RPL for a node operator
/// @notice _nodeAddress Address of the node operator to query
function getNodeMegapoolStakedRPL(address _nodeAddress) override external view returns (uint256) {
bytes32 migratedKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.migrated", _nodeAddress));
if (!getBool(migratedKey)) {
return 0;
}
bytes32 legacyKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.amount", _nodeAddress));
return getNodeStakedRPL(_nodeAddress) - getUint(legacyKey);
}
/// @notice Gets the time the the given node operator's previous unstake
/// @param _nodeAddress The address of the node operator to query for
function getNodeLastUnstakeTime(address _nodeAddress) override public view returns (uint256) {
return getUint(keccak256(abi.encodePacked("rpl.megapool.unstake.time", _nodeAddress)));
}
/// @notice Returns the timestamp at which a node last staked RPL
/// @param _nodeAddress The address of the node operator to query for
function getNodeRPLStakedTime(address _nodeAddress) override public view returns (uint256) {
return getUint(keccak256(abi.encodePacked("rpl.staked.node.time", _nodeAddress)));
}
/// @notice Returns the amount of RPL that is in the "unstaking" state
/// @param _nodeAddress The address of the node operator to query for
function getNodeUnstakingRPL(address _nodeAddress) override public view returns (uint256) {
return getUint(keccak256(abi.encodePacked("rpl.megapool.unstaking.amount", _nodeAddress)));
}
/// @notice Returns the amount of RPL that is locked for a given node
/// @param _nodeAddress The address of the node operator to query for
function getNodeLockedRPL(address _nodeAddress) override public view returns (uint256) {
return getUint(keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress)));
}
/// @notice Returns whether this node allows RPL locking or not
/// @param _nodeAddress The address of the node operator to query for
function getRPLLockingAllowed(address _nodeAddress) external view returns (bool) {
return getBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress)));
}
/// @notice Sets the allow state for this node to perform functions that require locking RPL
/// @param _nodeAddress The address of the node operator to change the state for
/// @param _allowed Whether locking is allowed or not
function setRPLLockingAllowed(address _nodeAddress, bool _allowed) override external onlyRPLWithdrawalAddressOrNode(_nodeAddress) {
// Set the value
setBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress)), _allowed);
// Log it
emit RPLLockingAllowed(_nodeAddress, _allowed, block.timestamp);
}
/// @notice Explicitly allow or remove allowance of an address to be able to stake on behalf of a node
/// @dev The node operator is determined by the address calling this method, it is here for backwards compatibility
/// @param _caller The address you wish to allow
/// @param _allowed Whether the address is allowed or denied
function setStakeRPLForAllowed(address _caller, bool _allowed) override external {
setStakeRPLForAllowed(msg.sender, _caller, _allowed);
}
/// @notice Explicitly allow or remove allowance of an address to be able to stake on behalf of a node
/// @param _nodeAddress The address of the node operator allowing the caller
/// @param _caller The address you wish to allow
/// @param _allowed Whether the address is allowed or denied
function setStakeRPLForAllowed(address _nodeAddress, address _caller, bool _allowed) override public onlyRPLWithdrawalAddressOrNode(_nodeAddress) onlyRegisteredNode(_nodeAddress) {
// Set the value
setBool(keccak256(abi.encodePacked("node.stake.for.allowed", _nodeAddress, _caller)), _allowed);
// Log it
emit StakeRPLForAllowed(_nodeAddress, _caller, _allowed, block.timestamp);
}
/// @notice Increases the calling node operator's megapool staked RPL by transferring RPL from msg.sender
function stakeRPL(uint256 _amount) override external onlyRegisteredNode(msg.sender) {
// Check caller here and skip `stakeRPLFor` to avoid unnecessary check for rocketMerkleDistributorMainnet caller
require(_callerAllowedFor(msg.sender), "Not allowed to stake for");
_stakeRPLFor(msg.sender, _amount);
}
/// @notice Accept an RPL stake from any address for a specified node
/// Requires caller to have approved this contract to spend RPL
/// Requires caller to be on the node operator's allow list (see `setStakeForAllowed`)
/// @param _nodeAddress The address of the node operator to stake on behalf of
/// @param _amount The amount of RPL to stake
function stakeRPLFor(address _nodeAddress, uint256 _amount) override external onlyRegisteredNode(_nodeAddress) {
// Must be node's RPL withdrawal address if set or the node's address or an allow listed address or rocketMerkleDistributorMainnet
if (msg.sender != getAddress(keccak256(abi.encodePacked("contract.address", "rocketMerkleDistributorMainnet")))) {
if (!_callerAllowedFor(_nodeAddress)) {
require(getBool(keccak256(abi.encodePacked("node.stake.for.allowed", _nodeAddress, msg.sender))), "Not allowed to stake for");
}
}
_stakeRPLFor(_nodeAddress, _amount);
}
/// @dev Internal implementation for staking process
function _stakeRPLFor(address _nodeAddress, uint256 _amount) internal {
// Transfer RPL in and increase stake
_transferRPLIn(msg.sender, _amount);
_increaseNodeRPLStake(_nodeAddress, _amount);
// Update last staked time
_setNodeLastStakeTime(_nodeAddress);
// Emit event
emit RPLStaked(_nodeAddress, msg.sender, _amount, block.timestamp);
}
/// @notice Moves an amount of RPL from megapool staking into unstaking state
/// @param _amount Amount of RPL to unstake
function unstakeRPL(uint256 _amount) override external {
unstakeRPLFor(msg.sender, _amount);
}
/// @notice Moves an amount of RPL from megapool staking into unstaking state
/// @param _nodeAddress Address of node to unstake for
/// @param _amount Amount of RPL to unstake
function unstakeRPLFor(address _nodeAddress, uint256 _amount) override public onlyRegisteredNode(_nodeAddress) {
require(_callerAllowedFor(_nodeAddress), "Not allowed to unstake for");
_unstakeRPLFor(_nodeAddress, _amount);
}
/// @dev Internal implementation for unstaking process
function _unstakeRPLFor(address _nodeAddress, uint256 _amount) internal {
// Withdraw any RPL that has been unstaking long enough
_withdrawUnstakingRPL(_nodeAddress);
// Move RPL from staking to unstaking
_decreaseNodeMegapoolRPLStake(_nodeAddress, _amount);
addUint(keccak256(abi.encodePacked("rpl.megapool.unstaking.amount", _nodeAddress)), _amount);
// Reset the unstake time
_setNodeLastUnstakeTime(_nodeAddress);
// Emit event
emit RPLUnstaked(_nodeAddress, _amount, block.timestamp);
}
/// @notice Withdraws any available unstaking RPL back to the node's RPL withdrawal address
function withdrawRPL() override external {
withdrawRPLFor(msg.sender);
}
/// @notice Withdraws any available unstaking RPL back to the node's RPL withdrawal address
/// @param _nodeAddress Address of node to withdraw for
function withdrawRPLFor(address _nodeAddress) override public onlyRegisteredNode(_nodeAddress) {
require(_callerAllowedFor(_nodeAddress), "Not allowed to withdraw for");
_withdrawRPLFor(_nodeAddress);
}
/// @dev Internal implementation of withdrawal process
function _withdrawRPLFor(address nodeAddress) internal {
uint256 amount = _withdrawUnstakingRPL(nodeAddress);
require(amount > 0, "No available unstaking RPL to withdraw");
emit RPLWithdrawn(nodeAddress, amount, block.timestamp);
}
/// @dev Withdraws any unstaking RPL back to the node operator
function _withdrawUnstakingRPL(address _nodeAddress) internal returns (uint256) {
// Get contracts
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
// Check unstaking period condition
uint256 lastUnstakeTime = getNodeLastUnstakeTime(_nodeAddress);
uint256 unstakingPeriod = rocketDAOProtocolSettingsNode.getUnstakingPeriod();
uint256 timeSinceLastUnstake = block.timestamp - lastUnstakeTime;
if (timeSinceLastUnstake <= unstakingPeriod) {
return 0;
}
// Check withdrawal cooldown
if (block.timestamp - getNodeRPLStakedTime(_nodeAddress) < rocketDAOProtocolSettingsNode.getWithdrawalCooldown()) {
return 0;
}
// Retrieve amount of RPL in unstaking state
bytes32 unstakingKey = keccak256(abi.encodePacked("rpl.megapool.unstaking.amount", _nodeAddress));
uint256 amountToWithdraw = getUint(unstakingKey);
if (amountToWithdraw == 0) {
return 0;
}
// Update unstaked value
setUint(unstakingKey, 0);
// Perform transfer
_transferRPLOut(_nodeAddress, amountToWithdraw);
return amountToWithdraw;
}
/// @dev Unstake legacy staked RPL
/// @param _amount The amount of RPL to withdraw
function unstakeLegacyRPL(uint256 _amount) override external {
unstakeLegacyRPLFor(msg.sender, _amount);
}
/// @dev Unstake legacy RPL for a given node operator
/// @param _nodeAddress Address of the node operator to withdraw legacy RPL for
/// @param _amount The amount of RPL to withdraw
function unstakeLegacyRPLFor(address _nodeAddress, uint256 _amount) override public onlyRegisteredNode(_nodeAddress) {
require(_callerAllowedFor(_nodeAddress), "Not allowed to unstake legacy RPL for");
_unstakeLegacyRPL(_nodeAddress, _amount);
}
/// @dev Internal implementation for legacy unstake process
function _unstakeLegacyRPL(address _nodeAddress, uint256 _amount) internal {
// Withdraw any RPL that has been unstaking long enough
_withdrawUnstakingRPL(_nodeAddress);
// Move RPL from staking to unstaking
_decreaseNodeLegacyRPLStake(_nodeAddress, _amount, true);
addUint(keccak256(abi.encodePacked("rpl.megapool.unstaking.amount", _nodeAddress)), _amount);
// Reset the unstake time
_setNodeLastUnstakeTime(_nodeAddress);
// Emit event
emit RPLLegacyUnstaked(_nodeAddress, _amount, block.timestamp);
}
/// @notice Locks an amount of RPL from being withdrawn even if the node operator is over capitalised
/// @param _nodeAddress The address of the node operator
/// @param _amount The amount of RPL to lock
function lockRPL(address _nodeAddress, uint256 _amount) override external onlyLatestNetworkContract() {
// Check status
require(getBool(keccak256(abi.encodePacked("rpl.locking.allowed", _nodeAddress))), "Node is not allowed to lock RPL");
// The node must have unlocked stake equaling or greater than the amount
uint256 rplStake = getNodeStakedRPL(_nodeAddress);
bytes32 lockedStakeKey = keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress));
uint256 lockedRPL = getUint(lockedStakeKey);
require(rplStake - lockedRPL >= _amount, "Not enough staked RPL");
// Increase locked RPL
setUint(lockedStakeKey, lockedRPL + _amount);
// Emit event
emit RPLLocked(_nodeAddress, _amount, block.timestamp);
}
/// @notice Unlocks an amount of RPL making it possible to withdraw if the nod is over capitalised
/// @param _nodeAddress The address of the node operator
/// @param _amount The amount of RPL to unlock
function unlockRPL(address _nodeAddress, uint256 _amount) override external onlyLatestNetworkContract() {
// The node must have locked stake equaling or greater than the amount
bytes32 lockedStakeKey = keccak256(abi.encodePacked("rpl.locked.node.amount", _nodeAddress));
uint256 lockedRPL = getUint(lockedStakeKey);
require(_amount <= lockedRPL, "Not enough locked RPL");
// Decrease locked RPL
setUint(lockedStakeKey, lockedRPL - _amount);
// Emit event
emit RPLUnlocked(_nodeAddress, _amount, block.timestamp);
}
/// @notice Transfers RPL from one node to another
/// @param _from The node to transfer from
/// @param _to The node to transfer to
/// @param _amount The amount of RPL to transfer
function transferRPL(address _from, address _to, uint256 _amount) override external onlyLatestNetworkContract() onlyRegisteredNode(_from) onlyRegisteredNode(_to) {
// Check sender has enough RPL
require(getNodeStakedRPL(_from) >= _amount, "Sender has insufficient RPL");
require(_from != _to, "Cannot transfer to same address");
// Transfer the stake
_decreaseNodeRPLStake(_from, _amount);
_increaseNodeRPLStake(_to, _amount);
// Emit event
emit RPLTransferred(_from, _to, _amount, block.timestamp);
}
/// @notice Burns an amount of RPL staked by a given node operator
/// @param _from The node to burn from
/// @param _amount The amount of RPL to burn
function burnRPL(address _from, uint256 _amount) override external onlyLatestNetworkContract() onlyRegisteredNode(_from) {
// Check sender has enough RPL
require(getNodeStakedRPL(_from) >= _amount, "Node has insufficient RPL");
// Decrease the stake amount
_decreaseNodeRPLStake(_from, _amount);
// Withdraw the RPL to this contract
rocketVault.withdrawToken(address(this), rplToken, _amount);
// Execute the token burn
IERC20Burnable(address(rplToken)).burn(_amount);
// Emit event
emit RPLBurned(_from, _amount, block.timestamp);
}
/// @notice Slash a node's legacy RPL by an ETH amount
/// Only accepts calls from registered minipools
/// @param _nodeAddress The address to slash RPL from
/// @param _ethSlashAmount The amount of RPL to slash denominated in ETH value
function slashRPL(address _nodeAddress, uint256 _ethSlashAmount) override external onlyRegisteredMinipool(msg.sender) {
// Load contracts
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
// Calculate RPL amount to slash
uint256 rplSlashAmount = calcBase * _ethSlashAmount / rocketNetworkPrices.getRPLPrice();
// Cap slashed amount to node's RPL stake
uint256 rplStake = getNodeLegacyStakedRPL(_nodeAddress);
if (rplSlashAmount > rplStake) {rplSlashAmount = rplStake;}
// Transfer slashed amount to auction contract
if (rplSlashAmount > 0) rocketVault.transferToken("rocketAuctionManager", IERC20(getContractAddress("rocketTokenRPL")), rplSlashAmount);
// Update RPL stake amounts
_decreaseNodeLegacyRPLStake(_nodeAddress, rplSlashAmount, false);
// Mark minipool as slashed
setBool(keccak256(abi.encodePacked("minipool.rpl.slashed", msg.sender)), true);
// Emit RPL slashed event
emit RPLSlashed(_nodeAddress, rplSlashAmount, _ethSlashAmount, block.timestamp);
}
/// @dev Increases a node operator's megapool staked RPL amount
/// @param _amount How much to increase staked RPL by
function _increaseNodeRPLStake(address _nodeAddress, uint256 _amount) internal {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
(,, uint224 value) = rocketNetworkSnapshots.latest(key);
_migrateLegacy(_nodeAddress, uint256(value));
rocketNetworkSnapshots.push(key, value + uint224(_amount));
// Increase total
addUint(totalKey, _amount);
addUint(totalMegapoolKey, _amount);
}
/// @dev Decreases a node operator's staked RPL, first taking from their legacy than their megapool staked RPL
/// Does not check conditions for minimum stake requirements
function _decreaseNodeRPLStake(address _nodeAddress, uint256 _amount) internal {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
(,, uint224 totalStakedRPL) = rocketNetworkSnapshots.latest(key);
_migrateLegacy(_nodeAddress, uint256(totalStakedRPL));
// Take from megapool amount if not enough legacy
uint256 legacyStakedRPL = getNodeLegacyStakedRPL(_nodeAddress);
uint256 legacyAmount = _amount;
if (legacyAmount > legacyStakedRPL) {
uint256 megapoolAmount = legacyAmount - legacyStakedRPL;
legacyAmount -= megapoolAmount;
// Decrease megapool total
subUint(totalMegapoolKey, megapoolAmount);
}
// Store new values
if (legacyAmount > 0) {
bytes32 legacyKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.amount", _nodeAddress));
subUint(legacyKey, legacyAmount);
}
rocketNetworkSnapshots.push(key, totalStakedRPL - uint224(_amount));
// Decrease total
subUint(totalKey, _amount);
}
/// @dev Decreases a node operator's megapool staked RPL amount
/// @param _nodeAddress Address of node to decrease megapool staked RPL for
/// @param _amount Amount to decrease by
function _decreaseNodeMegapoolRPLStake(address _nodeAddress, uint256 _amount) internal {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
(,, uint224 totalStakedRPL) = rocketNetworkSnapshots.latest(key);
_migrateLegacy(_nodeAddress, uint256(totalStakedRPL));
// Check node operator has sufficient RPL to reduce
uint256 legacyStakedRPL = getNodeLegacyStakedRPL(_nodeAddress);
uint256 lockedRPL = getNodeLockedRPL(_nodeAddress);
require(
uint256(totalStakedRPL) >= _amount + lockedRPL &&
uint256(totalStakedRPL) >= _amount + legacyStakedRPL,
"Insufficient RPL stake to reduce"
);
// Store new value
rocketNetworkSnapshots.push(key, totalStakedRPL - uint224(_amount));
// Decrease totals
subUint(totalKey, _amount);
subUint(totalMegapoolKey, _amount);
}
/// @dev Decreases a node operator's legacy staked RPL amount
/// @param _nodeAddress Address of node to decrease legacy staked RPL for
/// @param _amount Amount to decrease by
/// @param _ensureMinimums Whether to assert the NO has the minimum required legacy RPL stake and sufficient unlocked RPL for the decrease
function _decreaseNodeLegacyRPLStake(address _nodeAddress, uint256 _amount, bool _ensureMinimums) internal {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("rpl.staked.node.amount", _nodeAddress));
(,, uint224 totalStakedRPL) = rocketNetworkSnapshots.latest(key);
_migrateLegacy(_nodeAddress, uint256(totalStakedRPL));
// Compute legacy staked RPL storage key
bytes32 legacyKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.amount", _nodeAddress));
if (_ensureMinimums) {
// Check amount after decrease does not fall below minimum required
uint256 legacyStakedRPL = getUint(legacyKey);
uint256 minimumLegacyStakedRPL = getNodeMinimumLegacyRPLStake(_nodeAddress);
require(
legacyStakedRPL >= _amount + minimumLegacyStakedRPL,
"Insufficient legacy staked RPL"
);
// Check node has enough unlocked RPL for the reduction
uint256 lockedRPL = getNodeLockedRPL(_nodeAddress);
require(
uint256(totalStakedRPL) >= _amount + lockedRPL,
"Insufficient RPL stake to reduce"
);
}
// Store new values
rocketNetworkSnapshots.push(key, totalStakedRPL - uint224(_amount));
subUint(legacyKey, _amount);
// Decrease total
subUint(totalKey, _amount);
}
/// @notice Returns the total amount of a node operator's bonded ETH (minipool + megapool)
/// @param _nodeAddress Address of the node operator to query
function getNodeETHBonded(address _nodeAddress) public view returns (uint256) {
return getNodeMegapoolETHBonded(_nodeAddress) + getNodeMinipoolETHBonded(_nodeAddress);
}
/// @notice Returns the amount of a node operator's megapool bonded ETH
/// @param _nodeAddress Address of the node operator to query
function getNodeMegapoolETHBonded(address _nodeAddress) public view returns (uint256) {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("megapool.eth.provided.node.amount", _nodeAddress));
(, , uint224 value) = rocketNetworkSnapshots.latest(key);
return uint256(value);
}
/// @notice Returns the amount of a node operator's minipool bonded ETH
/// @param _nodeAddress Address of the node operator to query
function getNodeMinipoolETHBonded(address _nodeAddress) public view returns (uint256) {
// Get contracts
RocketMinipoolManagerInterface rocketMinipoolManager = RocketMinipoolManagerInterface(getContractAddress("rocketMinipoolManager"));
uint256 activeMinipoolCount = rocketMinipoolManager.getNodeActiveMinipoolCount(_nodeAddress);
// Retrieve stored ETH borrowed value
uint256 ethBorrowed = getNodeMinipoolETHBorrowed(_nodeAddress);
// ETH bonded is number of staking minipools * 32 - eth borrowed
uint256 totalEthStaked = activeMinipoolCount * 32 ether;
return totalEthStaked - ethBorrowed;
}
/// @notice Returns a node's borrowed ETH amount
/// @param _nodeAddress The address of the node operator to query
function getNodeMegapoolETHBorrowed(address _nodeAddress) public view returns (uint256) {
bytes32 key = keccak256(abi.encodePacked("megapool.eth.matched.node.amount", _nodeAddress));
return getUint(key);
}
/// @notice Returns a node's borrowed ETH amount
/// @param _nodeAddress The address of the node operator to query
function getNodeMinipoolETHBorrowed(address _nodeAddress) public view returns (uint256) {
RocketNetworkSnapshotsInterface rocketNetworkSnapshots = RocketNetworkSnapshotsInterface(getContractAddress("rocketNetworkSnapshots"));
bytes32 key = keccak256(abi.encodePacked("eth.matched.node.amount", _nodeAddress));
(,,uint224 value) = rocketNetworkSnapshots.latest(key);
return value;
}
/// @notice Returns a node's total borrowed ETH amount (minipool + megapool)
/// @param _nodeAddress The address of the node operator to query
function getNodeETHBorrowed(address _nodeAddress) public view returns (uint256) {
return getNodeMegapoolETHBorrowed(_nodeAddress) + getNodeMinipoolETHBorrowed(_nodeAddress);
}
/// @notice Returns the ratio between capital taken from users and bonded by a node operator for minipools
/// The value is a 1e18 precision fixed point integer value of (node capital + user capital) / node capital.
/// @param _nodeAddress The address of the node operator to query
/// @dev Inconsistent naming for backwards compatibility
function getNodeETHCollateralisationRatio(address _nodeAddress) public view returns (uint256) {
uint256 borrowedETH = getNodeMinipoolETHBorrowed(_nodeAddress);
uint256 bondedETH = getNodeMinipoolETHBonded(_nodeAddress);
if (borrowedETH == 0 || bondedETH == 0) {
return calcBase * 2;
}
uint256 ethTotal = borrowedETH + bondedETH;
return (ethTotal * calcBase) / (ethTotal - borrowedETH);
}
/// @notice Returns the minimum amount of legacy staked RPL a node must have after unstaking
/// @param _nodeAddress The address of the node operator to calculate for
function getNodeMinimumLegacyRPLStake(address _nodeAddress) public view returns (uint256) {
// Load contracts
RocketNetworkPricesInterface rocketNetworkPrices = RocketNetworkPricesInterface(getContractAddress("rocketNetworkPrices"));
RocketDAOProtocolSettingsNodeInterface rocketDAOProtocolSettingsNode = RocketDAOProtocolSettingsNodeInterface(getContractAddress("rocketDAOProtocolSettingsNode"));
// Calculate and return minimum
uint256 minimumRPLStakePercent = rocketDAOProtocolSettingsNode.getMinimumLegacyRPLStake();
uint256 borrowedETH = getNodeMinipoolETHBorrowed(_nodeAddress);
return borrowedETH * minimumRPLStakePercent / rocketNetworkPrices.getRPLPrice();
}
/// @dev If legacy RPL balance has not been migrated, migrate it. Otherwise, do nothing
function _migrateLegacy(address _nodeAddress, uint256 _amount) internal {
bytes32 migratedKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.migrated", _nodeAddress));
if (getBool(migratedKey)) {
return;
}
bytes32 legacyKey = keccak256(abi.encodePacked("rpl.legacy.staked.node.amount", _nodeAddress));
setUint(legacyKey, _amount);
setBool(migratedKey, true);
}
/// @dev Transfers RPL out of vault into node's withdrawal address
function _transferRPLOut(address _nodeAddress, uint256 _amount) internal {
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
rocketVault.withdrawToken(rplWithdrawalAddress, IERC20(getContractAddress("rocketTokenRPL")), _amount);
}
/// @dev Transfers RPL from msg.sender into vault
function _transferRPLIn(address _nodeAddress, uint256 _amount) internal {
// Transfer RPL tokens
require(rplToken.transferFrom(_nodeAddress, address(this), _amount), "Could not transfer RPL to staking contract");
// Deposit RPL tokens to vault
require(rplToken.approve(address(rocketVault), _amount), "Could not approve vault RPL deposit");
rocketVault.depositToken("rocketNodeStaking", rplToken, _amount);
}
/// @dev Sets the time of the given node operator's unstake to the current block time
function _setNodeLastUnstakeTime(address _nodeAddress) internal {
setUint(keccak256(abi.encodePacked("rpl.megapool.unstake.time", _nodeAddress)), block.timestamp);
}
/// @dev Sets the time of the given node operator's stake to the current block time
function _setNodeLastStakeTime(address _nodeAddress) internal {
setUint(keccak256(abi.encodePacked("rpl.staked.node.time", _nodeAddress)), block.timestamp);
}
/// @dev Implements caller restrictions (per RPIP-31):
/// - If a node’s RPL withdrawal address is unset, the call MUST come from one of: the node’s primary withdrawal address, or the node’s address
/// - If a node’s RPL withdrawal address is set, the call MUST come from the current RPL withdrawal address
function _callerAllowedFor(address _nodeAddress) internal view returns (bool) {
RocketNodeManagerInterface rocketNodeManager = RocketNodeManagerInterface(getContractAddress("rocketNodeManager"));
if (rocketNodeManager.getNodeRPLWithdrawalAddressIsSet(_nodeAddress)) {
address rplWithdrawalAddress = rocketNodeManager.getNodeRPLWithdrawalAddress(_nodeAddress);
return msg.sender == rplWithdrawalAddress;
} else {
address withdrawalAddress = rocketStorage.getNodeWithdrawalAddress(_nodeAddress);
return (msg.sender == _nodeAddress) || (msg.sender == withdrawalAddress);
}
}
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;
interface RocketStorageInterface {
// Deploy status
function getDeployedStatus() external view returns (bool);
// Guardian
function getGuardian() external view returns(address);
function setGuardian(address _newAddress) external;
function confirmGuardian() external;
// Getters
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);
// Setters
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;
// Deleters
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;
// Arithmetic
function addUint(bytes32 _key, uint256 _amount) external;
function subUint(bytes32 _key, uint256 _amount) external;
// Protected storage
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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)
pragma solidity >0.5.0 <0.9.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
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 getMaximumStakeForVotingPower() external view returns (uint256);
function getReducedBond() external view returns (uint256);
function getBaseBondArray() external view returns (uint256[] memory);
function getUnstakingPeriod() external view returns (uint256);
function getWithdrawalCooldown() external view returns (uint256);
function getMinimumLegacyRPLStake() external view returns (uint256);
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
// Represents the type of deposits required by a minipool
enum MinipoolDeposit {
None, // Marks an invalid deposit type
Full, // The minipool requires 32 ETH from the node operator, 16 ETH of which will be refinanced from user deposits
Half, // The minipool required 16 ETH from the node operator to be matched with 16 ETH from user deposits
Empty, // The minipool requires 0 ETH from the node operator to be matched with 32 ETH from user deposits (trusted nodes only)
Variable // Indicates this minipool is of the new generation that supports a variable deposit amount
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
// Represents a minipool's status within the network
enum MinipoolStatus {
Initialised, // The minipool has been initialised and is awaiting a deposit of user ETH
Prelaunch, // The minipool has enough ETH to begin staking and is awaiting launch by the node operator
Staking, // The minipool is currently staking
Withdrawable, // NO LONGER USED
Dissolved // The minipool has been dissolved and its user deposited ETH has been returned to the deposit pool
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
import "./MinipoolDeposit.sol";
import "./MinipoolStatus.sol";
// A struct containing all the information on-chain about a specific minipool
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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
// SPDX-License-Identifier: GPL-3.0-only
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);
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;
/// @notice Accounting for snapshotting of values based on block numbers
interface RocketNetworkSnapshotsInterface {
struct Checkpoint224 {
uint32 _block;
uint224 _value;
}
function push(bytes32 _key, uint224 _value) external;
function length(bytes32 _key) external view returns (uint256);
function latest(bytes32 _key) external view returns (bool exists, uint32 block, uint224 value);
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 lookupCheckpoint(bytes32 _key, uint32 _block) external view returns (bool exists, uint32 block, uint224 value);
function lookupRecent(bytes32 _key, uint32 _block, uint256 _recency) external view returns (uint224);
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
// A struct containing all the information on-chain about a specific node
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;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;
pragma abicoder v2;
import "../../types/NodeDetails.sol";
interface RocketNodeManagerInterface {
// Structs
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 getNodeAddresses(uint256 _offset, uint256 _limit) external view returns (address[] memory);
function deployMegapool() external returns (address);
function getExpressTicketCount(address _nodeAddress) external view returns (uint256);
function useExpressTicket(address _nodeAddress) external;
function provisionExpressTickets(address _nodeAddress) external;
function getExpressTicketsProvisioned(address _nodeAddress) external view returns (bool);
function refundExpressTicket(address _nodeAddress) external;
function getMegapoolAddress(address _nodeAddress) external view returns (address);
function getUnclaimedRewards(address _nodeAddress) external view returns (uint256);
function addUnclaimedRewards(address _nodeAddress) external payable;
function claimUnclaimedRewards(address _nodeAddress) external;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity >0.5.0 <0.9.0;
interface RocketNodeStakingInterface {
function getTotalStakedRPL() external view returns (uint256);
function getTotalMegapoolStakedRPL() external view returns (uint256);
function getTotalLegacyStakedRPL() external view returns (uint256);
function getNodeStakedRPL(address _nodeAddress) external view returns (uint256);
function getNodeMegapoolStakedRPL(address _nodeAddress) external view returns (uint256);
function getNodeLegacyStakedRPL(address _nodeAddress) external view returns (uint256);
function getNodeUnstakingRPL(address _nodeAddress) external view returns (uint256);
function getNodeLockedRPL(address _nodeAddress) external view returns (uint256);
function stakeRPLFor(address _nodeAddress, uint256 _amount) external;
function stakeRPL(uint256 _amount) external;
function unstakeRPL(uint256 _amount) external;
function unstakeRPLFor(address _nodeAddress, uint256 _amount) external;
function withdrawRPL() external;
function withdrawRPLFor(address _nodeAddress) external;
function unstakeLegacyRPL(uint256 _amount) external;
function unstakeLegacyRPLFor(address _nodeAddress, uint256 _amount) external;
function getNodeRPLStakedTime(address _nodeAddress) external view returns (uint256);
function getNodeLastUnstakeTime(address _nodeAddress) external view returns (uint256);
function setStakeRPLForAllowed(address _caller, bool _allowed) external;
function setStakeRPLForAllowed(address _nodeAddress, address _caller, bool _allowed) external;
function getRPLLockingAllowed(address _nodeAddress) external view returns (bool);
function setRPLLockingAllowed(address _nodeAddress, bool _allowed) external;
function getNodeETHBonded(address _nodeAddress) external view returns (uint256);
function getNodeMegapoolETHBonded(address _nodeAddress) external view returns (uint256);
function getNodeMinipoolETHBonded(address _nodeAddress) external view returns (uint256);
function getNodeETHBorrowed(address _nodeAddress) external view returns (uint256);
function getNodeMegapoolETHBorrowed(address _nodeAddress) external view returns (uint256);
function getNodeMinipoolETHBorrowed(address _nodeAddress) external view returns (uint256);
function getNodeMinimumLegacyRPLStake(address _nodeAddress) external view returns (uint256);
function getNodeETHCollateralisationRatio(address _nodeAddress) external view returns (uint256);
// Internal (not callable by users)
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 slashRPL(address _nodeAddress, uint256 _ethSlashAmount) external;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
import "../util/IERC20.sol";
interface RocketTokenRPLInterface is IERC20 {
function getInflationCalcTime() external view returns(uint256);
function getInflationIntervalTime() external view returns(uint256);
function getInflationIntervalRate() external view returns(uint256);
function getInflationIntervalsPassed() external view returns(uint256);
function getInflationIntervalStartTime() external view returns(uint256);
function getInflationRewardsContractAddress() external view returns(address);
function inflationCalculate() external view returns (uint256);
function inflationMintTokens() external returns (uint256);
function swapTokens(uint256 _amount) external;
}/**
* .
* / \
* |.'.|
* |'.'|
* ,'| |'.
* |,-'-|-'-.|
* __|_| | _ _ _____ _
* | ___ \| | | | | | ___ \ | |
* | |_/ /|__ ___| | _____| |_ | |_/ /__ ___ | |
* | // _ \ / __| |/ / _ \ __| | __/ _ \ / _ \| |
* | |\ \ (_) | (__| < __/ |_ | | | (_) | (_) | |
* \_| \_\___/ \___|_|\_\___|\__| \_| \___/ \___/|_|
* +---------------------------------------------------+
* | DECENTRALISED STAKING PROTOCOL FOR ETHEREUM |
* +---------------------------------------------------+
*
* Rocket Pool is a first-of-its-kind Ethereum staking pool protocol, designed to
* be community-owned, decentralised, permissionless, & trustless.
*
* For more information about Rocket Pool, visit https://rocketpool.net
*
* Authored by the Rocket Pool Core Team
* Contributors: https://github.com/rocket-pool/rocketpool/graphs/contributors
* A special thanks to the Rocket Pool community for all their contributions.
*
*/
pragma solidity >0.5.0 <0.9.0;
// SPDX-License-Identifier: GPL-3.0-only
import "../interface/RocketStorageInterface.sol";
/// @title Base settings / modifiers for each contract in Rocket Pool
/// @author David Rugendyke
abstract contract RocketBase {
// Calculate using this as the base
uint256 constant calcBase = 1 ether;
// Version of the contract
uint8 public version;
// The main storage contract where primary persistant storage is maintained
RocketStorageInterface rocketStorage = RocketStorageInterface(address(0));
/*** Modifiers **********************************************************/
/**
* @dev Throws if called by any sender that doesn't match a Rocket Pool network contract
*/
modifier onlyLatestNetworkContract() {
require(getBool(keccak256(abi.encodePacked("contract.exists", msg.sender))), "Invalid or outdated network contract");
_;
}
/**
* @dev Throws if called by any sender that doesn't match one of the supplied contract or is the latest version of that contract
*/
modifier onlyLatestContract(string memory _contractName, address _contractAddress) {
require(_contractAddress == getAddress(keccak256(abi.encodePacked("contract.address", _contractName))), "Invalid or outdated contract");
_;
}
/**
* @dev Throws if called by any sender that isn't a registered node
*/
modifier onlyRegisteredNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("node.exists", _nodeAddress))), "Invalid node");
_;
}
/**
* @dev Throws if called by any sender that isn't a trusted node DAO member
*/
modifier onlyTrustedNode(address _nodeAddress) {
require(getBool(keccak256(abi.encodePacked("dao.trustednodes.", "member", _nodeAddress))), "Invalid trusted node");
_;
}
/**
* @dev Throws if called by any sender that isn't a registered minipool
*/
modifier onlyRegisteredMinipool(address _minipoolAddress) {
require(getBool(keccak256(abi.encodePacked("minipool.exists", _minipoolAddress))), "Invalid minipool");
_;
}
/**
* @dev Throws if called by any sender that isn't a registered megapool
*/
modifier onlyRegisteredMegapool(address _megapoolAddress) {
require(getBool(keccak256(abi.encodePacked("megapool.exists", _megapoolAddress))), "Invalid megapool");
_;
}
/**
* @dev Throws if called by any sender that isn't a registered minipool or megapool
*/
modifier onlyRegisteredMinipoolOrMegapool(address _caller) {
require(
getBool(keccak256(abi.encodePacked("megapool.exists", _caller))) ||
getBool(keccak256(abi.encodePacked("minipool.exists", _caller)))
, "Invalid caller");
_;
}
/**
* @dev Throws if called by any account other than a guardian account (temporary account allowed access to settings before DAO is fully enabled)
*/
modifier onlyGuardian() {
require(msg.sender == rocketStorage.getGuardian(), "Account is not a temporary guardian");
_;
}
/*** Methods **********************************************************/
/// @dev Set the main Rocket Storage address
constructor(RocketStorageInterface _rocketStorageAddress) {
// Update the contract address
rocketStorage = RocketStorageInterface(_rocketStorageAddress);
}
/// @dev Get the address of a network contract by name
function getContractAddress(string memory _contractName) internal view returns (address) {
// Get the current contract address
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
// Check it
require(contractAddress != address(0x0), "Contract not found");
// Return
return contractAddress;
}
/// @dev Get the address of a network contract by name (returns address(0x0) instead of reverting if contract does not exist)
function getContractAddressUnsafe(string memory _contractName) internal view returns (address) {
// Get the current contract address
address contractAddress = getAddress(keccak256(abi.encodePacked("contract.address", _contractName)));
// Return
return contractAddress;
}
/// @dev Get the name of a network contract by address
function getContractName(address _contractAddress) internal view returns (string memory) {
// Get the contract name
string memory contractName = getString(keccak256(abi.encodePacked("contract.name", _contractAddress)));
// Check it
require(bytes(contractName).length > 0, "Contract not found");
// Return
return contractName;
}
/// @dev Get revert error message from a .call method
function getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
// If the _res length is less than 68, then the transaction failed silently (without a revert message)
if (_returnData.length < 68) return "Transaction reverted silently";
assembly {
// Slice the sighash.
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string)); // All that remains is the revert string
}
/*** Rocket Storage Methods ****************************************/
// Note: Unused helpers have been removed to keep contract sizes down
/// @dev Storage get methods
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); }
/// @dev Storage set methods
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); }
/// @dev Storage delete methods
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); }
/// @dev Storage arithmetic methods
function addUint(bytes32 _key, uint256 _amount) internal { rocketStorage.addUint(_key, _amount); }
function subUint(bytes32 _key, uint256 _amount) internal { rocketStorage.subUint(_key, _amount); }
}{
"viaIR": true,
"optimizer": {
"enabled": true,
"runs": 15000
},
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"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":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLLegacyUnstaked","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":"node","type":"address"},{"indexed":false,"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":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":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"RPLUnstaked","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":"getNodeETHBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeETHBorrowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","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":"getNodeLastUnstakeTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeLegacyStakedRPL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeLockedRPL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMegapoolETHBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMegapoolETHBorrowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMegapoolStakedRPL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMinimumLegacyRPLStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMinipoolETHBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeMinipoolETHBorrowed","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":"getNodeStakedRPL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"getNodeUnstakingRPL","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":"getTotalLegacyStakedRPL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalMegapoolStakedRPL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalStakedRPL","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":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeLegacyRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeLegacyRPLFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstakeRPLFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawRPL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_nodeAddress","type":"address"}],"name":"withdrawRPLFor","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
61010080604052346102015760208161525080380380916100208285610206565b83398101031261020157516001600160a01b038116810361020157600080546001600160a81b03191660089290921b610100600160a81b03169190911760071790556040517f72706c2e7374616b65642e746f74616c2e616d6f756e7400000000000000000060208201908152601782529061009d603782610206565b51902060805260405160208101907f72706c2e6d656761706f6f6c2e7374616b65642e746f74616c2e616d6f756e748252602081526100dd604082610206565b51902060a0526040516100f1604082610206565b600e81526d1c9bd8dad95d151bdad95b94941360921b60208201526001600160a01b039061011e9061023f565b1660c052604051610130604082610206565b600b81526a1c9bd8dad95d15985d5b1d60aa1b60208201526001600160a01b039061015a9061023f565b1660e052604051614ec8908161038882396080518181816104920152818161085701528181610fbf015281816114cd015281816120f0015281816139bd01528181613c740152614158015260a0518181816104bc0152818161088101528181611422015281816114f601528181613a720152613c9a015260c051818181611176015261446f015260e051818181611106015281816121dc015281816145000152614cc90152f35b600080fd5b601f909101601f19168101906001600160401b0382119082101761022957604052565b634e487b7160e01b600052604160045260246000fd5b60405160208101916f636f6e74726163742e6164647265737360801b83528181519160005b83811061036f5750508061028b92603092016000838201520301601f198101835282610206565b5190206000546040516321f8a72160e01b815260048101929092526020908290602490829060081c6001600160a01b03165afa9081156103635760009161031a575b506001600160a01b038116156102e05790565b60405162461bcd60e51b815260206004820152601260248201527110dbdb9d1c9858dd081b9bdd08199bdd5b9960721b6044820152606490fd5b6020813d60201161035b575b8161033360209383610206565b810103126103575751906001600160a01b03821682036103545750386102cd565b80fd5b5080fd5b3d9150610326565b6040513d6000823e3d90fd5b6020828201810151603087840101528593500161026456fe6080604052600436101561001257600080fd5b6000803560e01c8063088903a41461282f5780630dd56dfb1461280b57806310b63749146125c9578063194c63d81461239e578063245395a614611d845780632c177a5314611c1d57806333621a7614611b625780633d65c1fa1461183c5780633e200d4b146117ba57806345c2e44814611796578063479c50471461177257806354e8ca0a146115ea57806354fd4d50146115ca57806360043fb814611599578063641a24d21461152057806368325022146114b25780636cbcf9621461148e57806373897be81461146a5780638236f81314611446578063978fe3ed1461140a57806397be2143146113e6578063a06286bf146112c3578063a39e96c314611007578063a4be67df14610fe3578063b018c7d314610fa7578063b51c62ae14610f30578063b770f86e14610f0c578063c0d05dd814610ee8578063c601bf7814610cc7578063cb1c832114610b42578063d35e8c8314610a07578063e75942f9146109e3578063e9e70769146109bf578063ecac693614610980578063ed2fde70146106185763f4410be4146101a957600080fd5b34610615576040600319360112610615576101c2612a7d565b60243590610257610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612ad7565b519020613695565b612cc1565b61026081614265565b156105d15761026e81614a38565b508273ffffffffffffffffffffffffffffffffffffffff6102c5604051610296604082612ad7565b601681527f726f636b65744e6574776f726b536e617073686f7473000000000000000000006020820152613d1d565b1660405160208101906103188161021e87856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b5190206040517f79feb107000000000000000000000000000000000000000000000000000000008152816004820152606081602481865afa80156105c6576103e0918591610594575b506103bb7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff821661038e8189614888565b61039788613452565b906103aa6103a48a613093565b8b613086565b811015918261057f575b5050613f04565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8716906137c0565b823b1561057b576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660248201529082908290604490829084905af1801561057057610557575b5050604073ffffffffffffffffffffffffffffffffffffffff7faa4c88f0b9828cd8487d897217facaaca2a112ead081957e1f7fc52f92149a04926104b6857f0000000000000000000000000000000000000000000000000000000000000000614956565b6104e0857f0000000000000000000000000000000000000000000000000000000000000000614956565b61053d85845160208101906105358161021e87856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b5190206149c7565b61054681614e3d565b82519485524260208601521692a280f35b8161056191612ad7565b61056c578238610451565b8280fd5b6040513d84823e3d90fd5b8380fd5b61058b9192508a613086565b111538806103b4565b6105b6915060603d6060116105bf575b6105ae8183612ad7565b810190612e85565b91505038610361565b503d6105a4565b6040513d86823e3d90fd5b606460405162461bcd60e51b815260206004820152601a60248201527f4e6f7420616c6c6f77656420746f20756e7374616b6520666f720000000000006044820152fd5b80fd5b503461061557602060031936011261061557600435610685610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b61068e33614265565b156105d15761069c33614a38565b508173ffffffffffffffffffffffffffffffffffffffff6106c4604051610296604082612ad7565b1660405160208101906107178161021e33856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b5190206040517f79feb107000000000000000000000000000000000000000000000000000000008152816004820152606081602481865afa80156105c6576107de91859161095e575b506107b97bffffffffffffffffffffffffffffffffffffffffffffffffffffffff821661078d8133614888565b61079633613452565b906107a96107a333613093565b8a613086565b8110159182610952575050613f04565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616906137c0565b823b1561057b576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660248201529082908290604490829084905af1801561057057610939575b505061087b817f0000000000000000000000000000000000000000000000000000000000000000614956565b6108a5817f0000000000000000000000000000000000000000000000000000000000000000614956565b6108fb8160405160208101906105358161021e33856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b61090433614e3d565b6040519081524260208201527faa4c88f0b9828cd8487d897217facaaca2a112ead081957e1f7fc52f92149a0460403392a280f35b8161094391612ad7565b61094e57813861084f565b5080fd5b61058b91925089613086565b610977915060603d6060116105bf576105ae8183612ad7565b91505038610760565b50346106155760206003193601126106155760206109b761099f612a7d565b6109b16109ab82612eda565b9161328b565b90613086565b604051908152f35b50346106155760206003193601126106155760206109b76109de612a7d565b613509565b50346106155760206003193601126106155760206109b7610a02612a7d565b613452565b503461061557604060031936011261061557610a21612a7d565b60243590610a7d610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b610a8681614265565b15610ad857604073ffffffffffffffffffffffffffffffffffffffff82610acd7f0178232f2971603b3ffe89ab52d074a471507d935a7fee7477b636f72a64583194614a38565b506104e08582613f4f565b608460405162461bcd60e51b815260206004820152602560248201527f4e6f7420616c6c6f77656420746f20756e7374616b65206c656761637920525060448201527f4c20666f720000000000000000000000000000000000000000000000000000006064820152fd5b503461061557604060031936011261061557610c48610b5f612a7d565b610bb7610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b73ffffffffffffffffffffffffffffffffffffffff610c3760405160208101907f636f6e74726163742e616464726573730000000000000000000000000000000082527f726f636b65744d65726b6c654469737472696275746f724d61696e6e657400006030820152602e8152610c2f604e82612ad7565b51902061480b565b163303610c4b575b60243590614458565b80f35b610c5481614265565b610c3f57610cc2610cbd604051602081019061024a8161021e33888690603e926bffffffffffffffffffffffff1980927f6e6f64652e7374616b652e666f722e616c6c6f77656400000000000000000000855260601b16601684015260601b16602a8201520190565b612e3a565b610c3f565b503461061557604060031936011261061557610ce1612a7d565b60243590610d42610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b612c51565b610d97604051602081019061024a8161021e86856bffffffffffffffffffffffff196027927f72706c2e6c6f636b696e672e616c6c6f77656400000000000000000000000000835260601b1660138201520190565b15610ea457610da5816130e8565b6040516020810190610df78161021e86856bffffffffffffffffffffffff19602a927f72706c2e6c6f636b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902083610e0e610e078361372d565b8094612b47565b10610e60577fce4a5a05852c75132c79a7a41af76ced563f8391e69eea41a0b38214c4e847cf9261054673ffffffffffffffffffffffffffffffffffffffff92610e5a87604096613086565b906141f4565b606460405162461bcd60e51b815260206004820152601560248201527f4e6f7420656e6f756768207374616b65642052504c00000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601f60248201527f4e6f6465206973206e6f7420616c6c6f77656420746f206c6f636b2052504c006044820152fd5b50346106155760206003193601126106155760206109b7610f07612a7d565b6133fd565b50346106155760206003193601126106155760206109b7610f2b612a7d565b6133a8565b50346106155760206003193601126106155760206109b7610f4f612a7d565b604051610f9f8161021e86820194856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b51902061372d565b503461061557806003193601126106155760206109b77f000000000000000000000000000000000000000000000000000000000000000061372d565b50346106155760206003193601126106155760206109b7611002612a7d565b61328b565b503461061557604060031936011261061557611021612a7d565b6024359061107d610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b6110d5610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b816110df826130e8565b1061127f576110ee828261380a565b8273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016803b1561094e576040517f01e3366700000000000000000000000000000000000000000000000000000000815230600482015282816064818373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016968760248401528a60448401525af190811561127457839161125f575b5050803b1561094e578180916024604051809481937f42966c680000000000000000000000000000000000000000000000000000000083528960048401525af180156105705761124a575b5050604073ffffffffffffffffffffffffffffffffffffffff7f7a3b7812b93ab45ed01ea9fc22b37301461966d61ca09bc0859a84ca07298b129282519485524260208601521692a280f35b8161125491612ad7565b61056c5782386111fe565b8161126991612ad7565b61094e5781386111b3565b6040513d85823e3d90fd5b606460405162461bcd60e51b815260206004820152601960248201527f4e6f64652068617320696e73756666696369656e742052504c000000000000006044820152fd5b503461061557602060031936011261061557600435611330610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b61133933614265565b15610ad85761134733614a38565b506113528133613f4f565b6113a88160405160208101906105358161021e33856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b6113b133614e3d565b6040519081524260208201527f0178232f2971603b3ffe89ab52d074a471507d935a7fee7477b636f72a64583160403392a280f35b50346106155760206003193601126106155760206109b7611405612a7d565b61321e565b503461061557806003193601126106155760206109b77f000000000000000000000000000000000000000000000000000000000000000061372d565b50346106155760206003193601126106155760206109b7611465612a7d565b6131c9565b50346106155760206003193601126106155760206109b7611489612a7d565b6130e8565b50346106155760206003193601126106155760206109b76114ad612a7d565b613093565b503461061557806003193601126106155760206109b76114f17f000000000000000000000000000000000000000000000000000000000000000061372d565b61151a7f000000000000000000000000000000000000000000000000000000000000000061372d565b90612b47565b503461061557602060031936011261061557602061158f61153f612a7d565b60405161024a8161021e86820194856bffffffffffffffffffffffff196027927f72706c2e6c6f636b696e672e616c6c6f77656400000000000000000000000000835260601b1660138201520190565b6040519015158152f35b50346106155760206003193601126106155760206109b76115b8612a7d565b6109b16115c4826133a8565b9161300c565b503461061557806003193601126106155760ff6020915416604051908152f35b503461061557602060031936011261061557611604612a7d565b61165c610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b61166581614265565b1561172e5761167381614a38565b9081156116c457604073ffffffffffffffffffffffffffffffffffffffff7f9947063f70b076145616018b82ed1dd5585e15b7ae0a0b17a8b06bec4c4c31e29282519485524260208601521692a280f35b608460405162461bcd60e51b815260206004820152602660248201527f4e6f20617661696c61626c6520756e7374616b696e672052504c20746f20776960448201527f74686472617700000000000000000000000000000000000000000000000000006064820152fd5b606460405162461bcd60e51b815260206004820152601b60248201527f4e6f7420616c6c6f77656420746f20776974686472617720666f7200000000006044820152fd5b50346106155760206003193601126106155760206109b7611791612a7d565b61300c565b50346106155760206003193601126106155760206109b76117b5612a7d565b612eda565b503461061557602060031936011261061557611824610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b611830610cbd33614265565b610c4860043533614458565b503461061557606060031936011261061557611856612a7d565b61185e612aa5565b60443591821515830361057b5773ffffffffffffffffffffffffffffffffffffffff6118c0604051611891604082612ad7565b601181527f726f636b65744e6f64654d616e616765720000000000000000000000000000006020820152613d1d565b1690604051927fe667d82800000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff821693846004820152602081602481875afa8015611b575786918891611b17575b5015611aca57506020602493604051948580927fb71f0c7c0000000000000000000000000000000000000000000000000000000082528860048301525afa8015611abf578573ffffffffffffffffffffffffffffffffffffffff936119b485611a72947fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec5988c91611a90575b50163314612d90565b611a0c610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b604051611a6a8161021e8760208301958690603e926bffffffffffffffffffffffff1980927f6e6f64652e7374616b652e666f722e616c6c6f77656400000000000000000000855260601b16601684015260601b16602a8201520190565b519020613e91565b60408051951515865242602087015291169390819081015b0390a380f35b611ab2915060203d602011611ab8575b611aaa8183612ad7565b810190612d64565b386119ab565b503d611aa0565b6040513d88823e3d90fd5b7fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec59350611a729073ffffffffffffffffffffffffffffffffffffffff93611b12873314612d19565b6119b4565b9150506020813d602011611b4f575b81611b3360209383612ad7565b81010312611b4b57611b458691612d0c565b3861191f565b8680fd5b3d9150611b26565b6040513d89823e3d90fd5b5034610615578060031936011261061557611bcb610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b611bd433614265565b1561172e57611be233614a38565b80156116c4576040519081524260208201527f9947063f70b076145616018b82ed1dd5585e15b7ae0a0b17a8b06bec4c4c31e260403392a280f35b503461061557604060031936011261061557611c37612a7d565b60243590611c93610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b6040516020810190611ce58161021e85856bffffffffffffffffffffffff19602a927f72706c2e6c6f636b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b519020611cf18161372d565b90818411611d40577f95f42213e171837caaa6cc7f589ef03a30179b7b85e386dfb146a30c5b10cfa99261054673ffffffffffffffffffffffffffffffffffffffff92610e5a87604096612b47565b606460405162461bcd60e51b815260206004820152601560248201527f4e6f7420656e6f756768206c6f636b65642052504c00000000000000000000006044820152fd5b503461061557604060031936011261061557611d9e612a7d565b60243560405191611de9602084017f6d696e69706f6f6c2e657869737473000000000000000000000000000000000081523360601b9485602f8201526023815261024a604382612ad7565b1561235a5773ffffffffffffffffffffffffffffffffffffffff611e43604051611e14604082612ad7565b601381527f726f636b65744e6574776f726b507269636573000000000000000000000000006020820152613d1d565b1682670de0b6b3a76400000290670de0b6b3a76400008204840361232d57906020600492604051938480927f724d4a090000000000000000000000000000000000000000000000000000000082525afa908115611abf5786916122f7575b611eab9250612e01565b92611eb582613452565b8085116122ef575b50836121c4575b73ffffffffffffffffffffffffffffffffffffffff611eea604051610296604082612ad7565b166040516020810190611f3d8161021e87856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902086604051917f79feb107000000000000000000000000000000000000000000000000000000008352806004840152606083602481875afa9283156105705782936121a0575b50611fae7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841687614888565b61202c60405160208101906120038161021e8b856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b519020937bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a16906137c0565b843b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660248201529281908490604490829084905af1928315612193578793612172575b50509361215b73ffffffffffffffffffffffffffffffffffffffff936120ea606096947f38a2777b6a84fdb3fc375fe8ade69fdad1afdcdd93c79e7ae2319b806a626c4d98614956565b612114887f0000000000000000000000000000000000000000000000000000000000000000614956565b60405160208101917f6d696e69706f6f6c2e72706c2e736c61736865640000000000000000000000008352603482015260288152612153604882612ad7565b519020613e11565b60405195865260208601524260408601521692a280f35b81929593509061218191612ad7565b61218f5791849086386120a0565b8580fd5b50604051903d90823e3d90fd5b6121ba91935060603d6060116105bf576105ae8183612ad7565b9150509138611f85565b8473ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff612251604051612222604082612ad7565b600e81527f726f636b6574546f6b656e52504c0000000000000000000000000000000000006020820152613d1d565b1690803b1561056c5760a4839260405194859384927fee91035e00000000000000000000000000000000000000000000000000000000845260606004850152601460648501527f726f636b657441756374696f6e4d616e61676572000000000000000000000000608485015260248401528a60448401525af18015611abf576122db575b50611ec4565b856122e891969296612ad7565b93386122d5565b935038611ebd565b90506020823d602011612325575b8161231260209383612ad7565b8101031261218f57611eab915190611ea1565b3d9150612305565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b606460405162461bcd60e51b815260206004820152601060248201527f496e76616c6964206d696e69706f6f6c000000000000000000000000000000006044820152fd5b5034610615576040600319360112610615576123b8612a7d565b6123c0612ac8565b9073ffffffffffffffffffffffffffffffffffffffff6123e7604051611891604082612ad7565b1690604051927fe667d82800000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff821693846004820152602081602481875afa908115611abf57869161258f575b5015612554576020602493604051948580927fb71f0c7c0000000000000000000000000000000000000000000000000000000082528860048301525afa80156125495781612543936124da73ffffffffffffffffffffffffffffffffffffffff61252b947f6b33e987d80ef301261d0265922ffe70da2b332f0e097034ce01dbb998cbd013988b91611a905750163314612d90565b604051611a6a8161021e6020820194856bffffffffffffffffffffffff196027927f72706c2e6c6f636b696e672e616c6c6f77656400000000000000000000000000835260601b1660138201520190565b60408051911515825242602083015290918291820190565b0390a280f35b6040513d87823e3d90fd5b7f6b33e987d80ef301261d0265922ffe70da2b332f0e097034ce01dbb998cbd013925061252b816125439361258a873314612d19565b6124da565b90506020813d6020116125c1575b816125aa60209383612ad7565b8101031261218f576125bb90612d0c565b38612445565b3d915061259d565b5034610615576060600319360112610615576125e3612a7d565b6125eb612aa5565b60443590612647610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b61269f610252604051602081019061024a8161021e89856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b6126f7610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b81612701846130e8565b106127c75773ffffffffffffffffffffffffffffffffffffffff81169273ffffffffffffffffffffffffffffffffffffffff81169284841461278357612774817f3bf4a4ef95ccf3119f6977afa759933d4edd361281f5c3b91203f43104fa34329461276f8260409661380a565b613ac0565b8151908152426020820152a380f35b606460405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220746f2073616d652061646472657373006044820152fd5b606460405162461bcd60e51b815260206004820152601b60248201527f53656e6465722068617320696e73756666696369656e742052504c00000000006044820152fd5b50346106155760206003193601126106155760206109b761282a612a7d565b612b83565b503461061557604060031936011261061557612849612a7d565b612851612ac8565b73ffffffffffffffffffffffffffffffffffffffff612877604051611891604082612ad7565b166040517fe667d828000000000000000000000000000000000000000000000000000000008152336004820152602081602481855afa908115612549578591612a3f575b5015612a39576020602491604051928380927fb71f0c7c0000000000000000000000000000000000000000000000000000000082523360048301525afa9081156105c6576129289173ffffffffffffffffffffffffffffffffffffffff918691611a905750163314612d90565b612980610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b6129e3816040516020810190611a6a8161021e88338690603e926bffffffffffffffffffffffff1980927f6e6f64652e7374616b652e666f722e616c6c6f77656400000000000000000000855260601b16601684015260601b16602a8201520190565b60408051911515825242602083015273ffffffffffffffffffffffffffffffffffffffff929092169133917fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec59181908101611a8a565b50612928565b90506020813d602011612a75575b81612a5a60209383612ad7565b81010312612a7157612a6b90612d0c565b386128bb565b8480fd5b3d9150612a4d565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612aa057565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff82168203612aa057565b602435908115158203612aa057565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612b1857604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b91908203918211612b5457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b612bd8604051602081019061024a8161021e86856bffffffffffffffffffffffff196033927f72706c2e6c65676163792e7374616b65642e6e6f64652e6d6967726174656400835260601b16601f8201520190565b15612c4b57612c489061151a612c426040516020810190612c398161021e87856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b519020926130e8565b9161372d565b90565b50600090565b15612c5857565b608460405162461bcd60e51b8152602060048201526024808201527f496e76616c6964206f72206f75746461746564206e6574776f726b20636f6e7460448201527f72616374000000000000000000000000000000000000000000000000000000006064820152fd5b15612cc857565b606460405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964206e6f646500000000000000000000000000000000000000006044820152fd5b51908115158203612aa057565b15612d2057565b606460405162461bcd60e51b815260206004820152602060248201527f4d7573742062652063616c6c65642066726f6d206e6f646520616464726573736044820152fd5b90816020910312612aa0575173ffffffffffffffffffffffffffffffffffffffff81168103612aa05790565b15612d9757565b608460405162461bcd60e51b815260206004820152602a60248201527f4d7573742062652063616c6c65642066726f6d2052504c20776974686472617760448201527f616c2061646472657373000000000000000000000000000000000000000000006064820152fd5b8115612e0b570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b15612e4157565b606460405162461bcd60e51b815260206004820152601860248201527f4e6f7420616c6c6f77656420746f207374616b6520666f7200000000000000006044820152fd5b90816060910312612aa057612e9981612d0c565b91602082015163ffffffff81168103612aa0576040909201517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103612aa05790565b606073ffffffffffffffffffffffffffffffffffffffff612f02604051610296604082612ad7565b16916040516bffffffffffffffffffffffff1960208201927f6d656761706f6f6c2e6574682e70726f76696465642e6e6f64652e616d6f756e84527f74000000000000000000000000000000000000000000000000000000000000006040840152841b16604182015260358152612f7a605582612ad7565b5190206024604051809481937f79feb10700000000000000000000000000000000000000000000000000000000835260048301525afa8015613000577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91600091612fe057501690565b612ff9915060603d6060116105bf576105ae8183612ad7565b9150501690565b6040513d6000823e3d90fd5b606073ffffffffffffffffffffffffffffffffffffffff613034604051610296604082612ad7565b16916040516bffffffffffffffffffffffff1960208201927f6574682e6d6174636865642e6e6f64652e616d6f756e740000000000000000008452841b166037820152602b8152612f7a604b82612ad7565b91908201809211612b5457565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff19602a927f72706c2e6c6f636b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b6040516131398161021e6020820194856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b519020606073ffffffffffffffffffffffffffffffffffffffff613164604051610296604082612ad7565b16916024604051809481937f79feb10700000000000000000000000000000000000000000000000000000000835260048301525afa8015613000577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91600091612fe057501690565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff19602d927f72706c2e6d656761706f6f6c2e756e7374616b652e74696d6500000000000000835260601b1660198201520190565b61322a6109ab8261300c565b81158015613283575b613275576132419082613086565b670de0b6b3a7640000810290808204670de0b6b3a76400001481151715612b5457612c489261326f91612b47565b90612e01565b5050671bc16d674ec8000090565b508015613233565b602490602073ffffffffffffffffffffffffffffffffffffffff6132e46040516132b6604082612ad7565b601581527f726f636b65744d696e69706f6f6c4d616e61676572000000000000000000000084820152613d1d565b16604051938480927f1844ec0100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff861660048301525afa91821561300057600092613372575b506133469061300c565b6801bc16d674ec8000008202918083046801bc16d674ec8000001490151715612b5457612c4891612b47565b90916020823d6020116133a0575b8161338d60209383612ad7565b810103126106155750519061334661333c565b3d9150613380565b612c48906040516bffffffffffffffffffffffff1960208201927f6d656761706f6f6c2e6574682e6d6174636865642e6e6f64652e616d6f756e74845260601b16604082015260348152610f9f605482612ad7565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff196028927f72706c2e7374616b65642e6e6f64652e74696d65000000000000000000000000835260601b1660148201520190565b6134a7604051602081019061024a8161021e86856bffffffffffffffffffffffff196033927f72706c2e6c65676163792e7374616b65642e6e6f64652e6d6967726174656400835260601b16601f8201520190565b6134b457612c48906130e8565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b600473ffffffffffffffffffffffffffffffffffffffff613531604051611e14604082612ad7565b1691602073ffffffffffffffffffffffffffffffffffffffff61358960405161355b604082612ad7565b601d81527f726f636b657444414f50726f746f636f6c53657474696e67734e6f646500000084820152613d1d565b16604051938480927fce20fee60000000000000000000000000000000000000000000000000000000082525afa9182156130005760009261365f575b506135cf9061300c565b818102918183041490151715612b54576020600492604051938480927f724d4a090000000000000000000000000000000000000000000000000000000082525afa90811561300057600091613629575b612c489250612e01565b90506020823d602011613657575b8161364460209383612ad7565b81010312612aa057612c4891519061361f565b3d9150613637565b90916020823d60201161368d575b8161367a60209383612ad7565b81010312610615575051906135cf6135c5565b3d915061366d565b602073ffffffffffffffffffffffffffffffffffffffff60005460081c16916024604051809481937f7ae1cfca00000000000000000000000000000000000000000000000000000000835260048301525afa908115613000576000916136f9575090565b90506020813d602011613725575b8161371460209383612ad7565b81010312612aa057612c4890612d0c565b3d9150613707565b602073ffffffffffffffffffffffffffffffffffffffff60005460081c16916024604051809481937fbd02d0f500000000000000000000000000000000000000000000000000000000835260048301525afa90811561300057600091613791575090565b90506020813d6020116137b8575b816137ac60209383612ad7565b81010312612aa0575190565b3d915061379f565b907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff809116911603907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211612b5457565b9190600073ffffffffffffffffffffffffffffffffffffffff613834604051610296604082612ad7565b1660405160208101906138878161021e89856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902094604051907f79feb107000000000000000000000000000000000000000000000000000000008252866004830152606082602481865afa9182156105c6579061393f92918592613a9c575b506138fe7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831682614888565b61390781613452565b8690808811613a57575b50806139f3575b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8516906137c0565b94813b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101919091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff95909516602486015281908590604490829084905af1938415612193576139e193946139e3575b50507f0000000000000000000000000000000000000000000000000000000000000000614956565b565b816139ed91612ad7565b386139b9565b613a5091604051613a488161021e6020820194856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b519020614956565b3880613918565b613a62915087612b47565b613a96613a6f8289612b47565b917f0000000000000000000000000000000000000000000000000000000000000000614956565b38613911565b613ab691925060603d6060116105bf576105ae8183612ad7565b91505090386138d5565b9190600073ffffffffffffffffffffffffffffffffffffffff613aea604051610296604082612ad7565b166040516020810190613b3d8161021e89856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b519020946040517f79feb107000000000000000000000000000000000000000000000000000000008152866004820152606081602481865afa9081156105c657613baf917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff918691613cfb575b50168092614888565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841601947bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611613cce57813b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101919091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff95909516602486015281908590604490829084905af1938415612193576139e19394613cbe575b5050613c98817f00000000000000000000000000000000000000000000000000000000000000006149c7565b7f00000000000000000000000000000000000000000000000000000000000000006149c7565b81613cc891612ad7565b38613c6c565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b613d14915060603d6060116105bf576105ae8183612ad7565b91505038613ba6565b9060405160208101907f636f6e74726163742e61646472657373000000000000000000000000000000008252835160005b818110613dfb5750613d98939450603082610c2f92810160008382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612ad7565b73ffffffffffffffffffffffffffffffffffffffff811615613db75790565b606460405162461bcd60e51b815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152fd5b8060208092880101516030828601015201613d4e565b60009073ffffffffffffffffffffffffffffffffffffffff825460081c1690813b1561056c5782916044839260405194859384927fabfdcced0000000000000000000000000000000000000000000000000000000084526004840152600160248401525af1801561057057613e84575050565b81613e8e91612ad7565b50565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937fabfdcced0000000000000000000000000000000000000000000000000000000085526004850152151560248401525af1801561057057613e84575050565b15613f0b57565b606460405162461bcd60e51b815260206004820152602060248201527f496e73756666696369656e742052504c207374616b6520746f207265647563656044820152fd5b919060009273ffffffffffffffffffffffffffffffffffffffff613f7a604051610296604082612ad7565b16906040516020810190613fce8161021e85856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902090604051927f79feb107000000000000000000000000000000000000000000000000000000008452826004850152606084602481845afa938415611b575787946141d0575b507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff84166140408184614888565b60405160208101906140928161021e87856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b5190209461409f8661372d565b6140b16140ab86613509565b89613086565b1161418c576103bb6140d1926140ca6107a38c97613093565b1115613f04565b90803b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101949094527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9190911660248401528290604490829084905af1801561254957916139e1949584926141569461417c575b5050614956565b7f0000000000000000000000000000000000000000000000000000000000000000614956565b8161418691612ad7565b3861414f565b606460405162461bcd60e51b815260206004820152601e60248201527f496e73756666696369656e74206c6567616379207374616b65642052504c00006044820152fd5b6141ea91945060603d6060116105bf576105ae8183612ad7565b9150509238614016565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937fe2a4853a000000000000000000000000000000000000000000000000000000008552600485015260248401525af1801561057057613e84575050565b73ffffffffffffffffffffffffffffffffffffffff61428b604051611891604082612ad7565b169073ffffffffffffffffffffffffffffffffffffffff604051917fe667d8280000000000000000000000000000000000000000000000000000000083521690816004820152602081602481865afa9081156130005760009161441e575b501561436f576020906024604051809481937fb71f0c7c00000000000000000000000000000000000000000000000000000000835260048301525afa80156130005773ffffffffffffffffffffffffffffffffffffffff91600091614350575b5016331490565b614369915060203d602011611ab857611aaa8183612ad7565b38614349565b60249150602073ffffffffffffffffffffffffffffffffffffffff60005460081c16604051938480927f5b49ff620000000000000000000000000000000000000000000000000000000082528560048301525afa918215613000576000926143fd575b5033149081156143e0575090565b73ffffffffffffffffffffffffffffffffffffffff915016331490565b61441791925060203d602011611ab857611aaa8183612ad7565b90386143d2565b90506020813d602011614450575b8161443960209383612ad7565b81010312612aa05761444a90612d0c565b386142e9565b3d915061442c565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016604051907f23b872dd00000000000000000000000000000000000000000000000000000000825260009133600482015230602482015284604482015260208160648186865af19081156112745783916147d1575b50156147675773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906040517f095ea7b300000000000000000000000000000000000000000000000000000000815282600482015285602482015260208160448187865af19081156105c657849161472d575b50156146c357813b1561056c57829160a4839260405194859384927ff444295800000000000000000000000000000000000000000000000000000000845260606004850152601160648501527f726f636b65744e6f64655374616b696e67000000000000000000000000000000608485015260248401528960448401525af18015610570579260609273ffffffffffffffffffffffffffffffffffffffff927f27061f46a0d88c20b00223c4cabb9f6d02edcb48e4d61d72de015b4432f97647956146b3575b505061463d8582613ac0565b61469c60405160208101906146928161021e86856bffffffffffffffffffffffff196028927f72706c2e7374616b65642e6e6f64652e74696d65000000000000000000000000835260601b1660148201520190565b51902042906141f4565b6040519433865260208601524260408601521692a2565b816146bd91612ad7565b38614631565b608460405162461bcd60e51b815260206004820152602360248201527f436f756c64206e6f7420617070726f7665207661756c742052504c206465706f60448201527f73697400000000000000000000000000000000000000000000000000000000006064820152fd5b90506020813d60201161475f575b8161474860209383612ad7565b8101031261057b5761475990612d0c565b3861456b565b3d915061473b565b608460405162461bcd60e51b815260206004820152602a60248201527f436f756c64206e6f74207472616e736665722052504c20746f207374616b696e60448201527f6720636f6e7472616374000000000000000000000000000000000000000000006064820152fd5b90506020813d602011614803575b816147ec60209383612ad7565b8101031261056c576147fd90612d0c565b386144e3565b3d91506147df565b602073ffffffffffffffffffffffffffffffffffffffff60005460081c16916024604051809481937f21f8a72100000000000000000000000000000000000000000000000000000000835260048301525afa9081156130005760009161486f575090565b612c48915060203d602011611ab857611aaa8183612ad7565b60405160208101906148da8161021e85856bffffffffffffffffffffffff196033927f72706c2e6c65676163792e7374616b65642e6e6f64652e6d6967726174656400835260601b16601f8201520190565b519020906148e782613695565b614951576139e19261494c916040516149448161021e6020820194856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b5190206141f4565b613e11565b505050565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937febb9d8c9000000000000000000000000000000000000000000000000000000008552600485015260248401525af1801561057057613e84575050565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937fadb353dc000000000000000000000000000000000000000000000000000000008552600485015260248401525af1801561057057613e84575050565b60009073ffffffffffffffffffffffffffffffffffffffff614a90604051614a61604082612ad7565b601d81527f726f636b657444414f50726f746f636f6c53657474696e67734e6f64650000006020820152613d1d565b16614a9a826131c9565b604051907f36f837a8000000000000000000000000000000000000000000000000000000008252602082600481865afa918215612549578592614e07575b50614ae39042612b47565b1115614e02576004906020614b00614afa856133fd565b42612b47565b91604051938480927fd999c9b20000000000000000000000000000000000000000000000000000000082525afa9182156105c6578492614dce575b5010614dca576040516020810190614b938161021e85856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b51902091614ba08361372d565b928315614dc35773ffffffffffffffffffffffffffffffffffffffff825460081c1690813b1561056c5782916044839260405194859384927fe2a4853a00000000000000000000000000000000000000000000000000000000845260048401528160248401525af1801561057057614db3575b5090602073ffffffffffffffffffffffffffffffffffffffff602481614c6e604051614c40604082612ad7565b601181527f726f636b65744e6f64654d616e6167657200000000000000000000000000000086820152613d1d565b169360405194859384927fb71f0c7c0000000000000000000000000000000000000000000000000000000084521660048301525afa908115610570578291614d94575b5073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169073ffffffffffffffffffffffffffffffffffffffff614d10604051612222604082612ad7565b1691803b1561057b57606484928373ffffffffffffffffffffffffffffffffffffffff9360405196879586947f01e3366700000000000000000000000000000000000000000000000000000000865216600485015260248401528860448401525af1801561057057614d8157505090565b614d8c828092612ad7565b610615575090565b614dad915060203d602011611ab857611aaa8183612ad7565b38614cb1565b81614dbd91612ad7565b38614c13565b5091505090565b5090565b9091506020813d602011614dfa575b81614dea60209383612ad7565b8101031261057b57519038614b3b565b3d9150614ddd565b505090565b9091506020813d602011614e35575b81614e2360209383612ad7565b81010312612a71575190614ae3614ad8565b3d9150614e16565b6139e1906040516146928161021e6020820194856bffffffffffffffffffffffff19602d927f72706c2e6d656761706f6f6c2e756e7374616b652e74696d6500000000000000835260601b166019820152019056fea26469706673582212205ae51aa60ca5baa8cf19ceda4a451f6ebcdcdd55f4d8fc8e276d8be5f2a44e2864736f6c634300081e00330000000000000000000000001d8f8f00cfa6758d7be78336684788fb0ee0fa46
Deployed Bytecode
0x6080604052600436101561001257600080fd5b6000803560e01c8063088903a41461282f5780630dd56dfb1461280b57806310b63749146125c9578063194c63d81461239e578063245395a614611d845780632c177a5314611c1d57806333621a7614611b625780633d65c1fa1461183c5780633e200d4b146117ba57806345c2e44814611796578063479c50471461177257806354e8ca0a146115ea57806354fd4d50146115ca57806360043fb814611599578063641a24d21461152057806368325022146114b25780636cbcf9621461148e57806373897be81461146a5780638236f81314611446578063978fe3ed1461140a57806397be2143146113e6578063a06286bf146112c3578063a39e96c314611007578063a4be67df14610fe3578063b018c7d314610fa7578063b51c62ae14610f30578063b770f86e14610f0c578063c0d05dd814610ee8578063c601bf7814610cc7578063cb1c832114610b42578063d35e8c8314610a07578063e75942f9146109e3578063e9e70769146109bf578063ecac693614610980578063ed2fde70146106185763f4410be4146101a957600080fd5b34610615576040600319360112610615576101c2612a7d565b60243590610257610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612ad7565b519020613695565b612cc1565b61026081614265565b156105d15761026e81614a38565b508273ffffffffffffffffffffffffffffffffffffffff6102c5604051610296604082612ad7565b601681527f726f636b65744e6574776f726b536e617073686f7473000000000000000000006020820152613d1d565b1660405160208101906103188161021e87856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b5190206040517f79feb107000000000000000000000000000000000000000000000000000000008152816004820152606081602481865afa80156105c6576103e0918591610594575b506103bb7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff821661038e8189614888565b61039788613452565b906103aa6103a48a613093565b8b613086565b811015918261057f575b5050613f04565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8716906137c0565b823b1561057b576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660248201529082908290604490829084905af1801561057057610557575b5050604073ffffffffffffffffffffffffffffffffffffffff7faa4c88f0b9828cd8487d897217facaaca2a112ead081957e1f7fc52f92149a04926104b6857fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a306614956565b6104e0857fb9c18cdf42b0bf93d85c84e3a8154de029950fa3347d2280bad7d565666e1e20614956565b61053d85845160208101906105358161021e87856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b5190206149c7565b61054681614e3d565b82519485524260208601521692a280f35b8161056191612ad7565b61056c578238610451565b8280fd5b6040513d84823e3d90fd5b8380fd5b61058b9192508a613086565b111538806103b4565b6105b6915060603d6060116105bf575b6105ae8183612ad7565b810190612e85565b91505038610361565b503d6105a4565b6040513d86823e3d90fd5b606460405162461bcd60e51b815260206004820152601a60248201527f4e6f7420616c6c6f77656420746f20756e7374616b6520666f720000000000006044820152fd5b80fd5b503461061557602060031936011261061557600435610685610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b61068e33614265565b156105d15761069c33614a38565b508173ffffffffffffffffffffffffffffffffffffffff6106c4604051610296604082612ad7565b1660405160208101906107178161021e33856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b5190206040517f79feb107000000000000000000000000000000000000000000000000000000008152816004820152606081602481865afa80156105c6576107de91859161095e575b506107b97bffffffffffffffffffffffffffffffffffffffffffffffffffffffff821661078d8133614888565b61079633613452565b906107a96107a333613093565b8a613086565b8110159182610952575050613f04565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8616906137c0565b823b1561057b576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660248201529082908290604490829084905af1801561057057610939575b505061087b817fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a306614956565b6108a5817fb9c18cdf42b0bf93d85c84e3a8154de029950fa3347d2280bad7d565666e1e20614956565b6108fb8160405160208101906105358161021e33856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b61090433614e3d565b6040519081524260208201527faa4c88f0b9828cd8487d897217facaaca2a112ead081957e1f7fc52f92149a0460403392a280f35b8161094391612ad7565b61094e57813861084f565b5080fd5b61058b91925089613086565b610977915060603d6060116105bf576105ae8183612ad7565b91505038610760565b50346106155760206003193601126106155760206109b761099f612a7d565b6109b16109ab82612eda565b9161328b565b90613086565b604051908152f35b50346106155760206003193601126106155760206109b76109de612a7d565b613509565b50346106155760206003193601126106155760206109b7610a02612a7d565b613452565b503461061557604060031936011261061557610a21612a7d565b60243590610a7d610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b610a8681614265565b15610ad857604073ffffffffffffffffffffffffffffffffffffffff82610acd7f0178232f2971603b3ffe89ab52d074a471507d935a7fee7477b636f72a64583194614a38565b506104e08582613f4f565b608460405162461bcd60e51b815260206004820152602560248201527f4e6f7420616c6c6f77656420746f20756e7374616b65206c656761637920525060448201527f4c20666f720000000000000000000000000000000000000000000000000000006064820152fd5b503461061557604060031936011261061557610c48610b5f612a7d565b610bb7610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b73ffffffffffffffffffffffffffffffffffffffff610c3760405160208101907f636f6e74726163742e616464726573730000000000000000000000000000000082527f726f636b65744d65726b6c654469737472696275746f724d61696e6e657400006030820152602e8152610c2f604e82612ad7565b51902061480b565b163303610c4b575b60243590614458565b80f35b610c5481614265565b610c3f57610cc2610cbd604051602081019061024a8161021e33888690603e926bffffffffffffffffffffffff1980927f6e6f64652e7374616b652e666f722e616c6c6f77656400000000000000000000855260601b16601684015260601b16602a8201520190565b612e3a565b610c3f565b503461061557604060031936011261061557610ce1612a7d565b60243590610d42610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b612c51565b610d97604051602081019061024a8161021e86856bffffffffffffffffffffffff196027927f72706c2e6c6f636b696e672e616c6c6f77656400000000000000000000000000835260601b1660138201520190565b15610ea457610da5816130e8565b6040516020810190610df78161021e86856bffffffffffffffffffffffff19602a927f72706c2e6c6f636b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902083610e0e610e078361372d565b8094612b47565b10610e60577fce4a5a05852c75132c79a7a41af76ced563f8391e69eea41a0b38214c4e847cf9261054673ffffffffffffffffffffffffffffffffffffffff92610e5a87604096613086565b906141f4565b606460405162461bcd60e51b815260206004820152601560248201527f4e6f7420656e6f756768207374616b65642052504c00000000000000000000006044820152fd5b606460405162461bcd60e51b815260206004820152601f60248201527f4e6f6465206973206e6f7420616c6c6f77656420746f206c6f636b2052504c006044820152fd5b50346106155760206003193601126106155760206109b7610f07612a7d565b6133fd565b50346106155760206003193601126106155760206109b7610f2b612a7d565b6133a8565b50346106155760206003193601126106155760206109b7610f4f612a7d565b604051610f9f8161021e86820194856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b51902061372d565b503461061557806003193601126106155760206109b77fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a30661372d565b50346106155760206003193601126106155760206109b7611002612a7d565b61328b565b503461061557604060031936011261061557611021612a7d565b6024359061107d610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b6110d5610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b816110df826130e8565b1061127f576110ee828261380a565b8273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003bdc69c4e5e13e52a65f5583c23efb9636b469d616803b1561094e576040517f01e3366700000000000000000000000000000000000000000000000000000000815230600482015282816064818373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d33526068d116ce69f19a9ee46f0bd304f21a51f16968760248401528a60448401525af190811561127457839161125f575b5050803b1561094e578180916024604051809481937f42966c680000000000000000000000000000000000000000000000000000000083528960048401525af180156105705761124a575b5050604073ffffffffffffffffffffffffffffffffffffffff7f7a3b7812b93ab45ed01ea9fc22b37301461966d61ca09bc0859a84ca07298b129282519485524260208601521692a280f35b8161125491612ad7565b61056c5782386111fe565b8161126991612ad7565b61094e5781386111b3565b6040513d85823e3d90fd5b606460405162461bcd60e51b815260206004820152601960248201527f4e6f64652068617320696e73756666696369656e742052504c000000000000006044820152fd5b503461061557602060031936011261061557600435611330610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b61133933614265565b15610ad85761134733614a38565b506113528133613f4f565b6113a88160405160208101906105358161021e33856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b6113b133614e3d565b6040519081524260208201527f0178232f2971603b3ffe89ab52d074a471507d935a7fee7477b636f72a64583160403392a280f35b50346106155760206003193601126106155760206109b7611405612a7d565b61321e565b503461061557806003193601126106155760206109b77fb9c18cdf42b0bf93d85c84e3a8154de029950fa3347d2280bad7d565666e1e2061372d565b50346106155760206003193601126106155760206109b7611465612a7d565b6131c9565b50346106155760206003193601126106155760206109b7611489612a7d565b6130e8565b50346106155760206003193601126106155760206109b76114ad612a7d565b613093565b503461061557806003193601126106155760206109b76114f17fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a30661372d565b61151a7fb9c18cdf42b0bf93d85c84e3a8154de029950fa3347d2280bad7d565666e1e2061372d565b90612b47565b503461061557602060031936011261061557602061158f61153f612a7d565b60405161024a8161021e86820194856bffffffffffffffffffffffff196027927f72706c2e6c6f636b696e672e616c6c6f77656400000000000000000000000000835260601b1660138201520190565b6040519015158152f35b50346106155760206003193601126106155760206109b76115b8612a7d565b6109b16115c4826133a8565b9161300c565b503461061557806003193601126106155760ff6020915416604051908152f35b503461061557602060031936011261061557611604612a7d565b61165c610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b61166581614265565b1561172e5761167381614a38565b9081156116c457604073ffffffffffffffffffffffffffffffffffffffff7f9947063f70b076145616018b82ed1dd5585e15b7ae0a0b17a8b06bec4c4c31e29282519485524260208601521692a280f35b608460405162461bcd60e51b815260206004820152602660248201527f4e6f20617661696c61626c6520756e7374616b696e672052504c20746f20776960448201527f74686472617700000000000000000000000000000000000000000000000000006064820152fd5b606460405162461bcd60e51b815260206004820152601b60248201527f4e6f7420616c6c6f77656420746f20776974686472617720666f7200000000006044820152fd5b50346106155760206003193601126106155760206109b7611791612a7d565b61300c565b50346106155760206003193601126106155760206109b76117b5612a7d565b612eda565b503461061557602060031936011261061557611824610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b611830610cbd33614265565b610c4860043533614458565b503461061557606060031936011261061557611856612a7d565b61185e612aa5565b60443591821515830361057b5773ffffffffffffffffffffffffffffffffffffffff6118c0604051611891604082612ad7565b601181527f726f636b65744e6f64654d616e616765720000000000000000000000000000006020820152613d1d565b1690604051927fe667d82800000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff821693846004820152602081602481875afa8015611b575786918891611b17575b5015611aca57506020602493604051948580927fb71f0c7c0000000000000000000000000000000000000000000000000000000082528860048301525afa8015611abf578573ffffffffffffffffffffffffffffffffffffffff936119b485611a72947fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec5988c91611a90575b50163314612d90565b611a0c610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b604051611a6a8161021e8760208301958690603e926bffffffffffffffffffffffff1980927f6e6f64652e7374616b652e666f722e616c6c6f77656400000000000000000000855260601b16601684015260601b16602a8201520190565b519020613e91565b60408051951515865242602087015291169390819081015b0390a380f35b611ab2915060203d602011611ab8575b611aaa8183612ad7565b810190612d64565b386119ab565b503d611aa0565b6040513d88823e3d90fd5b7fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec59350611a729073ffffffffffffffffffffffffffffffffffffffff93611b12873314612d19565b6119b4565b9150506020813d602011611b4f575b81611b3360209383612ad7565b81010312611b4b57611b458691612d0c565b3861191f565b8680fd5b3d9150611b26565b6040513d89823e3d90fd5b5034610615578060031936011261061557611bcb610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b611bd433614265565b1561172e57611be233614a38565b80156116c4576040519081524260208201527f9947063f70b076145616018b82ed1dd5585e15b7ae0a0b17a8b06bec4c4c31e260403392a280f35b503461061557604060031936011261061557611c37612a7d565b60243590611c93610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b6040516020810190611ce58161021e85856bffffffffffffffffffffffff19602a927f72706c2e6c6f636b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b519020611cf18161372d565b90818411611d40577f95f42213e171837caaa6cc7f589ef03a30179b7b85e386dfb146a30c5b10cfa99261054673ffffffffffffffffffffffffffffffffffffffff92610e5a87604096612b47565b606460405162461bcd60e51b815260206004820152601560248201527f4e6f7420656e6f756768206c6f636b65642052504c00000000000000000000006044820152fd5b503461061557604060031936011261061557611d9e612a7d565b60243560405191611de9602084017f6d696e69706f6f6c2e657869737473000000000000000000000000000000000081523360601b9485602f8201526023815261024a604382612ad7565b1561235a5773ffffffffffffffffffffffffffffffffffffffff611e43604051611e14604082612ad7565b601381527f726f636b65744e6574776f726b507269636573000000000000000000000000006020820152613d1d565b1682670de0b6b3a76400000290670de0b6b3a76400008204840361232d57906020600492604051938480927f724d4a090000000000000000000000000000000000000000000000000000000082525afa908115611abf5786916122f7575b611eab9250612e01565b92611eb582613452565b8085116122ef575b50836121c4575b73ffffffffffffffffffffffffffffffffffffffff611eea604051610296604082612ad7565b166040516020810190611f3d8161021e87856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902086604051917f79feb107000000000000000000000000000000000000000000000000000000008352806004840152606083602481875afa9283156105705782936121a0575b50611fae7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841687614888565b61202c60405160208101906120038161021e8b856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b519020937bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8a16906137c0565b843b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101929092527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1660248201529281908490604490829084905af1928315612193578793612172575b50509361215b73ffffffffffffffffffffffffffffffffffffffff936120ea606096947f38a2777b6a84fdb3fc375fe8ade69fdad1afdcdd93c79e7ae2319b806a626c4d98614956565b612114887fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a306614956565b60405160208101917f6d696e69706f6f6c2e72706c2e736c61736865640000000000000000000000008352603482015260288152612153604882612ad7565b519020613e11565b60405195865260208601524260408601521692a280f35b81929593509061218191612ad7565b61218f5791849086386120a0565b8580fd5b50604051903d90823e3d90fd5b6121ba91935060603d6060116105bf576105ae8183612ad7565b9150509138611f85565b8473ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003bdc69c4e5e13e52a65f5583c23efb9636b469d61673ffffffffffffffffffffffffffffffffffffffff612251604051612222604082612ad7565b600e81527f726f636b6574546f6b656e52504c0000000000000000000000000000000000006020820152613d1d565b1690803b1561056c5760a4839260405194859384927fee91035e00000000000000000000000000000000000000000000000000000000845260606004850152601460648501527f726f636b657441756374696f6e4d616e61676572000000000000000000000000608485015260248401528a60448401525af18015611abf576122db575b50611ec4565b856122e891969296612ad7565b93386122d5565b935038611ebd565b90506020823d602011612325575b8161231260209383612ad7565b8101031261218f57611eab915190611ea1565b3d9150612305565b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b606460405162461bcd60e51b815260206004820152601060248201527f496e76616c6964206d696e69706f6f6c000000000000000000000000000000006044820152fd5b5034610615576040600319360112610615576123b8612a7d565b6123c0612ac8565b9073ffffffffffffffffffffffffffffffffffffffff6123e7604051611891604082612ad7565b1690604051927fe667d82800000000000000000000000000000000000000000000000000000000845273ffffffffffffffffffffffffffffffffffffffff821693846004820152602081602481875afa908115611abf57869161258f575b5015612554576020602493604051948580927fb71f0c7c0000000000000000000000000000000000000000000000000000000082528860048301525afa80156125495781612543936124da73ffffffffffffffffffffffffffffffffffffffff61252b947f6b33e987d80ef301261d0265922ffe70da2b332f0e097034ce01dbb998cbd013988b91611a905750163314612d90565b604051611a6a8161021e6020820194856bffffffffffffffffffffffff196027927f72706c2e6c6f636b696e672e616c6c6f77656400000000000000000000000000835260601b1660138201520190565b60408051911515825242602083015290918291820190565b0390a280f35b6040513d87823e3d90fd5b7f6b33e987d80ef301261d0265922ffe70da2b332f0e097034ce01dbb998cbd013925061252b816125439361258a873314612d19565b6124da565b90506020813d6020116125c1575b816125aa60209383612ad7565b8101031261218f576125bb90612d0c565b38612445565b3d915061259d565b5034610615576060600319360112610615576125e3612a7d565b6125eb612aa5565b60443590612647610d3d604051602081019061024a8161021e33856bffffffffffffffffffffffff196023927f636f6e74726163742e6578697374730000000000000000000000000000000000835260601b16600f8201520190565b61269f610252604051602081019061024a8161021e89856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b6126f7610252604051602081019061024a8161021e87856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b81612701846130e8565b106127c75773ffffffffffffffffffffffffffffffffffffffff81169273ffffffffffffffffffffffffffffffffffffffff81169284841461278357612774817f3bf4a4ef95ccf3119f6977afa759933d4edd361281f5c3b91203f43104fa34329461276f8260409661380a565b613ac0565b8151908152426020820152a380f35b606460405162461bcd60e51b815260206004820152601f60248201527f43616e6e6f74207472616e7366657220746f2073616d652061646472657373006044820152fd5b606460405162461bcd60e51b815260206004820152601b60248201527f53656e6465722068617320696e73756666696369656e742052504c00000000006044820152fd5b50346106155760206003193601126106155760206109b761282a612a7d565b612b83565b503461061557604060031936011261061557612849612a7d565b612851612ac8565b73ffffffffffffffffffffffffffffffffffffffff612877604051611891604082612ad7565b166040517fe667d828000000000000000000000000000000000000000000000000000000008152336004820152602081602481855afa908115612549578591612a3f575b5015612a39576020602491604051928380927fb71f0c7c0000000000000000000000000000000000000000000000000000000082523360048301525afa9081156105c6576129289173ffffffffffffffffffffffffffffffffffffffff918691611a905750163314612d90565b612980610252604051602081019061024a8161021e33856bffffffffffffffffffffffff19601f927f6e6f64652e657869737473000000000000000000000000000000000000000000835260601b16600b8201520190565b6129e3816040516020810190611a6a8161021e88338690603e926bffffffffffffffffffffffff1980927f6e6f64652e7374616b652e666f722e616c6c6f77656400000000000000000000855260601b16601684015260601b16602a8201520190565b60408051911515825242602083015273ffffffffffffffffffffffffffffffffffffffff929092169133917fb8502fe170368d1312ca3c9feac7aba9cd92406753d7eca9f11df9757081aec59181908101611a8a565b50612928565b90506020813d602011612a75575b81612a5a60209383612ad7565b81010312612a7157612a6b90612d0c565b386128bb565b8480fd5b3d9150612a4d565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203612aa057565b600080fd5b6024359073ffffffffffffffffffffffffffffffffffffffff82168203612aa057565b602435908115158203612aa057565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117612b1857604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b91908203918211612b5457565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b612bd8604051602081019061024a8161021e86856bffffffffffffffffffffffff196033927f72706c2e6c65676163792e7374616b65642e6e6f64652e6d6967726174656400835260601b16601f8201520190565b15612c4b57612c489061151a612c426040516020810190612c398161021e87856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b519020926130e8565b9161372d565b90565b50600090565b15612c5857565b608460405162461bcd60e51b8152602060048201526024808201527f496e76616c6964206f72206f75746461746564206e6574776f726b20636f6e7460448201527f72616374000000000000000000000000000000000000000000000000000000006064820152fd5b15612cc857565b606460405162461bcd60e51b815260206004820152600c60248201527f496e76616c6964206e6f646500000000000000000000000000000000000000006044820152fd5b51908115158203612aa057565b15612d2057565b606460405162461bcd60e51b815260206004820152602060248201527f4d7573742062652063616c6c65642066726f6d206e6f646520616464726573736044820152fd5b90816020910312612aa0575173ffffffffffffffffffffffffffffffffffffffff81168103612aa05790565b15612d9757565b608460405162461bcd60e51b815260206004820152602a60248201527f4d7573742062652063616c6c65642066726f6d2052504c20776974686472617760448201527f616c2061646472657373000000000000000000000000000000000000000000006064820152fd5b8115612e0b570490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b15612e4157565b606460405162461bcd60e51b815260206004820152601860248201527f4e6f7420616c6c6f77656420746f207374616b6520666f7200000000000000006044820152fd5b90816060910312612aa057612e9981612d0c565b91602082015163ffffffff81168103612aa0576040909201517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff81168103612aa05790565b606073ffffffffffffffffffffffffffffffffffffffff612f02604051610296604082612ad7565b16916040516bffffffffffffffffffffffff1960208201927f6d656761706f6f6c2e6574682e70726f76696465642e6e6f64652e616d6f756e84527f74000000000000000000000000000000000000000000000000000000000000006040840152841b16604182015260358152612f7a605582612ad7565b5190206024604051809481937f79feb10700000000000000000000000000000000000000000000000000000000835260048301525afa8015613000577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91600091612fe057501690565b612ff9915060603d6060116105bf576105ae8183612ad7565b9150501690565b6040513d6000823e3d90fd5b606073ffffffffffffffffffffffffffffffffffffffff613034604051610296604082612ad7565b16916040516bffffffffffffffffffffffff1960208201927f6574682e6d6174636865642e6e6f64652e616d6f756e740000000000000000008452841b166037820152602b8152612f7a604b82612ad7565b91908201809211612b5457565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff19602a927f72706c2e6c6f636b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b6040516131398161021e6020820194856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b519020606073ffffffffffffffffffffffffffffffffffffffff613164604051610296604082612ad7565b16916024604051809481937f79feb10700000000000000000000000000000000000000000000000000000000835260048301525afa8015613000577bffffffffffffffffffffffffffffffffffffffffffffffffffffffff91600091612fe057501690565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff19602d927f72706c2e6d656761706f6f6c2e756e7374616b652e74696d6500000000000000835260601b1660198201520190565b61322a6109ab8261300c565b81158015613283575b613275576132419082613086565b670de0b6b3a7640000810290808204670de0b6b3a76400001481151715612b5457612c489261326f91612b47565b90612e01565b5050671bc16d674ec8000090565b508015613233565b602490602073ffffffffffffffffffffffffffffffffffffffff6132e46040516132b6604082612ad7565b601581527f726f636b65744d696e69706f6f6c4d616e61676572000000000000000000000084820152613d1d565b16604051938480927f1844ec0100000000000000000000000000000000000000000000000000000000825273ffffffffffffffffffffffffffffffffffffffff861660048301525afa91821561300057600092613372575b506133469061300c565b6801bc16d674ec8000008202918083046801bc16d674ec8000001490151715612b5457612c4891612b47565b90916020823d6020116133a0575b8161338d60209383612ad7565b810103126106155750519061334661333c565b3d9150613380565b612c48906040516bffffffffffffffffffffffff1960208201927f6d656761706f6f6c2e6574682e6d6174636865642e6e6f64652e616d6f756e74845260601b16604082015260348152610f9f605482612ad7565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff196028927f72706c2e7374616b65642e6e6f64652e74696d65000000000000000000000000835260601b1660148201520190565b6134a7604051602081019061024a8161021e86856bffffffffffffffffffffffff196033927f72706c2e6c65676163792e7374616b65642e6e6f64652e6d6967726174656400835260601b16601f8201520190565b6134b457612c48906130e8565b612c4890604051610f9f8161021e6020820194856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b600473ffffffffffffffffffffffffffffffffffffffff613531604051611e14604082612ad7565b1691602073ffffffffffffffffffffffffffffffffffffffff61358960405161355b604082612ad7565b601d81527f726f636b657444414f50726f746f636f6c53657474696e67734e6f646500000084820152613d1d565b16604051938480927fce20fee60000000000000000000000000000000000000000000000000000000082525afa9182156130005760009261365f575b506135cf9061300c565b818102918183041490151715612b54576020600492604051938480927f724d4a090000000000000000000000000000000000000000000000000000000082525afa90811561300057600091613629575b612c489250612e01565b90506020823d602011613657575b8161364460209383612ad7565b81010312612aa057612c4891519061361f565b3d9150613637565b90916020823d60201161368d575b8161367a60209383612ad7565b81010312610615575051906135cf6135c5565b3d915061366d565b602073ffffffffffffffffffffffffffffffffffffffff60005460081c16916024604051809481937f7ae1cfca00000000000000000000000000000000000000000000000000000000835260048301525afa908115613000576000916136f9575090565b90506020813d602011613725575b8161371460209383612ad7565b81010312612aa057612c4890612d0c565b3d9150613707565b602073ffffffffffffffffffffffffffffffffffffffff60005460081c16916024604051809481937fbd02d0f500000000000000000000000000000000000000000000000000000000835260048301525afa90811561300057600091613791575090565b90506020813d6020116137b8575b816137ac60209383612ad7565b81010312612aa0575190565b3d915061379f565b907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff809116911603907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8211612b5457565b9190600073ffffffffffffffffffffffffffffffffffffffff613834604051610296604082612ad7565b1660405160208101906138878161021e89856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902094604051907f79feb107000000000000000000000000000000000000000000000000000000008252866004830152606082602481865afa9182156105c6579061393f92918592613a9c575b506138fe7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff831682614888565b61390781613452565b8690808811613a57575b50806139f3575b50507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8516906137c0565b94813b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101919091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff95909516602486015281908590604490829084905af1938415612193576139e193946139e3575b50507fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a306614956565b565b816139ed91612ad7565b386139b9565b613a5091604051613a488161021e6020820194856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b519020614956565b3880613918565b613a62915087612b47565b613a96613a6f8289612b47565b917fb9c18cdf42b0bf93d85c84e3a8154de029950fa3347d2280bad7d565666e1e20614956565b38613911565b613ab691925060603d6060116105bf576105ae8183612ad7565b91505090386138d5565b9190600073ffffffffffffffffffffffffffffffffffffffff613aea604051610296604082612ad7565b166040516020810190613b3d8161021e89856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b519020946040517f79feb107000000000000000000000000000000000000000000000000000000008152866004820152606081602481865afa9081156105c657613baf917bffffffffffffffffffffffffffffffffffffffffffffffffffffffff918691613cfb575b50168092614888565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841601947bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8611613cce57813b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101919091527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff95909516602486015281908590604490829084905af1938415612193576139e19394613cbe575b5050613c98817fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a3066149c7565b7fb9c18cdf42b0bf93d85c84e3a8154de029950fa3347d2280bad7d565666e1e206149c7565b81613cc891612ad7565b38613c6c565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b613d14915060603d6060116105bf576105ae8183612ad7565b91505038613ba6565b9060405160208101907f636f6e74726163742e61646472657373000000000000000000000000000000008252835160005b818110613dfb5750613d98939450603082610c2f92810160008382015203017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282612ad7565b73ffffffffffffffffffffffffffffffffffffffff811615613db75790565b606460405162461bcd60e51b815260206004820152601260248201527f436f6e7472616374206e6f7420666f756e6400000000000000000000000000006044820152fd5b8060208092880101516030828601015201613d4e565b60009073ffffffffffffffffffffffffffffffffffffffff825460081c1690813b1561056c5782916044839260405194859384927fabfdcced0000000000000000000000000000000000000000000000000000000084526004840152600160248401525af1801561057057613e84575050565b81613e8e91612ad7565b50565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937fabfdcced0000000000000000000000000000000000000000000000000000000085526004850152151560248401525af1801561057057613e84575050565b15613f0b57565b606460405162461bcd60e51b815260206004820152602060248201527f496e73756666696369656e742052504c207374616b6520746f207265647563656044820152fd5b919060009273ffffffffffffffffffffffffffffffffffffffff613f7a604051610296604082612ad7565b16906040516020810190613fce8161021e85856bffffffffffffffffffffffff19602a927f72706c2e7374616b65642e6e6f64652e616d6f756e7400000000000000000000835260601b1660168201520190565b51902090604051927f79feb107000000000000000000000000000000000000000000000000000000008452826004850152606084602481845afa938415611b575787946141d0575b507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff84166140408184614888565b60405160208101906140928161021e87856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b5190209461409f8661372d565b6140b16140ab86613509565b89613086565b1161418c576103bb6140d1926140ca6107a38c97613093565b1115613f04565b90803b1561056c576040517f5ba5964900000000000000000000000000000000000000000000000000000000815260048101949094527bffffffffffffffffffffffffffffffffffffffffffffffffffffffff9190911660248401528290604490829084905af1801561254957916139e1949584926141569461417c575b5050614956565b7fe9120b7223ae2a37e3e3d2dfb439c54ebbdeabe89bce6d355f59122854c4a306614956565b8161418691612ad7565b3861414f565b606460405162461bcd60e51b815260206004820152601e60248201527f496e73756666696369656e74206c6567616379207374616b65642052504c00006044820152fd5b6141ea91945060603d6060116105bf576105ae8183612ad7565b9150509238614016565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937fe2a4853a000000000000000000000000000000000000000000000000000000008552600485015260248401525af1801561057057613e84575050565b73ffffffffffffffffffffffffffffffffffffffff61428b604051611891604082612ad7565b169073ffffffffffffffffffffffffffffffffffffffff604051917fe667d8280000000000000000000000000000000000000000000000000000000083521690816004820152602081602481865afa9081156130005760009161441e575b501561436f576020906024604051809481937fb71f0c7c00000000000000000000000000000000000000000000000000000000835260048301525afa80156130005773ffffffffffffffffffffffffffffffffffffffff91600091614350575b5016331490565b614369915060203d602011611ab857611aaa8183612ad7565b38614349565b60249150602073ffffffffffffffffffffffffffffffffffffffff60005460081c16604051938480927f5b49ff620000000000000000000000000000000000000000000000000000000082528560048301525afa918215613000576000926143fd575b5033149081156143e0575090565b73ffffffffffffffffffffffffffffffffffffffff915016331490565b61441791925060203d602011611ab857611aaa8183612ad7565b90386143d2565b90506020813d602011614450575b8161443960209383612ad7565b81010312612aa05761444a90612d0c565b386142e9565b3d915061442c565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000d33526068d116ce69f19a9ee46f0bd304f21a51f16604051907f23b872dd00000000000000000000000000000000000000000000000000000000825260009133600482015230602482015284604482015260208160648186865af19081156112745783916147d1575b50156147675773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003bdc69c4e5e13e52a65f5583c23efb9636b469d616906040517f095ea7b300000000000000000000000000000000000000000000000000000000815282600482015285602482015260208160448187865af19081156105c657849161472d575b50156146c357813b1561056c57829160a4839260405194859384927ff444295800000000000000000000000000000000000000000000000000000000845260606004850152601160648501527f726f636b65744e6f64655374616b696e67000000000000000000000000000000608485015260248401528960448401525af18015610570579260609273ffffffffffffffffffffffffffffffffffffffff927f27061f46a0d88c20b00223c4cabb9f6d02edcb48e4d61d72de015b4432f97647956146b3575b505061463d8582613ac0565b61469c60405160208101906146928161021e86856bffffffffffffffffffffffff196028927f72706c2e7374616b65642e6e6f64652e74696d65000000000000000000000000835260601b1660148201520190565b51902042906141f4565b6040519433865260208601524260408601521692a2565b816146bd91612ad7565b38614631565b608460405162461bcd60e51b815260206004820152602360248201527f436f756c64206e6f7420617070726f7665207661756c742052504c206465706f60448201527f73697400000000000000000000000000000000000000000000000000000000006064820152fd5b90506020813d60201161475f575b8161474860209383612ad7565b8101031261057b5761475990612d0c565b3861456b565b3d915061473b565b608460405162461bcd60e51b815260206004820152602a60248201527f436f756c64206e6f74207472616e736665722052504c20746f207374616b696e60448201527f6720636f6e7472616374000000000000000000000000000000000000000000006064820152fd5b90506020813d602011614803575b816147ec60209383612ad7565b8101031261056c576147fd90612d0c565b386144e3565b3d91506147df565b602073ffffffffffffffffffffffffffffffffffffffff60005460081c16916024604051809481937f21f8a72100000000000000000000000000000000000000000000000000000000835260048301525afa9081156130005760009161486f575090565b612c48915060203d602011611ab857611aaa8183612ad7565b60405160208101906148da8161021e85856bffffffffffffffffffffffff196033927f72706c2e6c65676163792e7374616b65642e6e6f64652e6d6967726174656400835260601b16601f8201520190565b519020906148e782613695565b614951576139e19261494c916040516149448161021e6020820194856bffffffffffffffffffffffff196031927f72706c2e6c65676163792e7374616b65642e6e6f64652e616d6f756e74000000835260601b16601d8201520190565b5190206141f4565b613e11565b505050565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937febb9d8c9000000000000000000000000000000000000000000000000000000008552600485015260248401525af1801561057057613e84575050565b60009173ffffffffffffffffffffffffffffffffffffffff835460081c1691823b1561057b5790604484928360405195869485937fadb353dc000000000000000000000000000000000000000000000000000000008552600485015260248401525af1801561057057613e84575050565b60009073ffffffffffffffffffffffffffffffffffffffff614a90604051614a61604082612ad7565b601d81527f726f636b657444414f50726f746f636f6c53657474696e67734e6f64650000006020820152613d1d565b16614a9a826131c9565b604051907f36f837a8000000000000000000000000000000000000000000000000000000008252602082600481865afa918215612549578592614e07575b50614ae39042612b47565b1115614e02576004906020614b00614afa856133fd565b42612b47565b91604051938480927fd999c9b20000000000000000000000000000000000000000000000000000000082525afa9182156105c6578492614dce575b5010614dca576040516020810190614b938161021e85856bffffffffffffffffffffffff196031927f72706c2e6d656761706f6f6c2e756e7374616b696e672e616d6f756e74000000835260601b16601d8201520190565b51902091614ba08361372d565b928315614dc35773ffffffffffffffffffffffffffffffffffffffff825460081c1690813b1561056c5782916044839260405194859384927fe2a4853a00000000000000000000000000000000000000000000000000000000845260048401528160248401525af1801561057057614db3575b5090602073ffffffffffffffffffffffffffffffffffffffff602481614c6e604051614c40604082612ad7565b601181527f726f636b65744e6f64654d616e6167657200000000000000000000000000000086820152613d1d565b169360405194859384927fb71f0c7c0000000000000000000000000000000000000000000000000000000084521660048301525afa908115610570578291614d94575b5073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003bdc69c4e5e13e52a65f5583c23efb9636b469d6169073ffffffffffffffffffffffffffffffffffffffff614d10604051612222604082612ad7565b1691803b1561057b57606484928373ffffffffffffffffffffffffffffffffffffffff9360405196879586947f01e3366700000000000000000000000000000000000000000000000000000000865216600485015260248401528860448401525af1801561057057614d8157505090565b614d8c828092612ad7565b610615575090565b614dad915060203d602011611ab857611aaa8183612ad7565b38614cb1565b81614dbd91612ad7565b38614c13565b5091505090565b5090565b9091506020813d602011614dfa575b81614dea60209383612ad7565b8101031261057b57519038614b3b565b3d9150614ddd565b505090565b9091506020813d602011614e35575b81614e2360209383612ad7565b81010312612a71575190614ae3614ad8565b3d9150614e16565b6139e1906040516146928161021e6020820194856bffffffffffffffffffffffff19602d927f72706c2e6d656761706f6f6c2e756e7374616b652e74696d6500000000000000835260601b166019820152019056fea26469706673582212205ae51aa60ca5baa8cf19ceda4a451f6ebcdcdd55f4d8fc8e276d8be5f2a44e2864736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001d8f8f00cfa6758d7be78336684788fb0ee0fa46
-----Decoded View---------------
Arg [0] : _rocketStorageAddress (address): 0x1d8f8f00cfa6758d7bE78336684788Fb0ee0Fa46
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001d8f8f00cfa6758d7be78336684788fb0ee0fa46
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.