Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TokenVestingStaking
Compiler Version
v0.8.30+commit.73712a01
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "../libraries/Shared.sol";
import "../interfaces/ITokenVestingStaking.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
/// @notice A token holder contract that vests its ERC20 token to the
/// beneficiary. All tokens are locked until the end of the contract where the
/// balance is released. All tokens can be staked to solo and multi-contribution
/// nodes during the vesting period from this contract's balance.
///
/// If the contract is revoked, all funds are transferred to the revoker and the
/// contract is halted. Staked funds at revocation can be retrieved by the
/// revoker upon unstaking.
///
/// The vesting schedule is time-based (i.e. using block timestamps as opposed
/// to e.g. block numbers) and is therefore sensitive to timestamp manipulation
/// (which is something miners can do, to a certain degree). Therefore, it is
/// recommended to avoid using short time durations (less than a minute).
///
/// See `ITokenVestingStaking` for public API documentation.
contract TokenVestingStaking is ITokenVestingStaking, Shared {
using SafeERC20 for IERC20;
//////////////////////////////////////////////////////////////
// //
// Modifiers //
// //
//////////////////////////////////////////////////////////////
modifier onlyBeneficiary() {
require(msg.sender == beneficiary, "Vesting: Caller must be beneficiary");
_;
}
modifier onlyRevoker() {
require(msg.sender == revoker, "Vesting: Caller must be revoker");
_;
}
modifier onlyRevokerIfRevokedElseBeneficiary() {
if (revoked)
require(msg.sender == revoker, "Vesting: Caller must be revoker");
else
require(msg.sender == beneficiary, "Vesting: Caller must be beneficiary");
_;
}
modifier notRevoked() {
require(!revoked, "Vesting: token revoked");
_;
}
modifier afterStart() {
require(block.timestamp >= start, "Vesting: not started");
_;
}
//////////////////////////////////////////////////////////////
// //
// Variables //
// //
//////////////////////////////////////////////////////////////
// Vesting
address public beneficiary;
address public revoker;
bool public immutable transferableBeneficiary;
uint256 public immutable start;
uint256 public immutable end;
bool public revoked;
// Contracts
// solhint-disable-next-line var-name-mixedcase
IERC20 public immutable SESH;
IServiceNodeRewards public immutable rewardsContract;
IServiceNodeContributionFactory public immutable snContribFactory;
//////////////////////////////////////////////////////////////
// //
// State-changing functions //
// //
//////////////////////////////////////////////////////////////
/// @param beneficiary_ Address of the beneficiary to whom vested tokens
/// are transferred
/// @param revoker_ The person with the power to revoke the vesting.
/// Setting the zero address means it is not revocable.
/// @param start_ The unix time when the beneficiary can start staking the
/// tokens.
/// @param end_ The unix time of the end of the vesting period, everything
/// withdrawable after
/// @param transferableBeneficiary_ Whether the beneficiary address can be
/// transferred
/// @param rewardsContract_ The SESH staking rewards contract that can
/// be interacted with
/// @param sesh_ The SESH token address.
constructor(
address beneficiary_,
address revoker_,
uint256 start_,
uint256 end_,
bool transferableBeneficiary_,
IServiceNodeRewards rewardsContract_,
IServiceNodeContributionFactory snContribFactory_,
IERC20 sesh_
) nzAddr(beneficiary_) nzAddr(address(rewardsContract_)) nzAddr(address(sesh_)) {
require(start_ <= end_, "Vesting: start_ after end_");
require(block.timestamp < start_, "Vesting: start before current time");
beneficiary = beneficiary_;
revoker = revoker_;
start = start_;
end = end_;
transferableBeneficiary = transferableBeneficiary_;
rewardsContract = rewardsContract_;
snContribFactory = snContribFactory_;
SESH = sesh_;
}
//////////////////////////////////////////////////////////////
// //
// Rewards contract functions //
// //
//////////////////////////////////////////////////////////////
function addBLSPublicKey(
BN256G1.G1Point calldata blsPubkey,
IServiceNodeRewards.BLSSignatureParams calldata blsSignature,
IServiceNodeRewards.ServiceNodeParams calldata serviceNodeParams,
address snBeneficiary
) external onlyRevokerIfRevokedElseBeneficiary afterStart nzAddr(snBeneficiary) {
// NOTE: Configure custom beneficiary for investor
uint256 stakingRequirement = rewardsContract.stakingRequirement();
IServiceNodeRewards.Contributor[] memory contributors = new IServiceNodeRewards.Contributor[](1);
contributors[0] = IServiceNodeRewards.Contributor(IServiceNodeRewards.Staker(/*addr*/ address(this),
/*beneficiary*/ snBeneficiary),
stakingRequirement);
// NOTE: Allow staking requirement to be transferred
SESH.approve(address(rewardsContract), stakingRequirement);
// NOTE: Register node
rewardsContract.addBLSPublicKey(blsPubkey, blsSignature, serviceNodeParams, contributors);
}
function initiateExitBLSPublicKey(uint64 serviceNodeID) external onlyRevokerIfRevokedElseBeneficiary afterStart {
rewardsContract.initiateExitBLSPublicKey(serviceNodeID);
}
function claimRewards() external onlyRevokerIfRevokedElseBeneficiary afterStart {
rewardsContract.claimRewards();
}
function claimRewards(uint256 amount) external onlyRevokerIfRevokedElseBeneficiary afterStart {
rewardsContract.claimRewards(amount);
}
//////////////////////////////////////////////////////////////
// //
// Multi-contributor SN contract functions //
// //
//////////////////////////////////////////////////////////////
function getContributionContract(address contractAddr) private view returns (IServiceNodeContribution result) {
// NOTE: Retrieve contract
bool contractDeployed = snContribFactory.owns(contractAddr);
result = IServiceNodeContribution(contractAddr);
require(contractDeployed, "Contract address is not a valid multi-contributor SN contract");
}
function contributeFunds(address snContribAddr,
uint256 amount,
address snContribBeneficiary
) external onlyRevokerIfRevokedElseBeneficiary afterStart nzAddr(snContribBeneficiary) {
// NOTE: Approve and contribute funds
IServiceNodeContribution snContrib = getContributionContract(snContribAddr);
SESH.approve(snContribAddr, amount);
snContrib.contributeFunds(amount, snContribBeneficiary);
}
function withdrawContribution(address snContribAddr) external override onlyRevokerIfRevokedElseBeneficiary afterStart {
IServiceNodeContribution snContrib = getContributionContract(snContribAddr);
snContrib.withdrawContribution();
}
function updateBeneficiary(address snContribAddr,
address snContribBeneficiary
) external onlyRevokerIfRevokedElseBeneficiary afterStart nzAddr(snContribBeneficiary) {
IServiceNodeContribution snContrib = getContributionContract(snContribAddr);
snContrib.updateBeneficiary(snContribBeneficiary);
}
//////////////////////////////////////////////////////////////
// //
// Investor contract functions //
// //
//////////////////////////////////////////////////////////////
// @note Tokens are cliffed at the `end` time
function releasableAmount(IERC20 token) private view returns (uint256) {
return block.timestamp < end ? 0 : token.balanceOf(address(this));
}
function release(IERC20 token) external override onlyBeneficiary notRevoked {
uint256 amount = releasableAmount(token);
require(amount > 0, "Vesting: no tokens are due");
emit TokensReleased(token, amount);
token.safeTransfer(beneficiary, amount);
}
function revoke(IERC20 token) external override onlyRevoker {
if (!revoked) { // Only allowed to revoke whilst in vesting period
require(block.timestamp <= end, "Vesting: vesting expired");
revoked = true;
emit TokenVestingRevoked(token);
}
// NOTE: Revoker has to wait for vesting period as well for predictable
// circ. supply
uint256 amount = releasableAmount(token);
if (amount > 0) {
emit TokensRevokedReleased(token, amount);
token.safeTransfer(revoker, amount);
}
}
function transferBeneficiary(address beneficiary_) external override onlyBeneficiary nzAddr(beneficiary_) {
require(transferableBeneficiary, "Vesting: beneficiary not transferable");
emit BeneficiaryTransferred(beneficiary, beneficiary_);
beneficiary = beneficiary_;
}
function transferRevoker(address revoker_) external override onlyRevoker nzAddr(revoker_) {
emit RevokerTransferred(revoker, revoker_);
revoker = revoker_;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;
import "./IServiceNodeRewards.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
interface IServiceNodeContribution {
// Definitions
// Track the status of the multi-contribution contract. At any point in the
// contract's lifetime, `reset` can be invoked to set the contract back to
// `WaitForOperatorContrib`.
enum Status {
// Contract is initialised w/ no contributions. Call `contributeFunds`
// to transition into `OpenForPublicContrib`
WaitForOperatorContrib,
// Contract has been initially funded by operator. Public and reserved
// contributors can now call `contributeFunds`. When the contract is
// collaterialised with exactly the staking requirement, the contract
// transitions into `WaitForFinalized` state.
OpenForPublicContrib,
// Operator must invoke `finalizeNode` to transfer the tokens and the
// node registration details to the `stakingRewardsContract` to
// transition to `Finalized` state.
WaitForFinalized,
// Contract interactions are blocked until `reset` is called.
Finalized
}
struct ReservedContribution {
uint256 amount; // Amount that is reserved
bool received; // Records if the contributor has sent money to the contribution contract
}
//////////////////////////////////////////////////////////////
// //
// Events //
// //
//////////////////////////////////////////////////////////////
event Finalized ();
event NewContribution (address indexed contributor, address beneficiary, uint256 amount);
event OpenForPublicContribution ();
event Filled ();
event WithdrawContribution (address indexed contributor, uint256 amount);
event UpdateStakerBeneficiary (address indexed staker, address newBeneficiary);
event UpdateManualFinalize (bool newValue);
event UpdateFee (uint16 newFee);
event UpdatePubkeys (BN256G1.G1Point newBLSPubkey, uint256 newEd25519Pubkey);
event UpdateReservedContributors (IServiceNodeRewards.ReservedContributor[] newReservedContributors);
event Reset ();
//////////////////////////////////////////////////////////////
// //
// Variables //
// //
//////////////////////////////////////////////////////////////
function SESH() external view returns (IERC20);
function stakingRewardsContract() external view returns (IServiceNodeRewards);
function stakingRequirement() external view returns (uint256);
function blsPubkey() external view returns (uint256, uint256);
function serviceNodeParams() external view returns (IServiceNodeRewards.ServiceNodeParams memory);
function blsSignature() external view returns (IServiceNodeRewards.BLSSignatureParams memory);
function operator() external view returns (address);
function contributions(address) external view returns (uint256);
function contributionTimestamp(address) external view returns (uint256);
function contributorAddresses(uint256) external view returns (IServiceNodeRewards.Staker memory);
function maxContributors() external view returns (uint256);
function reservedContributions(address) external view returns (uint256, bool);
function reservedContributionsAddresses(uint256) external view returns (address);
function status() external view returns (Status);
function manualFinalize() external view returns (bool);
//////////////////////////////////////////////////////////////
// //
// Errors //
// //
//////////////////////////////////////////////////////////////
error CalcMinContributionGivenBadContribArgs (uint256 numContributors, uint256 maxNumContributors);
/// @notice Contract is not in a state where it can accept contributions
error ContributeFundsNotPossible (Status status);
error ContributionBelowMinAmount (uint256 contributed, uint256 min);
error ContributionBelowReservedAmount (uint256 contributed, uint256 reserved);
error ContributionExceedsStakingRequirement (uint256 totalContributed, uint256 totalReserved, uint256 stakingRequirement);
error DuplicateAddressInReservedContributor (uint256 index);
error FeeExceedsPossibleValue (uint16 fee, uint16 max);
error RequireWaitForOperatorContribStatus (Status status);
error FinalizeNotPossible (Status status);
error FirstContributionMustBeOperator (address contributor, address operator);
error BeneficiaryUpdatingDisabledNodeIsNotOpen(uint256 ed25519Pubkey);
/// @notice A wallet has attempted to contribute to the contract
/// before the operator's wallet has contributed.
error FirstReservedContributorMustBeOperator (uint256 index, address operator);
/// @notice A wallet has attempted an operation only permitted by the
/// operator
error OnlyOperatorIsAuthorised (address addr, address operator);
error MaxContributorsExceeded (uint256 maxContributors);
error RescueBalanceIsEmpty (address token);
error RescueNotPossible (Status status);
error ReservedContributorHasZeroAddress (uint256 index);
error ReservedContributionBelowMinAmount (uint256 index, uint256 contributed, uint256 min);
error ReservedContributionExceedsStakingRequirement(uint256 index, uint256 contributed, uint256 remaining);
/// @notice The rewards contract max contributor value has changed and no
/// longer matches this contract's max contributor value invalidating the
/// contract.
///
/// The operator or contributors should withdraw their funds and the operator
/// should deploy another contribution contract to attain a new contract with
/// the correct values.
error RewardsContractMaxContributorsChanged (uint256 oldMax, uint256 newMax);
/// @notice The staking requirement has changed on the rewards contract and
/// no longer matches this contract's staking requirement.
///
/// See `RewardsContractMaxContributorsChanged` for more info.
error RewardsContractStakingRequirementChanged (uint256 oldRequirement, uint256 newRequirement);
/// @notice Updating of beneficiary failed because the wallet that requested
/// it `nonContributorAddr` is not a contributor for this node.
error NonContributorUpdatedBeneficiary (address nonContributorAddr);
error TooManyReservedContributors (uint256 length, uint256 max);
error WithdrawTooEarly (uint256 contribTime, uint256 blockTime, uint256 delayRequired);
//////////////////////////////////////////////////////////////
// //
// State-changing functions //
// //
//////////////////////////////////////////////////////////////
/// @notice Update the flag that allows or disallows the contract from
/// automatically finalizing the contract when the staking requirement is met.
///
/// This can be called at any point of the contract's lifetime.
function updateManualFinalize(bool value) external;
/// @notice Update the node fee held in this contract.
///
/// This can only be called prior to the operator contributing funds to the
/// contract or alternatively after they have called `reset`.
function updateFee(uint16 fee) external;
/// @notice Update the public keys and their proofs held in the contract.
///
/// This can only be called prior to the operator contributing funds to the
/// contract or alternatively after they have called `reset`.
///
/// @param newBLSPubkey The new 64 byte BLS public key for the node.
/// @param newBLSSig The new 128 byte BLS proof-of-posession signature that proves
/// the caller knows the secret component of `key`.
/// @param ed25519Pubkey The new 32 byte Ed25519 public key for the node.
/// @param ed25519Sig0 First 32 byte component of the signature for the Ed25519 key.
/// @param ed25519Sig1 Second 32 byte component of the signature for the Ed25519 key.
function updatePubkeys(BN256G1.G1Point memory newBLSPubkey,
IServiceNodeRewards.BLSSignatureParams memory newBLSSig,
uint256 ed25519Pubkey,
uint256 ed25519Sig0,
uint256 ed25519Sig1) external;
/// @notice Update the reservation slots for contributors held in this contract.
///
/// This can only be called prior to the operator contributing funds to the
/// contract or alternatively after they have called `reset`.
///
/// The list of reservations can be empty which will reset the contract,
/// deleting any reservation data that is currently held. The list cannot
/// specify more reservations than `maxContributors` or otherwise the
/// function reverts.
///
/// @param reserved The new array of reserved contributors with their
/// proportion of stake they must fulfill in the node.
function updateReservedContributors(IServiceNodeRewards.ReservedContributor[] memory reserved) external;
/// @notice Update the beneficiary for the wallet/contributor that invokes
/// this call.
///
/// If the caller is not a contributor in this contract, the contract
/// reverts.
function updateBeneficiary(address newBeneficiary) external;
/// @notice Contribute funds to the contract for the node run by
/// `operator`. The `amount` of SESH token must be at least the
/// `minimumContribution` or their amount specified in their reserved
/// contribution (if applicable) otherwise the contribution is reverted.
///
/// Node registration parameters must be assigned prior to the operator
/// contribution or alternatively after `reset` is invoked.
///
/// The operator must contribute their minimum contribution/reservation
/// before the public or reserved contributors can contribute to the node.
/// The minimum an operator can contribute is 25% of the staking requirement
/// regardless of having a reservation or not.
///
/// @param amount The amount of SESH token to contribute to the contract.
/// @param beneficiary Optionally specify a beneficiary where rewards will
/// be paid out to. You may set this to `address(0)` to omit this field and
/// use the default behaviour which does one of two things,
///
/// 1. If the contributor has not assigned a beneficiary yet, it assigns
/// the current interacting wallet as the beneficiary (e.g. The rewards
/// are paid to the staking wallet).
///
/// 2. If the contributor has already assigned a beneficiary, the
/// beneficiary for the contributor remains unchanged.
function contributeFunds(uint256 amount, address beneficiary) external;
/// @notice Activate the node by transferring the registration details and
/// tokens to the `stakingRewardsContract`.
///
/// After finalisation the contract can be reused by invoking `reset`.
function finalize() external;
/// @notice Reset the contract allowing it to be reused to re-register the
/// pre-existing node by refunding and removing all stored contributions.
///
/// This function can be called any point in the lifetime of the contract to
/// bring it to its initial state. Node parameters (Ed25519 key, sig, fee)
/// and the BLS key and signature are preserved across reset and can be
/// updated piecemeal via the `update...` family of functions.
function reset() external;
/// @notice Helper function that invokes a reset and updates all possible
/// parameters for the registration.
///
/// This function is equivalent to calling in sequence:
///
/// - `reset`
/// - `updatePubkeys`
/// - `updateFee`
/// - `updateReservedContributors`
/// - `updateManualFinalize`
/// - `contributeFunds`
///
/// If reserved contributors are not desired, an empty array is accepted.
///
/// If the operator wishes to withhold their initial contribution, a `0`
/// amount is accepted. When a `0` amount is specified, `beneficiary` is
/// also ignored.
function resetUpdateAndContribute(BN256G1.G1Point memory key,
IServiceNodeRewards.BLSSignatureParams memory sig,
IServiceNodeRewards.ServiceNodeParams memory params,
IServiceNodeRewards.ReservedContributor[] memory reserved,
bool _manualFinalize,
address beneficiary,
uint256 amount) external;
/// @notice Function to allow owner to rescue any ERC20 tokens sent to the
/// contract after it has been finalized.
///
/// @dev Rescue is only allowed when finalized or no contribution has been
/// made to the contract so any token balance from contributors are either
/// absent or have been transferred to the `stakingRewardsContract` and the
/// remaining tokens can be sent without risking contributor collateral.
///
/// @param tokenAddress The ERC20 token to rescue from the contract.
function rescueERC20(address tokenAddress) external;
/// @notice Allows the contributor or operator to withdraw their contribution
/// from the contract.
///
/// After finalization, the registration is transferred to the
/// `stakingRewardsContract` and withdrawal by or the operator contributors
/// must be done through that contract.
function withdrawContribution() external;
//////////////////////////////////////////////////////////////
// //
// Non-state-changing functions //
// //
//////////////////////////////////////////////////////////////
/// @notice Calculates the minimum contribution amount given the current
/// contribution status of the contract.
///
/// @dev The minimum contribution is dynamically calculated based on the
/// number of contributors and the staking requirement. It returns
/// math.ceilDiv of the calculation
///
/// @return result The minimum contribution amount.
function minimumContribution() external view returns (uint256 result);
/// @notice Function to calculate the minimum contribution given the staking
/// parameters.
///
/// This function reverts if invalid parameters are given such that the
/// operations would wrap or divide by 0.
///
/// @param contributionRemaining The amount of contribution still available
/// to be contributed to this contract.
/// @param numContributors The number of contributors that have contributed
/// to the contract already including the operator.
/// @param maxNumContributors The maximum number of contributors allowed to
/// contribute to this contract.
function calcMinimumContribution(
uint256 contributionRemaining,
uint256 numContributors,
uint256 maxNumContributors
) external pure returns (uint256 result);
/// @notice Calculates the minimum operator contribution given the staking
/// requirement.
function minimumOperatorContribution(uint256 _stakingRequirement) external pure returns (uint256 result);
/// @dev This function allows unit-tests to query the length without having
/// to know the storage slot of the array size.
function contributorAddressesLength() external view returns (uint256 result);
/// @notice Get the contribution by the operator, defined to always be the
/// first contribution in the contract.
function operatorContribution() external view returns (uint256 result);
/// @notice Access the list of contributor addresses and corresponding contributions. The
/// first returned address (if any) is also the operator address.
function getContributions() external view returns (address[] memory addrs, address[] memory beneficiaries, uint256[] memory contribs);
/// @notice Access the list of reserved addresses and corresponding
/// contributions. The first returned address (if any) is also the operator
/// address.
function getReserved() external view returns (address[] memory addrs, uint256[] memory contribs, bool[] memory received);
/// @notice Sum up all the contributions recorded in the contributors list
function totalContribution() external view returns (uint256 result);
/// @notice Sum up all the reserved contributions recorded in the reserved list
function totalReservedContribution() external view returns (uint256 result);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;
import "./IServiceNodeRewards.sol";
interface IServiceNodeContributionFactory {
function stakingRewardsContract() external view returns (IServiceNodeRewards);
function deployedContracts(address) external view returns (bool);
function deploy(BN256G1.G1Point calldata key,
IServiceNodeRewards.BLSSignatureParams calldata sig,
IServiceNodeRewards.ServiceNodeParams calldata params,
IServiceNodeRewards.ReservedContributor[] calldata reserved,
bool manualFinalize) external returns (address result);
function owns(address contractAddress) external view returns (bool);
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../libraries/BN256G1.sol";
interface IServiceNodeRewards {
struct Staker {
address addr; // Address that is contributing the stake
address beneficiary; // Address rewards are paid out to
}
struct Contributor {
Staker staker; // Address details for contributor
uint256 stakedAmount; // Amount staked by the contributor
}
struct ReservedContributor {
address addr; // Address that is reserving a contribution amount
uint256 amount; // Amount that the address is reserving
}
struct SeedServiceNode {
BN256G1.G1Point blsPubkey;
uint256 ed25519Pubkey;
uint256 addedTimestamp;
Contributor[] contributors;
}
/// @notice Represents a node in the network.
struct ServiceNode {
uint64 next;
uint64 prev;
address operator;
BN256G1.G1Point blsPubkey;
uint256 addedTimestamp;
/// Timestamp of the first time a leave request was requeste on the node
uint256 leaveRequestTimestamp;
/// Timestamp of the latest time a leave request was requested on the
/// node. Multiple leave requests are permitted for node in the event
/// that the Session network rejects the request for various possible
/// reasons.
///
/// Subsequent leave requests can be overlapped to get the network to
/// re-emit the event to be witnessed by the Session network again.
uint256 latestLeaveRequestTimestamp;
uint256 deposit;
Contributor[] contributors;
uint256 ed25519Pubkey;
}
/// @notice Represents a recipient of rewards, how much they can claim and how much previously claimed.
struct Recipient {
uint256 rewards;
uint256 claimed;
}
struct BLSSignatureParams {
uint256 sigs0;
uint256 sigs1;
uint256 sigs2;
uint256 sigs3;
}
struct ServiceNodeParams {
uint256 serviceNodePubkey;
uint256 serviceNodeSignature1;
uint256 serviceNodeSignature2;
uint16 fee;
}
// Public Variables
function aggregatePubkey() external view returns (BN256G1.G1Point memory);
function blsNonSignerThreshold() external view returns (uint256);
function designatedToken() external view returns (IERC20);
function foundationPool() external view returns (IERC20);
function isStarted() external view returns (bool);
function liquidateTag() external view returns (bytes32);
function liquidatorRewardRatio() external view returns (uint256);
function maxContributors() external view returns (uint256);
function nextServiceNodeID() external view returns (uint64);
function poolShareOfLiquidationRatio() external view returns (uint256);
function proofOfPossessionTag() external view returns (bytes32);
function recipientRatio() external view returns (uint256);
function recipients(address) external view returns (uint256 rewards, uint256 claimed);
function exitTag() external view returns (bytes32);
function rewardTag() external view returns (bytes32);
function serviceNodes(uint64) external view returns (ServiceNode memory);
function serviceNodeIDs(bytes memory) external view returns (uint64);
function allServiceNodeIDs() external view returns (uint64[] memory ids, BN256G1.G1Point[] memory pubkeys);
function stakingRequirement() external view returns (uint256);
function totalNodes() external view returns (uint256);
// Function Signatures
function updateRewardsBalance(
address recipientAddress,
uint256 recipientRewards,
BLSSignatureParams calldata blsSignature,
uint64[] memory ids
) external;
function claimRewards() external;
function claimRewards(uint256 amount) external;
function addBLSPublicKey(
BN256G1.G1Point memory blsPubkey,
BLSSignatureParams memory blsSignature,
ServiceNodeParams memory serviceNodeParams,
Contributor[] memory contributors
) external;
function validateProofOfPossession(BN256G1.G1Point memory blsPubkey, BLSSignatureParams memory blsSignature, address caller, uint256 serviceNodePubkey) external;
function initiateExitBLSPublicKey(uint64 serviceNodeID) external;
function exitBLSPublicKeyWithSignature(
BN256G1.G1Point calldata blsPubkey,
uint256 timestamp,
BLSSignatureParams calldata blsSignature,
uint64[] memory ids
) external;
function exitBLSPublicKeyAfterWaitTime(uint64 serviceNodeID) external;
function liquidateBLSPublicKeyWithSignature(
BN256G1.G1Point calldata blsPubkey,
uint256 timestamp,
BLSSignatureParams calldata blsSignature,
uint64[] memory ids
) external;
function seedPublicKeyList(SeedServiceNode[] calldata nodes) external;
function rederiveTotalNodesAndAggregatePubkey() external;
function start() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../interfaces/IServiceNodeRewards.sol";
import "../interfaces/IServiceNodeContributionFactory.sol";
import "../interfaces/IServiceNodeContribution.sol";
interface ITokenVestingStaking {
//////////////////////////////////////////////////////////////
// //
// Events //
// //
//////////////////////////////////////////////////////////////
event TokensReleased (IERC20 indexed token, uint256 amount);
event TokensRevokedReleased (IERC20 indexed token, uint256 amount);
event TokenVestingRevoked (IERC20 indexed token);
event BeneficiaryTransferred(address oldBeneficiary, address newBeneficiary);
event RevokerTransferred (address oldRevoker, address newRevoker);
//////////////////////////////////////////////////////////////
// //
// Variables //
// //
//////////////////////////////////////////////////////////////
/// @notice Address configured to receive tokens after they've vested from
/// the contract. The beneficiary is transferable if the contract was
/// deployed with the `transferableBeneficiary` enabled.
function beneficiary() external view returns (address);
/// @notice Indicates if the beneficiary is transferable to a new address or
/// not.
function transferableBeneficiary() external view returns (bool);
/// @notice Start time of the contract's vesting period denoted as a unix
/// timestamp
function start() external view returns (uint256);
/// @notice End time of the contract's vesting period denoted as a unix
/// timestamp
function end() external view returns (uint256);
/// @notice The token that the contract is vesting to the investor.
function SESH() external view returns (IERC20);
/// @notice The contract that accepts investor tokens for staking
function rewardsContract() external view returns (IServiceNodeRewards);
/// @notice The contract that deploys multi-contributor contracts that the
/// investor can stake to.
function snContribFactory() external view returns (IServiceNodeContributionFactory);
/// @notice Address that has permissions to halt the vesting process and
/// withdraw the tokens. The revoker also has permissions to access admin
/// functions of the contract.
function revoker() external view returns (address);
//////////////////////////////////////////////////////////////
// //
// State-changing functions //
// //
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// //
// Rewards contract functions //
// //
//////////////////////////////////////////////////////////////
/// @notice Adds a BLS public key to the list of service nodes. Requires
/// a proof of possession BLS signature to prove user controls the public
/// key being added.
///
/// @param blsPubkey 64 byte BLS public key for the service node.
/// @param blsSignature 128 byte BLS proof of possession signature that
/// proves ownership of the `blsPubkey`.
/// @param serviceNodeParams The service node to add including the ed25519
/// public key and signature that proves ownership of the private component
/// of the public key and the desired fee the operator is charging.
/// @param snBeneficiary Address that should receive the staking rewards
/// This address may not be set to the zero address `address(0)`.
function addBLSPublicKey(
BN256G1.G1Point calldata blsPubkey,
IServiceNodeRewards.BLSSignatureParams calldata blsSignature,
IServiceNodeRewards.ServiceNodeParams calldata serviceNodeParams,
address snBeneficiary
) external;
/// @notice Initiates a request for the service node to leave the network by
/// their service node ID.
///
/// @param serviceNodeID The ID of the service node to be removed.
function initiateExitBLSPublicKey(uint64 serviceNodeID) external;
/// @notice Retrieves the unlocked balance from exited/deregistered nodes
/// back into this investor's contract.
function claimRewards() external;
/// @notice Claim a specific amount of unlocked balance from
/// exited/deregistered nodes back into this investor's contract.
function claimRewards(uint256 amount) external;
//////////////////////////////////////////////////////////////
// //
// Multi-contributor SN contract functions //
// //
//////////////////////////////////////////////////////////////
/// @notice Contribute funds to the specified multi-contribution contract.
///
/// @param snContribAddr Address of the multi-contributor contract to
/// update. Reverts if the contract was not deployed by the factory assigned
/// to this contract.
/// @param snContribBeneficiary Specify the address that will receive the
/// rewards. This address may be set to `address(0)` to use the default
/// behaviour. See `contributeFunds` in `IServiceNodeContribution`
function contributeFunds(address snContribAddr,
uint256 amount,
address snContribBeneficiary) external;
/// @notice Withdraw the contribution that has been made prior to a
/// multi-contributor contract in `contributeFunds` returning the funds
/// back to this investor's contract.
///
/// This is only valid if the multi-contribution contract has not finalised
/// yet or has already been reset.
///
/// - If it has been finalised the funds have been transferred to the
/// rewards contract in which they must exit the node to reclaim their
/// funds back to the investor's contract.
///
/// - If the contract has been reset the funds have been returned back to
/// this contract already.
///
/// @param snContribAddr Address of the multi-contributor contract to
/// update. Reverts if the contract was not deployed by the factory assigned
/// to this contract.
function withdrawContribution(address snContribAddr) external;
/// @notice Assign a new beneficiary for a multi-contributor contract that
/// this contract has contributed to prior.
/// @param snContribAddr Address of the multi-contributor contract to
/// update. Reverts if the contract was not deployed by the factory assigned
/// to this contract.
/// @param snContribBeneficiary Specify the address that will receive the
/// rewards. See notes on `snContribBeneficiary` for `contributeFunds`.
function updateBeneficiary(address snContribAddr, address snContribBeneficiary) external;
//////////////////////////////////////////////////////////////
// //
// Investor contract functions //
// //
//////////////////////////////////////////////////////////////
/// @notice Transfers vested tokens to beneficiary.
/// @param token ERC20 token which is being vested.
function release(IERC20 token) external;
/// @notice Revoke the vesting contract and return funds to the revoker.
/// This can be called multiple times by revoker to retrieve any additional
/// tokens that are sent to the contract after revocation.
///
/// On the first revocation, `TokenVestingRevoked` is emit and omitted for
/// subsequent calls.
///
/// @param token ERC20 token to retrieve the balance for
function revoke(IERC20 token) external;
/// @notice Changes the beneficiary for the contract. Only permitted if
/// `transferableBeneficiary` is set.
function transferBeneficiary(address beneficiary_) external;
/// @notice Change the revoker for the contract
function transferRevoker(address revoker_) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.26;
library BN256G1 {
uint256 internal constant FIELD_MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47;
struct G1Point {
uint X;
uint Y;
}
/// @return the generator of G1
function P1() internal pure returns (G1Point memory) {
return G1Point(1, 2);
}
/// @return r the negation of p, i.e. p.add(p.negate()) should be zero.
function negate(G1Point memory p) internal pure returns (G1Point memory r) {
if (p.X == 0 && p.Y == 0) return G1Point(0, 0);
return G1Point(p.X, FIELD_MODULUS - (p.Y % FIELD_MODULUS));
}
/// @return r the sum of two points of G1
function add(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) {
uint[4] memory input;
input[0] = p1.X;
input[1] = p1.Y;
input[2] = p2.X;
input[3] = p2.Y;
bool success;
assembly {
success := staticcall(sub(gas(), 2000), 6, input, 0x80, r, 0x40)
}
require(success, "Call to precompiled contract for add failed");
}
function getKeyForG1Point(G1Point memory point) internal pure returns (bytes memory) {
return abi.encode(point);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
/**
* @title Shared contract
* @notice Holds constants and modifiers that are used in multiple contracts
* @dev It would be nice if this could be a library, but modifiers can't be exported :(
*/
abstract contract Shared {
address internal constant _ZERO_ADDR = address(0);
bytes32 internal constant _NULL = "";
/// @dev Checks that a uint isn't zero/empty
modifier nzUint(uint256 u) {
require(u != 0, "Shared: uint input is empty");
_;
}
/// @dev Checks that an address isn't zero/empty
modifier nzAddr(address a) {
require(a != _ZERO_ADDR, "Shared: Zero-address is not permitted");
_;
}
/// @dev Checks that a bytes32 isn't zero/empty
modifier nzBytes32(bytes32 b) {
require(b != _NULL, "Shared: bytes32 input is empty");
_;
}
}{
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"runs": 1,
"enabled": true
},
"evmVersion": "paris",
"remappings": [],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"beneficiary_","type":"address"},{"internalType":"address","name":"revoker_","type":"address"},{"internalType":"uint256","name":"start_","type":"uint256"},{"internalType":"uint256","name":"end_","type":"uint256"},{"internalType":"bool","name":"transferableBeneficiary_","type":"bool"},{"internalType":"contract IServiceNodeRewards","name":"rewardsContract_","type":"address"},{"internalType":"contract IServiceNodeContributionFactory","name":"snContribFactory_","type":"address"},{"internalType":"contract IERC20","name":"sesh_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldBeneficiary","type":"address"},{"indexed":false,"internalType":"address","name":"newBeneficiary","type":"address"}],"name":"BeneficiaryTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRevoker","type":"address"},{"indexed":false,"internalType":"address","name":"newRevoker","type":"address"}],"name":"RevokerTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"}],"name":"TokenVestingRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensReleased","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensRevokedReleased","type":"event"},{"inputs":[],"name":"SESH","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"X","type":"uint256"},{"internalType":"uint256","name":"Y","type":"uint256"}],"internalType":"struct BN256G1.G1Point","name":"blsPubkey","type":"tuple"},{"components":[{"internalType":"uint256","name":"sigs0","type":"uint256"},{"internalType":"uint256","name":"sigs1","type":"uint256"},{"internalType":"uint256","name":"sigs2","type":"uint256"},{"internalType":"uint256","name":"sigs3","type":"uint256"}],"internalType":"struct IServiceNodeRewards.BLSSignatureParams","name":"blsSignature","type":"tuple"},{"components":[{"internalType":"uint256","name":"serviceNodePubkey","type":"uint256"},{"internalType":"uint256","name":"serviceNodeSignature1","type":"uint256"},{"internalType":"uint256","name":"serviceNodeSignature2","type":"uint256"},{"internalType":"uint16","name":"fee","type":"uint16"}],"internalType":"struct IServiceNodeRewards.ServiceNodeParams","name":"serviceNodeParams","type":"tuple"},{"internalType":"address","name":"snBeneficiary","type":"address"}],"name":"addBLSPublicKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"snContribAddr","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"snContribBeneficiary","type":"address"}],"name":"contributeFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"end","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"serviceNodeID","type":"uint64"}],"name":"initiateExitBLSPublicKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"release","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"revoke","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revoked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"revoker","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardsContract","outputs":[{"internalType":"contract IServiceNodeRewards","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"snContribFactory","outputs":[{"internalType":"contract IServiceNodeContributionFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"start","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"beneficiary_","type":"address"}],"name":"transferBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"revoker_","type":"address"}],"name":"transferRevoker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferableBeneficiary","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"snContribAddr","type":"address"},{"internalType":"address","name":"snContribBeneficiary","type":"address"}],"name":"updateBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"snContribAddr","type":"address"}],"name":"withdrawContribution","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
61014060405234801561001157600080fd5b50604051611dae380380611dae833981016040819052610030916101cc565b876001600160a01b0381166100605760405162461bcd60e51b81526004016100579061026e565b60405180910390fd5b836001600160a01b0381166100875760405162461bcd60e51b81526004016100579061026e565b826001600160a01b0381166100ae5760405162461bcd60e51b81526004016100579061026e565b878911156100fe5760405162461bcd60e51b815260206004820152601a60248201527f56657374696e673a2073746172745f20616674657220656e645f0000000000006044820152606401610057565b8842106101585760405162461bcd60e51b815260206004820152602260248201527f56657374696e673a207374617274206265666f72652063757272656e742074696044820152616d6560f01b6064820152608401610057565b5050600080546001600160a01b03199081166001600160a01b039b8c161790915560018054909116988a169890981790975560a09590955260c09390935290151560805284166101005283166101205290911660e052506102b3565b6001600160a01b03811681146101c957600080fd5b50565b600080600080600080600080610100898b0312156101e957600080fd5b88516101f4816101b4565b60208a0151909850610205816101b4565b60408a015160608b015160808c01519299509097509550801515811461022a57600080fd5b60a08a015190945061023b816101b4565b60c08a015190935061024c816101b4565b60e08a015190925061025d816101b4565b809150509295985092959890939650565b60208082526025908201527f5368617265643a205a65726f2d61646472657373206973206e6f74207065726d6040820152641a5d1d195960da1b606082015260800190565b60805160a05160c05160e0516101005161012051611a2761038760003960008181610230015261135f015260008181610141015281816103eb0152818161076e01528181610d3401528181610e9401528181610f1901526112220152600081816102c5015281816108d80152610e670152600081816102ff01528181610b3d015261125d015260008181610290015281816103970152818161072e0152818161084e01528181610a2901528181610ccb01528181610ffc01526111c60152600081816101bf01526104a60152611a276000f3fe608060405234801561001057600080fd5b50600436106100fc5760003560e01c80630962ef791461010157806314bbe21c146101165780631916558714610129578063220cce971461013c57806335dec5d114610179578063372500ab1461018c57806338af3eed1461019457806343cac780146101a757806352208a5f146101ba57806363d256ce146101f15780637249d9d91461020557806374a8f103146102185780638a0b4e991461022b57806395e3fd3714610252578063a35c470914610265578063ac8d6c0c14610278578063be9a65551461028b578063c3aca558146102c0578063d9054b09146102e7578063efbe1c1c146102fa575b600080fd5b61011461010f3660046115f3565b610321565b005b610114610124366004611621565b610453565b610114610137366004611621565b610589565b6101637f000000000000000000000000000000000000000000000000000000000000000081565b604051610170919061163e565b60405180910390f35b600154610163906001600160a01b031681565b6101146106c1565b600054610163906001600160a01b031681565b6101146101b5366004611652565b6107e1565b6101e17f000000000000000000000000000000000000000000000000000000000000000081565b6040519015158152602001610170565b6001546101e190600160a01b900460ff1681565b610114610213366004611694565b6109bc565b610114610226366004611621565b610b00565b6101637f000000000000000000000000000000000000000000000000000000000000000081565b6101146102603660046116df565b610c5e565b610114610273366004611621565b610f8f565b610114610286366004611621565b61109e565b6102b27f000000000000000000000000000000000000000000000000000000000000000081565b604051908152602001610170565b6101637f000000000000000000000000000000000000000000000000000000000000000081565b6101146102f5366004611741565b611159565b6102b27f000000000000000000000000000000000000000000000000000000000000000081565b600154600160a01b900460ff161561036b576001546001600160a01b031633146103665760405162461bcd60e51b815260040161035d9061176a565b60405180910390fd5b610395565b6000546001600160a01b031633146103955760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000000000004210156103d55760405162461bcd60e51b815260040161035d906117e4565b604051630962ef7960e01b8152600481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690630962ef79906024015b600060405180830381600087803b15801561043857600080fd5b505af115801561044c573d6000803e3d6000fd5b5050505050565b6000546001600160a01b0316331461047d5760405162461bcd60e51b815260040161035d906117a1565b806001600160a01b0381166104a45760405162461bcd60e51b815260040161035d90611812565b7f000000000000000000000000000000000000000000000000000000000000000061051f5760405162461bcd60e51b815260206004820152602560248201527f56657374696e673a2062656e6566696369617279206e6f74207472616e7366656044820152647261626c6560d81b606482015260840161035d565b6000546040517f57005c5083fa0952870a7906715a2f6f9ef2d01b4a423e4b3ce59c6129b1a7639161055e916001600160a01b03909116908590611857565b60405180910390a150600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105b35760405162461bcd60e51b815260040161035d906117a1565b600154600160a01b900460ff16156106065760405162461bcd60e51b815260206004820152601660248201527515995cdd1a5b99ce881d1bdad95b881c995d9bdad95960521b604482015260640161035d565b600061061182611259565b9050600081116106605760405162461bcd60e51b815260206004820152601a60248201527956657374696e673a206e6f20746f6b656e73206172652064756560301b604482015260640161035d565b816001600160a01b03167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df931798260405161069b91815260200190565b60405180910390a26000546106bd906001600160a01b038481169116836112fd565b5050565b600154600160a01b900460ff1615610702576001546001600160a01b031633146106fd5760405162461bcd60e51b815260040161035d9061176a565b61072c565b6000546001600160a01b0316331461072c5760405162461bcd60e51b815260040161035d906117a1565b7f000000000000000000000000000000000000000000000000000000000000000042101561076c5760405162461bcd60e51b815260040161035d906117e4565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663372500ab6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107c757600080fd5b505af11580156107db573d6000803e3d6000fd5b50505050565b600154600160a01b900460ff1615610822576001546001600160a01b0316331461081d5760405162461bcd60e51b815260040161035d9061176a565b61084c565b6000546001600160a01b0316331461084c5760405162461bcd60e51b815260040161035d906117a1565b7f000000000000000000000000000000000000000000000000000000000000000042101561088c5760405162461bcd60e51b815260040161035d906117e4565b806001600160a01b0381166108b35760405162461bcd60e51b815260040161035d90611812565b60006108be8561135a565b60405163095ea7b360e01b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b39061090f9088908890600401611871565b6020604051808303816000875af115801561092e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610952919061188a565b50604051632816ee7360e01b8152600481018590526001600160a01b038481166024830152821690632816ee7390604401600060405180830381600087803b15801561099d57600080fd5b505af11580156109b1573d6000803e3d6000fd5b505050505050505050565b600154600160a01b900460ff16156109fd576001546001600160a01b031633146109f85760405162461bcd60e51b815260040161035d9061176a565b610a27565b6000546001600160a01b03163314610a275760405162461bcd60e51b815260040161035d906117a1565b7f0000000000000000000000000000000000000000000000000000000000000000421015610a675760405162461bcd60e51b815260040161035d906117e4565b806001600160a01b038116610a8e5760405162461bcd60e51b815260040161035d90611812565b6000610a998461135a565b604051630557fe9560e11b81529091506001600160a01b03821690630aaffd2a90610ac890869060040161163e565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b5050505050505050565b6001546001600160a01b03163314610b2a5760405162461bcd60e51b815260040161035d9061176a565b600154600160a01b900460ff16610bee577f0000000000000000000000000000000000000000000000000000000000000000421115610ba65760405162461bcd60e51b815260206004820152601860248201527715995cdd1a5b99ce881d995cdd1a5b99c8195e1c1a5c995960421b604482015260640161035d565b6001805460ff60a01b1916600160a01b1790556040516001600160a01b038216907f39983c6d4d174a7aee564f449d4a5c3c7ac9649d72b7793c56901183996f8af690600090a25b6000610bf982611259565b905080156106bd57816001600160a01b03167fa415e62e43678c8b550c180a7ef9a2031e826b306d4052104d288f3c83ac964b82604051610c3c91815260200190565b60405180910390a26001546106bd906001600160a01b038481169116836112fd565b600154600160a01b900460ff1615610c9f576001546001600160a01b03163314610c9a5760405162461bcd60e51b815260040161035d9061176a565b610cc9565b6000546001600160a01b03163314610cc95760405162461bcd60e51b815260040161035d906117a1565b7f0000000000000000000000000000000000000000000000000000000000000000421015610d095760405162461bcd60e51b815260040161035d906117e4565b806001600160a01b038116610d305760405162461bcd60e51b815260040161035d90611812565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166356d399e86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db491906118ac565b60408051600180825281830190925291925060009190816020015b6040805160808101825260009181018281526060820183905281526020810191909152815260200190600190039081610dcf57505060408051608081018252309181019182526001600160a01b0387166060820152908152602081018490528151919250908290600090610e4557610e456118c5565b602090810291909101015260405163095ea7b360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063095ea7b390610ebe907f0000000000000000000000000000000000000000000000000000000000000000908690600401611871565b6020604051808303816000875af1158015610edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f01919061188a565b50604051632f1fbfb360e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063bc7efecc90610f54908a908a908a90879060040161193a565b600060405180830381600087803b158015610f6e57600080fd5b505af1158015610f82573d6000803e3d6000fd5b5050505050505050505050565b600154600160a01b900460ff1615610fd0576001546001600160a01b03163314610fcb5760405162461bcd60e51b815260040161035d9061176a565b610ffa565b6000546001600160a01b03163314610ffa5760405162461bcd60e51b815260040161035d906117a1565b7f000000000000000000000000000000000000000000000000000000000000000042101561103a5760405162461bcd60e51b815260040161035d906117e4565b60006110458261135a565b9050806001600160a01b0316630d616d206040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561108257600080fd5b505af1158015611096573d6000803e3d6000fd5b505050505050565b6001546001600160a01b031633146110c85760405162461bcd60e51b815260040161035d9061176a565b806001600160a01b0381166110ef5760405162461bcd60e51b815260040161035d90611812565b6001546040517fd0fc5fb9c7c77f1a24739dedc1219c212e20f8711ce4551d2e97909e0f3f59ba9161112e916001600160a01b03909116908590611857565b60405180910390a150600180546001600160a01b0319166001600160a01b0392909216919091179055565b600154600160a01b900460ff161561119a576001546001600160a01b031633146111955760405162461bcd60e51b815260040161035d9061176a565b6111c4565b6000546001600160a01b031633146111c45760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000000000004210156112045760405162461bcd60e51b815260040161035d906117e4565b60405163d9054b0960e01b81526001600160401b03821660048201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063d9054b099060240161041e565b60007f000000000000000000000000000000000000000000000000000000000000000042106112f4576040516370a0823160e01b81526001600160a01b038316906370a08231906112ae90309060040161163e565b602060405180830381865afa1580156112cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ef91906118ac565b6112f7565b60005b92915050565b61135583846001600160a01b031663a9059cbb8585604051602401611323929190611871565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611468565b505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f7bc39bf846040518263ffffffff1660e01b81526004016113a9919061163e565b602060405180830381865afa1580156113c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ea919061188a565b9050829150806114625760405162461bcd60e51b815260206004820152603d60248201527f436f6e74726163742061646472657373206973206e6f7420612076616c69642060448201527f6d756c74692d636f6e7472696275746f7220534e20636f6e7472616374000000606482015260840161035d565b50919050565b600061147d6001600160a01b038416836114c2565b905080516000141580156114a25750808060200190518101906114a0919061188a565b155b156113555782604051635274afe760e01b815260040161035d919061163e565b60606114d0838360006114d7565b9392505050565b6060814710156114fc573060405163cd78605960e01b815260040161035d919061163e565b600080856001600160a01b0316848660405161151891906119c2565b60006040518083038185875af1925050503d8060008114611555576040519150601f19603f3d011682016040523d82523d6000602084013e61155a565b606091505b509150915061156a868383611574565b9695505050505050565b60608261158957611584826115c7565b6114d0565b81511580156115a057506001600160a01b0384163b155b156115c05783604051639996b31560e01b815260040161035d919061163e565b50806114d0565b8051156115d75780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006020828403121561160557600080fd5b5035919050565b6001600160a01b03811681146115f057600080fd5b60006020828403121561163357600080fd5b81356114d08161160c565b6001600160a01b0391909116815260200190565b60008060006060848603121561166757600080fd5b83356116728161160c565b92506020840135915060408401356116898161160c565b809150509250925092565b600080604083850312156116a757600080fd5b82356116b28161160c565b915060208301356116c28161160c565b809150509250929050565b60006080828403121561146257600080fd5b6000806000808486036101608112156116f757600080fd5b604081121561170557600080fd5b5084935061171686604087016116cd565b92506117258660c087016116cd565b91506101408501356117368161160c565b939692955090935050565b60006020828403121561175357600080fd5b81356001600160401b03811681146114d057600080fd5b6020808252601f908201527f56657374696e673a2043616c6c6572206d757374206265207265766f6b657200604082015260600190565b60208082526023908201527f56657374696e673a2043616c6c6572206d7573742062652062656e656669636960408201526261727960e81b606082015260800190565b60208082526014908201527315995cdd1a5b99ce881b9bdd081cdd185c9d195960621b604082015260600190565b60208082526025908201527f5368617265643a205a65726f2d61646472657373206973206e6f74207065726d6040820152641a5d1d195960da1b606082015260800190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60006020828403121561189c57600080fd5b815180151581146114d057600080fd5b6000602082840312156118be57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600081518084526020840193506020830160005b82811015611930578151805180516001600160a01b0390811689526020918201511681890152908101516040880152606090960195909101906001016118ef565b5093949350505050565b84358152602080860135818301528435604080840191909152858201356060808501919091528187013560808501528087013560a0850152853560c08501529185013560e084015284013561010083015260009084013561ffff81168082146119a257600080fd5b80610120850152505061016061014083015261156a6101608301846118db565b6000825160005b818110156119e357602081860181015185830152016119c9565b50600092019182525091905056fea26469706673582212204dfd0f42419cf27aaccc404b541487609f3d6e69b884b40aa554d68d51345df064736f6c634300081e0033000000000000000000000000b00e81207bcda63c9e290e0b748252418818c869000000000000000000000000f985ad6b3ecc748b41f4e8aeb0b698c1c7d1906000000000000000000000000000000000000000000000000000000000682d1780000000000000000000000000000000000000000000000000000000006bef7e800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c000000000000000000000000008129be2d5ef7acd39483c19f28de86b7ef19dbca00000000000000000000000010ea9e5303670331bdddfa66a4cea47dae4fcf3b
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100fc5760003560e01c80630962ef791461010157806314bbe21c146101165780631916558714610129578063220cce971461013c57806335dec5d114610179578063372500ab1461018c57806338af3eed1461019457806343cac780146101a757806352208a5f146101ba57806363d256ce146101f15780637249d9d91461020557806374a8f103146102185780638a0b4e991461022b57806395e3fd3714610252578063a35c470914610265578063ac8d6c0c14610278578063be9a65551461028b578063c3aca558146102c0578063d9054b09146102e7578063efbe1c1c146102fa575b600080fd5b61011461010f3660046115f3565b610321565b005b610114610124366004611621565b610453565b610114610137366004611621565b610589565b6101637f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c0081565b604051610170919061163e565b60405180910390f35b600154610163906001600160a01b031681565b6101146106c1565b600054610163906001600160a01b031681565b6101146101b5366004611652565b6107e1565b6101e17f000000000000000000000000000000000000000000000000000000000000000181565b6040519015158152602001610170565b6001546101e190600160a01b900460ff1681565b610114610213366004611694565b6109bc565b610114610226366004611621565b610b00565b6101637f0000000000000000000000008129be2d5ef7acd39483c19f28de86b7ef19dbca81565b6101146102603660046116df565b610c5e565b610114610273366004611621565b610f8f565b610114610286366004611621565b61109e565b6102b27f00000000000000000000000000000000000000000000000000000000682d178081565b604051908152602001610170565b6101637f00000000000000000000000010ea9e5303670331bdddfa66a4cea47dae4fcf3b81565b6101146102f5366004611741565b611159565b6102b27f000000000000000000000000000000000000000000000000000000006bef7e8081565b600154600160a01b900460ff161561036b576001546001600160a01b031633146103665760405162461bcd60e51b815260040161035d9061176a565b60405180910390fd5b610395565b6000546001600160a01b031633146103955760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d17804210156103d55760405162461bcd60e51b815260040161035d906117e4565b604051630962ef7960e01b8152600481018290527f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c006001600160a01b031690630962ef79906024015b600060405180830381600087803b15801561043857600080fd5b505af115801561044c573d6000803e3d6000fd5b5050505050565b6000546001600160a01b0316331461047d5760405162461bcd60e51b815260040161035d906117a1565b806001600160a01b0381166104a45760405162461bcd60e51b815260040161035d90611812565b7f000000000000000000000000000000000000000000000000000000000000000161051f5760405162461bcd60e51b815260206004820152602560248201527f56657374696e673a2062656e6566696369617279206e6f74207472616e7366656044820152647261626c6560d81b606482015260840161035d565b6000546040517f57005c5083fa0952870a7906715a2f6f9ef2d01b4a423e4b3ce59c6129b1a7639161055e916001600160a01b03909116908590611857565b60405180910390a150600080546001600160a01b0319166001600160a01b0392909216919091179055565b6000546001600160a01b031633146105b35760405162461bcd60e51b815260040161035d906117a1565b600154600160a01b900460ff16156106065760405162461bcd60e51b815260206004820152601660248201527515995cdd1a5b99ce881d1bdad95b881c995d9bdad95960521b604482015260640161035d565b600061061182611259565b9050600081116106605760405162461bcd60e51b815260206004820152601a60248201527956657374696e673a206e6f20746f6b656e73206172652064756560301b604482015260640161035d565b816001600160a01b03167fc7798891864187665ac6dd119286e44ec13f014527aeeb2b8eb3fd413df931798260405161069b91815260200190565b60405180910390a26000546106bd906001600160a01b038481169116836112fd565b5050565b600154600160a01b900460ff1615610702576001546001600160a01b031633146106fd5760405162461bcd60e51b815260040161035d9061176a565b61072c565b6000546001600160a01b0316331461072c5760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d178042101561076c5760405162461bcd60e51b815260040161035d906117e4565b7f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c006001600160a01b031663372500ab6040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107c757600080fd5b505af11580156107db573d6000803e3d6000fd5b50505050565b600154600160a01b900460ff1615610822576001546001600160a01b0316331461081d5760405162461bcd60e51b815260040161035d9061176a565b61084c565b6000546001600160a01b0316331461084c5760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d178042101561088c5760405162461bcd60e51b815260040161035d906117e4565b806001600160a01b0381166108b35760405162461bcd60e51b815260040161035d90611812565b60006108be8561135a565b60405163095ea7b360e01b81529091506001600160a01b037f00000000000000000000000010ea9e5303670331bdddfa66a4cea47dae4fcf3b169063095ea7b39061090f9088908890600401611871565b6020604051808303816000875af115801561092e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610952919061188a565b50604051632816ee7360e01b8152600481018590526001600160a01b038481166024830152821690632816ee7390604401600060405180830381600087803b15801561099d57600080fd5b505af11580156109b1573d6000803e3d6000fd5b505050505050505050565b600154600160a01b900460ff16156109fd576001546001600160a01b031633146109f85760405162461bcd60e51b815260040161035d9061176a565b610a27565b6000546001600160a01b03163314610a275760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d1780421015610a675760405162461bcd60e51b815260040161035d906117e4565b806001600160a01b038116610a8e5760405162461bcd60e51b815260040161035d90611812565b6000610a998461135a565b604051630557fe9560e11b81529091506001600160a01b03821690630aaffd2a90610ac890869060040161163e565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b5050505050505050565b6001546001600160a01b03163314610b2a5760405162461bcd60e51b815260040161035d9061176a565b600154600160a01b900460ff16610bee577f000000000000000000000000000000000000000000000000000000006bef7e80421115610ba65760405162461bcd60e51b815260206004820152601860248201527715995cdd1a5b99ce881d995cdd1a5b99c8195e1c1a5c995960421b604482015260640161035d565b6001805460ff60a01b1916600160a01b1790556040516001600160a01b038216907f39983c6d4d174a7aee564f449d4a5c3c7ac9649d72b7793c56901183996f8af690600090a25b6000610bf982611259565b905080156106bd57816001600160a01b03167fa415e62e43678c8b550c180a7ef9a2031e826b306d4052104d288f3c83ac964b82604051610c3c91815260200190565b60405180910390a26001546106bd906001600160a01b038481169116836112fd565b600154600160a01b900460ff1615610c9f576001546001600160a01b03163314610c9a5760405162461bcd60e51b815260040161035d9061176a565b610cc9565b6000546001600160a01b03163314610cc95760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d1780421015610d095760405162461bcd60e51b815260040161035d906117e4565b806001600160a01b038116610d305760405162461bcd60e51b815260040161035d90611812565b60007f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c006001600160a01b03166356d399e86040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db491906118ac565b60408051600180825281830190925291925060009190816020015b6040805160808101825260009181018281526060820183905281526020810191909152815260200190600190039081610dcf57505060408051608081018252309181019182526001600160a01b0387166060820152908152602081018490528151919250908290600090610e4557610e456118c5565b602090810291909101015260405163095ea7b360e01b81526001600160a01b037f00000000000000000000000010ea9e5303670331bdddfa66a4cea47dae4fcf3b169063095ea7b390610ebe907f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c00908690600401611871565b6020604051808303816000875af1158015610edd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f01919061188a565b50604051632f1fbfb360e21b81526001600160a01b037f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c00169063bc7efecc90610f54908a908a908a90879060040161193a565b600060405180830381600087803b158015610f6e57600080fd5b505af1158015610f82573d6000803e3d6000fd5b5050505050505050505050565b600154600160a01b900460ff1615610fd0576001546001600160a01b03163314610fcb5760405162461bcd60e51b815260040161035d9061176a565b610ffa565b6000546001600160a01b03163314610ffa5760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d178042101561103a5760405162461bcd60e51b815260040161035d906117e4565b60006110458261135a565b9050806001600160a01b0316630d616d206040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561108257600080fd5b505af1158015611096573d6000803e3d6000fd5b505050505050565b6001546001600160a01b031633146110c85760405162461bcd60e51b815260040161035d9061176a565b806001600160a01b0381166110ef5760405162461bcd60e51b815260040161035d90611812565b6001546040517fd0fc5fb9c7c77f1a24739dedc1219c212e20f8711ce4551d2e97909e0f3f59ba9161112e916001600160a01b03909116908590611857565b60405180910390a150600180546001600160a01b0319166001600160a01b0392909216919091179055565b600154600160a01b900460ff161561119a576001546001600160a01b031633146111955760405162461bcd60e51b815260040161035d9061176a565b6111c4565b6000546001600160a01b031633146111c45760405162461bcd60e51b815260040161035d906117a1565b7f00000000000000000000000000000000000000000000000000000000682d17804210156112045760405162461bcd60e51b815260040161035d906117e4565b60405163d9054b0960e01b81526001600160401b03821660048201527f000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c006001600160a01b03169063d9054b099060240161041e565b60007f000000000000000000000000000000000000000000000000000000006bef7e8042106112f4576040516370a0823160e01b81526001600160a01b038316906370a08231906112ae90309060040161163e565b602060405180830381865afa1580156112cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112ef91906118ac565b6112f7565b60005b92915050565b61135583846001600160a01b031663a9059cbb8585604051602401611323929190611871565b604051602081830303815290604052915060e01b6020820180516001600160e01b038381831617835250505050611468565b505050565b6000807f0000000000000000000000008129be2d5ef7acd39483c19f28de86b7ef19dbca6001600160a01b031663f7bc39bf846040518263ffffffff1660e01b81526004016113a9919061163e565b602060405180830381865afa1580156113c6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113ea919061188a565b9050829150806114625760405162461bcd60e51b815260206004820152603d60248201527f436f6e74726163742061646472657373206973206e6f7420612076616c69642060448201527f6d756c74692d636f6e7472696275746f7220534e20636f6e7472616374000000606482015260840161035d565b50919050565b600061147d6001600160a01b038416836114c2565b905080516000141580156114a25750808060200190518101906114a0919061188a565b155b156113555782604051635274afe760e01b815260040161035d919061163e565b60606114d0838360006114d7565b9392505050565b6060814710156114fc573060405163cd78605960e01b815260040161035d919061163e565b600080856001600160a01b0316848660405161151891906119c2565b60006040518083038185875af1925050503d8060008114611555576040519150601f19603f3d011682016040523d82523d6000602084013e61155a565b606091505b509150915061156a868383611574565b9695505050505050565b60608261158957611584826115c7565b6114d0565b81511580156115a057506001600160a01b0384163b155b156115c05783604051639996b31560e01b815260040161035d919061163e565b50806114d0565b8051156115d75780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b50565b60006020828403121561160557600080fd5b5035919050565b6001600160a01b03811681146115f057600080fd5b60006020828403121561163357600080fd5b81356114d08161160c565b6001600160a01b0391909116815260200190565b60008060006060848603121561166757600080fd5b83356116728161160c565b92506020840135915060408401356116898161160c565b809150509250925092565b600080604083850312156116a757600080fd5b82356116b28161160c565b915060208301356116c28161160c565b809150509250929050565b60006080828403121561146257600080fd5b6000806000808486036101608112156116f757600080fd5b604081121561170557600080fd5b5084935061171686604087016116cd565b92506117258660c087016116cd565b91506101408501356117368161160c565b939692955090935050565b60006020828403121561175357600080fd5b81356001600160401b03811681146114d057600080fd5b6020808252601f908201527f56657374696e673a2043616c6c6572206d757374206265207265766f6b657200604082015260600190565b60208082526023908201527f56657374696e673a2043616c6c6572206d7573742062652062656e656669636960408201526261727960e81b606082015260800190565b60208082526014908201527315995cdd1a5b99ce881b9bdd081cdd185c9d195960621b604082015260600190565b60208082526025908201527f5368617265643a205a65726f2d61646472657373206973206e6f74207065726d6040820152641a5d1d195960da1b606082015260800190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b60006020828403121561189c57600080fd5b815180151581146114d057600080fd5b6000602082840312156118be57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b600081518084526020840193506020830160005b82811015611930578151805180516001600160a01b0390811689526020918201511681890152908101516040880152606090960195909101906001016118ef565b5093949350505050565b84358152602080860135818301528435604080840191909152858201356060808501919091528187013560808501528087013560a0850152853560c08501529185013560e084015284013561010083015260009084013561ffff81168082146119a257600080fd5b80610120850152505061016061014083015261156a6101608301846118db565b6000825160005b818110156119e357602081860181015185830152016119c9565b50600092019182525091905056fea26469706673582212204dfd0f42419cf27aaccc404b541487609f3d6e69b884b40aa554d68d51345df064736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b00e81207bcda63c9e290e0b748252418818c869000000000000000000000000f985ad6b3ecc748b41f4e8aeb0b698c1c7d1906000000000000000000000000000000000000000000000000000000000682d1780000000000000000000000000000000000000000000000000000000006bef7e800000000000000000000000000000000000000000000000000000000000000001000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c000000000000000000000000008129be2d5ef7acd39483c19f28de86b7ef19dbca00000000000000000000000010ea9e5303670331bdddfa66a4cea47dae4fcf3b
-----Decoded View---------------
Arg [0] : beneficiary_ (address): 0xb00E81207bcDA63c9E290E0b748252418818c869
Arg [1] : revoker_ (address): 0xF985AD6b3ecc748b41f4E8aeB0B698c1c7D19060
Arg [2] : start_ (uint256): 1747785600
Arg [3] : end_ (uint256): 1810857600
Arg [4] : transferableBeneficiary_ (bool): True
Arg [5] : rewardsContract_ (address): 0xC2B9fC251aC068763EbDfdecc792E3352E351c00
Arg [6] : snContribFactory_ (address): 0x8129bE2D5eF7ACd39483C19F28DE86b7EF19DBCA
Arg [7] : sesh_ (address): 0x10Ea9E5303670331Bdddfa66A4cEA47dae4fcF3b
-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 000000000000000000000000b00e81207bcda63c9e290e0b748252418818c869
Arg [1] : 000000000000000000000000f985ad6b3ecc748b41f4e8aeb0b698c1c7d19060
Arg [2] : 00000000000000000000000000000000000000000000000000000000682d1780
Arg [3] : 000000000000000000000000000000000000000000000000000000006bef7e80
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 000000000000000000000000c2b9fc251ac068763ebdfdecc792e3352e351c00
Arg [6] : 0000000000000000000000008129be2d5ef7acd39483c19f28de86b7ef19dbca
Arg [7] : 00000000000000000000000010ea9e5303670331bdddfa66a4cea47dae4fcf3b
Deployed Bytecode Sourcemap
1073:9879:10:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7036:147;;;;;;:::i;:::-;;:::i;:::-;;10471:296;;;;;;:::i;:::-;;:::i;9581:285::-;;;;;;:::i;:::-;;:::i;3115:64::-;;;;;;;;;;;;:::i;:::-;;;;;;;;2666:56;;;;;-1:-1:-1;;;;;2666:56:10;;;6903:127;;;:::i;2600:60::-;;;;;-1:-1:-1;;;;;2600:60:10;;;7924:490;;;;;;:::i;:::-;;:::i;2728:72::-;;;;;;;;2020:14:11;;2013:22;1995:41;;1983:2;1968:18;2728:72:10;1855:187:11;2924:56:10;;;;;-1:-1:-1;;;2924:56:10;;;;;;8678:352;;;;;;:::i;:::-;;:::i;9872:593::-;;;;;;:::i;:::-;;:::i;3185:65::-;;;;;5512:1195;;;;;;:::i;:::-;;:::i;8420:252::-;;;;;;:::i;:::-;;:::i;10773:177::-;;;;;;:::i;:::-;;:::i;2806:54::-;;;;;;;;3698:25:11;;;3686:2;3671:18;2806:54:10;3552:177:11;3056:53:10;;;;;6713:184;;;;;;:::i;:::-;;:::i;2866:52::-;;;;;7036:147;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;;;;;;;;;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;7140:36:::2;::::0;-1:-1:-1;;;7140:36:10;;::::2;::::0;::::2;3698:25:11::0;;;7140:15:10::2;-1:-1:-1::0;;;;;7140:28:10::2;::::0;::::2;::::0;3671:18:11;;7140:36:10::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;7036:147:::0;:::o;10471:296::-;1569:11;;-1:-1:-1;;;;;1569:11:10;1555:10;:25;1547:73;;;;-1:-1:-1;;;1547:73:10;;;;;;;:::i;:::-;10563:12;-1:-1:-1;;;;;658:15:9;::::1;650:65;;;;-1:-1:-1::0;;;650:65:9::1;;;;;;;:::i;:::-;10595:23:10::2;10587:73;;;::::0;-1:-1:-1;;;10587:73:10;;5965:2:11;10587:73:10::2;::::0;::::2;5947:21:11::0;6004:2;5984:18;;;5977:30;6043:34;6023:18;;;6016:62;-1:-1:-1;;;6094:18:11;;;6087:35;6139:19;;10587:73:10::2;5763:401:11::0;10587:73:10::2;10698:11;::::0;10675:49:::2;::::0;::::2;::::0;::::2;::::0;-1:-1:-1;;;;;10698:11:10;;::::2;::::0;10711:12;;10675:49:::2;:::i;:::-;;;;;;;;-1:-1:-1::0;10734:11:10::2;:26:::0;;-1:-1:-1;;;;;;10734:26:10::2;-1:-1:-1::0;;;;;10734:26:10;;;::::2;::::0;;;::::2;::::0;;10471:296::o;9581:285::-;1569:11;;-1:-1:-1;;;;;1569:11:10;1555:10;:25;1547:73;;;;-1:-1:-1;;;1547:73:10;;;;;;;:::i;:::-;2078:7:::1;::::0;-1:-1:-1;;;2078:7:10;::::1;;;2077:8;2069:43;;;::::0;-1:-1:-1;;;2069:43:10;;6676:2:11;2069:43:10::1;::::0;::::1;6658:21:11::0;6715:2;6695:18;;;6688:30;-1:-1:-1;;;6734:18:11;;;6727:52;6796:18;;2069:43:10::1;6474:346:11::0;2069:43:10::1;9667:14:::2;9684:23;9701:5;9684:16;:23::i;:::-;9667:40;;9734:1;9725:6;:10;9717:49;;;::::0;-1:-1:-1;;;9717:49:10;;7027:2:11;9717:49:10::2;::::0;::::2;7009:21:11::0;7066:2;7046:18;;;7039:30;-1:-1:-1;;;7085:18:11;;;7078:56;7151:18;;9717:49:10::2;6825:350:11::0;9717:49:10::2;9796:5;-1:-1:-1::0;;;;;9781:29:10::2;;9803:6;9781:29;;;;3698:25:11::0;;3686:2;3671:18;;3552:177;9781:29:10::2;;;;;;;;9839:11;::::0;9820:39:::2;::::0;-1:-1:-1;;;;;9820:18:10;;::::2;::::0;9839:11:::2;9852:6:::0;9820:18:::2;:39::i;:::-;9657:209;9581:285:::0;:::o;6903:127::-;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;6993:15:::2;-1:-1:-1::0;;;;;6993:28:10::2;;:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;6903:127::o:0;7924:490::-;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;8144:20:::0;-1:-1:-1;;;;;658:15:9;::::2;650:65;;;;-1:-1:-1::0;;;650:65:9::2;;;;;;;:::i;:::-;8222:34:10::3;8259:38;8283:13;8259:23;:38::i;:::-;8307:35;::::0;-1:-1:-1;;;8307:35:10;;8222:75;;-1:-1:-1;;;;;;8307:4:10::3;:12;::::0;::::3;::::0;:35:::3;::::0;8320:13;;8335:6;;8307:35:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;8352:55:10::3;::::0;-1:-1:-1;;;8352:55:10;;::::3;::::0;::::3;7915:25:11::0;;;-1:-1:-1;;;;;7976:32:11;;;7956:18;;;7949:60;8352:25:10;::::3;::::0;::::3;::::0;7888:18:11;;8352:55:10::3;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;8166:248;2235:1:::2;7924:490:::0;;;:::o;8678:352::-;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;8857:20:::0;-1:-1:-1;;;;;658:15:9;::::2;650:65;;;;-1:-1:-1::0;;;650:65:9::2;;;;;;;:::i;:::-;8889:34:10::3;8926:38;8950:13;8926:23;:38::i;:::-;8974:49;::::0;-1:-1:-1;;;8974:49:10;;8889:75;;-1:-1:-1;;;;;;8974:27:10;::::3;::::0;::::3;::::0;:49:::3;::::0;9002:20;;8974:49:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;8879:151;2235:1:::2;8678:352:::0;;:::o;9872:593::-;1699:7;;-1:-1:-1;;;;;1699:7:10;1685:10;:21;1677:65;;;;-1:-1:-1;;;1677:65:10;;;;;;;:::i;:::-;9947:7:::1;::::0;-1:-1:-1;;;9947:7:10;::::1;;;9942:222;;10048:3;10029:15;:22;;10021:59;;;::::0;-1:-1:-1;;;10021:59:10;;8222:2:11;10021:59:10::1;::::0;::::1;8204:21:11::0;8261:2;8241:18;;;8234:30;-1:-1:-1;;;8280:18:11;;;8273:54;8344:18;;10021:59:10::1;8020:348:11::0;10021:59:10::1;10104:4;10094:14:::0;;-1:-1:-1;;;;10094:14:10::1;-1:-1:-1::0;;;10094:14:10::1;::::0;;10127:26:::1;::::0;-1:-1:-1;;;;;10127:26:10;::::1;::::0;::::1;::::0;10094:14;;10127:26:::1;9942:222;10278:14;10295:23;10312:5;10295:16;:23::i;:::-;10278:40:::0;-1:-1:-1;10332:10:10;;10328:131:::1;;10385:5;-1:-1:-1::0;;;;;10363:36:10::1;;10392:6;10363:36;;;;3698:25:11::0;;3686:2;3671:18;;3552:177;10363:36:10::1;;;;;;;;10432:7;::::0;10413:35:::1;::::0;-1:-1:-1;;;;;10413:18:10;;::::1;::::0;10432:7:::1;10441:6:::0;10413:18:::1;:35::i;5512:1195::-:0;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;5825:13:::0;-1:-1:-1;;;;;658:15:9;::::2;650:65;;;;-1:-1:-1::0;;;650:65:9::2;;;;;;;:::i;:::-;5909:26:10::3;5965:15;-1:-1:-1::0;;;;;5965:34:10::3;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6067:40;::::0;;6105:1:::3;6067:40:::0;;;;;::::3;::::0;;;5909:92;;-1:-1:-1;6011:53:10::3;::::0;6067:40;::::3;;;;-1:-1:-1::0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6067:40:10::3;;;;;;;;;;;;-1:-1:-1::0;;6135:304:10::3;::::0;;6167:166;;;;;6211:4:::3;6135:304:::0;;::::3;6167:166:::0;;;-1:-1:-1;;;;;6167:166:10;::::3;::::0;;;;6135:304;;;6167:166:::3;6135:304:::0;::::3;::::0;;;6117:15;;;;-1:-1:-1;6135:304:10;6117:15;;-1:-1:-1;;6117:15:10::3;;;;:::i;:::-;;::::0;;::::3;::::0;;;;;:322;6511:58:::3;::::0;-1:-1:-1;;;6511:58:10;;-1:-1:-1;;;;;6511:4:10::3;:12;::::0;::::3;::::0;:58:::3;::::0;6532:15:::3;::::0;6550:18;;6511:58:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;6611:89:10::3;::::0;-1:-1:-1;;;6611:89:10;;-1:-1:-1;;;;;6611:15:10::3;:31;::::0;::::3;::::0;:89:::3;::::0;6643:9;;6654:12;;6668:17;;6687:12;;6611:89:::3;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::3;;;;;;;;;;;;::::0;::::3;;;;;;;;;5840:867;;2235:1:::2;5512:1195:::0;;;;:::o;8420:252::-;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;8548:34:::2;8585:38;8609:13;8585:23;:38::i;:::-;8548:75;;8633:9;-1:-1:-1::0;;;;;8633:30:10::2;;:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;8538:134;8420:252:::0;:::o;10773:177::-;1699:7;;-1:-1:-1;;;;;1699:7:10;1685:10;:21;1677:65;;;;-1:-1:-1;;;1677:65:10;;;;;;;:::i;:::-;10853:8;-1:-1:-1;;;;;658:15:9;::::1;650:65;;;;-1:-1:-1::0;;;650:65:9::1;;;;;;;:::i;:::-;10897:7:10::2;::::0;10878:37:::2;::::0;::::2;::::0;::::2;::::0;-1:-1:-1;;;;;10897:7:10;;::::2;::::0;10906:8;;10878:37:::2;:::i;:::-;;;;;;;;-1:-1:-1::0;10925:7:10::2;:18:::0;;-1:-1:-1;;;;;;10925:18:10::2;-1:-1:-1::0;;;;;10925:18:10;;;::::2;::::0;;;::::2;::::0;;10773:177::o;6713:184::-;1827:7;;-1:-1:-1;;;1827:7:10;;;;1823:190;;;1870:7;;-1:-1:-1;;;;;1870:7:10;1856:10;:21;1848:65;;;;-1:-1:-1;;;1848:65:10;;;;;;;:::i;:::-;1823:190;;;1962:11;;-1:-1:-1;;;;;1962:11:10;1948:10;:25;1940:73;;;;-1:-1:-1;;;1940:73:10;;;;;;;:::i;:::-;2195:5:::1;2176:15;:24;;2168:57;;;;-1:-1:-1::0;;;2168:57:10::1;;;;;;;:::i;:::-;6835:55:::2;::::0;-1:-1:-1;;;6835:55:10;;-1:-1:-1;;;;;11500:31:11;;6835:55:10::2;::::0;::::2;11482:50:11::0;6835:15:10::2;-1:-1:-1::0;;;;;6835:40:10::2;::::0;::::2;::::0;11455:18:11;;6835:55:10::2;11338:200:11::0;9422:153:10;9484:7;9528:3;9510:15;:21;:58;;9538:30;;-1:-1:-1;;;9538:30:10;;-1:-1:-1;;;;;9538:15:10;;;;;:30;;9562:4;;9538:30;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9510:58;;;9534:1;9510:58;9503:65;9422:153;-1:-1:-1;;9422:153:10:o;1303:160:2:-;1385:71;1405:5;1427;-1:-1:-1;;;;;1427:14:2;;1444:2;1448:5;1412:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1412:43:2;;;;;;;;;;;1385:19;:71::i;:::-;1303:160;;;:::o;7525:393:10:-;7602:31;7680:21;7704:16;-1:-1:-1;;;;;7704:21:10;;7726:12;7704:35;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7680:59;;7798:12;7749:62;;7829:16;7821:90;;;;-1:-1:-1;;;7821:90:10;;11745:2:11;7821:90:10;;;11727:21:11;11784:2;11764:18;;;11757:30;11823:34;11803:18;;;11796:62;11894:31;11874:18;;;11867:59;11943:19;;7821:90:10;11543:425:11;7821:90:10;7635:283;7525:393;;;:::o;4059:629:2:-;4478:23;4504:33;-1:-1:-1;;;;;4504:27:2;;4532:4;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4664:5;4631:40;;-1:-1:-1;;;4631:40:2;;;;;;;;:::i;2705:151:3:-;2780:12;2811:38;2833:6;2841:4;2847:1;2811:21;:38::i;:::-;2804:45;2705:151;-1:-1:-1;;;2705:151:3:o;3180:392::-;3279:12;3331:5;3307:21;:29;3303:108;;;3394:4;3359:41;;-1:-1:-1;;;3359:41:3;;;;;;;;:::i;3303:108::-;3421:12;3435:23;3462:6;-1:-1:-1;;;;;3462:11:3;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;3510:26;:55::i;:::-;3503:62;3180:392;-1:-1:-1;;;;;;3180:392:3:o;4625:582::-;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;;;;;;5071:18:3;;;:23;5045:49;5041:119;;;5138:6;5121:24;;-1:-1:-1;;;5121:24:3;;;;;;;;:::i;5041:119::-;-1:-1:-1;5180:10:3;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;-1:-1:-1;;;6225:17:3;;;;;;;;;;;5870:383;5743:516;:::o;14:226:11:-;73:6;126:2;114:9;105:7;101:23;97:32;94:52;;;142:1;139;132:12;94:52;-1:-1:-1;187:23:11;;14:226;-1:-1:-1;14:226:11:o;245:131::-;-1:-1:-1;;;;;320:31:11;;310:42;;300:70;;366:1;363;356:12;381:247;440:6;493:2;481:9;472:7;468:23;464:32;461:52;;;509:1;506;499:12;461:52;548:9;535:23;567:31;592:5;567:31;:::i;898:231::-;-1:-1:-1;;;;;1090:32:11;;;;1072:51;;1060:2;1045:18;;898:231::o;1342:508::-;1419:6;1427;1435;1488:2;1476:9;1467:7;1463:23;1459:32;1456:52;;;1504:1;1501;1494:12;1456:52;1543:9;1530:23;1562:31;1587:5;1562:31;:::i;:::-;1612:5;-1:-1:-1;1690:2:11;1675:18;;1662:32;;-1:-1:-1;1772:2:11;1757:18;;1744:32;1785:33;1744:32;1785:33;:::i;:::-;1837:7;1827:17;;;1342:508;;;;;:::o;2047:388::-;2115:6;2123;2176:2;2164:9;2155:7;2151:23;2147:32;2144:52;;;2192:1;2189;2182:12;2144:52;2231:9;2218:23;2250:31;2275:5;2250:31;:::i;:::-;2300:5;-1:-1:-1;2357:2:11;2342:18;;2329:32;2370:33;2329:32;2370:33;:::i;:::-;2422:7;2412:17;;;2047:388;;;;;:::o;2688:167::-;2759:5;2804:3;2795:6;2790:3;2786:16;2782:26;2779:46;;;2821:1;2818;2811:12;2860:687;3048:6;3056;3064;3072;3116:9;3107:7;3103:23;3146:3;3142:2;3138:12;3135:32;;;3163:1;3160;3153:12;3135:32;3187:2;3183;3179:11;3176:31;;;3203:1;3200;3193:12;3176:31;;3226:9;3216:19;;3254:74;3320:7;3315:2;3304:9;3300:18;3254:74;:::i;:::-;3244:84;;3347:75;3414:7;3408:3;3397:9;3393:19;3347:75;:::i;:::-;3337:85;;3472:3;3461:9;3457:19;3444:33;3486:31;3511:5;3486:31;:::i;:::-;2860:687;;;;-1:-1:-1;2860:687:11;;-1:-1:-1;;2860:687:11:o;3955:284::-;4013:6;4066:2;4054:9;4045:7;4041:23;4037:32;4034:52;;;4082:1;4079;4072:12;4034:52;4108:23;;-1:-1:-1;;;;;4160:30:11;;4150:41;;4140:69;;4205:1;4202;4195:12;4244:355;4446:2;4428:21;;;4485:2;4465:18;;;4458:30;4524:33;4519:2;4504:18;;4497:61;4590:2;4575:18;;4244:355::o;4604:399::-;4806:2;4788:21;;;4845:2;4825:18;;;4818:30;4884:34;4879:2;4864:18;;4857:62;-1:-1:-1;;;4950:2:11;4935:18;;4928:33;4993:3;4978:19;;4604:399::o;5008:344::-;5210:2;5192:21;;;5249:2;5229:18;;;5222:30;-1:-1:-1;;;5283:2:11;5268:18;;5261:50;5343:2;5328:18;;5008:344::o;5357:401::-;5559:2;5541:21;;;5598:2;5578:18;;;5571:30;5637:34;5632:2;5617:18;;5610:62;-1:-1:-1;;;5703:2:11;5688:18;;5681:35;5748:3;5733:19;;5357:401::o;6169:300::-;-1:-1:-1;;;;;6361:32:11;;;6343:51;;6430:32;;6425:2;6410:18;;6403:60;6331:2;6316:18;;6169:300::o;7180:274::-;-1:-1:-1;;;;;7372:32:11;;;;7354:51;;7436:2;7421:18;;7414:34;7342:2;7327:18;;7180:274::o;7459:277::-;7526:6;7579:2;7567:9;7558:7;7554:23;7550:32;7547:52;;;7595:1;7592;7585:12;7547:52;7627:9;7621:16;7680:5;7673:13;7666:21;7659:5;7656:32;7646:60;;7702:1;7699;7692:12;8373:184;8443:6;8496:2;8484:9;8475:7;8471:23;8467:32;8464:52;;;8512:1;8509;8502:12;8464:52;-1:-1:-1;8535:16:11;;8373:184;-1:-1:-1;8373:184:11:o;8694:127::-;8755:10;8750:3;8746:20;8743:1;8736:31;8786:4;8783:1;8776:15;8810:4;8807:1;8800:15;8826:661;8890:3;8928:5;8922:12;8955:6;8950:3;8943:19;8987:4;8982:3;8978:14;8971:21;;9026:4;9019:5;9015:16;9049:1;9059:403;9073:6;9070:1;9067:13;9059:403;;;9132:13;;9168:9;;9206;;-1:-1:-1;;;;;9202:35:11;;;9190:48;;9292:4;9284:13;;;9278:20;9274:46;9258:14;;;9251:70;9363:13;;;9357:20;9350:4;9341:14;;9334:44;9407:4;9398:14;;;;9435:17;;;;9234:1;9088:9;9059:403;;;-1:-1:-1;9478:3:11;;8826:661;-1:-1:-1;;;;8826:661:11:o;9492:1841::-;10025:20;;10054:24;;10148:4;10136:17;;;10123:31;10170:20;;;10163:37;10245:20;;10296:2;10281:18;;;10274:35;;;;10367:17;;;10354:31;10416:2;10401:18;;;10394:35;;;;10487:15;;;10474:29;10534:3;10519:19;;10512:36;10606:15;;;10593:29;10653:3;10638:19;;10631:36;10712:20;;10763:3;10748:19;;10741:36;10835:17;;;10822:31;10884:3;10869:19;;10862:36;10956:15;;10943:29;11003:3;10988:19;;10981:36;9974:4;;11054:15;;11041:29;11102:6;11089:20;;11128:15;;;11118:43;;11157:1;11154;11147:12;11118:43;11198:2;11192:3;11181:9;11177:19;11170:31;;;11238:3;11232;11221:9;11217:19;11210:32;11259:68;11322:3;11311:9;11307:19;11299:6;11259:68;:::i;11973:412::-;12102:3;12140:6;12134:13;12165:1;12175:129;12189:6;12186:1;12183:13;12175:129;;;12287:4;12271:14;;;12267:25;;12261:32;12248:11;;;12241:53;12204:12;12175:129;;;-1:-1:-1;12359:1:11;12323:16;;12348:13;;;-1:-1:-1;12323:16:11;11973:412;-1:-1:-1;11973:412:11:o
Swarm Source
ipfs://4dfd0f42419cf27aaccc404b541487609f3d6e69b884b40aa554d68d51345df0
Loading...
Loading
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.