Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
DxPoolStakingFeePoolV2
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/utils/StorageSlot.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts/proxy/utils/UUPSUpgradeable.sol";
import "./interfaces/IDxpoolStakingFeePoolV2.sol";
import "./storage/DxpoolStakingFeePoolStorage.sol";
import "./storage/DxpoolStakingFeePoolStorageV2.sol";
/**
,--. ,--. ,--. ,--.
,---.,-' '-. ,--,--.| |,-. ,---. ,-| |,--. ,--. ,---. ,---. ,---. | |
( .-''-. .-'' ,-. || /| .-. : ' .-. | \ `' / | .-. || .-. || .-. || |
.-' `) | | \ '-' || \ \\ --..--.\ `-' | / /. \ | '-' '' '-' '' '-' '| |
`----' `--' `--`--'`--'`--'`----''--' `---' '--' '--'| |-' `---' `---' `--'
`--'
**/
contract DxPoolStakingFeePoolV2 is
IDxpoolStakingFeePoolV2,
DxpoolStakingFeePoolStorage,
Initializable,
UUPSUpgradeable,
ReentrancyGuard,
DxpoolStakingFeePoolStorageV2
{
using Address for address payable;
uint64 constant SHARE_FRACTAL = 32e9;
uint256 constant PRECISION_FACTOR = 1e32;
uint256 constant COMMISSION_RATE_MAX = 1e4;
constructor() initializer {}
// initialize
function initialize(address operatorAddress_, address adminAddress_) initializer external {
require(operatorAddress_ != address(0));
require(adminAddress_ != address(0));
adminAddress = adminAddress_;
operatorAddress = operatorAddress_;
totalShares = 0;
stakeCommissionFeeRate = 0;
isOpenForWithdrawal = true;
accRewardPerShare = 0;
accTotalStakeCommissionFee = 0;
totalTransferredToColdWallet = 0;
totalTransferredFromSSV = 0;
lastRewardBlock = block.number;
lastPeriodReward = getTotalRewards();
}
function initialize_version_2() adminOnly external reinitializer(2) {
accRewardPerShare *= 1e26;
accRewardPerShare /= SHARE_FRACTAL;
accTotalStakeCommissionFee *= 1e26;
}
function migrateValidatorsFromV1(bytes[] calldata validatorPubKeys) external nonReentrant operatorOnly {
// require(isOpenForWithdrawal == false, "Pool must be closed");
for (uint256 i = 0; i < validatorPubKeys.length; i++) {
bytes memory pubKey = validatorPubKeys[i];
(address depositor, ,uint32 joinTime) = decodeValidatorInfo(DEPRECATED_validatorOwnerAndJoinTime[pubKey]);
require(depositor != address(0), "Validator not in pool");
bytes32 hashedPubKey = hashValidatorPublicKey(pubKey);
validatorHashedPubkeyToInfo[hashedPubKey] = encodeValidatorInfo(depositor, SHARE_FRACTAL, joinTime);
// delete old data
delete DEPRECATED_validatorOwnerAndJoinTime[pubKey];
}
}
function migrateUsersFromV1(address[] calldata userList) external nonReentrant operatorOnly {
// require(isOpenForWithdrawal == false, "Pool must be closed");
for (uint256 i = 0; i < userList.length; i++) {
address userAddress = userList[i];
// confirm exist user
require(
DEPRECATED_users[userAddress].validatorCount > 0 ||
DEPRECATED_users[userAddress].totalReward > 0 ||
DEPRECATED_users[userAddress].debit > 0 ||
DEPRECATED_users[userAddress].claimedReward > 0,
"User does not exist"
);
// Copy user data
users[userAddress].validatorShares = DEPRECATED_users[userAddress].validatorCount;
users[userAddress].totalReward = DEPRECATED_users[userAddress].totalReward;
users[userAddress].debit = DEPRECATED_users[userAddress].debit;
users[userAddress].claimedReward = DEPRECATED_users[userAddress].claimedReward;
// initialize user lastCheckpoint
users[userAddress].lastCheckpoint = uint32(block.timestamp);
totalShares -= users[userAddress].validatorShares;
users[userAddress].validatorShares *= SHARE_FRACTAL;
totalShares += users[userAddress].validatorShares;
// delete old user data
delete DEPRECATED_users[userAddress];
}
}
function migrateFromV1Complete() external nonReentrant operatorOnly {
// finally update
updatePool();
}
// Only admin can update contract
function _authorizeUpgrade(address) internal override adminOnly {}
// decode or encode validator information
function decodeValidatorInfo(uint256 data) public pure returns (address, uint64, uint32) {
address ownerAddress = address(uint160(data));
uint64 shares = uint64((data >> 160) & ((1 << 64) - 1));
uint32 joinPoolTimestamp = uint32(data >> 224);
return (ownerAddress, shares, joinPoolTimestamp);
}
function encodeValidatorInfo(address ownerAddress, uint64 shares, uint32 joinPoolTimestamp) public pure returns (uint256) {
return uint256(uint160(ownerAddress)) | (uint256(shares) << 160) | uint256(joinPoolTimestamp) << 224;
}
// get total rewards since contract created
function getTotalRewards() public view returns (uint256) {
return address(this).balance
+ totalTransferredToColdWallet
+ totalPaidToUserRewards
+ totalClaimedStakeCommissionFee
- totalTransferredFromSSV;
}
// get commission have earned
function getAccStakeCommissionFee() public view returns (uint256) {
uint256 currentPeriodReward = getTotalRewards();
return (
accTotalStakeCommissionFee + PRECISION_FACTOR * (currentPeriodReward - lastPeriodReward)
* stakeCommissionFeeRate / COMMISSION_RATE_MAX
) / PRECISION_FACTOR;
}
// compute a Reward by adding pending reward to user totalRewards
function computeReward(address depositor) internal {
uint256 userValidatorShares = users[depositor].validatorShares;
if (userValidatorShares > 0) {
uint256 pending = userValidatorShares * accRewardPerShare / PRECISION_FACTOR - users[depositor].debit;
users[depositor].totalReward += uint128(pending);
}
}
// compute a ssv remaing reward by adding ssv remaingingEth to user totalRewards
function computeRewardWithSSVRemaingEth(address depositor, uint256 ssvRemainingEth) internal {
uint256 userValidatorShares = users[depositor].validatorShares;
if (userValidatorShares > 0) {
uint256 pending = userValidatorShares * accRewardPerShare / PRECISION_FACTOR - users[depositor].debit;
users[depositor].totalReward += uint128(pending);
}
users[depositor].totalReward += uint128(ssvRemainingEth);
}
function updatePool() internal {
if (block.number <= lastRewardBlock || totalShares == 0) {
return;
}
uint256 currentPeriodReward = getTotalRewards();
accRewardPerShare += PRECISION_FACTOR * (currentPeriodReward - lastPeriodReward) / totalShares
* (COMMISSION_RATE_MAX - stakeCommissionFeeRate) / COMMISSION_RATE_MAX;
accTotalStakeCommissionFee += PRECISION_FACTOR
* (currentPeriodReward - lastPeriodReward) * stakeCommissionFeeRate / COMMISSION_RATE_MAX;
lastRewardBlock = block.number;
lastPeriodReward = currentPeriodReward;
}
/**
Operator Functions
Those methods Reference: https://github.com/pancakeswap/pancake-smart-contracts/blob/master/projects/farms-pools/contracts/MasterChef.sol
*/
function enterPool(bytes calldata validatorPubKey, address depositor, uint256 effectiveBalance) external nonReentrant operatorOnly {
// One validator joined, the previous time period ends.
bytes32 hashedValidatorPubKey = hashValidatorPublicKey(validatorPubKey);
updatePool();
_enterPool(hashedValidatorPubKey, depositor, effectiveBalance);
emit ValidatorEntered(validatorPubKey, depositor, block.timestamp);
}
function _enterPool(bytes32 hashedValidatorPubKey, address depositor, uint256 effectiveBalance) internal {
require(validatorHashedPubkeyToInfo[hashedValidatorPubKey] == 0, "validator already in pool");
require(depositor != address(0), "depositorAddress not be empty");
require(effectiveBalance >= 32e9 && effectiveBalance <= 2048e9, "Effective balance must be between 32 and 2048 ether");
// compute reward
computeReward(depositor);
users[depositor].validatorShares += uint64(effectiveBalance);
totalShares += effectiveBalance;
validatorHashedPubkeyToInfo[hashedValidatorPubKey] = encodeValidatorInfo(depositor, uint64(effectiveBalance), uint32(block.timestamp));
users[depositor].debit = uint128(users[depositor].validatorShares * accRewardPerShare / PRECISION_FACTOR);
users[depositor].lastCheckpoint = uint32(block.timestamp);
}
function leavePool(
bytes calldata validatorPubKey,
uint256 ssvRemainingEth
) external nonReentrant operatorOnly {
bytes32 hashedValidatorPubKey = hashValidatorPublicKey(validatorPubKey);
updatePool();
address depositor = _leavePool(hashedValidatorPubKey, ssvRemainingEth);
emit ValidatorLeft(validatorPubKey, depositor, block.timestamp);
}
function _leavePool(
bytes32 hashedValidatorPubKey,
uint256 ssvRemainingEth
) internal returns (address depositorAddress) {
(address depositor, uint64 shares, ) = decodeValidatorInfo(validatorHashedPubkeyToInfo[hashedValidatorPubKey]);
require(depositor != address(0), "Validator not in pool");
computeRewardWithSSVRemaingEth(depositor, ssvRemainingEth);
totalShares -= shares;
totalSSVRemainingEth += ssvRemainingEth;
users[depositor].validatorShares -= shares;
users[depositor].debit = uint128(users[depositor].validatorShares * accRewardPerShare / PRECISION_FACTOR);
delete validatorHashedPubkeyToInfo[hashedValidatorPubKey];
return depositor;
}
function batchLeavePool(
bytes calldata validatorPubkeyArray,
uint256[] calldata ssvRemainingEthArray
) external nonReentrant operatorOnly {
require(validatorPubkeyArray.length % 48 == 0, "pubKeyArray length not multiple of 48");
uint256 validatorCount = validatorPubkeyArray.length / 48;
require(validatorCount == ssvRemainingEthArray.length, "validatorPubkeys byte array length incorrect");
updatePool();
for(uint256 i = 0; i < validatorCount; i++) {
bytes32 hashedPubKey = hashValidatorPublicKey(validatorPubkeyArray[i*48:(i+1)*48]);
address depositor = _leavePool(hashedPubKey, ssvRemainingEthArray[i]);
emit ValidatorLeft(validatorPubkeyArray[i*48:(i+1)*48], depositor, block.timestamp);
}
}
function batchEnterPool(
bytes calldata validatorPubkeyArray,
address[] calldata depositorAddresses,
uint256[] calldata effectiveBalances
) external nonReentrant operatorOnly {
require(depositorAddresses.length == 1 || depositorAddresses.length * 48 == validatorPubkeyArray.length, "Invalid depositorAddresses length");
updatePool();
uint256 validatorCount = validatorPubkeyArray.length / 48;
bytes32 hashedPubKey;
if (depositorAddresses.length == 1) {
for(uint256 i = 0; i < validatorCount; i++) {
hashedPubKey = hashValidatorPublicKey(validatorPubkeyArray[i*48:(i+1)*48]);
_enterPool(hashedPubKey, depositorAddresses[0], effectiveBalances[i]);
emit ValidatorEntered(validatorPubkeyArray[i*48:(i+1)*48], depositorAddresses[0], block.timestamp);
}
} else {
for(uint256 i = 0; i < validatorCount; i++) {
hashedPubKey = hashValidatorPublicKey(validatorPubkeyArray[i*48:(i+1)*48]);
_enterPool(hashedPubKey, depositorAddresses[i], effectiveBalances[i]);
emit ValidatorEntered(validatorPubkeyArray[i*48:(i+1)*48], depositorAddresses[i], block.timestamp);
}
}
}
function updateValidatorShares(
bytes[] calldata validatorPubKeys,
uint128[] calldata effectiveBalances
) external nonReentrant operatorOnly {
require(validatorPubKeys.length == effectiveBalances.length, "Validator array length mismatch");
updatePool();
for (uint32 i = 0; i < validatorPubKeys.length; i++) {
bytes32 hashedValidatorPubKey = hashValidatorPublicKey(validatorPubKeys[i]);
_processValidatorShares(hashedValidatorPubKey, effectiveBalances[i]);
}
}
function _processValidatorShares(
bytes32 hashedValidatorPubKey,
uint128 effectiveBalance
) internal {
(address depositor, uint64 currentShares, uint32 joinTime) = decodeValidatorInfo(validatorHashedPubkeyToInfo[hashedValidatorPubKey]);
require(depositor != address(0), "PubKey does not exist");
require(effectiveBalance >= 32e9 && effectiveBalance <= 2048e9, "Invalid effective balance");
validatorHashedPubkeyToInfo[hashedValidatorPubKey] = encodeValidatorInfo(depositor, uint64(effectiveBalance), joinTime);
computeReward(depositor);
totalShares = totalShares - currentShares + effectiveBalance;
users[depositor].validatorShares = users[depositor].validatorShares - currentShares + uint128(effectiveBalance);
users[depositor].debit = uint128(users[depositor].validatorShares * accRewardPerShare / PRECISION_FACTOR);
}
// @returns totalRewards, unclaimedRewards, claimedRewards
function computeRewards(address depositor) internal view returns (uint256, uint256, uint256) {
uint256 accRewardPerShareWithCurPeriod = accRewardPerShare;
if (block.number > lastRewardBlock && totalShares > 0) {
uint256 currentPeriodReward = getTotalRewards();
accRewardPerShareWithCurPeriod +=
PRECISION_FACTOR * (currentPeriodReward - lastPeriodReward) / totalShares * (COMMISSION_RATE_MAX - stakeCommissionFeeRate) / COMMISSION_RATE_MAX;
}
uint256 totalReward =
users[depositor].validatorShares * accRewardPerShareWithCurPeriod / PRECISION_FACTOR
+ users[depositor].totalReward - users[depositor].debit;
if (totalReward > users[depositor].claimedReward) {
return (totalReward, totalReward - users[depositor].claimedReward, users[depositor].claimedReward);
} else {
return (users[depositor].claimedReward, 0, users[depositor].claimedReward);
}
}
// This function estimates user totalRewards, unclaimedRewards, claimedRewards based on latest timestamp.
function getUserRewardInfo(address depositor) external view returns (uint256, uint256, uint256) {
require(depositor != address(0), "depositorAddress not be empty");
return computeRewards(depositor);
}
function _claimReward(
address depositor,
address payable withdrawAddress,
uint256 amount
) internal {
if (withdrawAddress == address(0)) {
withdrawAddress = payable(depositor);
}
computeReward(depositor);
users[depositor].debit = uint128(users[depositor].validatorShares * accRewardPerShare / PRECISION_FACTOR);
uint256 unClaimedReward = users[depositor].totalReward - users[depositor].claimedReward;
if (amount == 0) {
users[depositor].claimedReward += uint128(unClaimedReward);
totalPaidToUserRewards += unClaimedReward;
emit ValidatorRewardClaimed(depositor, withdrawAddress, unClaimedReward);
require(unClaimedReward <= address(this).balance, "Please Contact stake.dxpool.com to fix");
withdrawAddress.sendValue(unClaimedReward);
} else {
require(amount <= unClaimedReward, "Not enough unClaimed rewards");
users[depositor].claimedReward += uint128(amount);
totalPaidToUserRewards += amount;
emit ValidatorRewardClaimed(depositor, withdrawAddress, amount);
require(amount <= address(this).balance, "Please Contact stake.dxpool.com to fix");
withdrawAddress.sendValue(amount);
}
}
// claim rewards from the fee pool
function claimReward(address payable withdrawAddress, uint256 amount) external nonReentrant {
require(isOpenForWithdrawal, "Pool is not open for withdrawal");
updatePool();
_claimReward(msg.sender, withdrawAddress, amount);
}
/**
* Admin Functions
*/
function setStakeCommissionFeeRate(uint256 commissionFeeRate) external nonReentrant adminOnly {
updatePool();
stakeCommissionFeeRate = commissionFeeRate;
emit CommissionFeeRateChanged(stakeCommissionFeeRate);
}
// Claim accumulated commission fees
function claimStakeCommissionFee(address payable withdrawAddress, uint256 amount)
external
nonReentrant
adminOnly
{
updatePool();
uint256 totalCommissionFee = accTotalStakeCommissionFee / PRECISION_FACTOR;
uint256 unclaimedCommissionFee = totalCommissionFee - totalClaimedStakeCommissionFee;
if (amount == 0) {
totalClaimedStakeCommissionFee += unclaimedCommissionFee;
emit CommissionClaimed(withdrawAddress, unclaimedCommissionFee);
withdrawAddress.sendValue(unclaimedCommissionFee);
} else {
require(amount <= unclaimedCommissionFee, "Not enough unclaimed commission fee");
totalClaimedStakeCommissionFee += amount;
emit CommissionClaimed(withdrawAddress, amount);
withdrawAddress.sendValue(amount);
}
}
function _transferValidator(bytes calldata validatorPubKey, address to, uint256 ssvRemainingEth) internal {
bytes32 hashedValidatorPubKey = hashValidatorPublicKey(validatorPubKey);
(address validatorOwner, uint64 shares, ) = decodeValidatorInfo(validatorHashedPubkeyToInfo[hashedValidatorPubKey]);
require(validatorOwner != address(0), "Validator not in pool");
require(to != address(0), "to address must be set to nonzero");
require(to != validatorOwner, "cannot transfer validator owner to oneself");
_leavePool(hashedValidatorPubKey, ssvRemainingEth);
_enterPool(hashedValidatorPubKey, to, shares);
emit ValidatorTransferred(validatorPubKey, validatorOwner, to, block.timestamp);
}
function transferValidatorByAdmin(bytes calldata validatorPubkeys, address[] calldata toAddresses, uint256[] calldata ssvRemainingEthArray) external nonReentrant adminOnly {
require(validatorPubkeys.length == toAddresses.length * 48 && validatorPubkeys.length == ssvRemainingEthArray.length * 48, "validatorPubkeys byte array length incorrect");
for (uint256 i = 0; i < toAddresses.length; i++) {
_transferValidator(
validatorPubkeys[i * 48 : (i + 1) * 48],
toAddresses[i],
ssvRemainingEthArray[i]
);
}
}
// Admin handle emergency situations where we want to temporarily pause all withdrawals.
function closePoolForWithdrawal() external nonReentrant adminOnly {
require(isOpenForWithdrawal, "Pool is already closed for withdrawal");
isOpenForWithdrawal = false;
}
function openPoolForWithdrawal() external nonReentrant adminOnly {
require(!isOpenForWithdrawal, "Pool is already open for withdrawal");
isOpenForWithdrawal = true;
}
function changeOperator(address newOperatorAddress) external nonReentrant adminOnly {
require(newOperatorAddress != address(0));
operatorAddress = newOperatorAddress;
emit OperatorChanged(operatorAddress);
}
function emergencyWithdraw (address[] calldata depositor, address[] calldata withdrawAddress, uint256 maxAmount)
external
nonReentrant
adminOnly
{
require(withdrawAddress.length == depositor.length || withdrawAddress.length == 1, "withdrawAddress length incorrect");
updatePool();
if (withdrawAddress.length == 1) {
for (uint256 i = 0; i < depositor.length; i++) {
_claimReward(depositor[i], payable(withdrawAddress[0]), maxAmount);
}
} else {
for (uint256 i = 0; i < depositor.length; i++) {
_claimReward(depositor[i], payable(withdrawAddress[i]), maxAmount);
}
}
}
function increaseTotalTransferredFromSSV() external payable nonReentrant adminOnly {
totalTransferredFromSSV += msg.value;
}
function saveToColdWallet(address wallet, uint256 amount) external nonReentrant adminOnly {
require(amount <= address(this).balance, "Not enough balance");
totalTransferredToColdWallet += amount;
payable(wallet).sendValue(amount);
}
function loadFromColdWallet() external payable nonReentrant adminOnly {
require(msg.value <= totalTransferredToColdWallet, "Too much transferred from cold wallet");
totalTransferredToColdWallet -= msg.value;
}
function getTotalShares() external view returns (uint256) {
return totalShares;
}
function getPoolInfo() external view returns (uint256, uint256, uint256, uint256, uint256, uint256, bool) {
return (
lastRewardBlock,
accRewardPerShare / PRECISION_FACTOR,
totalShares,
totalClaimedStakeCommissionFee,
totalPaidToUserRewards,
totalTransferredToColdWallet,
isOpenForWithdrawal
);
}
function getUserInfo(address user) external view returns (uint256, uint256, uint256, uint256, uint256) {
return (
users[user].validatorShares,
users[user].totalReward,
users[user].debit,
users[user].claimedReward,
users[user].lastCheckpoint
);
}
function getStakeCommissionFeeInfo() external view returns (uint256, uint256, uint256) {
uint256 totalCommissionFee = getAccStakeCommissionFee();
uint256 unclaimedCommissionFee = totalCommissionFee - totalClaimedStakeCommissionFee;
return (
totalCommissionFee,
unclaimedCommissionFee,
totalClaimedStakeCommissionFee
);
}
function justifyValidatorInPool(bytes calldata validatorPubKey) external view returns (bool, uint64, uint256) {
bytes32 hashedValidatorPubKey = hashValidatorPublicKey(validatorPubKey);
if (validatorHashedPubkeyToInfo[hashedValidatorPubKey] == 0) {
return (false, 0, 0);
} else {
(, uint64 shares, uint256 timestamp) = decodeValidatorInfo(validatorHashedPubkeyToInfo[hashedValidatorPubKey]);
return (true, shares, timestamp);
}
}
function justifyEnoughTransferredFromSSV() external view returns (bool) {
if (totalTransferredFromSSV >= totalSSVRemainingEth) {
return true;
}
return false;
}
function hashValidatorPublicKey(bytes memory validatorPubKey) public pure returns (bytes32) {
require(validatorPubKey.length == 48, "pubkey must be 48 bytes");
return sha256(abi.encodePacked(validatorPubKey, bytes16(0)));
}
/**
* Modifiers
*/
modifier operatorOnly() {
require(msg.sender == operatorAddress, "Only Dxpool staking operator allowed");
_;
}
modifier adminOnly() {
require(msg.sender == adminAddress, "Only Dxpool staking admin allowed");
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Storage Message
contract DxpoolStakingFeePoolStorageV2 {
struct UserInfo {
uint128 validatorShares;
uint128 totalReward;
uint128 debit;
uint128 claimedReward;
uint32 lastCheckpoint;
}
mapping(address => UserInfo) internal users;
mapping(bytes32 => uint256) internal validatorHashedPubkeyToInfo;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// Storage Message
contract DxpoolStakingFeePoolStorage {
// user struct
struct DEPRECATED_UserInfo {
uint128 validatorCount;
uint128 totalReward;
uint128 debit;
uint128 claimedReward;
}
// admin, operator address
address internal adminAddress;
address internal operatorAddress;
uint256 public totalClaimedStakeCommissionFee;
uint256 public totalPaidToUserRewards;
uint256 public totalTransferredToColdWallet;
uint256 internal totalShares;
uint256 public stakeCommissionFeeRate;
bool public isOpenForWithdrawal;
mapping(address => DEPRECATED_UserInfo) internal DEPRECATED_users;
mapping(bytes => uint256) internal DEPRECATED_validatorOwnerAndJoinTime;
uint256 internal accRewardPerShare;
uint256 internal accTotalStakeCommissionFee;
uint256 internal lastRewardBlock;
uint256 internal lastPeriodReward;
uint256 public totalTransferredFromSSV;
uint256 public totalSSVRemainingEth;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
interface IDxpoolStakingFeePoolV2 {
event ValidatorEntered(bytes validatorPubkey, address depositorAddress, uint256 ts);
event ValidatorLeft(bytes validatorPubkey, address depositorAddress, uint256 ts);
event ValidatorRewardClaimed(address depositorAddress, address withdrawAddress, uint256 rewardAmount);
event ValidatorTransferred(bytes indexed validatorPubkey, address indexed from, address indexed to, uint256 ts);
event OperatorChanged(address newOperator);
event CommissionFeeRateChanged(uint256 newFeeRate);
event CommissionClaimed(address withdrawAddress, uint256 collectedAmount);
// Only operator can do those operations
/**
* @notice Add a validator to the pool
* @dev operatorOnly.
*/
function enterPool(bytes calldata validatorPubKey, address depositorAddress, uint256 effectiveBalance) external;
/**
* @notice Remove a validator from the pool
* @dev operatorOnly.
*/
function leavePool(bytes calldata validatorPubKey, uint256 ssvRemainingEth) external;
/**
* @notice Add many validators to the pool
* @dev operatorOnly.
*/
function batchEnterPool(bytes calldata validatorPubKeys, address[] calldata depositorAddresses, uint256[] calldata effectiveBalances) external;
/**
* @notice Remove many validators from the pool
* @dev operatorOnly.
*/
function batchLeavePool(bytes calldata validatorPubKeys, uint256[] calldata ssvRemaingEthArray) external;
/**
* @notice Update validator shares
* @dev operatorOnly.
*/
function updateValidatorShares(bytes[] calldata validatorPubKeys, uint128[] calldata effectiveBalances) external;
// Only admin can do those operations
/**
* @notice Set the contract commission fee rate
* @dev adminOnly.
*/
function setStakeCommissionFeeRate(uint256 stakeCommissionFeeRate) external;
/**
* @notice Claim commission fees up to `amount`.
* @dev adminOnly.
*/
function claimStakeCommissionFee(address payable withdrawAddress, uint256 amount) external;
/**
* @notice Change the contract operator
* @dev adminOnly.
*/
function changeOperator(address newOperator) external;
/**
* @notice Disable withdrawal permission
* @dev adminOnly.
*/
function closePoolForWithdrawal() external;
/**
* @notice Enable withdrawal permission
* @dev adminOnly.
*/
function openPoolForWithdrawal() external;
/**
* @notice Transfer one or more validators to new fee pool owners.
* @dev adminOnly.
*/
function transferValidatorByAdmin(bytes calldata validatorPubKeys, address[] calldata toAddresses, uint256[] calldata ssvLeftTimeRewardArray) external;
/**
* @notice Admin function to help users recover funds from a lost or stolen wallet
* @dev adminOnly.
*/
function emergencyWithdraw(address[] calldata depositor, address[] calldata withdrawAddress, uint256 amount) external;
/**
* @notice Admin function to transfer balance into a cold wallet for safe.
* @dev adminOnly.
*/
function saveToColdWallet(address wallet, uint256 amount) external;
/**
* @notice Admin function to transfer balance back from a cold wallet.
* @dev adminOnly.
*/
function loadFromColdWallet() external payable;
// EveryOne can use those functions
/**
* @notice The amount of rewards a depositor can withdraw, and all rewards they have ever withdrawn
*/
function getUserRewardInfo(address depositor) external view returns (uint256 totalRewards, uint256 unclaimedRewards, uint256 claimedRewards);
/**
* @notice Allow a depositor (`msg.sender`) to collect their tip rewards from the pool.
* @dev Emits an {ValidatorRewardCollected} event.
*/
function claimReward(address payable withdrawAddress, uint256 amount) external;
/**
* @notice A summary of the pool's current state
*/
function getPoolInfo() external view returns (
uint256 lastRewardBlock,
uint256 accRewardPerValidator,
uint256 totalValidatorsCount,
uint256 totalClaimedStakeCommissionFee,
uint256 totalPaidToUserRewards,
uint256 totalTransferredToColdWallet,
bool isPoolOpenForWithdrawal
);
/**
* @notice A summary of the depositor's activity in the pool
* @param user The depositor's address
*/
function getUserInfo(address user) external view returns (
uint256 validatorShares,
uint256 totalReward,
uint256 debit,
uint256 claimedReward,
uint256 lastCheckpoint
);
/**
* @notice A summary of pool stake commission fee
*/
function getStakeCommissionFeeInfo() external view returns (
uint256 totalStakeCommissionFee,
uint256 unclaimedStakeCommissionFee,
uint256 claimedStakeCommissionFee
);
/**
* @notice Justify whether a validator in pool
* @param validatorPubkey a validator publicKey
*/
function justifyValidatorInPool(bytes calldata validatorPubkey) external view returns (
bool inPool,
uint64 shares,
uint256 timestamp
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol)
pragma solidity ^0.8.22;
import {IERC1822Proxiable} from "../../interfaces/draft-IERC1822.sol";
import {ERC1967Utils} from "../ERC1967/ERC1967Utils.sol";
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*/
abstract contract UUPSUpgradeable is IERC1822Proxiable {
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable
address private immutable __self = address(this);
/**
* @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
* and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
* while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
* If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
* be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
* during an upgrade.
*/
string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
/**
* @dev The call is from an unauthorized context.
*/
error UUPSUnauthorizedCallContext();
/**
* @dev The storage `slot` is unsupported as a UUID.
*/
error UUPSUnsupportedProxiableUUID(bytes32 slot);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
_checkProxy();
_;
}
/**
* @dev Check that the execution is not being performed through a delegate call. This allows a function to be
* callable on the implementing contract but not through proxies.
*/
modifier notDelegated() {
_checkNotDelegated();
_;
}
/**
* @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the
* implementation. It is used to validate the implementation's compatibility when performing an upgrade.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
*/
function proxiableUUID() external view virtual notDelegated returns (bytes32) {
return ERC1967Utils.IMPLEMENTATION_SLOT;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*
* @custom:oz-upgrades-unsafe-allow-reachable delegatecall
*/
function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallUUPS(newImplementation, data);
}
/**
* @dev Reverts if the execution is not performed via delegatecall or the execution
* context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
*/
function _checkProxy() internal view virtual {
if (
address(this) == __self || // Must be called through delegatecall
ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
) {
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Reverts if the execution is performed via delegatecall.
* See {notDelegated}.
*/
function _checkNotDelegated() internal view virtual {
if (address(this) != __self) {
// Must not be called through delegatecall
revert UUPSUnauthorizedCallContext();
}
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
/**
* @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
*
* As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
* is expected to be the implementation slot in ERC-1967.
*
* Emits an {IERC1967-Upgraded} event.
*/
function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
revert UUPSUnsupportedProxiableUUID(slot);
}
ERC1967Utils.upgradeToAndCall(newImplementation, data);
} catch {
// The implementation is not UUPS
revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol)
pragma solidity ^0.8.20;
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
* reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
* case an upgrade adds a module that needs to be initialized.
*
* For example:
*
* [.hljs-theme-light.nopadding]
* ```solidity
* contract MyToken is ERC20Upgradeable {
* function initialize() initializer public {
* __ERC20_init("MyToken", "MTK");
* }
* }
*
* contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
* function initializeV2() reinitializer(2) public {
* __ERC20Permit_init("MyToken");
* }
* }
* ```
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*
* [CAUTION]
* ====
* Avoid leaving a contract uninitialized.
*
* An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
* contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
* the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
*
* [.hljs-theme-light.nopadding]
* ```
* /// @custom:oz-upgrades-unsafe-allow constructor
* constructor() {
* _disableInitializers();
* }
* ```
* ====
*/
abstract contract Initializable {
/**
* @dev Storage of the initializable contract.
*
* It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
* when using with upgradeable contracts.
*
* @custom:storage-location erc7201:openzeppelin.storage.Initializable
*/
struct InitializableStorage {
/**
* @dev Indicates that the contract has been initialized.
*/
uint64 _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool _initializing;
}
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
/**
* @dev The contract is already initialized.
*/
error InvalidInitialization();
/**
* @dev The contract is not initializing.
*/
error NotInitializing();
/**
* @dev Triggered when the contract has been initialized or reinitialized.
*/
event Initialized(uint64 version);
/**
* @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
* `onlyInitializing` functions can be used to initialize parent contracts.
*
* Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
* number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
* production.
*
* Emits an {Initialized} event.
*/
modifier initializer() {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
// Cache values to avoid duplicated sloads
bool isTopLevelCall = !$._initializing;
uint64 initialized = $._initialized;
// Allowed calls:
// - initialSetup: the contract is not in the initializing state and no previous version was
// initialized
// - construction: the contract is initialized at version 1 (no reinitialization) and the
// current contract is just being deployed
bool initialSetup = initialized == 0 && isTopLevelCall;
bool construction = initialized == 1 && address(this).code.length == 0;
if (!initialSetup && !construction) {
revert InvalidInitialization();
}
$._initialized = 1;
if (isTopLevelCall) {
$._initializing = true;
}
_;
if (isTopLevelCall) {
$._initializing = false;
emit Initialized(1);
}
}
/**
* @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
* contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
* used to initialize parent contracts.
*
* A reinitializer may be used after the original initialization step. This is essential to configure modules that
* are added through upgrades and that require initialization.
*
* When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
* cannot be nested. If one is invoked in the context of another, execution will revert.
*
* Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
* a contract, executing them in the right order is up to the developer or operator.
*
* WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
*
* Emits an {Initialized} event.
*/
modifier reinitializer(uint64 version) {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing || $._initialized >= version) {
revert InvalidInitialization();
}
$._initialized = version;
$._initializing = true;
_;
$._initializing = false;
emit Initialized(version);
}
/**
* @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
* {initializer} and {reinitializer} modifiers, directly or indirectly.
*/
modifier onlyInitializing() {
_checkInitializing();
_;
}
/**
* @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
*/
function _checkInitializing() internal view virtual {
if (!_isInitializing()) {
revert NotInitializing();
}
}
/**
* @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
* Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
* to any version. It is recommended to use this to lock implementation contracts that are designed to be called
* through proxies.
*
* Emits an {Initialized} event the first time it is successfully executed.
*/
function _disableInitializers() internal virtual {
// solhint-disable-next-line var-name-mixedcase
InitializableStorage storage $ = _getInitializableStorage();
if ($._initializing) {
revert InvalidInitialization();
}
if ($._initialized != type(uint64).max) {
$._initialized = type(uint64).max;
emit Initialized(type(uint64).max);
}
}
/**
* @dev Returns the highest version that has been initialized. See {reinitializer}.
*/
function _getInitializedVersion() internal view returns (uint64) {
return _getInitializableStorage()._initialized;
}
/**
* @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
*/
function _isInitializing() internal view returns (bool) {
return _getInitializableStorage()._initializing;
}
/**
* @dev Pointer to storage slot. Allows integrators to override it with a custom storage location.
*
* NOTE: Consider following the ERC-7201 formula to derive storage locations.
*/
function _initializableStorageSlot() internal pure virtual returns (bytes32) {
return INITIALIZABLE_STORAGE;
}
/**
* @dev Returns a pointer to the storage namespace.
*/
// solhint-disable-next-line var-name-mixedcase
function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
bytes32 slot = _initializableStorageSlot();
assembly {
$.slot := slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)
pragma solidity ^0.8.20;
import {Errors} from "./Errors.sol";
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert Errors.InsufficientBalance(address(this).balance, amount);
}
(bool success, bytes memory returndata) = recipient.call{value: amount}("");
if (!success) {
_revert(returndata);
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {Errors.FailedCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert Errors.InsufficientBalance(address(this).balance, value);
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
* of an unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {Errors.FailedCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly ("memory-safe") {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert Errors.FailedCall();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of common custom errors used in multiple contracts
*
* IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
* It is recommended to avoid relying on the error API for critical functionality.
*
* _Available since v5.1._
*/
library Errors {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error InsufficientBalance(uint256 balance, uint256 needed);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedCall();
/**
* @dev The deployment failed.
*/
error FailedDeployment();
/**
* @dev A necessary precompile is missing.
*/
error MissingPrecompile(address);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)
pragma solidity ^0.8.22;
import {IBeacon} from "../beacon/IBeacon.sol";
import {IERC1967} from "../../interfaces/IERC1967.sol";
import {Address} from "../../utils/Address.sol";
import {StorageSlot} from "../../utils/StorageSlot.sol";
/**
* @dev This library provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.
*/
library ERC1967Utils {
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev The `implementation` of the proxy is invalid.
*/
error ERC1967InvalidImplementation(address implementation);
/**
* @dev The `admin` of the proxy is invalid.
*/
error ERC1967InvalidAdmin(address admin);
/**
* @dev The `beacon` of the proxy is invalid.
*/
error ERC1967InvalidBeacon(address beacon);
/**
* @dev An upgrade function sees `msg.value > 0` that may be lost.
*/
error ERC1967NonPayable();
/**
* @dev Returns the current implementation address.
*/
function getImplementation() internal view returns (address) {
return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the ERC-1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
if (newImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(newImplementation);
}
StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Performs implementation upgrade with additional setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) internal {
_setImplementation(newImplementation);
emit IERC1967.Upgraded(newImplementation);
if (data.length > 0) {
Address.functionDelegateCall(newImplementation, data);
} else {
_checkNonPayable();
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Returns the current admin.
*
* TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
* the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
* `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
*/
function getAdmin() internal view returns (address) {
return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the ERC-1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
if (newAdmin == address(0)) {
revert ERC1967InvalidAdmin(address(0));
}
StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {IERC1967-AdminChanged} event.
*/
function changeAdmin(address newAdmin) internal {
emit IERC1967.AdminChanged(getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
*/
// solhint-disable-next-line private-vars-leading-underscore
bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Returns the current beacon.
*/
function getBeacon() internal view returns (address) {
return StorageSlot.getAddressSlot(BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the ERC-1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
if (newBeacon.code.length == 0) {
revert ERC1967InvalidBeacon(newBeacon);
}
StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
address beaconImplementation = IBeacon(newBeacon).implementation();
if (beaconImplementation.code.length == 0) {
revert ERC1967InvalidImplementation(beaconImplementation);
}
}
/**
* @dev Change the beacon and trigger a setup call if data is nonempty.
* This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
* to avoid stuck value in the contract.
*
* Emits an {IERC1967-BeaconUpgraded} event.
*
* CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
* it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
* efficiency.
*/
function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
_setBeacon(newBeacon);
emit IERC1967.BeaconUpgraded(newBeacon);
if (data.length > 0) {
Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
} else {
_checkNonPayable();
}
}
/**
* @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
* if an upgrade doesn't perform an initialization call.
*/
function _checkNonPayable() private {
if (msg.value > 0) {
revert ERC1967NonPayable();
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
* proxy whose upgrades are fully controlled by the current implementation.
*/
interface IERC1822Proxiable {
/**
* @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
* address.
*
* IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
* bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
* function revert if invoked through a proxy.
*/
function proxiableUUID() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
pragma solidity ^0.8.20;
/**
* @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
*/
interface IERC1967 {
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Emitted when the beacon is changed.
*/
event BeaconUpgraded(address indexed beacon);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
pragma solidity ^0.8.20;
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeacon {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {UpgradeableBeacon} will check that this address is a contract.
*/
function implementation() external view returns (address);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": []
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"collectedAmount","type":"uint256"}],"name":"CommissionClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFeeRate","type":"uint256"}],"name":"CommissionFeeRateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOperator","type":"address"}],"name":"OperatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":false,"internalType":"address","name":"depositorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"ValidatorEntered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":false,"internalType":"address","name":"depositorAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"ValidatorLeft","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"depositorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"withdrawAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardAmount","type":"uint256"}],"name":"ValidatorRewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes","name":"validatorPubkey","type":"bytes"},{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"ts","type":"uint256"}],"name":"ValidatorTransferred","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubkeyArray","type":"bytes"},{"internalType":"address[]","name":"depositorAddresses","type":"address[]"},{"internalType":"uint256[]","name":"effectiveBalances","type":"uint256[]"}],"name":"batchEnterPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubkeyArray","type":"bytes"},{"internalType":"uint256[]","name":"ssvRemainingEthArray","type":"uint256[]"}],"name":"batchLeavePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOperatorAddress","type":"address"}],"name":"changeOperator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"withdrawAddress","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimStakeCommissionFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"closePoolForWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"data","type":"uint256"}],"name":"decodeValidatorInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"depositor","type":"address[]"},{"internalType":"address[]","name":"withdrawAddress","type":"address[]"},{"internalType":"uint256","name":"maxAmount","type":"uint256"}],"name":"emergencyWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ownerAddress","type":"address"},{"internalType":"uint64","name":"shares","type":"uint64"},{"internalType":"uint32","name":"joinPoolTimestamp","type":"uint32"}],"name":"encodeValidatorInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubKey","type":"bytes"},{"internalType":"address","name":"depositor","type":"address"},{"internalType":"uint256","name":"effectiveBalance","type":"uint256"}],"name":"enterPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAccStakeCommissionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getStakeCommissionFeeInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"}],"name":"getUserRewardInfo","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubKey","type":"bytes"}],"name":"hashValidatorPublicKey","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"increaseTotalTransferredFromSSV","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operatorAddress_","type":"address"},{"internalType":"address","name":"adminAddress_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initialize_version_2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isOpenForWithdrawal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"justifyEnoughTransferredFromSSV","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubKey","type":"bytes"}],"name":"justifyValidatorInPool","outputs":[{"internalType":"bool","name":"","type":"bool"},{"internalType":"uint64","name":"","type":"uint64"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubKey","type":"bytes"},{"internalType":"uint256","name":"ssvRemainingEth","type":"uint256"}],"name":"leavePool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"loadFromColdWallet","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"migrateFromV1Complete","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"userList","type":"address[]"}],"name":"migrateUsersFromV1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"validatorPubKeys","type":"bytes[]"}],"name":"migrateValidatorsFromV1","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"openPoolForWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"wallet","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"saveToColdWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"commissionFeeRate","type":"uint256"}],"name":"setStakeCommissionFeeRate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeCommissionFeeRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalClaimedStakeCommissionFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalPaidToUserRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSSVRemainingEth","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTransferredFromSSV","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTransferredToColdWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubkeys","type":"bytes"},{"internalType":"address[]","name":"toAddresses","type":"address[]"},{"internalType":"uint256[]","name":"ssvRemainingEthArray","type":"uint256[]"}],"name":"transferValidatorByAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"validatorPubKeys","type":"bytes[]"},{"internalType":"uint128[]","name":"effectiveBalances","type":"uint128[]"}],"name":"updateValidatorShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
60a060405230608052348015610013575f80fd5b5060016010557ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000810460ff1615906001600160401b03165f811580156100625750825b90505f826001600160401b0316600114801561007d5750303b155b90508115801561008b575080155b156100a95760405163f92ee8a960e01b815260040160405180910390fd5b84546001600160401b031916600117855583156100d757845460ff60401b1916680100000000000000001785555b831561011d57845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050506080516140696101485f395f8181612a7b01528181612aa40152612c0401526140695ff3fe608060405260043610610254575f3560e01c80636386c1c71161013f578063b5a13095116100b3578063e627f2db11610078578063e627f2db14610786578063eb2f385d1461079a578063ec9729cf146107a2578063fc4b0fb5146107b7578063fd8b916c146107cb578063ff7f6398146107ea575f80fd5b8063b5a13095146106c0578063bece2531146106d9578063d1d59fd0146106ee578063d5002f2e14610753578063dff10adb14610767575f80fd5b80639c9ba9de116101045780639c9ba9de146105fe578063a5166a6214610612578063a5c4125914610631578063ad0b13eb14610650578063ad3cb1cc1461066f578063b2d39634146106ac575f80fd5b80636386c1c7146104c857806369517310146105585780636951b9df146105775780637143bf7a1461059b5780638093dc3f146105ba575f80fd5b80633c901a55116101d65780634f1ef2861161019b5780634f1ef2861461040e57806352d1902d1461042157806357639d85146104355780635968571e146104495780635ad220481461045e57806360246c881461047d575f80fd5b80633c901a551461036d5780633e87399e1461039c57806340b0bb95146103bb578063485cc955146103d05780634b745b93146103ef575f80fd5b806326e5c4611161021c57806326e5c461146102f357806327f23c2b1461031257806333db92071461032757806336ec1fe81461032f578063379317051461034e575f80fd5b806306394c9b146102585780630a4613b414610279578063174e31c41461029857806319f344ba146102b75780631b2fd9c3146102cb575b5f80fd5b348015610263575f80fd5b506102776102723660046136ce565b610809565b005b348015610284575f80fd5b506102776102933660046136e9565b6108b4565b3480156102a3575f80fd5b506102776102b2366004613700565b610922565b3480156102c2575f80fd5b5061027761099d565b3480156102d6575f80fd5b506102e060035481565b6040519081526020015b60405180910390f35b3480156102fe575f80fd5b5061027761030d36600461376e565b610a46565b34801561031d575f80fd5b506102e060065481565b610277610b1c565b34801561033a575f80fd5b506102776103493660046137f5565b610b6a565b348015610359575f80fd5b506102e0610368366004613903565b610cd6565b348015610378575f80fd5b50610381610d9c565b604080519384526020840192909252908201526060016102ea565b3480156103a7575f80fd5b506102776103b636600461393c565b610dca565b3480156103c6575f80fd5b506102e060025481565b3480156103db575f80fd5b506102776103ea3660046139a6565b610f26565b3480156103fa575f80fd5b506102776104093660046139dd565b61109c565b61027761041c366004613a1b565b611209565b34801561042c575f80fd5b506102e0611224565b348015610440575f80fd5b506102e061123f565b348015610454575f80fd5b506102e0600f5481565b348015610469575f80fd5b50610277610478366004613700565b6112b5565b348015610488575f80fd5b50610491611467565b604080519788526020880196909652948601939093526060850191909152608084015260a0830152151560c082015260e0016102ea565b3480156104d3575f80fd5b506105306104e23660046136ce565b6001600160a01b03165f908152601160205260409020805460018201546002909201546001600160801b0380831694600160801b938490048216948281169490049091169163ffffffff1690565b604080519586526020860194909452928401919091526060830152608082015260a0016102ea565b348015610563575f80fd5b506103816105723660046136ce565b6114b5565b348015610582575f80fd5b5061058b611525565b60405190151581526020016102ea565b3480156105a6575f80fd5b506102776105b5366004613a67565b61153c565b3480156105c5575f80fd5b506105d96105d4366004613abf565b61160a565b6040805193151584526001600160401b039092166020840152908201526060016102ea565b348015610609575f80fd5b506102776116a0565b34801561061d575f80fd5b5061027761062c366004613af1565b6116e4565b34801561063c575f80fd5b5061027761064b3660046139dd565b611899565b34801561065b575f80fd5b5061027761066a366004613700565b611b54565b34801561067a575f80fd5b5061069f604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516102ea9190613b25565b3480156106b7575f80fd5b50610277611bf4565b3480156106cb575f80fd5b5060075461058b9060ff1681565b3480156106e4575f80fd5b506102e0600e5481565b3480156106f9575f80fd5b506107206107083660046136e9565b9060a082901c6001600160401b03169060e083901c90565b604080516001600160a01b0390941684526001600160401b03909216602084015263ffffffff16908201526060016102ea565b34801561075e575f80fd5b506005546102e0565b348015610772575f80fd5b50610277610781366004613b5a565b611c99565b348015610791575f80fd5b506102e0611da6565b610277611de1565b3480156107ad575f80fd5b506102e060045481565b3480156107c2575f80fd5b50610277611e83565b3480156107d6575f80fd5b506102e06107e5366004613bf6565b611fcd565b3480156107f5575f80fd5b50610277610804366004613b5a565b612002565b6108116122ad565b5f546001600160a01b031633146108435760405162461bcd60e51b815260040161083a90613c51565b60405180910390fd5b6001600160a01b038116610855575f80fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e54906020015b60405180910390a16108b16001601055565b50565b6108bc6122ad565b5f546001600160a01b031633146108e55760405162461bcd60e51b815260040161083a90613c51565b6108ed6122d7565b60068190556040518181527f06bd4ba843bc678397fc73783e3a42479424b41319e584574f445770d303803e9060200161089f565b61092a6122ad565b60075460ff1661097c5760405162461bcd60e51b815260206004820152601f60248201527f506f6f6c206973206e6f74206f70656e20666f72207769746864726177616c00604482015260640161083a565b6109846122d7565b61098f3383836123c5565b6109996001601055565b5050565b6109a56122ad565b5f546001600160a01b031633146109ce5760405162461bcd60e51b815260040161083a90613c51565b60075460ff1615610a2d5760405162461bcd60e51b815260206004820152602360248201527f506f6f6c20697320616c7265616479206f70656e20666f7220776974686472616044820152621dd85b60ea1b606482015260840161083a565b6007805460ff19166001179055610a446001601055565b565b610a4e6122ad565b6001546001600160a01b03163314610a785760405162461bcd60e51b815260040161083a90613c92565b5f610ab784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b9050610ac16122d7565b5f610acc82846126ca565b90507f07cd33a03f4973ff12a258610683c0eeae6c92a52e2914a07e333bc5b8db41b085858342604051610b039493929190613cfe565b60405180910390a15050610b176001601055565b505050565b610b246122ad565b5f546001600160a01b03163314610b4d5760405162461bcd60e51b815260040161083a90613c51565b34600e5f828254610b5e9190613d41565b90915550506001601055565b610b726122ad565b5f546001600160a01b03163314610b9b5760405162461bcd60e51b815260040161083a90613c51565b81841480610ba95750600182145b610bf55760405162461bcd60e51b815260206004820181905260248201527f776974686472617741646472657373206c656e67746820696e636f7272656374604482015260640161083a565b610bfd6122d7565b6001829003610c75575f5b84811015610c6f57610c67868683818110610c2557610c25613d54565b9050602002016020810190610c3a91906136ce565b85855f818110610c4c57610c4c613d54565b9050602002016020810190610c6191906136ce565b846123c5565b600101610c08565b50610cc5565b5f5b84811015610cc357610cbb868683818110610c9457610c94613d54565b9050602002016020810190610ca991906136ce565b858584818110610c4c57610c4c613d54565b600101610c77565b505b610ccf6001601055565b5050505050565b5f8151603014610d285760405162461bcd60e51b815260206004820152601760248201527f7075626b6579206d757374206265203438206279746573000000000000000000604482015260640161083a565b604051600290610d3e9084905f90602001613d7f565b60408051601f1981840301815290829052610d5891613da3565b602060405180830381855afa158015610d73573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610d969190613dae565b92915050565b5f805f80610da861123f565b90505f60025482610db99190613dc5565b600254929690955091935090915050565b610dd26122ad565b6001546001600160a01b03163314610dfc5760405162461bcd60e51b815260040161083a90613c92565b828114610e4b5760405162461bcd60e51b815260206004820152601f60248201527f56616c696461746f72206172726179206c656e677468206d69736d6174636800604482015260640161083a565b610e536122d7565b5f5b63ffffffff8116841115610f15575f610eca86868463ffffffff16818110610e7f57610e7f613d54565b9050602002810190610e919190613dd8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b9050610f028185858563ffffffff16818110610ee857610ee8613d54565b9050602002016020810190610efd9190613e1a565b612835565b5080610f0d81613e40565b915050610e55565b50610f206001601055565b50505050565b5f610f2f612a48565b805490915060ff600160401b82041615906001600160401b03165f81158015610f555750825b90505f826001600160401b03166001148015610f705750303b155b905081158015610f7e575080155b15610f9c5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610fc657845460ff60401b1916600160401b1785555b6001600160a01b038716610fd8575f80fd5b6001600160a01b038616610fea575f80fd5b5f80546001600160a01b038089166001600160a01b031992831617835560018054918b1691909216178155600582905560068290556007805460ff19169091179055600a819055600b8190556004819055600e5543600c5561104a611da6565b600d55831561109357845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6110a46122ad565b6001546001600160a01b031633146110ce5760405162461bcd60e51b815260040161083a90613c92565b5f5b818110156111fe575f8383838181106110eb576110eb613d54565b90506020028101906110fd9190613dd8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052506040519495509384935061117192506009915061114a908690613da3565b9081526020016040518091039020549060a082901c6001600160401b03169060e083901c90565b919350909150506001600160a01b03821661119e5760405162461bcd60e51b815260040161083a90613e64565b5f6111a884610cd6565b90506111ba8364077359400084611fcd565b5f828152601260205260409081902091909155516009906111dc908690613da3565b90815260200160405180910390205f90555050505080806001019150506110d0565b506109996001601055565b611211612a70565b61121a82612b14565b6109998282612b3d565b5f61122d612bf9565b505f8051602061401483398151915290565b5f80611249611da6565b90506904ee2d6d415b85acef8160201b612710600654600d548461126d9190613dc5565b611284906904ee2d6d415b85acef8160201b613e93565b61128e9190613e93565b6112989190613ebe565b600b546112a59190613d41565b6112af9190613ebe565b91505090565b6112bd6122ad565b5f546001600160a01b031633146112e65760405162461bcd60e51b815260040161083a90613c51565b6112ee6122d7565b5f6904ee2d6d415b85acef8160201b600b5461130a9190613ebe565b90505f6002548261131b9190613dc5565b9050825f03611394578060025f8282546113359190613d41565b9091555050604080516001600160a01b0386168152602081018390527f8e14daa5332205b1634040e1054e93d1f5396ec8bf0115d133b7fbaf4a52e411910160405180910390a161138f6001600160a01b03851682612c42565b61145b565b808311156113f05760405162461bcd60e51b815260206004820152602360248201527f4e6f7420656e6f75676820756e636c61696d656420636f6d6d697373696f6e2060448201526266656560e81b606482015260840161083a565b8260025f8282546114019190613d41565b9091555050604080516001600160a01b0386168152602081018590527f8e14daa5332205b1634040e1054e93d1f5396ec8bf0115d133b7fbaf4a52e411910160405180910390a161145b6001600160a01b03851684612c42565b50506109996001601055565b5f805f805f805f600c546904ee2d6d415b85acef8160201b600a5461148c9190613ebe565b600554600254600354600454600754959d949c50929a509098509650945060ff90911692509050565b5f80806001600160a01b03841661150e5760405162461bcd60e51b815260206004820152601d60248201527f6465706f7369746f7241646472657373206e6f7420626520656d707479000000604482015260640161083a565b61151784612cce565b9250925092505b9193909250565b5f600f54600e54106115375750600190565b505f90565b6115446122ad565b6001546001600160a01b0316331461156e5760405162461bcd60e51b815260040161083a90613c92565b5f6115ad85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b90506115b76122d7565b6115c2818484612ea9565b7f8aa859c9608ae3b4a15372294daf4207f79c797c0842a494e4597bf0fd07876b858585426040516115f79493929190613cfe565b60405180910390a150610f206001601055565b5f805f8061164c86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b5f8181526012602052604081205491925003611671575f805f93509350935050611699565b5f908152601260205260409020546001935060a081901c6001600160401b0316925060e01c90505b9250925092565b6116a86122ad565b6001546001600160a01b031633146116d25760405162461bcd60e51b815260040161083a90613c92565b6116da6122d7565b610a446001601055565b6116ec6122ad565b6001546001600160a01b031633146117165760405162461bcd60e51b815260040161083a90613c92565b611721603084613ed1565b1561177c5760405162461bcd60e51b815260206004820152602560248201527f7075624b65794172726179206c656e677468206e6f74206d756c7469706c65206044820152640decc4068760db1b606482015260840161083a565b5f611788603085613ebe565b90508181146117a95760405162461bcd60e51b815260040161083a90613ee4565b6117b16122d7565b5f5b8181101561188d575f6117f087876117cc856030613e93565b906117d8866001613d41565b6117e3906030613e93565b92610e9193929190613f30565b90505f6118158287878681811061180957611809613d54565b905060200201356126ca565b90507f07cd33a03f4973ff12a258610683c0eeae6c92a52e2914a07e333bc5b8db41b08888611845866030613e93565b90611851876001613d41565b61185c906030613e93565b9261186993929190613f30565b834260405161187b9493929190613cfe565b60405180910390a150506001016117b3565b5050610f206001601055565b6118a16122ad565b6001546001600160a01b031633146118cb5760405162461bcd60e51b815260040161083a90613c92565b5f5b818110156111fe575f8383838181106118e8576118e8613d54565b90506020020160208101906118fd91906136ce565b6001600160a01b0381165f908152600860205260409020549091506001600160801b031615158061195457506001600160a01b0381165f90815260086020526040902054600160801b90046001600160801b031615155b8061198157506001600160a01b0381165f908152600860205260409020600101546001600160801b031615155b806119b557506001600160a01b0381165f90815260086020526040902060010154600160801b90046001600160801b031615155b6119f75760405162461bcd60e51b8152602060048201526013602482015272155cd95c88191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161083a565b6001600160a01b0381165f9081526008602090815260408083208054601190935290832080546001600160801b039384166001600160801b0319918216811783558354600160801b9081900486168102808317855560019586018054968601805497891697909516871785555482900487169091029094179091556002909101805463ffffffff19164263ffffffff161790556005805492909316179290611aa0908490613dc5565b90915550506001600160a01b0381165f90815260116020526040812080546407735940009290611ada9084906001600160801b0316613f57565b82546101009290920a6001600160801b038181021990931691831602179091556001600160a01b0383165f9081526011602052604081205460058054919093169350611b27908490613d41565b90915550506001600160a01b03165f908152600860205260408120818155600190810191909155016118cd565b611b5c6122ad565b5f546001600160a01b03163314611b855760405162461bcd60e51b815260040161083a90613c51565b47811115611bca5760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b604482015260640161083a565b8060045f828254611bdb9190613d41565b9091555061098f90506001600160a01b03831682612c42565b611bfc6122ad565b5f546001600160a01b03163314611c255760405162461bcd60e51b815260040161083a90613c51565b60075460ff16611c855760405162461bcd60e51b815260206004820152602560248201527f506f6f6c20697320616c726561647920636c6f73656420666f722077697468646044820152641c985dd85b60da1b606482015260840161083a565b6007805460ff19169055610a446001601055565b611ca16122ad565b5f546001600160a01b03163314611cca5760405162461bcd60e51b815260040161083a90613c51565b611cd5836030613e93565b85148015611cec5750611ce9816030613e93565b85145b611d085760405162461bcd60e51b815260040161083a90613ee4565b5f5b83811015611d9357611d8b8787611d22846030613e93565b90611d2e856001613d41565b611d39906030613e93565b92611d4693929190613f30565b878785818110611d5857611d58613d54565b9050602002016020810190611d6d91906136ce565b868686818110611d7f57611d7f613d54565b90506020020135613111565b600101611d0a565b50611d9e6001601055565b505050505050565b5f600e5460025460035460045447611dbe9190613d41565b611dc89190613d41565b611dd29190613d41565b611ddc9190613dc5565b905090565b611de96122ad565b5f546001600160a01b03163314611e125760405162461bcd60e51b815260040161083a90613c51565b600454341115611e725760405162461bcd60e51b815260206004820152602560248201527f546f6f206d756368207472616e736665727265642066726f6d20636f6c642077604482015264185b1b195d60da1b606482015260840161083a565b3460045f828254610b5e9190613dc5565b5f546001600160a01b03163314611eac5760405162461bcd60e51b815260040161083a90613c51565b60025f611eb7612a48565b8054909150600160401b900460ff1680611ede575080546001600160401b03808416911610155b15611efc5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155600a80546a52b7d2dcc80cd2e400000091905f90611f3c908490613e93565b9091555050600a805464077359400091905f90611f5a908490613ebe565b925050819055506a52b7d2dcc80cd2e4000000600b5f828254611f7d9190613e93565b9091555050805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050565b6001600160a01b03831667ffffffffffffffff60a01b60a084901b16176001600160e01b031960e083901b16175b9392505050565b61200a6122ad565b6001546001600160a01b031633146120345760405162461bcd60e51b815260040161083a90613c92565b600183148061204c57508461204a846030613e93565b145b6120a25760405162461bcd60e51b815260206004820152602160248201527f496e76616c6964206465706f7369746f72416464726573736573206c656e67746044820152600d60fb1b606482015260840161083a565b6120aa6122d7565b5f6120b6603087613ebe565b90505f60018590036121d3575f5b828110156121cd576120e889896120dc846030613e93565b906117d8856001613d41565b91506121338288885f81811061210057612100613d54565b905060200201602081019061211591906136ce565b87878581811061212757612127613d54565b90506020020135612ea9565b7f8aa859c9608ae3b4a15372294daf4207f79c797c0842a494e4597bf0fd07876b8989612161846030613e93565b9061216d856001613d41565b612178906030613e93565b9261218593929190613f30565b89895f81811061219757612197613d54565b90506020020160208101906121ac91906136ce565b426040516121bd9493929190613cfe565b60405180910390a16001016120c4565b506122a1565b5f5b8281101561229f576121ed89896120dc846030613e93565b91506122058288888481811061210057612100613d54565b7f8aa859c9608ae3b4a15372294daf4207f79c797c0842a494e4597bf0fd07876b8989612233846030613e93565b9061223f856001613d41565b61224a906030613e93565b9261225793929190613f30565b89898581811061226957612269613d54565b905060200201602081019061227e91906136ce565b4260405161228f9493929190613cfe565b60405180910390a16001016121d5565b505b5050611d9e6001601055565b6002601054036122d057604051633ee5aeb560e01b815260040160405180910390fd5b6002601055565b600c54431115806122e85750600554155b156122ef57565b5f6122f8611da6565b905061271060065461271061230d9190613dc5565b600554600d5461231d9085613dc5565b612334906904ee2d6d415b85acef8160201b613e93565b61233e9190613ebe565b6123489190613e93565b6123529190613ebe565b600a5f8282546123629190613d41565b9091555050600654600d54612710919061237c9084613dc5565b612393906904ee2d6d415b85acef8160201b613e93565b61239d9190613e93565b6123a79190613ebe565b600b5f8282546123b79190613d41565b909155505043600c55600d55565b6001600160a01b0382166123d7578291505b6123e0836132ef565b600a546001600160a01b0384165f908152601160205260409020546904ee2d6d415b85acef8160201b9161241c916001600160801b0316613e93565b6124269190613ebe565b6001600160a01b0384165f9081526011602052604081206001810180546001600160801b0319166001600160801b0394851617908190559054919261247992600160801b92839004821692900416613f80565b6001600160801b03169050815f03612585576001600160a01b0384165f90815260116020526040902060010180548291906010906124c8908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508060035f8282546124fd9190613d41565b9091555050604080516001600160a01b038087168252851660208201529081018290527f4c3c95bc264760245b1b3c69c79fca66e06b23442e5cebcc374f48467c9b984f9060600160405180910390a14781111561256d5760405162461bcd60e51b815260040161083a90613fbe565b6125806001600160a01b03841682612c42565b610f20565b808211156125d55760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f75676820756e436c61696d6564207265776172647300000000604482015260640161083a565b6001600160a01b0384165f9081526011602052604090206001018054839190601090612612908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508160035f8282546126479190613d41565b9091555050604080516001600160a01b038087168252851660208201529081018390527f4c3c95bc264760245b1b3c69c79fca66e06b23442e5cebcc374f48467c9b984f9060600160405180910390a1478211156126b75760405162461bcd60e51b815260040161083a90613fbe565b610f206001600160a01b03841683612c42565b5f8281526012602052604081205460a081901c6001600160401b03166001600160a01b03821661270c5760405162461bcd60e51b815260040161083a90613e64565b61271682856133d2565b806001600160401b031660055f8282546127309190613dc5565b9250508190555083600f5f8282546127489190613d41565b90915550506001600160a01b0382165f90815260116020526040812080546001600160401b03841692906127869084906001600160801b0316613f80565b82546101009290920a6001600160801b03818102199093169183160217909155600a546001600160a01b0385165f908152601160205260409020546904ee2d6d415b85acef8160201b93506127db9216613e93565b6127e59190613ebe565b6001600160a01b0383165f90815260116020908152604080832060010180546001600160801b0319166001600160801b039590951694909417909355878252601290529081205550905092915050565b5f8281526012602052604090205460a081901c6001600160401b031660e082901c6001600160a01b0383166128a45760405162461bcd60e51b8152602060048201526015602482015274141d5892d95e48191bd95cc81b9bdd08195e1a5cdd605a1b604482015260640161083a565b640773594000846001600160801b0316101580156128d157506501dcd6500000846001600160801b031611155b61291d5760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964206566666563746976652062616c616e636500000000000000604482015260640161083a565b612928838583611fcd565b5f8681526012602052604090205561293f836132ef565b836001600160801b0316826001600160401b03166005546129609190613dc5565b61296a9190613d41565b6005556001600160a01b0383165f9081526011602052604090205484906129a4906001600160401b038516906001600160801b0316613f80565b6129ae9190613f9f565b6001600160a01b0384165f90815260116020526040902080546001600160801b0319166001600160801b03929092169182179055600a546904ee2d6d415b85acef8160201b916129fe9190613e93565b612a089190613ebe565b6001600160a01b03939093165f90815260116020526040902060010180546001600160801b0319166001600160801b039094169390931790925550505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d96565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480612af657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316612aea5f80516020614014833981519152546001600160a01b031690565b6001600160a01b031614155b15610a445760405163703e46dd60e11b815260040160405180910390fd5b5f546001600160a01b031633146108b15760405162461bcd60e51b815260040161083a90613c51565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612b97575060408051601f3d908101601f19168201909252612b9491810190613dae565b60015b612bbf57604051634c9c8ce360e01b81526001600160a01b038316600482015260240161083a565b5f805160206140148339815191528114612bef57604051632a87526960e21b81526004810182905260240161083a565b610b1783836134ec565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610a445760405163703e46dd60e11b815260040160405180910390fd5b80471015612c6c5760405163cf47918160e01b81524760048201526024810182905260440161083a565b5f80836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114612cb6576040519150601f19603f3d011682016040523d82523d5f602084013e612cbb565b606091505b509150915081610f2057610f2081613541565b5f805f80600a549050600c5443118015612ce957505f600554115b15612d5f575f612cf7611da6565b9050612710600654612710612d0c9190613dc5565b600554600d54612d1c9085613dc5565b612d33906904ee2d6d415b85acef8160201b613e93565b612d3d9190613ebe565b612d479190613e93565b612d519190613ebe565b612d5b9083613d41565b9150505b6001600160a01b0385165f908152601160205260408120600181015490546001600160801b0391821691600160801b82048116916904ee2d6d415b85acef8160201b91612dae91879116613e93565b612db89190613ebe565b612dc29190613d41565b612dcc9190613dc5565b6001600160a01b0387165f90815260116020526040902060010154909150600160801b90046001600160801b0316811115612e72576001600160a01b0386165f908152601160205260409020600101548190612e3890600160801b90046001600160801b031682613dc5565b6001600160a01b0388165f908152601160205260409020600101549196509450600160801b90046001600160801b0316925061151e915050565b505050506001600160a01b0382165f90815260116020526040812060010154600160801b90046001600160801b031691508161151e565b5f8381526012602052604090205415612f045760405162461bcd60e51b815260206004820152601960248201527f76616c696461746f7220616c726561647920696e20706f6f6c00000000000000604482015260640161083a565b6001600160a01b038216612f5a5760405162461bcd60e51b815260206004820152601d60248201527f6465706f7369746f7241646472657373206e6f7420626520656d707479000000604482015260640161083a565b6407735940008110158015612f7557506501dcd65000008111155b612fdd5760405162461bcd60e51b815260206004820152603360248201527f4566666563746976652062616c616e6365206d75737420626520626574776565604482015272371019991030b7321019181a1c1032ba3432b960691b606482015260840161083a565b612fe6826132ef565b6001600160a01b0382165f90815260116020526040812080546001600160401b038416929061301f9084906001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508060055f8282546130549190613d41565b909155506130659050828242611fcd565b5f84815260126020908152604080832093909355600a546001600160a01b03861683526011909152919020546904ee2d6d415b85acef8160201b916130b2916001600160801b0316613e93565b6130bc9190613ebe565b6001600160a01b03929092165f9081526011602052604090206001810180546001600160801b0319166001600160801b039094169390931790925550600201805463ffffffff19164263ffffffff1617905550565b5f61315085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b5f8181526012602052604090205490915060a081901c6001600160401b03166001600160a01b0382166131955760405162461bcd60e51b815260040161083a90613e64565b6001600160a01b0385166131f55760405162461bcd60e51b815260206004820152602160248201527f746f2061646472657373206d7573742062652073657420746f206e6f6e7a65726044820152606f60f81b606482015260840161083a565b816001600160a01b0316856001600160a01b0316036132695760405162461bcd60e51b815260206004820152602a60248201527f63616e6e6f74207472616e736665722076616c696461746f72206f776e6572206044820152693a379037b732b9b2b63360b11b606482015260840161083a565b61327383856126ca565b506132888386836001600160401b0316612ea9565b846001600160a01b0316826001600160a01b031688886040516132ac929190614004565b604051908190038120428252907fae24802f5dcf9eb23697e34d9f536295d24fc5a2684ed27559aa35ae878138269060200160405180910390a450505050505050565b6001600160a01b0381165f908152601160205260409020546001600160801b03168015610999576001600160a01b0382165f90815260116020526040812060010154600a546001600160801b03909116906904ee2d6d415b85acef8160201b906133599085613e93565b6133639190613ebe565b61336d9190613dc5565b6001600160a01b0384165f908152601160205260409020805491925082916010906133a9908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b6001600160a01b0382165f908152601160205260409020546001600160801b031680156134b2576001600160a01b0383165f90815260116020526040812060010154600a546001600160801b03909116906904ee2d6d415b85acef8160201b9061343c9085613e93565b6134469190613ebe565b6134509190613dc5565b6001600160a01b0385165f9081526011602052604090208054919250829160109061348c908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505b6001600160a01b0383165f90815260116020526040902080548391906010906133a9908490600160801b90046001600160801b0316613f9f565b6134f58261356a565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561353957610b1782826135cd565b61099961363f565b8051156135515780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b806001600160a01b03163b5f0361359f57604051634c9c8ce360e01b81526001600160a01b038216600482015260240161083a565b5f8051602061401483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516135e99190613da3565b5f60405180830381855af49150503d805f8114613621576040519150601f19603f3d011682016040523d82523d5f602084013e613626565b606091505b509150915061363685838361365e565b95945050505050565b3415610a445760405163b398979f60e01b815260040160405180910390fd5b6060826136735761366e82613541565b611ffb565b815115801561368a57506001600160a01b0384163b155b156136b357604051639996b31560e01b81526001600160a01b038516600482015260240161083a565b5080611ffb565b6001600160a01b03811681146108b1575f80fd5b5f602082840312156136de575f80fd5b8135611ffb816136ba565b5f602082840312156136f9575f80fd5b5035919050565b5f8060408385031215613711575f80fd5b823561371c816136ba565b946020939093013593505050565b5f8083601f84011261373a575f80fd5b5081356001600160401b03811115613750575f80fd5b602083019150836020828501011115613767575f80fd5b9250929050565b5f805f60408486031215613780575f80fd5b83356001600160401b03811115613795575f80fd5b6137a18682870161372a565b909790965060209590950135949350505050565b5f8083601f8401126137c5575f80fd5b5081356001600160401b038111156137db575f80fd5b6020830191508360208260051b8501011115613767575f80fd5b5f805f805f60608688031215613809575f80fd5b85356001600160401b0381111561381e575f80fd5b61382a888289016137b5565b90965094505060208601356001600160401b03811115613848575f80fd5b613854888289016137b5565b96999598509660400135949350505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112613889575f80fd5b81356001600160401b038111156138a2576138a2613866565b604051601f8201601f19908116603f011681016001600160401b03811182821017156138d0576138d0613866565b6040528181528382016020018510156138e7575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215613913575f80fd5b81356001600160401b03811115613928575f80fd5b6139348482850161387a565b949350505050565b5f805f806040858703121561394f575f80fd5b84356001600160401b03811115613964575f80fd5b613970878288016137b5565b90955093505060208501356001600160401b0381111561398e575f80fd5b61399a878288016137b5565b95989497509550505050565b5f80604083850312156139b7575f80fd5b82356139c2816136ba565b915060208301356139d2816136ba565b809150509250929050565b5f80602083850312156139ee575f80fd5b82356001600160401b03811115613a03575f80fd5b613a0f858286016137b5565b90969095509350505050565b5f8060408385031215613a2c575f80fd5b8235613a37816136ba565b915060208301356001600160401b03811115613a51575f80fd5b613a5d8582860161387a565b9150509250929050565b5f805f8060608587031215613a7a575f80fd5b84356001600160401b03811115613a8f575f80fd5b613a9b8782880161372a565b9095509350506020850135613aaf816136ba565b9396929550929360400135925050565b5f8060208385031215613ad0575f80fd5b82356001600160401b03811115613ae5575f80fd5b613a0f8582860161372a565b5f805f8060408587031215613b04575f80fd5b84356001600160401b03811115613b19575f80fd5b6139708782880161372a565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f805f805f8060608789031215613b6f575f80fd5b86356001600160401b03811115613b84575f80fd5b613b9089828a0161372a565b90975095505060208701356001600160401b03811115613bae575f80fd5b613bba89828a016137b5565b90955093505060408701356001600160401b03811115613bd8575f80fd5b613be489828a016137b5565b979a9699509497509295939492505050565b5f805f60608486031215613c08575f80fd5b8335613c13816136ba565b925060208401356001600160401b0381168114613c2e575f80fd5b9150604084013563ffffffff81168114613c46575f80fd5b809150509250925092565b60208082526021908201527f4f6e6c79204478706f6f6c207374616b696e672061646d696e20616c6c6f77656040820152601960fa1b606082015260800190565b60208082526024908201527f4f6e6c79204478706f6f6c207374616b696e67206f70657261746f7220616c6c6040820152631bddd95960e21b606082015260800190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b606081525f613d11606083018688613cd6565b6001600160a01b03949094166020830152506040015292915050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610d9657610d96613d2d565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f613d8a8285613d68565b6001600160801b03199390931683525050601001919050565b5f611ffb8284613d68565b5f60208284031215613dbe575f80fd5b5051919050565b81810381811115610d9657610d96613d2d565b5f808335601e19843603018112613ded575f80fd5b8301803591506001600160401b03821115613e06575f80fd5b602001915036819003821315613767575f80fd5b5f60208284031215613e2a575f80fd5b81356001600160801b0381168114611ffb575f80fd5b5f63ffffffff821663ffffffff8103613e5b57613e5b613d2d565b60010192915050565b60208082526015908201527415985b1a59185d1bdc881b9bdd081a5b881c1bdbdb605a1b604082015260600190565b8082028115828204841417610d9657610d96613d2d565b634e487b7160e01b5f52601260045260245ffd5b5f82613ecc57613ecc613eaa565b500490565b5f82613edf57613edf613eaa565b500690565b6020808252602c908201527f76616c696461746f725075626b6579732062797465206172726179206c656e6760408201526b1d1a081a5b98dbdc9c9958dd60a21b606082015260800190565b5f8085851115613f3e575f80fd5b83861115613f4a575f80fd5b5050820193919092039150565b6001600160801b038181168382160290811690818114613f7957613f79613d2d565b5092915050565b6001600160801b038281168282160390811115610d9657610d96613d2d565b6001600160801b038181168382160190811115610d9657610d96613d2d565b60208082526026908201527f506c6561736520436f6e74616374207374616b652e6478706f6f6c2e636f6d206040820152650e8de40ccd2f60d31b606082015260800190565b818382375f910190815291905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220df6c00e029d5b8912026e947e3b26571ccd1e039f71f7488d8ab80c2f314799864736f6c634300081a0033
Deployed Bytecode
0x608060405260043610610254575f3560e01c80636386c1c71161013f578063b5a13095116100b3578063e627f2db11610078578063e627f2db14610786578063eb2f385d1461079a578063ec9729cf146107a2578063fc4b0fb5146107b7578063fd8b916c146107cb578063ff7f6398146107ea575f80fd5b8063b5a13095146106c0578063bece2531146106d9578063d1d59fd0146106ee578063d5002f2e14610753578063dff10adb14610767575f80fd5b80639c9ba9de116101045780639c9ba9de146105fe578063a5166a6214610612578063a5c4125914610631578063ad0b13eb14610650578063ad3cb1cc1461066f578063b2d39634146106ac575f80fd5b80636386c1c7146104c857806369517310146105585780636951b9df146105775780637143bf7a1461059b5780638093dc3f146105ba575f80fd5b80633c901a55116101d65780634f1ef2861161019b5780634f1ef2861461040e57806352d1902d1461042157806357639d85146104355780635968571e146104495780635ad220481461045e57806360246c881461047d575f80fd5b80633c901a551461036d5780633e87399e1461039c57806340b0bb95146103bb578063485cc955146103d05780634b745b93146103ef575f80fd5b806326e5c4611161021c57806326e5c461146102f357806327f23c2b1461031257806333db92071461032757806336ec1fe81461032f578063379317051461034e575f80fd5b806306394c9b146102585780630a4613b414610279578063174e31c41461029857806319f344ba146102b75780631b2fd9c3146102cb575b5f80fd5b348015610263575f80fd5b506102776102723660046136ce565b610809565b005b348015610284575f80fd5b506102776102933660046136e9565b6108b4565b3480156102a3575f80fd5b506102776102b2366004613700565b610922565b3480156102c2575f80fd5b5061027761099d565b3480156102d6575f80fd5b506102e060035481565b6040519081526020015b60405180910390f35b3480156102fe575f80fd5b5061027761030d36600461376e565b610a46565b34801561031d575f80fd5b506102e060065481565b610277610b1c565b34801561033a575f80fd5b506102776103493660046137f5565b610b6a565b348015610359575f80fd5b506102e0610368366004613903565b610cd6565b348015610378575f80fd5b50610381610d9c565b604080519384526020840192909252908201526060016102ea565b3480156103a7575f80fd5b506102776103b636600461393c565b610dca565b3480156103c6575f80fd5b506102e060025481565b3480156103db575f80fd5b506102776103ea3660046139a6565b610f26565b3480156103fa575f80fd5b506102776104093660046139dd565b61109c565b61027761041c366004613a1b565b611209565b34801561042c575f80fd5b506102e0611224565b348015610440575f80fd5b506102e061123f565b348015610454575f80fd5b506102e0600f5481565b348015610469575f80fd5b50610277610478366004613700565b6112b5565b348015610488575f80fd5b50610491611467565b604080519788526020880196909652948601939093526060850191909152608084015260a0830152151560c082015260e0016102ea565b3480156104d3575f80fd5b506105306104e23660046136ce565b6001600160a01b03165f908152601160205260409020805460018201546002909201546001600160801b0380831694600160801b938490048216948281169490049091169163ffffffff1690565b604080519586526020860194909452928401919091526060830152608082015260a0016102ea565b348015610563575f80fd5b506103816105723660046136ce565b6114b5565b348015610582575f80fd5b5061058b611525565b60405190151581526020016102ea565b3480156105a6575f80fd5b506102776105b5366004613a67565b61153c565b3480156105c5575f80fd5b506105d96105d4366004613abf565b61160a565b6040805193151584526001600160401b039092166020840152908201526060016102ea565b348015610609575f80fd5b506102776116a0565b34801561061d575f80fd5b5061027761062c366004613af1565b6116e4565b34801561063c575f80fd5b5061027761064b3660046139dd565b611899565b34801561065b575f80fd5b5061027761066a366004613700565b611b54565b34801561067a575f80fd5b5061069f604051806040016040528060058152602001640352e302e360dc1b81525081565b6040516102ea9190613b25565b3480156106b7575f80fd5b50610277611bf4565b3480156106cb575f80fd5b5060075461058b9060ff1681565b3480156106e4575f80fd5b506102e0600e5481565b3480156106f9575f80fd5b506107206107083660046136e9565b9060a082901c6001600160401b03169060e083901c90565b604080516001600160a01b0390941684526001600160401b03909216602084015263ffffffff16908201526060016102ea565b34801561075e575f80fd5b506005546102e0565b348015610772575f80fd5b50610277610781366004613b5a565b611c99565b348015610791575f80fd5b506102e0611da6565b610277611de1565b3480156107ad575f80fd5b506102e060045481565b3480156107c2575f80fd5b50610277611e83565b3480156107d6575f80fd5b506102e06107e5366004613bf6565b611fcd565b3480156107f5575f80fd5b50610277610804366004613b5a565b612002565b6108116122ad565b5f546001600160a01b031633146108435760405162461bcd60e51b815260040161083a90613c51565b60405180910390fd5b6001600160a01b038116610855575f80fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040519081527f4721129e0e676ed6a92909bb24e853ccdd63ad72280cc2e974e38e480e0e6e54906020015b60405180910390a16108b16001601055565b50565b6108bc6122ad565b5f546001600160a01b031633146108e55760405162461bcd60e51b815260040161083a90613c51565b6108ed6122d7565b60068190556040518181527f06bd4ba843bc678397fc73783e3a42479424b41319e584574f445770d303803e9060200161089f565b61092a6122ad565b60075460ff1661097c5760405162461bcd60e51b815260206004820152601f60248201527f506f6f6c206973206e6f74206f70656e20666f72207769746864726177616c00604482015260640161083a565b6109846122d7565b61098f3383836123c5565b6109996001601055565b5050565b6109a56122ad565b5f546001600160a01b031633146109ce5760405162461bcd60e51b815260040161083a90613c51565b60075460ff1615610a2d5760405162461bcd60e51b815260206004820152602360248201527f506f6f6c20697320616c7265616479206f70656e20666f7220776974686472616044820152621dd85b60ea1b606482015260840161083a565b6007805460ff19166001179055610a446001601055565b565b610a4e6122ad565b6001546001600160a01b03163314610a785760405162461bcd60e51b815260040161083a90613c92565b5f610ab784848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b9050610ac16122d7565b5f610acc82846126ca565b90507f07cd33a03f4973ff12a258610683c0eeae6c92a52e2914a07e333bc5b8db41b085858342604051610b039493929190613cfe565b60405180910390a15050610b176001601055565b505050565b610b246122ad565b5f546001600160a01b03163314610b4d5760405162461bcd60e51b815260040161083a90613c51565b34600e5f828254610b5e9190613d41565b90915550506001601055565b610b726122ad565b5f546001600160a01b03163314610b9b5760405162461bcd60e51b815260040161083a90613c51565b81841480610ba95750600182145b610bf55760405162461bcd60e51b815260206004820181905260248201527f776974686472617741646472657373206c656e67746820696e636f7272656374604482015260640161083a565b610bfd6122d7565b6001829003610c75575f5b84811015610c6f57610c67868683818110610c2557610c25613d54565b9050602002016020810190610c3a91906136ce565b85855f818110610c4c57610c4c613d54565b9050602002016020810190610c6191906136ce565b846123c5565b600101610c08565b50610cc5565b5f5b84811015610cc357610cbb868683818110610c9457610c94613d54565b9050602002016020810190610ca991906136ce565b858584818110610c4c57610c4c613d54565b600101610c77565b505b610ccf6001601055565b5050505050565b5f8151603014610d285760405162461bcd60e51b815260206004820152601760248201527f7075626b6579206d757374206265203438206279746573000000000000000000604482015260640161083a565b604051600290610d3e9084905f90602001613d7f565b60408051601f1981840301815290829052610d5891613da3565b602060405180830381855afa158015610d73573d5f803e3d5ffd5b5050506040513d601f19601f82011682018060405250810190610d969190613dae565b92915050565b5f805f80610da861123f565b90505f60025482610db99190613dc5565b600254929690955091935090915050565b610dd26122ad565b6001546001600160a01b03163314610dfc5760405162461bcd60e51b815260040161083a90613c92565b828114610e4b5760405162461bcd60e51b815260206004820152601f60248201527f56616c696461746f72206172726179206c656e677468206d69736d6174636800604482015260640161083a565b610e536122d7565b5f5b63ffffffff8116841115610f15575f610eca86868463ffffffff16818110610e7f57610e7f613d54565b9050602002810190610e919190613dd8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b9050610f028185858563ffffffff16818110610ee857610ee8613d54565b9050602002016020810190610efd9190613e1a565b612835565b5080610f0d81613e40565b915050610e55565b50610f206001601055565b50505050565b5f610f2f612a48565b805490915060ff600160401b82041615906001600160401b03165f81158015610f555750825b90505f826001600160401b03166001148015610f705750303b155b905081158015610f7e575080155b15610f9c5760405163f92ee8a960e01b815260040160405180910390fd5b845467ffffffffffffffff191660011785558315610fc657845460ff60401b1916600160401b1785555b6001600160a01b038716610fd8575f80fd5b6001600160a01b038616610fea575f80fd5b5f80546001600160a01b038089166001600160a01b031992831617835560018054918b1691909216178155600582905560068290556007805460ff19169091179055600a819055600b8190556004819055600e5543600c5561104a611da6565b600d55831561109357845460ff60401b19168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50505050505050565b6110a46122ad565b6001546001600160a01b031633146110ce5760405162461bcd60e51b815260040161083a90613c92565b5f5b818110156111fe575f8383838181106110eb576110eb613d54565b90506020028101906110fd9190613dd8565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201829052506040519495509384935061117192506009915061114a908690613da3565b9081526020016040518091039020549060a082901c6001600160401b03169060e083901c90565b919350909150506001600160a01b03821661119e5760405162461bcd60e51b815260040161083a90613e64565b5f6111a884610cd6565b90506111ba8364077359400084611fcd565b5f828152601260205260409081902091909155516009906111dc908690613da3565b90815260200160405180910390205f90555050505080806001019150506110d0565b506109996001601055565b611211612a70565b61121a82612b14565b6109998282612b3d565b5f61122d612bf9565b505f8051602061401483398151915290565b5f80611249611da6565b90506904ee2d6d415b85acef8160201b612710600654600d548461126d9190613dc5565b611284906904ee2d6d415b85acef8160201b613e93565b61128e9190613e93565b6112989190613ebe565b600b546112a59190613d41565b6112af9190613ebe565b91505090565b6112bd6122ad565b5f546001600160a01b031633146112e65760405162461bcd60e51b815260040161083a90613c51565b6112ee6122d7565b5f6904ee2d6d415b85acef8160201b600b5461130a9190613ebe565b90505f6002548261131b9190613dc5565b9050825f03611394578060025f8282546113359190613d41565b9091555050604080516001600160a01b0386168152602081018390527f8e14daa5332205b1634040e1054e93d1f5396ec8bf0115d133b7fbaf4a52e411910160405180910390a161138f6001600160a01b03851682612c42565b61145b565b808311156113f05760405162461bcd60e51b815260206004820152602360248201527f4e6f7420656e6f75676820756e636c61696d656420636f6d6d697373696f6e2060448201526266656560e81b606482015260840161083a565b8260025f8282546114019190613d41565b9091555050604080516001600160a01b0386168152602081018590527f8e14daa5332205b1634040e1054e93d1f5396ec8bf0115d133b7fbaf4a52e411910160405180910390a161145b6001600160a01b03851684612c42565b50506109996001601055565b5f805f805f805f600c546904ee2d6d415b85acef8160201b600a5461148c9190613ebe565b600554600254600354600454600754959d949c50929a509098509650945060ff90911692509050565b5f80806001600160a01b03841661150e5760405162461bcd60e51b815260206004820152601d60248201527f6465706f7369746f7241646472657373206e6f7420626520656d707479000000604482015260640161083a565b61151784612cce565b9250925092505b9193909250565b5f600f54600e54106115375750600190565b505f90565b6115446122ad565b6001546001600160a01b0316331461156e5760405162461bcd60e51b815260040161083a90613c92565b5f6115ad85858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b90506115b76122d7565b6115c2818484612ea9565b7f8aa859c9608ae3b4a15372294daf4207f79c797c0842a494e4597bf0fd07876b858585426040516115f79493929190613cfe565b60405180910390a150610f206001601055565b5f805f8061164c86868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b5f8181526012602052604081205491925003611671575f805f93509350935050611699565b5f908152601260205260409020546001935060a081901c6001600160401b0316925060e01c90505b9250925092565b6116a86122ad565b6001546001600160a01b031633146116d25760405162461bcd60e51b815260040161083a90613c92565b6116da6122d7565b610a446001601055565b6116ec6122ad565b6001546001600160a01b031633146117165760405162461bcd60e51b815260040161083a90613c92565b611721603084613ed1565b1561177c5760405162461bcd60e51b815260206004820152602560248201527f7075624b65794172726179206c656e677468206e6f74206d756c7469706c65206044820152640decc4068760db1b606482015260840161083a565b5f611788603085613ebe565b90508181146117a95760405162461bcd60e51b815260040161083a90613ee4565b6117b16122d7565b5f5b8181101561188d575f6117f087876117cc856030613e93565b906117d8866001613d41565b6117e3906030613e93565b92610e9193929190613f30565b90505f6118158287878681811061180957611809613d54565b905060200201356126ca565b90507f07cd33a03f4973ff12a258610683c0eeae6c92a52e2914a07e333bc5b8db41b08888611845866030613e93565b90611851876001613d41565b61185c906030613e93565b9261186993929190613f30565b834260405161187b9493929190613cfe565b60405180910390a150506001016117b3565b5050610f206001601055565b6118a16122ad565b6001546001600160a01b031633146118cb5760405162461bcd60e51b815260040161083a90613c92565b5f5b818110156111fe575f8383838181106118e8576118e8613d54565b90506020020160208101906118fd91906136ce565b6001600160a01b0381165f908152600860205260409020549091506001600160801b031615158061195457506001600160a01b0381165f90815260086020526040902054600160801b90046001600160801b031615155b8061198157506001600160a01b0381165f908152600860205260409020600101546001600160801b031615155b806119b557506001600160a01b0381165f90815260086020526040902060010154600160801b90046001600160801b031615155b6119f75760405162461bcd60e51b8152602060048201526013602482015272155cd95c88191bd95cc81b9bdd08195e1a5cdd606a1b604482015260640161083a565b6001600160a01b0381165f9081526008602090815260408083208054601190935290832080546001600160801b039384166001600160801b0319918216811783558354600160801b9081900486168102808317855560019586018054968601805497891697909516871785555482900487169091029094179091556002909101805463ffffffff19164263ffffffff161790556005805492909316179290611aa0908490613dc5565b90915550506001600160a01b0381165f90815260116020526040812080546407735940009290611ada9084906001600160801b0316613f57565b82546101009290920a6001600160801b038181021990931691831602179091556001600160a01b0383165f9081526011602052604081205460058054919093169350611b27908490613d41565b90915550506001600160a01b03165f908152600860205260408120818155600190810191909155016118cd565b611b5c6122ad565b5f546001600160a01b03163314611b855760405162461bcd60e51b815260040161083a90613c51565b47811115611bca5760405162461bcd60e51b81526020600482015260126024820152714e6f7420656e6f7567682062616c616e636560701b604482015260640161083a565b8060045f828254611bdb9190613d41565b9091555061098f90506001600160a01b03831682612c42565b611bfc6122ad565b5f546001600160a01b03163314611c255760405162461bcd60e51b815260040161083a90613c51565b60075460ff16611c855760405162461bcd60e51b815260206004820152602560248201527f506f6f6c20697320616c726561647920636c6f73656420666f722077697468646044820152641c985dd85b60da1b606482015260840161083a565b6007805460ff19169055610a446001601055565b611ca16122ad565b5f546001600160a01b03163314611cca5760405162461bcd60e51b815260040161083a90613c51565b611cd5836030613e93565b85148015611cec5750611ce9816030613e93565b85145b611d085760405162461bcd60e51b815260040161083a90613ee4565b5f5b83811015611d9357611d8b8787611d22846030613e93565b90611d2e856001613d41565b611d39906030613e93565b92611d4693929190613f30565b878785818110611d5857611d58613d54565b9050602002016020810190611d6d91906136ce565b868686818110611d7f57611d7f613d54565b90506020020135613111565b600101611d0a565b50611d9e6001601055565b505050505050565b5f600e5460025460035460045447611dbe9190613d41565b611dc89190613d41565b611dd29190613d41565b611ddc9190613dc5565b905090565b611de96122ad565b5f546001600160a01b03163314611e125760405162461bcd60e51b815260040161083a90613c51565b600454341115611e725760405162461bcd60e51b815260206004820152602560248201527f546f6f206d756368207472616e736665727265642066726f6d20636f6c642077604482015264185b1b195d60da1b606482015260840161083a565b3460045f828254610b5e9190613dc5565b5f546001600160a01b03163314611eac5760405162461bcd60e51b815260040161083a90613c51565b60025f611eb7612a48565b8054909150600160401b900460ff1680611ede575080546001600160401b03808416911610155b15611efc5760405163f92ee8a960e01b815260040160405180910390fd5b805468ffffffffffffffffff19166001600160401b03831617600160401b178155600a80546a52b7d2dcc80cd2e400000091905f90611f3c908490613e93565b9091555050600a805464077359400091905f90611f5a908490613ebe565b925050819055506a52b7d2dcc80cd2e4000000600b5f828254611f7d9190613e93565b9091555050805460ff60401b191681556040516001600160401b03831681527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15050565b6001600160a01b03831667ffffffffffffffff60a01b60a084901b16176001600160e01b031960e083901b16175b9392505050565b61200a6122ad565b6001546001600160a01b031633146120345760405162461bcd60e51b815260040161083a90613c92565b600183148061204c57508461204a846030613e93565b145b6120a25760405162461bcd60e51b815260206004820152602160248201527f496e76616c6964206465706f7369746f72416464726573736573206c656e67746044820152600d60fb1b606482015260840161083a565b6120aa6122d7565b5f6120b6603087613ebe565b90505f60018590036121d3575f5b828110156121cd576120e889896120dc846030613e93565b906117d8856001613d41565b91506121338288885f81811061210057612100613d54565b905060200201602081019061211591906136ce565b87878581811061212757612127613d54565b90506020020135612ea9565b7f8aa859c9608ae3b4a15372294daf4207f79c797c0842a494e4597bf0fd07876b8989612161846030613e93565b9061216d856001613d41565b612178906030613e93565b9261218593929190613f30565b89895f81811061219757612197613d54565b90506020020160208101906121ac91906136ce565b426040516121bd9493929190613cfe565b60405180910390a16001016120c4565b506122a1565b5f5b8281101561229f576121ed89896120dc846030613e93565b91506122058288888481811061210057612100613d54565b7f8aa859c9608ae3b4a15372294daf4207f79c797c0842a494e4597bf0fd07876b8989612233846030613e93565b9061223f856001613d41565b61224a906030613e93565b9261225793929190613f30565b89898581811061226957612269613d54565b905060200201602081019061227e91906136ce565b4260405161228f9493929190613cfe565b60405180910390a16001016121d5565b505b5050611d9e6001601055565b6002601054036122d057604051633ee5aeb560e01b815260040160405180910390fd5b6002601055565b600c54431115806122e85750600554155b156122ef57565b5f6122f8611da6565b905061271060065461271061230d9190613dc5565b600554600d5461231d9085613dc5565b612334906904ee2d6d415b85acef8160201b613e93565b61233e9190613ebe565b6123489190613e93565b6123529190613ebe565b600a5f8282546123629190613d41565b9091555050600654600d54612710919061237c9084613dc5565b612393906904ee2d6d415b85acef8160201b613e93565b61239d9190613e93565b6123a79190613ebe565b600b5f8282546123b79190613d41565b909155505043600c55600d55565b6001600160a01b0382166123d7578291505b6123e0836132ef565b600a546001600160a01b0384165f908152601160205260409020546904ee2d6d415b85acef8160201b9161241c916001600160801b0316613e93565b6124269190613ebe565b6001600160a01b0384165f9081526011602052604081206001810180546001600160801b0319166001600160801b0394851617908190559054919261247992600160801b92839004821692900416613f80565b6001600160801b03169050815f03612585576001600160a01b0384165f90815260116020526040902060010180548291906010906124c8908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508060035f8282546124fd9190613d41565b9091555050604080516001600160a01b038087168252851660208201529081018290527f4c3c95bc264760245b1b3c69c79fca66e06b23442e5cebcc374f48467c9b984f9060600160405180910390a14781111561256d5760405162461bcd60e51b815260040161083a90613fbe565b6125806001600160a01b03841682612c42565b610f20565b808211156125d55760405162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f75676820756e436c61696d6564207265776172647300000000604482015260640161083a565b6001600160a01b0384165f9081526011602052604090206001018054839190601090612612908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508160035f8282546126479190613d41565b9091555050604080516001600160a01b038087168252851660208201529081018390527f4c3c95bc264760245b1b3c69c79fca66e06b23442e5cebcc374f48467c9b984f9060600160405180910390a1478211156126b75760405162461bcd60e51b815260040161083a90613fbe565b610f206001600160a01b03841683612c42565b5f8281526012602052604081205460a081901c6001600160401b03166001600160a01b03821661270c5760405162461bcd60e51b815260040161083a90613e64565b61271682856133d2565b806001600160401b031660055f8282546127309190613dc5565b9250508190555083600f5f8282546127489190613d41565b90915550506001600160a01b0382165f90815260116020526040812080546001600160401b03841692906127869084906001600160801b0316613f80565b82546101009290920a6001600160801b03818102199093169183160217909155600a546001600160a01b0385165f908152601160205260409020546904ee2d6d415b85acef8160201b93506127db9216613e93565b6127e59190613ebe565b6001600160a01b0383165f90815260116020908152604080832060010180546001600160801b0319166001600160801b039590951694909417909355878252601290529081205550905092915050565b5f8281526012602052604090205460a081901c6001600160401b031660e082901c6001600160a01b0383166128a45760405162461bcd60e51b8152602060048201526015602482015274141d5892d95e48191bd95cc81b9bdd08195e1a5cdd605a1b604482015260640161083a565b640773594000846001600160801b0316101580156128d157506501dcd6500000846001600160801b031611155b61291d5760405162461bcd60e51b815260206004820152601960248201527f496e76616c6964206566666563746976652062616c616e636500000000000000604482015260640161083a565b612928838583611fcd565b5f8681526012602052604090205561293f836132ef565b836001600160801b0316826001600160401b03166005546129609190613dc5565b61296a9190613d41565b6005556001600160a01b0383165f9081526011602052604090205484906129a4906001600160401b038516906001600160801b0316613f80565b6129ae9190613f9f565b6001600160a01b0384165f90815260116020526040902080546001600160801b0319166001600160801b03929092169182179055600a546904ee2d6d415b85acef8160201b916129fe9190613e93565b612a089190613ebe565b6001600160a01b03939093165f90815260116020526040902060010180546001600160801b0319166001600160801b039094169390931790925550505050565b5f807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610d96565b306001600160a01b037f00000000000000000000000052ef4e0f4cb45ee8111a3f6255f8915e6e684ebd161480612af657507f00000000000000000000000052ef4e0f4cb45ee8111a3f6255f8915e6e684ebd6001600160a01b0316612aea5f80516020614014833981519152546001600160a01b031690565b6001600160a01b031614155b15610a445760405163703e46dd60e11b815260040160405180910390fd5b5f546001600160a01b031633146108b15760405162461bcd60e51b815260040161083a90613c51565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612b97575060408051601f3d908101601f19168201909252612b9491810190613dae565b60015b612bbf57604051634c9c8ce360e01b81526001600160a01b038316600482015260240161083a565b5f805160206140148339815191528114612bef57604051632a87526960e21b81526004810182905260240161083a565b610b1783836134ec565b306001600160a01b037f00000000000000000000000052ef4e0f4cb45ee8111a3f6255f8915e6e684ebd1614610a445760405163703e46dd60e11b815260040160405180910390fd5b80471015612c6c5760405163cf47918160e01b81524760048201526024810182905260440161083a565b5f80836001600160a01b0316836040515f6040518083038185875af1925050503d805f8114612cb6576040519150601f19603f3d011682016040523d82523d5f602084013e612cbb565b606091505b509150915081610f2057610f2081613541565b5f805f80600a549050600c5443118015612ce957505f600554115b15612d5f575f612cf7611da6565b9050612710600654612710612d0c9190613dc5565b600554600d54612d1c9085613dc5565b612d33906904ee2d6d415b85acef8160201b613e93565b612d3d9190613ebe565b612d479190613e93565b612d519190613ebe565b612d5b9083613d41565b9150505b6001600160a01b0385165f908152601160205260408120600181015490546001600160801b0391821691600160801b82048116916904ee2d6d415b85acef8160201b91612dae91879116613e93565b612db89190613ebe565b612dc29190613d41565b612dcc9190613dc5565b6001600160a01b0387165f90815260116020526040902060010154909150600160801b90046001600160801b0316811115612e72576001600160a01b0386165f908152601160205260409020600101548190612e3890600160801b90046001600160801b031682613dc5565b6001600160a01b0388165f908152601160205260409020600101549196509450600160801b90046001600160801b0316925061151e915050565b505050506001600160a01b0382165f90815260116020526040812060010154600160801b90046001600160801b031691508161151e565b5f8381526012602052604090205415612f045760405162461bcd60e51b815260206004820152601960248201527f76616c696461746f7220616c726561647920696e20706f6f6c00000000000000604482015260640161083a565b6001600160a01b038216612f5a5760405162461bcd60e51b815260206004820152601d60248201527f6465706f7369746f7241646472657373206e6f7420626520656d707479000000604482015260640161083a565b6407735940008110158015612f7557506501dcd65000008111155b612fdd5760405162461bcd60e51b815260206004820152603360248201527f4566666563746976652062616c616e6365206d75737420626520626574776565604482015272371019991030b7321019181a1c1032ba3432b960691b606482015260840161083a565b612fe6826132ef565b6001600160a01b0382165f90815260116020526040812080546001600160401b038416929061301f9084906001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b031602179055508060055f8282546130549190613d41565b909155506130659050828242611fcd565b5f84815260126020908152604080832093909355600a546001600160a01b03861683526011909152919020546904ee2d6d415b85acef8160201b916130b2916001600160801b0316613e93565b6130bc9190613ebe565b6001600160a01b03929092165f9081526011602052604090206001810180546001600160801b0319166001600160801b039094169390931790925550600201805463ffffffff19164263ffffffff1617905550565b5f61315085858080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250610cd692505050565b5f8181526012602052604090205490915060a081901c6001600160401b03166001600160a01b0382166131955760405162461bcd60e51b815260040161083a90613e64565b6001600160a01b0385166131f55760405162461bcd60e51b815260206004820152602160248201527f746f2061646472657373206d7573742062652073657420746f206e6f6e7a65726044820152606f60f81b606482015260840161083a565b816001600160a01b0316856001600160a01b0316036132695760405162461bcd60e51b815260206004820152602a60248201527f63616e6e6f74207472616e736665722076616c696461746f72206f776e6572206044820152693a379037b732b9b2b63360b11b606482015260840161083a565b61327383856126ca565b506132888386836001600160401b0316612ea9565b846001600160a01b0316826001600160a01b031688886040516132ac929190614004565b604051908190038120428252907fae24802f5dcf9eb23697e34d9f536295d24fc5a2684ed27559aa35ae878138269060200160405180910390a450505050505050565b6001600160a01b0381165f908152601160205260409020546001600160801b03168015610999576001600160a01b0382165f90815260116020526040812060010154600a546001600160801b03909116906904ee2d6d415b85acef8160201b906133599085613e93565b6133639190613ebe565b61336d9190613dc5565b6001600160a01b0384165f908152601160205260409020805491925082916010906133a9908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505050565b6001600160a01b0382165f908152601160205260409020546001600160801b031680156134b2576001600160a01b0383165f90815260116020526040812060010154600a546001600160801b03909116906904ee2d6d415b85acef8160201b9061343c9085613e93565b6134469190613ebe565b6134509190613dc5565b6001600160a01b0385165f9081526011602052604090208054919250829160109061348c908490600160801b90046001600160801b0316613f9f565b92506101000a8154816001600160801b0302191690836001600160801b03160217905550505b6001600160a01b0383165f90815260116020526040902080548391906010906133a9908490600160801b90046001600160801b0316613f9f565b6134f58261356a565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a280511561353957610b1782826135cd565b61099961363f565b8051156135515780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b806001600160a01b03163b5f0361359f57604051634c9c8ce360e01b81526001600160a01b038216600482015260240161083a565b5f8051602061401483398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b60605f80846001600160a01b0316846040516135e99190613da3565b5f60405180830381855af49150503d805f8114613621576040519150601f19603f3d011682016040523d82523d5f602084013e613626565b606091505b509150915061363685838361365e565b95945050505050565b3415610a445760405163b398979f60e01b815260040160405180910390fd5b6060826136735761366e82613541565b611ffb565b815115801561368a57506001600160a01b0384163b155b156136b357604051639996b31560e01b81526001600160a01b038516600482015260240161083a565b5080611ffb565b6001600160a01b03811681146108b1575f80fd5b5f602082840312156136de575f80fd5b8135611ffb816136ba565b5f602082840312156136f9575f80fd5b5035919050565b5f8060408385031215613711575f80fd5b823561371c816136ba565b946020939093013593505050565b5f8083601f84011261373a575f80fd5b5081356001600160401b03811115613750575f80fd5b602083019150836020828501011115613767575f80fd5b9250929050565b5f805f60408486031215613780575f80fd5b83356001600160401b03811115613795575f80fd5b6137a18682870161372a565b909790965060209590950135949350505050565b5f8083601f8401126137c5575f80fd5b5081356001600160401b038111156137db575f80fd5b6020830191508360208260051b8501011115613767575f80fd5b5f805f805f60608688031215613809575f80fd5b85356001600160401b0381111561381e575f80fd5b61382a888289016137b5565b90965094505060208601356001600160401b03811115613848575f80fd5b613854888289016137b5565b96999598509660400135949350505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112613889575f80fd5b81356001600160401b038111156138a2576138a2613866565b604051601f8201601f19908116603f011681016001600160401b03811182821017156138d0576138d0613866565b6040528181528382016020018510156138e7575f80fd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215613913575f80fd5b81356001600160401b03811115613928575f80fd5b6139348482850161387a565b949350505050565b5f805f806040858703121561394f575f80fd5b84356001600160401b03811115613964575f80fd5b613970878288016137b5565b90955093505060208501356001600160401b0381111561398e575f80fd5b61399a878288016137b5565b95989497509550505050565b5f80604083850312156139b7575f80fd5b82356139c2816136ba565b915060208301356139d2816136ba565b809150509250929050565b5f80602083850312156139ee575f80fd5b82356001600160401b03811115613a03575f80fd5b613a0f858286016137b5565b90969095509350505050565b5f8060408385031215613a2c575f80fd5b8235613a37816136ba565b915060208301356001600160401b03811115613a51575f80fd5b613a5d8582860161387a565b9150509250929050565b5f805f8060608587031215613a7a575f80fd5b84356001600160401b03811115613a8f575f80fd5b613a9b8782880161372a565b9095509350506020850135613aaf816136ba565b9396929550929360400135925050565b5f8060208385031215613ad0575f80fd5b82356001600160401b03811115613ae5575f80fd5b613a0f8582860161372a565b5f805f8060408587031215613b04575f80fd5b84356001600160401b03811115613b19575f80fd5b6139708782880161372a565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f805f805f8060608789031215613b6f575f80fd5b86356001600160401b03811115613b84575f80fd5b613b9089828a0161372a565b90975095505060208701356001600160401b03811115613bae575f80fd5b613bba89828a016137b5565b90955093505060408701356001600160401b03811115613bd8575f80fd5b613be489828a016137b5565b979a9699509497509295939492505050565b5f805f60608486031215613c08575f80fd5b8335613c13816136ba565b925060208401356001600160401b0381168114613c2e575f80fd5b9150604084013563ffffffff81168114613c46575f80fd5b809150509250925092565b60208082526021908201527f4f6e6c79204478706f6f6c207374616b696e672061646d696e20616c6c6f77656040820152601960fa1b606082015260800190565b60208082526024908201527f4f6e6c79204478706f6f6c207374616b696e67206f70657261746f7220616c6c6040820152631bddd95960e21b606082015260800190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b606081525f613d11606083018688613cd6565b6001600160a01b03949094166020830152506040015292915050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610d9657610d96613d2d565b634e487b7160e01b5f52603260045260245ffd5b5f81518060208401855e5f93019283525090919050565b5f613d8a8285613d68565b6001600160801b03199390931683525050601001919050565b5f611ffb8284613d68565b5f60208284031215613dbe575f80fd5b5051919050565b81810381811115610d9657610d96613d2d565b5f808335601e19843603018112613ded575f80fd5b8301803591506001600160401b03821115613e06575f80fd5b602001915036819003821315613767575f80fd5b5f60208284031215613e2a575f80fd5b81356001600160801b0381168114611ffb575f80fd5b5f63ffffffff821663ffffffff8103613e5b57613e5b613d2d565b60010192915050565b60208082526015908201527415985b1a59185d1bdc881b9bdd081a5b881c1bdbdb605a1b604082015260600190565b8082028115828204841417610d9657610d96613d2d565b634e487b7160e01b5f52601260045260245ffd5b5f82613ecc57613ecc613eaa565b500490565b5f82613edf57613edf613eaa565b500690565b6020808252602c908201527f76616c696461746f725075626b6579732062797465206172726179206c656e6760408201526b1d1a081a5b98dbdc9c9958dd60a21b606082015260800190565b5f8085851115613f3e575f80fd5b83861115613f4a575f80fd5b5050820193919092039150565b6001600160801b038181168382160290811690818114613f7957613f79613d2d565b5092915050565b6001600160801b038281168282160390811115610d9657610d96613d2d565b6001600160801b038181168382160190811115610d9657610d96613d2d565b60208082526026908201527f506c6561736520436f6e74616374207374616b652e6478706f6f6c2e636f6d206040820152650e8de40ccd2f60d31b606082015260800190565b818382375f910190815291905056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca2646970667358221220df6c00e029d5b8912026e947e3b26571ccd1e039f71f7488d8ab80c2f314799864736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.