Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 14010805 | 1530 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
StakefishServicesContract
Compiler Version
v0.8.4+commit.c7e474f2
Optimization Enabled:
Yes with 100000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// Copyright (C) 2021 BITFISH LIMITED
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity 0.8.4;
import "./interfaces/deposit_contract.sol";
import "./interfaces/IStakefishServicesContract.sol";
import "./libraries/Address.sol";
contract StakefishServicesContract is IStakefishServicesContract {
using Address for address payable;
uint256 private constant HOUR = 3600;
uint256 private constant DAY = 24 * HOUR;
uint256 private constant WEEK = 7 * DAY;
uint256 private constant YEAR = 365 * DAY;
uint256 private constant MAX_SECONDS_IN_EXIT_QUEUE = 1 * YEAR;
uint256 private constant COMMISSION_RATE_SCALE = 1000000;
// Packed into a single slot
uint24 private _commissionRate;
address private _operatorAddress;
uint64 private _exitDate;
State private _state;
bytes32 private _operatorDataCommitment;
mapping(address => mapping(address => uint256)) private _allowances;
mapping(address => mapping(address => uint256)) private _allowedWithdrawals;
mapping(address => uint256) private _deposits;
uint256 private _totalDeposits;
uint256 private _operatorClaimable;
IDepositContract public constant depositContract =
IDepositContract(0x00000000219ab540356cBB839Cbe05303d7705Fa);
modifier onlyOperator() {
require(
msg.sender == _operatorAddress,
"Caller is not the operator"
);
_;
}
modifier initializer() {
require(
_state == State.NotInitialized,
"Contract is already initialized"
);
_state = State.PreDeposit;
_;
}
function initialize(
uint24 commissionRate,
address operatorAddress,
bytes32 operatorDataCommitment
)
external
initializer
{
require(uint256(commissionRate) <= COMMISSION_RATE_SCALE, "Commission rate exceeds scale");
_commissionRate = commissionRate;
_operatorAddress = operatorAddress;
_operatorDataCommitment = operatorDataCommitment;
}
receive() payable external {
if (_state == State.PreDeposit) {
revert("Plain Ether transfer not allowed");
}
}
function updateExitDate(uint64 newExitDate)
external
override
onlyOperator
{
require(
_state == State.PostDeposit,
"Validator is not active"
);
require(
newExitDate < _exitDate,
"Not earlier than the original value"
);
_exitDate = newExitDate;
}
function createValidator(
bytes calldata validatorPubKey, // 48 bytes
bytes calldata depositSignature, // 96 bytes
bytes32 depositDataRoot,
uint64 exitDate
)
external
override
onlyOperator
{
require(_state == State.PreDeposit, "Validator has been created");
_state = State.PostDeposit;
require(validatorPubKey.length == 48, "Invalid validator public key");
require(depositSignature.length == 96, "Invalid deposit signature");
require(_operatorDataCommitment == keccak256(
abi.encodePacked(
address(this),
validatorPubKey,
depositSignature,
depositDataRoot,
exitDate
)
), "Data doesn't match commitment");
_exitDate = exitDate;
depositContract.deposit{value: 32 ether}(
validatorPubKey,
abi.encodePacked(uint96(0x010000000000000000000000), address(this)),
depositSignature,
depositDataRoot
);
emit ValidatorDeposited(validatorPubKey);
}
function deposit()
external
payable
override
returns (uint256 surplus)
{
require(
_state == State.PreDeposit,
"Validator already created"
);
return _handleDeposit(msg.sender);
}
function depositOnBehalfOf(address depositor)
external
payable
override
returns (uint256 surplus)
{
require(
_state == State.PreDeposit,
"Validator already created"
);
return _handleDeposit(depositor);
}
function endOperatorServices()
external
override
{
uint256 balance = address(this).balance;
require(balance > 0, "Can't end with 0 balance");
require(_state == State.PostDeposit, "Not allowed in the current state");
require((msg.sender == _operatorAddress && block.timestamp > _exitDate) ||
(_deposits[msg.sender] > 0 && block.timestamp > _exitDate + MAX_SECONDS_IN_EXIT_QUEUE), "Not allowed at the current time");
_state = State.Withdrawn;
if (balance > 32 ether) {
uint256 profit = balance - 32 ether;
uint256 finalCommission = profit * _commissionRate / COMMISSION_RATE_SCALE;
_operatorClaimable += finalCommission;
}
emit ServiceEnd();
}
function operatorClaim()
external
override
onlyOperator
returns (uint256)
{
uint256 claimable = _operatorClaimable;
if (claimable > 0) {
_operatorClaimable = 0;
payable(_operatorAddress).sendValue(claimable);
emit Claim(_operatorAddress, claimable);
}
return claimable;
}
string private constant WITHDRAWALS_NOT_ALLOWED =
"Not allowed when validator is active";
function withdrawAll(uint256 minimumETHAmount)
external
override
returns (uint256)
{
require(_state != State.PostDeposit, WITHDRAWALS_NOT_ALLOWED);
uint256 value = _executeWithdrawal(msg.sender, payable(msg.sender), _deposits[msg.sender]);
require(value >= minimumETHAmount, "Less than minimum amount");
return value;
}
function withdraw(
uint256 amount,
uint256 minimumETHAmount
)
external
override
returns (uint256)
{
require(_state != State.PostDeposit, WITHDRAWALS_NOT_ALLOWED);
uint256 value = _executeWithdrawal(msg.sender, payable(msg.sender), amount);
require(value >= minimumETHAmount, "Less than minimum amount");
return value;
}
function withdrawTo(
uint256 amount,
address payable beneficiary,
uint256 minimumETHAmount
)
external
override
returns (uint256)
{
require(_state != State.PostDeposit, WITHDRAWALS_NOT_ALLOWED);
uint256 value = _executeWithdrawal(msg.sender, beneficiary, amount);
require(value >= minimumETHAmount, "Less than minimum amount");
return value;
}
function approve(
address spender,
uint256 amount
)
public
override
returns (bool)
{
_approve(msg.sender, spender, amount);
return true;
}
function increaseAllowance(
address spender,
uint256 addedValue
)
external
override
returns (bool)
{
_approve(msg.sender, spender, _allowances[msg.sender][spender] + addedValue);
return true;
}
function decreaseAllowance(
address spender,
uint256 subtractedValue
)
external
override
returns (bool)
{
_approve(msg.sender, spender, _allowances[msg.sender][spender] - subtractedValue);
return true;
}
function forceDecreaseAllowance(
address spender,
uint256 subtractedValue
)
external
override
returns (bool)
{
uint256 currentAllowance = _allowances[msg.sender][spender];
_approve(msg.sender, spender, currentAllowance - _min(subtractedValue, currentAllowance));
return true;
}
function approveWithdrawal(
address spender,
uint256 amount
)
external
override
returns (bool)
{
_approveWithdrawal(msg.sender, spender, amount);
return true;
}
function increaseWithdrawalAllowance(
address spender,
uint256 addedValue
)
external
override
returns (bool)
{
_approveWithdrawal(msg.sender, spender, _allowedWithdrawals[msg.sender][spender] + addedValue);
return true;
}
function decreaseWithdrawalAllowance(
address spender,
uint256 subtractedValue
)
external
override
returns (bool)
{
_approveWithdrawal(msg.sender, spender, _allowedWithdrawals[msg.sender][spender] - subtractedValue);
return true;
}
function forceDecreaseWithdrawalAllowance(
address spender,
uint256 subtractedValue
)
external
override
returns (bool)
{
uint256 currentAllowance = _allowedWithdrawals[msg.sender][spender];
_approveWithdrawal(msg.sender, spender, currentAllowance - _min(subtractedValue, currentAllowance));
return true;
}
function withdrawFrom(
address depositor,
address payable beneficiary,
uint256 amount,
uint256 minimumETHAmount
)
external
override
returns (uint256)
{
require(_state != State.PostDeposit, WITHDRAWALS_NOT_ALLOWED);
uint256 spenderAllowance = _allowedWithdrawals[depositor][msg.sender];
uint256 newAllowance = spenderAllowance - amount;
// Please note that there is no need to require(_deposit <= spenderAllowance)
// here because modern versions of Solidity insert underflow checks
_allowedWithdrawals[depositor][msg.sender] = newAllowance;
emit WithdrawalApproval(depositor, msg.sender, newAllowance);
uint256 value = _executeWithdrawal(depositor, beneficiary, amount);
require(value >= minimumETHAmount, "Less than minimum amount");
return value;
}
function transferDeposit(
address to,
uint256 amount
)
external
override
returns (bool)
{
_transfer(msg.sender, to, amount);
return true;
}
function transferDepositFrom(
address from,
address to,
uint256 amount
)
external
override
returns (bool)
{
uint256 currentAllowance = _allowances[from][msg.sender];
_approve(from, msg.sender, currentAllowance - amount);
_transfer(from, to, amount);
return true;
}
function withdrawalAllowance(
address depositor,
address spender
)
external
view
override
returns (uint256)
{
return _allowedWithdrawals[depositor][spender];
}
function getCommissionRate()
external
view
override
returns (uint256)
{
return _commissionRate;
}
function getExitDate()
external
view
override
returns (uint256)
{
return _exitDate;
}
function getState()
external
view
override
returns(State)
{
return _state;
}
function getOperatorAddress()
external
view
override
returns (address)
{
return _operatorAddress;
}
function getDeposit(address depositor)
external
view
override
returns (uint256)
{
return _deposits[depositor];
}
function getTotalDeposits()
external
view
override
returns (uint256)
{
return _totalDeposits;
}
function getAllowance(
address owner,
address spender
)
external
view
override
returns (uint256)
{
return _allowances[owner][spender];
}
function getOperatorDataCommitment()
external
view
override
returns (bytes32)
{
return _operatorDataCommitment;
}
function getOperatorClaimable()
external
view
override
returns (uint256)
{
return _operatorClaimable;
}
function getWithdrawableAmount(address owner)
external
view
override
returns (uint256)
{
if (_state == State.PostDeposit) {
return 0;
}
return _deposits[owner] * (address(this).balance - _operatorClaimable) / _totalDeposits;
}
function _executeWithdrawal(
address depositor,
address payable beneficiary,
uint256 amount
)
internal
returns (uint256)
{
require(amount > 0, "Amount shouldn't be zero");
uint256 value = amount * (address(this).balance - _operatorClaimable) / _totalDeposits;
// Modern versions of Solidity automatically add underflow checks,
// so we don't need to `require(_deposits[_depositor] < _deposit` here:
_deposits[depositor] -= amount;
_totalDeposits -= amount;
emit Withdrawal(depositor, beneficiary, amount, value);
payable(beneficiary).sendValue(value);
return value;
}
// NOTE: This throws (on underflow) if the contract's balance was more than
// 32 ether before the call
function _handleDeposit(address depositor)
internal
returns (uint256 surplus)
{
uint256 depositSize = msg.value;
surplus = (address(this).balance > 32 ether) ?
(address(this).balance - 32 ether) : 0;
uint256 acceptedDeposit = depositSize - surplus;
_deposits[depositor] += acceptedDeposit;
_totalDeposits += acceptedDeposit;
emit Deposit(depositor, acceptedDeposit);
if (surplus > 0) {
payable(depositor).sendValue(surplus);
}
}
function _transfer(
address from,
address to,
uint256 amount
)
internal
{
require(to != address(0), "Transfer to the zero address");
_deposits[from] -= amount;
_deposits[to] += amount;
emit Transfer(from, to, amount);
}
function _approve(
address owner,
address spender,
uint256 amount
)
internal
{
require(spender != address(0), "Approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _approveWithdrawal(
address owner,
address spender,
uint256 amount
)
internal
{
require(spender != address(0), "Approve to the zero address");
_allowedWithdrawals[owner][spender] = amount;
emit WithdrawalApproval(owner, spender, amount);
}
function _min(
uint256 a,
uint256 b
)
internal
pure
returns (uint256)
{
return a < b ? a : b;
}
}// ┏━━━┓━┏┓━┏┓━━┏━━━┓━━┏━━━┓━━━━┏━━━┓━━━━━━━━━━━━━━━━━━━┏┓━━━━━┏━━━┓━━━━━━━━━┏┓━━━━━━━━━━━━━━┏┓━
// ┃┏━━┛┏┛┗┓┃┃━━┃┏━┓┃━━┃┏━┓┃━━━━┗┓┏┓┃━━━━━━━━━━━━━━━━━━┏┛┗┓━━━━┃┏━┓┃━━━━━━━━┏┛┗┓━━━━━━━━━━━━┏┛┗┓
// ┃┗━━┓┗┓┏┛┃┗━┓┗┛┏┛┃━━┃┃━┃┃━━━━━┃┃┃┃┏━━┓┏━━┓┏━━┓┏━━┓┏┓┗┓┏┛━━━━┃┃━┗┛┏━━┓┏━┓━┗┓┏┛┏━┓┏━━┓━┏━━┓┗┓┏┛
// ┃┏━━┛━┃┃━┃┏┓┃┏━┛┏┛━━┃┃━┃┃━━━━━┃┃┃┃┃┏┓┃┃┏┓┃┃┏┓┃┃━━┫┣┫━┃┃━━━━━┃┃━┏┓┃┏┓┃┃┏┓┓━┃┃━┃┏┛┗━┓┃━┃┏━┛━┃┃━
// ┃┗━━┓━┃┗┓┃┃┃┃┃┃┗━┓┏┓┃┗━┛┃━━━━┏┛┗┛┃┃┃━┫┃┗┛┃┃┗┛┃┣━━┃┃┃━┃┗┓━━━━┃┗━┛┃┃┗┛┃┃┃┃┃━┃┗┓┃┃━┃┗┛┗┓┃┗━┓━┃┗┓
// ┗━━━┛━┗━┛┗┛┗┛┗━━━┛┗┛┗━━━┛━━━━┗━━━┛┗━━┛┃┏━┛┗━━┛┗━━┛┗┛━┗━┛━━━━┗━━━┛┗━━┛┗┛┗┛━┗━┛┗┛━┗━━━┛┗━━┛━┗━┛
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┃┃━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┗┛━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
// SPDX-License-Identifier: CC0-1.0
pragma solidity 0.8.4;
// This interface is designed to be compatible with the Vyper version.
/// @notice This is the Ethereum 2.0 deposit contract interface.
/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs
interface IDepositContract {
/// @notice A processed deposit event.
event DepositEvent(
bytes pubkey,
bytes withdrawal_credentials,
bytes amount,
bytes signature,
bytes index
);
/// @notice Submit a Phase 0 DepositData object.
/// @param pubkey A BLS12-381 public key.
/// @param withdrawal_credentials Commitment to a public key for withdrawals.
/// @param signature A BLS12-381 signature.
/// @param deposit_data_root The SHA-256 hash of the SSZ-encoded DepositData object.
/// Used as a protection against malformed input.
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) external payable;
/// @notice Query the current deposit root hash.
/// @return The deposit root hash.
function get_deposit_root() external view returns (bytes32);
/// @notice Query the current deposit count.
/// @return The deposit count encoded as a little endian 64-bit number.
function get_deposit_count() external view returns (bytes memory);
}
// Based on official specification in https://eips.ethereum.org/EIPS/eip-165
interface ERC165 {
/// @notice Query if a contract implements an interface
/// @param interfaceId The interface identifier, as specified in ERC-165
/// @dev Interface identification is specified in ERC-165. This function
/// uses less than 30,000 gas.
/// @return `true` if the contract implements `interfaceId` and
/// `interfaceId` is not 0xffffffff, `false` otherwise
function supportsInterface(bytes4 interfaceId) external pure returns (bool);
}
// This is a rewrite of the Vyper Eth2.0 deposit contract in Solidity.
// It tries to stay as close as possible to the original source code.
/// @notice This is the Ethereum 2.0 deposit contract interface.
/// For more information see the Phase 0 specification under https://github.com/ethereum/eth2.0-specs
contract DepositContract is IDepositContract, ERC165 {
uint constant DEPOSIT_CONTRACT_TREE_DEPTH = 32;
// NOTE: this also ensures `deposit_count` will fit into 64-bits
uint constant MAX_DEPOSIT_COUNT = 2**DEPOSIT_CONTRACT_TREE_DEPTH - 1;
bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] branch;
uint256 deposit_count;
bytes32[DEPOSIT_CONTRACT_TREE_DEPTH] zero_hashes;
constructor() {
// Compute hashes in empty sparse Merkle tree
for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH - 1; height++)
zero_hashes[height + 1] = sha256(abi.encodePacked(zero_hashes[height], zero_hashes[height]));
}
function get_deposit_root() override external view returns (bytes32) {
bytes32 node;
uint size = deposit_count;
for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {
if ((size & 1) == 1)
node = sha256(abi.encodePacked(branch[height], node));
else
node = sha256(abi.encodePacked(node, zero_hashes[height]));
size /= 2;
}
return sha256(abi.encodePacked(
node,
to_little_endian_64(uint64(deposit_count)),
bytes24(0)
));
}
function get_deposit_count() override external view returns (bytes memory) {
return to_little_endian_64(uint64(deposit_count));
}
function deposit(
bytes calldata pubkey,
bytes calldata withdrawal_credentials,
bytes calldata signature,
bytes32 deposit_data_root
) override external payable {
// Extended ABI length checks since dynamic types are used.
require(pubkey.length == 48, "DepositContract: invalid pubkey length");
require(withdrawal_credentials.length == 32, "DepositContract: invalid withdrawal_credentials length");
require(signature.length == 96, "DepositContract: invalid signature length");
// Check deposit amount
require(msg.value >= 1 ether, "DepositContract: deposit value too low");
require(msg.value % 1 gwei == 0, "DepositContract: deposit value not multiple of gwei");
uint deposit_amount = msg.value / 1 gwei;
require(deposit_amount <= type(uint64).max, "DepositContract: deposit value too high");
// Emit `DepositEvent` log
bytes memory amount = to_little_endian_64(uint64(deposit_amount));
emit DepositEvent(
pubkey,
withdrawal_credentials,
amount,
signature,
to_little_endian_64(uint64(deposit_count))
);
// Compute deposit data root (`DepositData` hash tree root)
bytes32 pubkey_root = sha256(abi.encodePacked(pubkey, bytes16(0)));
bytes32 signature_root = sha256(abi.encodePacked(
sha256(abi.encodePacked(signature[:64])),
sha256(abi.encodePacked(signature[64:], bytes32(0)))
));
bytes32 node = sha256(abi.encodePacked(
sha256(abi.encodePacked(pubkey_root, withdrawal_credentials)),
sha256(abi.encodePacked(amount, bytes24(0), signature_root))
));
// Verify computed and expected deposit data roots match
require(node == deposit_data_root, "DepositContract: reconstructed DepositData does not match supplied deposit_data_root");
// Avoid overflowing the Merkle tree (and prevent edge case in computing `branch`)
require(deposit_count < MAX_DEPOSIT_COUNT, "DepositContract: merkle tree full");
// Add deposit data root to Merkle tree (update a single `branch` node)
deposit_count += 1;
uint size = deposit_count;
for (uint height = 0; height < DEPOSIT_CONTRACT_TREE_DEPTH; height++) {
if ((size & 1) == 1) {
branch[height] = node;
return;
}
node = sha256(abi.encodePacked(branch[height], node));
size /= 2;
}
// As the loop should always end prematurely with the `return` statement,
// this code should be unreachable. We assert `false` just to be safe.
assert(false);
}
function supportsInterface(bytes4 interfaceId) override external pure returns (bool) {
return interfaceId == type(ERC165).interfaceId || interfaceId == type(IDepositContract).interfaceId;
}
function to_little_endian_64(uint64 value) internal pure returns (bytes memory ret) {
ret = new bytes(8);
bytes8 bytesValue = bytes8(value);
// Byteswapping during copying to bytes.
ret[0] = bytesValue[7];
ret[1] = bytesValue[6];
ret[2] = bytesValue[5];
ret[3] = bytesValue[4];
ret[4] = bytesValue[3];
ret[5] = bytesValue[2];
ret[6] = bytesValue[1];
ret[7] = bytesValue[0];
}
}// Copyright (C) 2021 BITFISH LIMITED
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.0;
/// @notice Governs the life cycle of a single Eth2 validator with ETH provided by multiple stakers.
interface IStakefishServicesContract {
/// @notice The life cycle of a services contract.
enum State {
NotInitialized,
PreDeposit,
PostDeposit,
Withdrawn
}
/// @notice Emitted when a `spender` is set to allow the transfer of an `owner`'s deposit stake amount.
/// `amount` is the new allownace.
/// @dev Also emitted when {transferDepositFrom} is called.
event Approval(
address indexed owner,
address indexed spender,
uint256 amount
);
/// @notice Emitted when deposit stake amount is transferred.
/// @param from The address of deposit stake owner.
/// @param to The address of deposit stake beneficiary.
/// @param amount The amount of transferred deposit stake.
event Transfer(
address indexed from,
address indexed to,
uint256 amount
);
/// @notice Emitted when a `spender` is set to allow withdrawal on behalf of a `owner`.
/// `amount` is the new allowance.
/// @dev Also emitted when {WithdrawFrom} is called.
event WithdrawalApproval(
address indexed owner,
address indexed spender,
uint256 amount
);
/// @notice Emitted when `owner`'s ETH are withdrawan to `to`.
/// @param owner The address of deposit stake owner.
/// @param to The address of ETH beneficiary.
/// @param amount The amount of deposit stake to be converted to ETH.
/// @param value The amount of withdrawn ETH.
event Withdrawal(
address indexed owner,
address indexed to,
uint256 amount,
uint256 value
);
/// @notice Emitted when 32 ETH is transferred to the eth2 deposit contract.
/// @param pubkey A BLS12-381 public key.
event ValidatorDeposited(
bytes pubkey // 48 bytes
);
/// @notice Emitted when a validator exits and the operator settles the commission.
event ServiceEnd();
/// @notice Emitted when deposit to the services contract.
/// @param from The address of the deposit stake owner.
/// @param amount The accepted amount of ETH deposited into the services contract.
event Deposit(
address from,
uint256 amount
);
/// @notice Emitted when operaotr claims commission fee.
/// @param receiver The address of the operator.
/// @param amount The amount of ETH sent to the operator address.
event Claim(
address receiver,
uint256 amount
);
/// @notice Updates the exit date of the validator.
/// @dev The exit date should be in the range of uint64.
/// @param newExitDate The new exit date should come before the previously specified exit date.
function updateExitDate(uint64 newExitDate) external;
/// @notice Submits a Phase 0 DepositData to the eth2 deposit contract.
/// @dev The Keccak hash of the contract address and all submitted data should match the `_operatorDataCommitment`.
/// Emits a {ValidatorDeposited} event.
/// @param validatorPubKey A BLS12-381 public key.
/// @param depositSignature A BLS12-381 signature.
/// @param depositDataRoot The SHA-256 hash of the SSZ-encoded DepositData object.
/// @param exitDate The expected exit date of the created validator
function createValidator(
bytes calldata validatorPubKey, // 48 bytes
bytes calldata depositSignature, // 96 bytes
bytes32 depositDataRoot,
uint64 exitDate
) external;
/// @notice Deposits `msg.value` of ETH.
/// @dev If the balance of the contract exceeds 32 ETH, the excess will be sent
/// back to `msg.sender`.
/// Emits a {Deposit} event.
function deposit() external payable returns (uint256 surplus);
/// @notice Deposits `msg.value` of ETH on behalf of `depositor`.
/// @dev If the balance of the contract exceeds 32 ETH, the excess will be sent
/// back to `depositor`.
/// Emits a {Deposit} event.
function depositOnBehalfOf(address depositor) external payable returns (uint256 surplus);
/// @notice Settles operator service commission and enable withdrawal.
/// @dev It can be called by operator if the time has passed `_exitDate`.
/// It can be called by any address if the time has passed `_exitDate + MAX_SECONDS_IN_EXIT_QUEUE`.
/// Emits a {ServiceEnd} event.
function endOperatorServices() external;
/// @notice Withdraws all the ETH of `msg.sender`.
/// @dev It can only be called when the contract state is not `PostDeposit`.
/// Emits a {Withdrawal} event.
/// @param minimumETHAmount The minimum amount of ETH that must be received for the transaction not to revert.
function withdrawAll(uint256 minimumETHAmount) external returns (uint256);
/// @notice Withdraws the ETH of `msg.sender` which is corresponding to the `amount` of deposit stake.
/// @dev It can only be called when the contract state is not `PostDeposit`.
/// Emits a {Withdrawal} event.
/// @param amount The amount of deposit stake to be converted to ETH.
/// @param minimumETHAmount The minimum amount of ETH that must be received for the transaction not to revert.
function withdraw(uint256 amount, uint256 minimumETHAmount) external returns (uint256);
/// @notice Withdraws the ETH of `msg.sender` which is corresponding to the `amount` of deposit stake to a specified address.
/// @dev It can only be called when the contract state is not `PostDeposit`.
/// Emits a {Withdrawal} event.
/// @param amount The amount of deposit stake to be converted to ETH.
/// @param beneficiary The address of ETH receiver.
/// @param minimumETHAmount The minimum amount of ETH that must be received for the transaction not to revert.
function withdrawTo(
uint256 amount,
address payable beneficiary,
uint256 minimumETHAmount
) external returns (uint256);
/// @notice Sets `amount` as the allowance of `spender` over the caller's deposit stake.
/// @dev Emits an {Approval} event.
function approve(address spender, uint256 amount) external returns (bool);
/// @notice Increases the allowance granted to `spender` by the caller.
/// @dev Emits an {Approval} event indicating the upated allowances;
function increaseAllowance(address spender, uint256 addValue) external returns (bool);
/// @notice Decreases the allowance granted to `spender` by the caller.
/// @dev Emits an {Approval} event indicating the upated allowances;
/// It reverts if current allowance is less than `subtractedValue`.
function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
/// @notice Decreases the allowance granted to `spender` by the caller.
/// @dev Emits an {Approval} event indicating the upated allowances;
/// It sets allowance to zero if current allowance is less than `subtractedValue`.
function forceDecreaseAllowance(address spender, uint256 subtractedValue) external returns (bool);
/// @notice Sets `amount` as the allowance of `spender` over the caller's deposit amount that can be withdrawn.
/// @dev Emits an {WithdrawalApproval} event.
function approveWithdrawal(address spender, uint256 amount) external returns (bool);
/// @notice Increases the allowance of withdrawal granted to `spender` by the caller.
/// @dev Emits an {WithdrawalApproval} event indicating the upated allowances;
function increaseWithdrawalAllowance(address spender, uint256 addValue) external returns (bool);
/// @notice Decreases the allowance of withdrawal granted to `spender` by the caller.
/// @dev Emits an {WithdrawwalApproval} event indicating the upated allowances;
/// It reverts if current allowance is less than `subtractedValue`.
function decreaseWithdrawalAllowance(address spender, uint256 subtractedValue) external returns (bool);
/// @notice Decreases the allowance of withdrawal granted to `spender` by the caller.
/// @dev Emits an {WithdrawwalApproval} event indicating the upated allowances;
/// It reverts if current allowance is less than `subtractedValue`.
function forceDecreaseWithdrawalAllowance(address spender, uint256 subtractedValue) external returns (bool);
/// @notice Withdraws the ETH of `depositor` which is corresponding to the `amount` of deposit stake to a specified address.
/// @dev Emits a {Withdrawal} event.
/// Emits a {WithdrawalApproval} event indicating the updated allowance.
/// @param depositor The address of deposit stake holder.
/// @param beneficiary The address of ETH receiver.
/// @param amount The amount of deposit stake to be converted to ETH.
/// @param minimumETHAmount The minimum amount of ETH that must be received for the transaction not to revert.
function withdrawFrom(
address depositor,
address payable beneficiary,
uint256 amount,
uint256 minimumETHAmount
) external returns (uint256);
/// @notice Transfers `amount` deposit stake from caller to `to`.
/// @dev Emits a {Transfer} event.
function transferDeposit(address to, uint256 amount) external returns (bool);
/// @notice Transfers `amount` deposit stake from `from` to `to`.
/// @dev Emits a {Transfer} event.
/// Emits an {Approval} event indicating the updated allowance.
function transferDepositFrom(
address from,
address to,
uint256 amount
) external returns (bool);
/// @notice Transfers operator claimable commission fee to the operator address.
/// @dev Emits a {Claim} event.
function operatorClaim() external returns (uint256);
/// @notice Returns the remaining number of deposit stake that `spender` will be allowed to withdraw
/// on behalf of `depositor` through {withdrawFrom}.
function withdrawalAllowance(address depositor, address spender) external view returns (uint256);
/// @notice Returns the operator service commission rate.
function getCommissionRate() external view returns (uint256);
/// @notice Returns operator claimable commission fee.
function getOperatorClaimable() external view returns (uint256);
/// @notice Returns the exit date of the validator.
function getExitDate() external view returns (uint256);
/// @notice Returns the state of the contract.
function getState() external view returns (State);
/// @notice Returns the address of operator.
function getOperatorAddress() external view returns (address);
/// @notice Returns the amount of deposit stake owned by `depositor`.
function getDeposit(address depositor) external view returns (uint256);
/// @notice Returns the total amount of deposit stake.
function getTotalDeposits() external view returns (uint256);
/// @notice Returns the remaining number of deposit stake that `spender` will be allowed to transfer
/// on behalf of `depositor` through {transferDepositFrom}.
function getAllowance(address owner, address spender) external view returns (uint256);
/// @notice Returns the commitment which is the hash of the contract address and all inputs to the `createValidator` function.
function getOperatorDataCommitment() external view returns (bytes32);
/// @notice Returns the amount of ETH that is withdrawable by `owner`.
function getWithdrawableAmount(address owner) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
// Source: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/4d0f8c1da8654a478f046ea7cf83d2166e1025af/contracts/utils/Address.sol
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @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, it is bubbled up by this
* function (like regular Solidity function calls).
*
* 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.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @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`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) private pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// 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 {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}{
"optimizer": {
"enabled": true,
"runs": 100000
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[],"name":"ServiceEnd","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"pubkey","type":"bytes"}],"name":"ValidatorDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Withdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalApproval","type":"event"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approveWithdrawal","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"validatorPubKey","type":"bytes"},{"internalType":"bytes","name":"depositSignature","type":"bytes"},{"internalType":"bytes32","name":"depositDataRoot","type":"bytes32"},{"internalType":"uint64","name":"exitDate","type":"uint64"}],"name":"createValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseWithdrawalAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[{"internalType":"uint256","name":"surplus","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositContract","outputs":[{"internalType":"contract IDepositContract","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"}],"name":"depositOnBehalfOf","outputs":[{"internalType":"uint256","name":"surplus","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"endOperatorServices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"forceDecreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"forceDecreaseWithdrawalAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"getAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCommissionRate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"}],"name":"getDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getExitDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperatorAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperatorClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOperatorDataCommitment","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getState","outputs":[{"internalType":"enum IStakefishServicesContract.State","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"getWithdrawableAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseWithdrawalAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint24","name":"commissionRate","type":"uint24"},{"internalType":"address","name":"operatorAddress","type":"address"},{"internalType":"bytes32","name":"operatorDataCommitment","type":"bytes32"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"operatorClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferDeposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferDepositFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"newExitDate","type":"uint64"}],"name":"updateExitDate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minimumETHAmount","type":"uint256"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minimumETHAmount","type":"uint256"}],"name":"withdrawAll","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"address payable","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minimumETHAmount","type":"uint256"}],"name":"withdrawFrom","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"beneficiary","type":"address"},{"internalType":"uint256","name":"minimumETHAmount","type":"uint256"}],"name":"withdrawTo","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"depositor","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"withdrawalAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
608060405234801561001057600080fd5b50612bfa806100206000396000f3fe6080604052600436106102025760003560e01c8063671a24f11161011d578063cfe2edcb116100b0578063e94ad65b1161007f578063f54c071411610064578063f54c071414610767578063f632c1af14610787578063f67771751461079c57600080fd5b8063e94ad65b14610723578063f4970e711461074757600080fd5b8063cfe2edcb146106a5578063d0e30db0146106b8578063d4fdc309146106c0578063e1254fba146106e057600080fd5b8063924d2784116100ec578063924d27841461060b578063958e2d3114610645578063a457c2d714610665578063caa7262b1461068557600080fd5b8063671a24f1146105a15780636a8d8d8d146105b65780636ce858bf146105d65780637fcd7332146105f657600080fd5b8063395093511161019557806350f3dbec1161016457806350f3dbec146104ee5780635d13d5141461050e5780635d722feb1461052e578063666c10351461058157600080fd5b806339509351146104745780633e4eb36c14610494578063441a3e70146104ae57806346fcb042146104ce57600080fd5b8063171808af116101d1578063171808af146103a95780631865c57d146103c95780631ca800971461040c5780632ec338ba1461042157600080fd5b8063095ea7b3146102de5780630af4187d146103135780630e2cc32714610374578063168a48221461039457600080fd5b366102d95760016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff16600381111561026a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f506c61696e204574686572207472616e73666572206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b005b600080fd5b3480156102ea57600080fd5b506102fe6102f936600461276c565b6107bc565b60405190151581526020015b60405180910390f35b34801561031f57600080fd5b5061036661032e3660046126af565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205490565b60405190815260200161030a565b34801561038057600080fd5b506102fe61038f36600461276c565b6107d2565b3480156103a057600080fd5b50600554610366565b3480156103b557600080fd5b506102fe6103c436600461276c565b61081b565b3480156103d557600080fd5b506000547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660405161030a9190612a53565b34801561041857600080fd5b50600154610366565b34801561042d57600080fd5b506000546301000000900473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161030a565b34801561048057600080fd5b506102fe61048f36600461276c565b610876565b3480156104a057600080fd5b5060005462ffffff16610366565b3480156104ba57600080fd5b506103666104c9366004612880565b6108ba565b3480156104da57600080fd5b506102fe6104e936600461276c565b6109f3565b3480156104fa57600080fd5b506102fe61050936600461276c565b610a3f565b34801561051a57600080fd5b506102d7610529366004612797565b610a4c565b34801561053a57600080fd5b506103666105493660046126af565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260036020908152604080832093909416825291909152205490565b34801561058d57600080fd5b506102fe61059c36600461276c565b610ec9565b3480156105ad57600080fd5b50600654610366565b3480156105c257600080fd5b506102d76105d13660046128a1565b610f0d565b3480156105e257600080fd5b506102d76105f136600461281c565b61116f565b34801561060257600080fd5b506102d7611350565b34801561061757600080fd5b5060005477010000000000000000000000000000000000000000000000900467ffffffffffffffff16610366565b34801561065157600080fd5b50610366610660366004612842565b611691565b34801561067157600080fd5b506102fe61068036600461276c565b6117d9565b34801561069157600080fd5b506103666106a036600461285a565b61181d565b6103666106b3366004612693565b611957565b610366611a2c565b3480156106cc57600080fd5b506103666106db3660046126e7565b611b06565b3480156106ec57600080fd5b506103666106fb366004612693565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561072f57600080fd5b5061044f6f219ab540356cbb839cbe05303d7705fa81565b34801561075357600080fd5b506102fe61076236600461276c565b611ce9565b34801561077357600080fd5b506102fe61078236600461272c565b611cf6565b34801561079357600080fd5b50610366611d4e565b3480156107a857600080fd5b506103666107b7366004612693565b611e6d565b60006107c9338484611f2a565b50600192915050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610816908690612aa7565b612016565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161086c908561085d86856120f9565b6108679085612b35565b611f2a565b5060019392505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610867908690612aa7565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff16600381111561091f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba16024913990610972576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b50600061098033338661210f565b9050828110156109ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b9392505050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161086c9085610a3586856120f9565b6108169085612b35565b60006107c933848461226f565b6000546301000000900473ffffffffffffffffffffffffffffffffffffffff163314610ad4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865206f70657261746f7200000000000060448201526064016102ce565b60016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115610b37577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14610b9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f56616c696461746f7220686173206265656e206372656174656400000000000060448201526064016102ce565b600080547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905560308514610c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f496e76616c69642076616c696461746f72207075626c6963206b65790000000060448201526064016102ce565b60608314610cbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c6964206465706f736974207369676e61747572650000000000000060448201526064016102ce565b30868686868686604051602001610cd8979695949392919061296e565b6040516020818303038152906040528051906020012060015414610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4461746120646f65736e2774206d6174636820636f6d6d69746d656e7400000060448201526064016102ce565b600080547fff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000067ffffffffffffffff841602179055604080517f010000000000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b16602c8201526f219ab540356cbb839cbe05303d7705fa916322895118916801bc16d674ec800000918a918a91016040516020818303038152906040528989896040518863ffffffff1660e01b8152600401610e5696959493929190612a04565b6000604051808303818588803b158015610e6f57600080fd5b505af1158015610e83573d6000803e3d6000fd5b50505050507fc7114975f4ef557d4d63c6e4171d351eb22178fecbeefc10214791527c1df0c58686604051610eb99291906129f0565b60405180910390a1505050505050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610816908690612b35565b6000546301000000900473ffffffffffffffffffffffffffffffffffffffff163314610f95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865206f70657261746f7200000000000060448201526064016102ce565b60026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115610ff8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1461105f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f56616c696461746f72206973206e6f742061637469766500000000000000000060448201526064016102ce565b60005467ffffffffffffffff77010000000000000000000000000000000000000000000000909104811690821610611119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4e6f74206561726c696572207468616e20746865206f726967696e616c20766160448201527f6c7565000000000000000000000000000000000000000000000000000000000060648201526084016102ce565b6000805467ffffffffffffffff90921677010000000000000000000000000000000000000000000000027fff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffff909216919091179055565b600080547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156111d1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f436f6e747261637420697320616c726561647920696e697469616c697a65640060448201526064016102ce565b600080547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000179055620f424062ffffff841611156112f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f436f6d6d697373696f6e20726174652065786365656473207363616c6500000060448201526064016102ce565b6000805473ffffffffffffffffffffffffffffffffffffffff9093166301000000027fffffffffffffffffff000000000000000000000000000000000000000000000090931662ffffff9094169390931791909117909155600155565b47806113b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e277420656e64207769746820302062616c616e6365000000000000000060448201526064016102ce565b60026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff16600381111561141b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4e6f7420616c6c6f77656420696e207468652063757272656e7420737461746560448201526064016102ce565b6000546301000000900473ffffffffffffffffffffffffffffffffffffffff16331480156114d6575060005477010000000000000000000000000000000000000000000000900467ffffffffffffffff1642115b8061154e5750336000908152600460205260409020541580159061154e5750611502610e106018612af8565b61150e9061016d612af8565b611519906001612af8565b60005461154b919077010000000000000000000000000000000000000000000000900467ffffffffffffffff16612aa7565b42115b6115b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4e6f7420616c6c6f776564206174207468652063757272656e742074696d650060448201526064016102ce565b600080547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f03000000000000000000000000000000000000000000000000000000000000001790556801bc16d674ec8000008111156116655760006116236801bc16d674ec80000083612b35565b6000805491925090620f42409061163f9062ffffff1684612af8565b6116499190612abf565b9050806006600082825461165d9190612aa7565b909155505050505b6040517ffbd6622fc13ddf86275d242b7ed2c826cd2a9bc82b2c6db61a651c8b044339f690600090a150565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156116f6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba16024913990611749576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b5033600081815260046020526040812054909161176791819061210f565b9050828110156117d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b92915050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610867908690612b35565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611882577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba160249139906118d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b5060006118e333858761210f565b90508281101561194f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b949350505050565b600060016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156119bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611a23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f56616c696461746f7220616c726561647920637265617465640000000000000060448201526064016102ce565b6117d3826123c1565b600060016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611a91577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611af8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f56616c696461746f7220616c726561647920637265617465640000000000000060448201526064016102ce565b611b01336123c1565b905090565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611b6b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba16024913990611bbe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260036020908152604080832033845290915281205490611bfb8583612b35565b73ffffffffffffffffffffffffffffffffffffffff8816600081815260036020908152604080832033808552908352928190208590555184815293945090927f86cf336bf0eef9691e91aad1f012fdff22e082219d77b1b84289e919a1ed1326910160405180910390a36000611c7288888861210f565b905084811015611cde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b979650505050505050565b60006107c9338484612016565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020908152604080832033808552925282205490611d389086906108678685612b35565b611d4385858561226f565b506001949350505050565b600080546301000000900473ffffffffffffffffffffffffffffffffffffffff163314611dd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865206f70657261746f7200000000000060448201526064016102ce565b6006548015611b01576000600681905554611e0f906301000000900473ffffffffffffffffffffffffffffffffffffffff16826124d0565b60005460408051630100000090920473ffffffffffffffffffffffffffffffffffffffff168252602082018390527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4910160405180910390a1905090565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611ed2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415611ee057506000919050565b600554600654611ef09047612b35565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260046020526040902054611f209190612af8565b6117d39190612abf565b73ffffffffffffffffffffffffffffffffffffffff8216611fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f417070726f766520746f20746865207a65726f2061646472657373000000000060448201526064016102ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8216612093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f417070726f766520746f20746865207a65726f2061646472657373000000000060448201526064016102ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526003602090815260408083209487168084529482529182902085905590518481527f86cf336bf0eef9691e91aad1f012fdff22e082219d77b1b84289e919a1ed13269101612009565b600081831061210857816109ec565b5090919050565b600080821161217a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f416d6f756e742073686f756c646e2774206265207a65726f000000000000000060448201526064016102ce565b60006005546006544761218d9190612b35565b6121979085612af8565b6121a19190612abf565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600460205260408120805492935085929091906121db908490612b35565b9250508190555082600560008282546121f49190612b35565b9091555050604080518481526020810183905273ffffffffffffffffffffffffffffffffffffffff80871692908816917fc2b4a290c20fb28939d29f102514fbffd2b73c059ffba8b78250c94161d5fcc6910160405180910390a361194f73ffffffffffffffffffffffffffffffffffffffff8516826124d0565b73ffffffffffffffffffffffffffffffffffffffff82166122ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f5472616e7366657220746f20746865207a65726f20616464726573730000000060448201526064016102ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602052604081208054839290612321908490612b35565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000908152600460205260408120805483929061235b908490612aa7565b925050819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161200991815260200190565b6000346801bc16d674ec80000047116123db5760006123ee565b6123ee6801bc16d674ec80000047612b35565b915060006123fc8383612b35565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260046020526040812080549293508392909190612436908490612aa7565b92505081905550806005600082825461244f9190612aa7565b90915550506040805173ffffffffffffffffffffffffffffffffffffffff86168152602081018390527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c910160405180910390a182156124c9576124c973ffffffffffffffffffffffffffffffffffffffff8516846124d0565b5050919050565b8047101561253a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016102ce565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612594576040519150601f19603f3d011682016040523d82523d6000602084013e612599565b606091505b505090508061262a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016102ce565b505050565b60008083601f840112612640578182fd5b50813567ffffffffffffffff811115612657578182fd5b60208301915083602082850101111561266f57600080fd5b9250929050565b803567ffffffffffffffff8116811461268e57600080fd5b919050565b6000602082840312156126a4578081fd5b81356109ec81612b7b565b600080604083850312156126c1578081fd5b82356126cc81612b7b565b915060208301356126dc81612b7b565b809150509250929050565b600080600080608085870312156126fc578182fd5b843561270781612b7b565b9350602085013561271781612b7b565b93969395505050506040820135916060013590565b600080600060608486031215612740578283fd5b833561274b81612b7b565b9250602084013561275b81612b7b565b929592945050506040919091013590565b6000806040838503121561277e578182fd5b823561278981612b7b565b946020939093013593505050565b600080600080600080608087890312156127af578182fd5b863567ffffffffffffffff808211156127c6578384fd5b6127d28a838b0161262f565b909850965060208901359150808211156127ea578384fd5b506127f789828a0161262f565b9095509350506040870135915061281060608801612676565b90509295509295509295565b600080600060608486031215612830578283fd5b833562ffffff8116811461274b578384fd5b600060208284031215612853578081fd5b5035919050565b60008060006060848603121561286e578283fd5b83359250602084013561275b81612b7b565b60008060408385031215612892578182fd5b50508035926020909101359150565b6000602082840312156128b2578081fd5b6109ec82612676565b81835281816020850137506000806020838501015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600081518084526020825b8281101561292957848101820151868201830152810161290e565b8281111561293957838284880101525b50807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401168601019250505092915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16815285876014830137600086820160148101828152868882375060149501948501939093525060c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016603483015250603c01949350505050565b60208152600061194f6020830184866128bb565b608081526000612a1860808301888a6128bb565b8281036020840152612a2a8188612903565b90508281036040840152612a3f8186886128bb565b915050826060830152979650505050505050565b6020810160048310612a8e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6020815260006109ec6020830184612903565b60008219821115612aba57612aba612b4c565b500190565b600082612af3577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b3057612b30612b4c565b500290565b600082821015612b4757612b47612b4c565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81168114612b9d57600080fd5b5056fe4e6f7420616c6c6f776564207768656e2076616c696461746f7220697320616374697665a26469706673582212200b7cedc9067ec1d24c831fc4b3489f87a6a061209f64b8e65feac3fd71122a1764736f6c63430008040033
Deployed Bytecode
0x6080604052600436106102025760003560e01c8063671a24f11161011d578063cfe2edcb116100b0578063e94ad65b1161007f578063f54c071411610064578063f54c071414610767578063f632c1af14610787578063f67771751461079c57600080fd5b8063e94ad65b14610723578063f4970e711461074757600080fd5b8063cfe2edcb146106a5578063d0e30db0146106b8578063d4fdc309146106c0578063e1254fba146106e057600080fd5b8063924d2784116100ec578063924d27841461060b578063958e2d3114610645578063a457c2d714610665578063caa7262b1461068557600080fd5b8063671a24f1146105a15780636a8d8d8d146105b65780636ce858bf146105d65780637fcd7332146105f657600080fd5b8063395093511161019557806350f3dbec1161016457806350f3dbec146104ee5780635d13d5141461050e5780635d722feb1461052e578063666c10351461058157600080fd5b806339509351146104745780633e4eb36c14610494578063441a3e70146104ae57806346fcb042146104ce57600080fd5b8063171808af116101d1578063171808af146103a95780631865c57d146103c95780631ca800971461040c5780632ec338ba1461042157600080fd5b8063095ea7b3146102de5780630af4187d146103135780630e2cc32714610374578063168a48221461039457600080fd5b366102d95760016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff16600381111561026a577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14156102d7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f506c61696e204574686572207472616e73666572206e6f7420616c6c6f77656460448201526064015b60405180910390fd5b005b600080fd5b3480156102ea57600080fd5b506102fe6102f936600461276c565b6107bc565b60405190151581526020015b60405180910390f35b34801561031f57600080fd5b5061036661032e3660046126af565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205490565b60405190815260200161030a565b34801561038057600080fd5b506102fe61038f36600461276c565b6107d2565b3480156103a057600080fd5b50600554610366565b3480156103b557600080fd5b506102fe6103c436600461276c565b61081b565b3480156103d557600080fd5b506000547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660405161030a9190612a53565b34801561041857600080fd5b50600154610366565b34801561042d57600080fd5b506000546301000000900473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161030a565b34801561048057600080fd5b506102fe61048f36600461276c565b610876565b3480156104a057600080fd5b5060005462ffffff16610366565b3480156104ba57600080fd5b506103666104c9366004612880565b6108ba565b3480156104da57600080fd5b506102fe6104e936600461276c565b6109f3565b3480156104fa57600080fd5b506102fe61050936600461276c565b610a3f565b34801561051a57600080fd5b506102d7610529366004612797565b610a4c565b34801561053a57600080fd5b506103666105493660046126af565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260036020908152604080832093909416825291909152205490565b34801561058d57600080fd5b506102fe61059c36600461276c565b610ec9565b3480156105ad57600080fd5b50600654610366565b3480156105c257600080fd5b506102d76105d13660046128a1565b610f0d565b3480156105e257600080fd5b506102d76105f136600461281c565b61116f565b34801561060257600080fd5b506102d7611350565b34801561061757600080fd5b5060005477010000000000000000000000000000000000000000000000900467ffffffffffffffff16610366565b34801561065157600080fd5b50610366610660366004612842565b611691565b34801561067157600080fd5b506102fe61068036600461276c565b6117d9565b34801561069157600080fd5b506103666106a036600461285a565b61181d565b6103666106b3366004612693565b611957565b610366611a2c565b3480156106cc57600080fd5b506103666106db3660046126e7565b611b06565b3480156106ec57600080fd5b506103666106fb366004612693565b73ffffffffffffffffffffffffffffffffffffffff1660009081526004602052604090205490565b34801561072f57600080fd5b5061044f6f219ab540356cbb839cbe05303d7705fa81565b34801561075357600080fd5b506102fe61076236600461276c565b611ce9565b34801561077357600080fd5b506102fe61078236600461272c565b611cf6565b34801561079357600080fd5b50610366611d4e565b3480156107a857600080fd5b506103666107b7366004612693565b611e6d565b60006107c9338484611f2a565b50600192915050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610816908690612aa7565b612016565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161086c908561085d86856120f9565b6108679085612b35565b611f2a565b5060019392505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610867908690612aa7565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff16600381111561091f577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba16024913990610972576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b50600061098033338661210f565b9050828110156109ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b9392505050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff87168452909152812054909161086c9085610a3586856120f9565b6108169085612b35565b60006107c933848461226f565b6000546301000000900473ffffffffffffffffffffffffffffffffffffffff163314610ad4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865206f70657261746f7200000000000060448201526064016102ce565b60016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115610b37577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14610b9e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f56616c696461746f7220686173206265656e206372656174656400000000000060448201526064016102ce565b600080547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f020000000000000000000000000000000000000000000000000000000000000017905560308514610c51576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f496e76616c69642076616c696461746f72207075626c6963206b65790000000060448201526064016102ce565b60608314610cbb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f496e76616c6964206465706f736974207369676e61747572650000000000000060448201526064016102ce565b30868686868686604051602001610cd8979695949392919061296e565b6040516020818303038152906040528051906020012060015414610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4461746120646f65736e2774206d6174636820636f6d6d69746d656e7400000060448201526064016102ce565b600080547fff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffff167701000000000000000000000000000000000000000000000067ffffffffffffffff841602179055604080517f010000000000000000000000000000000000000000000000000000000000000060208201527fffffffffffffffffffffffffffffffffffffffff0000000000000000000000003060601b16602c8201526f219ab540356cbb839cbe05303d7705fa916322895118916801bc16d674ec800000918a918a91016040516020818303038152906040528989896040518863ffffffff1660e01b8152600401610e5696959493929190612a04565b6000604051808303818588803b158015610e6f57600080fd5b505af1158015610e83573d6000803e3d6000fd5b50505050507fc7114975f4ef557d4d63c6e4171d351eb22178fecbeefc10214791527c1df0c58686604051610eb99291906129f0565b60405180910390a1505050505050565b33600081815260036020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610816908690612b35565b6000546301000000900473ffffffffffffffffffffffffffffffffffffffff163314610f95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865206f70657261746f7200000000000060448201526064016102ce565b60026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115610ff8577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1461105f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f56616c696461746f72206973206e6f742061637469766500000000000000000060448201526064016102ce565b60005467ffffffffffffffff77010000000000000000000000000000000000000000000000909104811690821610611119576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4e6f74206561726c696572207468616e20746865206f726967696e616c20766160448201527f6c7565000000000000000000000000000000000000000000000000000000000060648201526084016102ce565b6000805467ffffffffffffffff90921677010000000000000000000000000000000000000000000000027fff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffff909216919091179055565b600080547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156111d1577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611238576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f436f6e747261637420697320616c726561647920696e697469616c697a65640060448201526064016102ce565b600080547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0100000000000000000000000000000000000000000000000000000000000000179055620f424062ffffff841611156112f3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f436f6d6d697373696f6e20726174652065786365656473207363616c6500000060448201526064016102ce565b6000805473ffffffffffffffffffffffffffffffffffffffff9093166301000000027fffffffffffffffffff000000000000000000000000000000000000000000000090931662ffffff9094169390931791909117909155600155565b47806113b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f43616e277420656e64207769746820302062616c616e6365000000000000000060448201526064016102ce565b60026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff16600381111561141b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611482576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4e6f7420616c6c6f77656420696e207468652063757272656e7420737461746560448201526064016102ce565b6000546301000000900473ffffffffffffffffffffffffffffffffffffffff16331480156114d6575060005477010000000000000000000000000000000000000000000000900467ffffffffffffffff1642115b8061154e5750336000908152600460205260409020541580159061154e5750611502610e106018612af8565b61150e9061016d612af8565b611519906001612af8565b60005461154b919077010000000000000000000000000000000000000000000000900467ffffffffffffffff16612aa7565b42115b6115b4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4e6f7420616c6c6f776564206174207468652063757272656e742074696d650060448201526064016102ce565b600080547effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f03000000000000000000000000000000000000000000000000000000000000001790556801bc16d674ec8000008111156116655760006116236801bc16d674ec80000083612b35565b6000805491925090620f42409061163f9062ffffff1684612af8565b6116499190612abf565b9050806006600082825461165d9190612aa7565b909155505050505b6040517ffbd6622fc13ddf86275d242b7ed2c826cd2a9bc82b2c6db61a651c8b044339f690600090a150565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156116f6577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba16024913990611749576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b5033600081815260046020526040812054909161176791819061210f565b9050828110156117d3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b92915050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490916107c9918590610867908690612b35565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611882577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba160249139906118d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b5060006118e333858761210f565b90508281101561194f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b949350505050565b600060016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff1660038111156119bc577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611a23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f56616c696461746f7220616c726561647920637265617465640000000000000060448201526064016102ce565b6117d3826123c1565b600060016000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611a91577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b14611af8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f56616c696461746f7220616c726561647920637265617465640000000000000060448201526064016102ce565b611b01336123c1565b905090565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611b6b577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415604051806060016040528060248152602001612ba16024913990611bbe576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016102ce9190612a94565b5073ffffffffffffffffffffffffffffffffffffffff8516600090815260036020908152604080832033845290915281205490611bfb8583612b35565b73ffffffffffffffffffffffffffffffffffffffff8816600081815260036020908152604080832033808552908352928190208590555184815293945090927f86cf336bf0eef9691e91aad1f012fdff22e082219d77b1b84289e919a1ed1326910160405180910390a36000611c7288888861210f565b905084811015611cde576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4c657373207468616e206d696e696d756d20616d6f756e74000000000000000060448201526064016102ce565b979650505050505050565b60006107c9338484612016565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260026020908152604080832033808552925282205490611d389086906108678685612b35565b611d4385858561226f565b506001949350505050565b600080546301000000900473ffffffffffffffffffffffffffffffffffffffff163314611dd7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f43616c6c6572206973206e6f7420746865206f70657261746f7200000000000060448201526064016102ce565b6006548015611b01576000600681905554611e0f906301000000900473ffffffffffffffffffffffffffffffffffffffff16826124d0565b60005460408051630100000090920473ffffffffffffffffffffffffffffffffffffffff168252602082018390527f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4910160405180910390a1905090565b600060026000547f0100000000000000000000000000000000000000000000000000000000000000900460ff166003811115611ed2577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b1415611ee057506000919050565b600554600654611ef09047612b35565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260046020526040902054611f209190612af8565b6117d39190612abf565b73ffffffffffffffffffffffffffffffffffffffff8216611fa7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f417070726f766520746f20746865207a65726f2061646472657373000000000060448201526064016102ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8216612093576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f417070726f766520746f20746865207a65726f2061646472657373000000000060448201526064016102ce565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526003602090815260408083209487168084529482529182902085905590518481527f86cf336bf0eef9691e91aad1f012fdff22e082219d77b1b84289e919a1ed13269101612009565b600081831061210857816109ec565b5090919050565b600080821161217a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f416d6f756e742073686f756c646e2774206265207a65726f000000000000000060448201526064016102ce565b60006005546006544761218d9190612b35565b6121979085612af8565b6121a19190612abf565b73ffffffffffffffffffffffffffffffffffffffff86166000908152600460205260408120805492935085929091906121db908490612b35565b9250508190555082600560008282546121f49190612b35565b9091555050604080518481526020810183905273ffffffffffffffffffffffffffffffffffffffff80871692908816917fc2b4a290c20fb28939d29f102514fbffd2b73c059ffba8b78250c94161d5fcc6910160405180910390a361194f73ffffffffffffffffffffffffffffffffffffffff8516826124d0565b73ffffffffffffffffffffffffffffffffffffffff82166122ec576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f5472616e7366657220746f20746865207a65726f20616464726573730000000060448201526064016102ce565b73ffffffffffffffffffffffffffffffffffffffff831660009081526004602052604081208054839290612321908490612b35565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000908152600460205260408120805483929061235b908490612aa7565b925050819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161200991815260200190565b6000346801bc16d674ec80000047116123db5760006123ee565b6123ee6801bc16d674ec80000047612b35565b915060006123fc8383612b35565b73ffffffffffffffffffffffffffffffffffffffff8516600090815260046020526040812080549293508392909190612436908490612aa7565b92505081905550806005600082825461244f9190612aa7565b90915550506040805173ffffffffffffffffffffffffffffffffffffffff86168152602081018390527fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c910160405180910390a182156124c9576124c973ffffffffffffffffffffffffffffffffffffffff8516846124d0565b5050919050565b8047101561253a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a20696e73756666696369656e742062616c616e636500000060448201526064016102ce565b60008273ffffffffffffffffffffffffffffffffffffffff168260405160006040518083038185875af1925050503d8060008114612594576040519150601f19603f3d011682016040523d82523d6000602084013e612599565b606091505b505090508061262a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603a60248201527f416464726573733a20756e61626c6520746f2073656e642076616c75652c207260448201527f6563697069656e74206d6179206861766520726576657274656400000000000060648201526084016102ce565b505050565b60008083601f840112612640578182fd5b50813567ffffffffffffffff811115612657578182fd5b60208301915083602082850101111561266f57600080fd5b9250929050565b803567ffffffffffffffff8116811461268e57600080fd5b919050565b6000602082840312156126a4578081fd5b81356109ec81612b7b565b600080604083850312156126c1578081fd5b82356126cc81612b7b565b915060208301356126dc81612b7b565b809150509250929050565b600080600080608085870312156126fc578182fd5b843561270781612b7b565b9350602085013561271781612b7b565b93969395505050506040820135916060013590565b600080600060608486031215612740578283fd5b833561274b81612b7b565b9250602084013561275b81612b7b565b929592945050506040919091013590565b6000806040838503121561277e578182fd5b823561278981612b7b565b946020939093013593505050565b600080600080600080608087890312156127af578182fd5b863567ffffffffffffffff808211156127c6578384fd5b6127d28a838b0161262f565b909850965060208901359150808211156127ea578384fd5b506127f789828a0161262f565b9095509350506040870135915061281060608801612676565b90509295509295509295565b600080600060608486031215612830578283fd5b833562ffffff8116811461274b578384fd5b600060208284031215612853578081fd5b5035919050565b60008060006060848603121561286e578283fd5b83359250602084013561275b81612b7b565b60008060408385031215612892578182fd5b50508035926020909101359150565b6000602082840312156128b2578081fd5b6109ec82612676565b81835281816020850137506000806020838501015260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b600081518084526020825b8281101561292957848101820151868201830152810161290e565b8281111561293957838284880101525b50807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401168601019250505092915050565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000008860601b16815285876014830137600086820160148101828152868882375060149501948501939093525060c01b7fffffffffffffffff00000000000000000000000000000000000000000000000016603483015250603c01949350505050565b60208152600061194f6020830184866128bb565b608081526000612a1860808301888a6128bb565b8281036020840152612a2a8188612903565b90508281036040840152612a3f8186886128bb565b915050826060830152979650505050505050565b6020810160048310612a8e577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b91905290565b6020815260006109ec6020830184612903565b60008219821115612aba57612aba612b4c565b500190565b600082612af3577f4e487b710000000000000000000000000000000000000000000000000000000081526012600452602481fd5b500490565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615612b3057612b30612b4c565b500290565b600082821015612b4757612b47612b4c565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81168114612b9d57600080fd5b5056fe4e6f7420616c6c6f776564207768656e2076616c696461746f7220697320616374697665a26469706673582212200b7cedc9067ec1d24c831fc4b3489f87a6a061209f64b8e65feac3fd71122a1764736f6c63430008040033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.