Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00
Cross-Chain Transactions
Loading...
Loading
Contract Name:
POHNodeRegistry
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title POHNodeRegistry — Proof of Planet Node Registration
* @notice Manages the registration and reputation of mining nodes in the
* Proof of Planet network. Supports two tiers:
*
* Tier 1 — Data Nodes: Any phone. Collect sensor data + run science compute.
* Tier 2 — Validation Nodes: More powerful devices. Cross-check and verify data.
*
* Features:
* - Device registration with unique device IDs
* - School program: batch-register devices under a school name (higher caps)
* - Validator staking: optional POH stake for premium validator rewards
* - Slashing: bad validators lose staked tokens
* - Reputation: on-chain reputation score tracked per address
*/
contract POHNodeRegistry is Ownable {
using SafeERC20 for IERC20;
// ── Constants ─────────────────────────────────────────────────────────
uint8 public constant TIER_DATA = 1;
uint8 public constant TIER_VALIDATOR = 2;
uint256 public constant MIN_STAKE = 1000 ether; // 1,000 POH minimum stake
// ── State ─────────────────────────────────────────────────────────────
IERC20 public immutable token;
struct Node {
address owner;
uint8 tier;
bool active;
uint256 registeredAt;
}
struct School {
string name;
address admin;
uint256 registeredAt;
uint256 nodeCount;
}
/// @notice Node data by device ID
mapping(bytes32 => Node) public nodes;
/// @notice All device IDs owned by an address
mapping(address => bytes32[]) public ownerDevices;
/// @notice School data by school ID (keccak256 of name)
mapping(bytes32 => School) public schools;
/// @notice Device ID → school ID (zero if not a school device)
mapping(bytes32 => bytes32) public deviceSchool;
/// @notice Validator stake amount per address
mapping(address => uint256) public validatorStake;
/// @notice Reputation score per address (starts at 0, increases with good behavior)
mapping(address => uint256) public reputation;
// ── Counters ──────────────────────────────────────────────────────────
uint256 public totalNodes;
uint256 public totalValidators;
uint256 public totalSchools;
uint256 public totalStaked;
// ── Events ────────────────────────────────────────────────────────────
event NodeRegistered(
bytes32 indexed deviceId,
address indexed owner,
uint8 tier
);
event NodeDeactivated(bytes32 indexed deviceId, address indexed owner);
event SchoolRegistered(
bytes32 indexed schoolId,
string name,
address indexed admin,
uint256 nodeCount
);
event StakeDeposited(address indexed validator, uint256 amount);
event StakeWithdrawn(address indexed validator, uint256 amount);
event ValidatorSlashed(
address indexed validator,
uint256 amount,
string reason
);
event ReputationUpdated(address indexed node, uint256 newScore);
// ── Constructor ───────────────────────────────────────────────────────
constructor(address _token) Ownable(msg.sender) {
require(_token != address(0), "Registry: token is zero");
token = IERC20(_token);
}
// ── Register a node ───────────────────────────────────────────────────
/**
* @notice Register a device as a Data Node (tier 1) or Validation Node (tier 2).
* @param _deviceId Unique device identifier (hash of device attestation)
* @param _tier 1 = Data Node, 2 = Validation Node
*/
function registerNode(bytes32 _deviceId, uint8 _tier) external {
require(_deviceId != bytes32(0), "Registry: empty device ID");
require(_tier == TIER_DATA || _tier == TIER_VALIDATOR, "Registry: invalid tier");
require(nodes[_deviceId].owner == address(0), "Registry: device already registered");
nodes[_deviceId] = Node({
owner: msg.sender,
tier: _tier,
active: true,
registeredAt: block.timestamp
});
ownerDevices[msg.sender].push(_deviceId);
totalNodes++;
if (_tier == TIER_VALIDATOR) {
totalValidators++;
}
emit NodeRegistered(_deviceId, msg.sender, _tier);
}
// ── Deactivate a node ─────────────────────────────────────────────────
/**
* @notice Deactivate a node. Only the node owner can deactivate.
* @param _deviceId The device to deactivate
*/
function deactivateNode(bytes32 _deviceId) external {
Node storage node = nodes[_deviceId];
require(node.owner == msg.sender, "Registry: not your device");
require(node.active, "Registry: already inactive");
node.active = false;
totalNodes--;
if (node.tier == TIER_VALIDATOR) {
totalValidators--;
}
emit NodeDeactivated(_deviceId, msg.sender);
}
// ── Register a school ─────────────────────────────────────────────────
/**
* @notice Register a school with multiple devices. Schools get higher
* reward caps to incentivize educational participation.
* @param _name Human-readable school name (stored on-chain)
* @param _deviceIds Array of device IDs for the school's nodes
*/
function registerSchool(
string calldata _name,
bytes32[] calldata _deviceIds
) external {
require(bytes(_name).length > 0, "Registry: empty name");
require(_deviceIds.length > 0, "Registry: no devices");
bytes32 schoolId = keccak256(abi.encodePacked(_name, msg.sender));
require(schools[schoolId].admin == address(0), "Registry: school exists");
schools[schoolId] = School({
name: _name,
admin: msg.sender,
registeredAt: block.timestamp,
nodeCount: _deviceIds.length
});
for (uint256 i = 0; i < _deviceIds.length; i++) {
bytes32 deviceId = _deviceIds[i];
require(deviceId != bytes32(0), "Registry: empty device ID");
require(nodes[deviceId].owner == address(0), "Registry: device already registered");
nodes[deviceId] = Node({
owner: msg.sender,
tier: TIER_DATA,
active: true,
registeredAt: block.timestamp
});
ownerDevices[msg.sender].push(deviceId);
deviceSchool[deviceId] = schoolId;
totalNodes++;
}
totalSchools++;
emit SchoolRegistered(schoolId, _name, msg.sender, _deviceIds.length);
}
// ── Validator staking ─────────────────────────────────────────────────
/**
* @notice Stake POH tokens to become a premium validator. Higher stake =
* higher trust and rewards. Must approve tokens first.
* @param _amount Amount of POH to stake (minimum MIN_STAKE)
*/
function stakeForValidation(uint256 _amount) external {
require(_amount >= MIN_STAKE, "Registry: below minimum stake");
token.safeTransferFrom(msg.sender, address(this), _amount);
validatorStake[msg.sender] += _amount;
totalStaked += _amount;
emit StakeDeposited(msg.sender, _amount);
}
/**
* @notice Withdraw staked tokens. Validators can unstake at any time,
* but lose premium rewards while unstaked.
* @param _amount Amount of POH to withdraw
*/
function unstake(uint256 _amount) external {
require(_amount > 0, "Registry: zero amount");
require(validatorStake[msg.sender] >= _amount, "Registry: insufficient stake");
validatorStake[msg.sender] -= _amount;
totalStaked -= _amount;
token.safeTransfer(msg.sender, _amount);
emit StakeWithdrawn(msg.sender, _amount);
}
// ── Owner: Slash a bad validator ──────────────────────────────────────
/**
* @notice Slash a validator's stake for approving fake data or malicious
* behavior. Slashed tokens are burned (sent to address(0) is not
* possible with SafeERC20, so they stay in the contract as a
* penalty pool for future redistribution).
* @param _validator The validator to slash
* @param _amount Amount to slash (cannot exceed their stake)
* @param _reason Human-readable reason (stored in event for transparency)
*/
function slashValidator(
address _validator,
uint256 _amount,
string calldata _reason
) external onlyOwner {
require(_amount > 0, "Registry: zero amount");
require(validatorStake[_validator] >= _amount, "Registry: slash exceeds stake");
require(bytes(_reason).length > 0, "Registry: reason required");
validatorStake[_validator] -= _amount;
totalStaked -= _amount;
// Slashed tokens remain in contract as penalty pool
// Reduce reputation
if (reputation[_validator] >= 10) {
reputation[_validator] -= 10;
} else {
reputation[_validator] = 0;
}
emit ValidatorSlashed(_validator, _amount, _reason);
emit ReputationUpdated(_validator, reputation[_validator]);
}
// ── Owner: Update reputation ──────────────────────────────────────────
/**
* @notice Update a node operator's reputation score. Called by backend
* after validating data quality over time.
* @param _node The node operator's address
* @param _score New reputation score
*/
function setReputation(address _node, uint256 _score) external onlyOwner {
reputation[_node] = _score;
emit ReputationUpdated(_node, _score);
}
/**
* @notice Batch update reputation scores for multiple addresses.
* @param _nodes Array of node operator addresses
* @param _scores Array of new reputation scores
*/
function setReputationBatch(
address[] calldata _nodes,
uint256[] calldata _scores
) external onlyOwner {
require(_nodes.length == _scores.length, "Registry: length mismatch");
for (uint256 i = 0; i < _nodes.length; i++) {
reputation[_nodes[i]] = _scores[i];
emit ReputationUpdated(_nodes[i], _scores[i]);
}
}
// ── View: Get devices for an owner ────────────────────────────────────
function getOwnerDevices(address _owner) external view returns (bytes32[] memory) {
return ownerDevices[_owner];
}
/// @notice Get the number of devices registered by an address
function getOwnerDeviceCount(address _owner) external view returns (uint256) {
return ownerDevices[_owner].length;
}
/// @notice Check if a device is registered and active
function isActiveNode(bytes32 _deviceId) external view returns (bool) {
return nodes[_deviceId].active;
}
/// @notice Check if an address is a staked validator
function isStakedValidator(address _addr) external view returns (bool) {
return validatorStake[_addr] >= MIN_STAKE;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 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 {
/**
* @dev An operation with an ERC-20 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 Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _callOptionalReturnBool(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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
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.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
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 Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
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 {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
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 silently catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
bool success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
returnSize := returndatasize()
returnValue := mload(0)
}
return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}{
"evmVersion": "cancun",
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"deviceId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"NodeDeactivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"deviceId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint8","name":"tier","type":"uint8"}],"name":"NodeRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"node","type":"address"},{"indexed":false,"internalType":"uint256","name":"newScore","type":"uint256"}],"name":"ReputationUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"schoolId","type":"bytes32"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":true,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"uint256","name":"nodeCount","type":"uint256"}],"name":"SchoolRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"validator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"validator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"StakeWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"validator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"ValidatorSlashed","type":"event"},{"inputs":[],"name":"MIN_STAKE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIER_DATA","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIER_VALIDATOR","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_deviceId","type":"bytes32"}],"name":"deactivateNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"deviceSchool","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getOwnerDeviceCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"getOwnerDevices","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_deviceId","type":"bytes32"}],"name":"isActiveNode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_addr","type":"address"}],"name":"isStakedValidator","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nodes","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint8","name":"tier","type":"uint8"},{"internalType":"bool","name":"active","type":"bool"},{"internalType":"uint256","name":"registeredAt","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownerDevices","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_deviceId","type":"bytes32"},{"internalType":"uint8","name":"_tier","type":"uint8"}],"name":"registerNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"bytes32[]","name":"_deviceIds","type":"bytes32[]"}],"name":"registerSchool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"reputation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"schools","outputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"address","name":"admin","type":"address"},{"internalType":"uint256","name":"registeredAt","type":"uint256"},{"internalType":"uint256","name":"nodeCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_node","type":"address"},{"internalType":"uint256","name":"_score","type":"uint256"}],"name":"setReputation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_nodes","type":"address[]"},{"internalType":"uint256[]","name":"_scores","type":"uint256[]"}],"name":"setReputationBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_validator","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"string","name":"_reason","type":"string"}],"name":"slashValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"stakeForValidation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalNodes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSchools","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalValidators","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validatorStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60a060405234801562000010575f80fd5b5060405162001c3338038062001c3383398101604081905262000033916200011f565b33806200005a57604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b6200006581620000d0565b506001600160a01b038116620000be5760405162461bcd60e51b815260206004820152601760248201527f52656769737472793a20746f6b656e206973207a65726f000000000000000000604482015260640162000051565b6001600160a01b03166080526200014e565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b5f6020828403121562000130575f80fd5b81516001600160a01b038116811462000147575f80fd5b9392505050565b608051611abe620001755f395f81816104a9015281816108300152610ca20152611abe5ff3fe608060405234801561000f575f80fd5b50600436106101c6575f3560e01c8063966bda8d116100fe578063c2e347301161009e578063e46b47861161006e578063e46b47861461047e578063f2fde38b14610491578063fc0c546a146104a4578063fed4a929146104cb575f80fd5b8063c2e34730146103d9578063c81b356b146103ec578063cb1c2b5c146103f5578063d86e697d14610405575f80fd5b8063b120c16a116100d9578063b120c16a14610374578063b9f7945114610387578063bfb4493f146103a6578063c197f763146103c6575f80fd5b8063966bda8d1461032b578063a24443901461033e578063a7cb1ab214610351575f80fd5b8063715018a6116101695780638b8ca530116101445780638b8ca530146102e25780638da5cb5b146102f55780638ef7e36c146103195780639592d42414610322575f80fd5b8063715018a6146102c9578063817b1cd2146102d157806381f347c1146102da575f80fd5b80632e17de78116101a45780632e17de781461025557806339b7fcc61461026857806348f8ca9c146102875780636a1902a5146102a1575f80fd5b80630bc811ef146101ca57806313562156146101fc5780631520fb0114610240575b5f80fd5b6101e96101d8366004611519565b60046020525f908152604090205481565b6040519081526020015b60405180910390f35b61023061020a36600461154b565b6001600160a01b03165f90815260056020526040902054683635c9adc5dea00000111590565b60405190151581526020016101f3565b61025361024e3660046115b0565b6104f4565b005b610253610263366004611519565b610742565b6101e961027636600461154b565b60056020525f908152604090205481565b61028f600281565b60405160ff90911681526020016101f3565b6101e96102af36600461154b565b6001600160a01b03165f9081526002602052604090205490565b610253610890565b6101e9600a5481565b61028f600181565b6102536102f0366004611647565b6108a3565b5f546001600160a01b03165b6040516001600160a01b0390911681526020016101f3565b6101e960095481565b6101e960075481565b610253610339366004611519565b610c3c565b61025361034c366004611519565b610d37565b61036461035f366004611519565b610e6e565b6040516101f394939291906116a2565b61025361038236600461170d565b610f27565b6101e961039536600461154b565b60066020525f908152604090205481565b6103b96103b436600461154b565b610f87565b6040516101f39190611735565b6102536103d4366004611778565b610ff0565b6102536103e73660046117ab565b6111da565b6101e960085481565b6101e9683635c9adc5dea0000081565b61044c610413366004611519565b600160208190525f918252604090912080549101546001600160a01b0382169160ff600160a01b8204811692600160a81b909204169084565b604080516001600160a01b03909516855260ff90931660208501529015159183019190915260608201526080016101f3565b6101e961048c36600461170d565b611327565b61025361049f36600461154b565b611352565b6103017f000000000000000000000000000000000000000000000000000000000000000081565b6102306104d9366004611519565b5f90815260016020526040902054600160a81b900460ff1690565b6104fc61138f565b5f83116105485760405162461bcd60e51b8152602060048201526015602482015274149959da5cdd1c9e4e881e995c9bc8185b5bdd5b9d605a1b60448201526064015b60405180910390fd5b6001600160a01b0384165f908152600560205260409020548311156105af5760405162461bcd60e51b815260206004820152601d60248201527f52656769737472793a20736c6173682065786365656473207374616b65000000604482015260640161053f565b806105fc5760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a20726561736f6e20726571756972656400000000000000604482015260640161053f565b6001600160a01b0384165f90815260056020526040812080548592906106239084906117f5565b9250508190555082600a5f82825461063b91906117f5565b90915550506001600160a01b0384165f90815260066020526040902054600a11610692576001600160a01b0384165f9081526006602052604081208054600a92906106879084906117f5565b909155506106ab9050565b6001600160a01b0384165f908152600660205260408120555b836001600160a01b03167f074c8604eab659bccd1619a91a9588244a2442723fdcb05af0aa39da9fc686578484846040516106e893929190611836565b60405180910390a26001600160a01b0384165f818152600660209081526040918290205491519182527ffc577563f1b9a0461e24abef1e1fcc0d33d3d881f20b5df6dda59de4aae2c821910160405180910390a250505050565b5f81116107895760405162461bcd60e51b8152602060048201526015602482015274149959da5cdd1c9e4e881e995c9bc8185b5bdd5b9d605a1b604482015260640161053f565b335f908152600560205260409020548111156107e75760405162461bcd60e51b815260206004820152601c60248201527f52656769737472793a20696e73756666696369656e74207374616b6500000000604482015260640161053f565b335f90815260056020526040812080548392906108059084906117f5565b9250508190555080600a5f82825461081d91906117f5565b9091555061085790506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633836113bb565b60405181815233907f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc906020015b60405180910390a250565b61089861138f565b6108a15f61141f565b565b826108e75760405162461bcd60e51b815260206004820152601460248201527352656769737472793a20656d707479206e616d6560601b604482015260640161053f565b8061092b5760405162461bcd60e51b815260206004820152601460248201527352656769737472793a206e6f206465766963657360601b604482015260640161053f565b5f84843360405160200161094193929190611858565b60408051601f1981840301815291815281516020928301205f81815260039093529120600101549091506001600160a01b0316156109c15760405162461bcd60e51b815260206004820152601760248201527f52656769737472793a207363686f6f6c20657869737473000000000000000000604482015260640161053f565b604051806080016040528086868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525093855250503360208085019190915242604080860191909152606090940187905285835260039052502081518190610a35908261190e565b5060208201516001820180546001600160a01b0319166001600160a01b03909216919091179055604082015160028201556060909101516003909101555f5b82811015610be0575f848483818110610a8f57610a8f6119ce565b60200291909101359150819050610ae45760405162461bcd60e51b8152602060048201526019602482015278149959da5cdd1c9e4e88195b5c1d1e4819195d9a58d9481251603a1b604482015260640161053f565b5f818152600160205260409020546001600160a01b031615610b185760405162461bcd60e51b815260040161053f906119e2565b60408051608081018252338082526001602080840182815284860183815242606087019081525f89815285855288812097518854945193511515600160a81b0260ff60a81b1960ff95909516600160a01b026001600160a81b03199096166001600160a01b03929092169190911794909417929092169290921786559051948301949094559183526002825283832080549182018155835281832001849055838252600490529081208490556007805491610bd283611a25565b909155505050600101610a74565b5060098054905f610bf083611a25565b9091555050604051339082907f9d204dba9ec1406faf02a456c0051cdc1ca3aec56bfdb07c6e15ff912f3db88490610c2d90899089908890611a3d565b60405180910390a35050505050565b683635c9adc5dea00000811015610c955760405162461bcd60e51b815260206004820152601d60248201527f52656769737472793a2062656c6f77206d696e696d756d207374616b65000000604482015260640161053f565b610cca6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001633308461146e565b335f9081526005602052604081208054839290610ce8908490611a60565b9250508190555080600a5f828254610d009190611a60565b909155505060405181815233907f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290602001610885565b5f81815260016020526040902080546001600160a01b03163314610d9d5760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a206e6f7420796f75722064657669636500000000000000604482015260640161053f565b8054600160a81b900460ff16610df55760405162461bcd60e51b815260206004820152601a60248201527f52656769737472793a20616c726561647920696e616374697665000000000000604482015260640161053f565b805460ff60a81b1916815560078054905f610e0f83611a73565b90915550508054600119600160a01b90910460ff1601610e3e5760088054905f610e3883611a73565b91905055505b604051339083907f754a384455665aa78001cfb183e181f0f5ca7ccbccb296291800ad874663e208905f90a35050565b60036020525f9081526040902080548190610e8890611892565b80601f0160208091040260200160405190810160405280929190818152602001828054610eb490611892565b8015610eff5780601f10610ed657610100808354040283529160200191610eff565b820191905f5260205f20905b815481529060010190602001808311610ee257829003601f168201915b505050506001830154600284015460039094015492936001600160a01b039091169290915084565b610f2f61138f565b6001600160a01b0382165f8181526006602052604090819020839055517ffc577563f1b9a0461e24abef1e1fcc0d33d3d881f20b5df6dda59de4aae2c82190610f7b9084815260200190565b60405180910390a25050565b6001600160a01b0381165f90815260026020908152604091829020805483518184028101840190945280845260609392830182828015610fe457602002820191905f5260205f20905b815481526020019060010190808311610fd0575b50505050509050919050565b816110395760405162461bcd60e51b8152602060048201526019602482015278149959da5cdd1c9e4e88195b5c1d1e4819195d9a58d9481251603a1b604482015260640161053f565b60ff81166001148061104e575060ff81166002145b6110935760405162461bcd60e51b81526020600482015260166024820152752932b3b4b9ba393c9d1034b73b30b634b2103a34b2b960511b604482015260640161053f565b5f828152600160205260409020546001600160a01b0316156110c75760405162461bcd60e51b815260040161053f906119e2565b604080516080810182523380825260ff8085166020808501918252600185870181815242606088019081525f8b815283855289812098518954965193511515600160a81b0260ff60a81b1994909816600160a01b026001600160a81b03199097166001600160a01b039190911617959095179190911694909417865592519483019490945591825260028352928120805493840181558152908120909101839055600780549161117683611a25565b909155505060011960ff82160161119c5760088054905f61119683611a25565b91905055505b60405160ff82168152339083907fab63a41f59db12195348e063acb888e6251960f7686f21c8cdf4c8b82cedadf19060200160405180910390a35050565b6111e261138f565b8281146112315760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a206c656e677468206d69736d6174636800000000000000604482015260640161053f565b5f5b838110156113205782828281811061124d5761124d6119ce565b9050602002013560065f878785818110611269576112696119ce565b905060200201602081019061127e919061154b565b6001600160a01b0316815260208101919091526040015f20558484828181106112a9576112a96119ce565b90506020020160208101906112be919061154b565b6001600160a01b03167ffc577563f1b9a0461e24abef1e1fcc0d33d3d881f20b5df6dda59de4aae2c8218484848181106112fa576112fa6119ce565b9050602002013560405161131091815260200190565b60405180910390a2600101611233565b5050505050565b6002602052815f5260405f208181548110611340575f80fd5b905f5260205f20015f91509150505481565b61135a61138f565b6001600160a01b03811661138357604051631e4fbdf760e01b81525f600482015260240161053f565b61138c8161141f565b50565b5f546001600160a01b031633146108a15760405163118cdaa760e01b815233600482015260240161053f565b6040516001600160a01b0383811660248301526044820183905261141a91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506114ad565b505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0384811660248301528381166044830152606482018390526114a79186918216906323b872dd906084016113e8565b50505050565b5f8060205f8451602086015f885af1806114cc576040513d5f823e3d81fd5b50505f513d915081156114e35780600114156114f0565b6001600160a01b0384163b155b156114a757604051635274afe760e01b81526001600160a01b038516600482015260240161053f565b5f60208284031215611529575f80fd5b5035919050565b80356001600160a01b0381168114611546575f80fd5b919050565b5f6020828403121561155b575f80fd5b61156482611530565b9392505050565b5f8083601f84011261157b575f80fd5b50813567ffffffffffffffff811115611592575f80fd5b6020830191508360208285010111156115a9575f80fd5b9250929050565b5f805f80606085870312156115c3575f80fd5b6115cc85611530565b935060208501359250604085013567ffffffffffffffff8111156115ee575f80fd5b6115fa8782880161156b565b95989497509550505050565b5f8083601f840112611616575f80fd5b50813567ffffffffffffffff81111561162d575f80fd5b6020830191508360208260051b85010111156115a9575f80fd5b5f805f806040858703121561165a575f80fd5b843567ffffffffffffffff80821115611671575f80fd5b61167d8883890161156b565b90965094506020870135915080821115611695575f80fd5b506115fa87828801611606565b608081525f85518060808401525f5b818110156116ce57602081890181015160a08684010152016116b1565b505f60a08285018101919091526001600160a01b039690961660208401526040830194909452506060810191909152601f909101601f19160101919050565b5f806040838503121561171e575f80fd5b61172783611530565b946020939093013593505050565b602080825282518282018190525f9190848201906040850190845b8181101561176c57835183529284019291840191600101611750565b50909695505050505050565b5f8060408385031215611789575f80fd5b82359150602083013560ff811681146117a0575f80fd5b809150509250929050565b5f805f80604085870312156117be575f80fd5b843567ffffffffffffffff808211156117d5575f80fd5b61167d88838901611606565b634e487b7160e01b5f52601160045260245ffd5b81810381811115611808576118086117e1565b92915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b838152604060208201525f61184f60408301848661180e565b95945050505050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806118a657607f821691505b6020821081036118c457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561141a57805f5260205f20601f840160051c810160208510156118ef5750805b601f840160051c820191505b81811015611320575f81556001016118fb565b815167ffffffffffffffff8111156119285761192861187e565b61193c816119368454611892565b846118ca565b602080601f83116001811461196f575f84156119585750858301515b5f19600386901b1c1916600185901b1785556119c6565b5f85815260208120601f198616915b8281101561199d5788860151825594840194600190910190840161197e565b50858210156119ba57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52603260045260245ffd5b60208082526023908201527f52656769737472793a2064657669636520616c726561647920726567697374656040820152621c995960ea1b606082015260800190565b5f60018201611a3657611a366117e1565b5060010190565b604081525f611a5060408301858761180e565b9050826020830152949350505050565b80820180821115611808576118086117e1565b5f81611a8157611a816117e1565b505f19019056fea26469706673582212201d7d3e3efa9ea87e0856ea18951a47425359675183aaae483aab041c87d676bf64736f6c63430008180033000000000000000000000000280ddb8b67ad8cf791d370fe59227d19e989fb07
Deployed Bytecode
0x608060405234801561000f575f80fd5b50600436106101c6575f3560e01c8063966bda8d116100fe578063c2e347301161009e578063e46b47861161006e578063e46b47861461047e578063f2fde38b14610491578063fc0c546a146104a4578063fed4a929146104cb575f80fd5b8063c2e34730146103d9578063c81b356b146103ec578063cb1c2b5c146103f5578063d86e697d14610405575f80fd5b8063b120c16a116100d9578063b120c16a14610374578063b9f7945114610387578063bfb4493f146103a6578063c197f763146103c6575f80fd5b8063966bda8d1461032b578063a24443901461033e578063a7cb1ab214610351575f80fd5b8063715018a6116101695780638b8ca530116101445780638b8ca530146102e25780638da5cb5b146102f55780638ef7e36c146103195780639592d42414610322575f80fd5b8063715018a6146102c9578063817b1cd2146102d157806381f347c1146102da575f80fd5b80632e17de78116101a45780632e17de781461025557806339b7fcc61461026857806348f8ca9c146102875780636a1902a5146102a1575f80fd5b80630bc811ef146101ca57806313562156146101fc5780631520fb0114610240575b5f80fd5b6101e96101d8366004611519565b60046020525f908152604090205481565b6040519081526020015b60405180910390f35b61023061020a36600461154b565b6001600160a01b03165f90815260056020526040902054683635c9adc5dea00000111590565b60405190151581526020016101f3565b61025361024e3660046115b0565b6104f4565b005b610253610263366004611519565b610742565b6101e961027636600461154b565b60056020525f908152604090205481565b61028f600281565b60405160ff90911681526020016101f3565b6101e96102af36600461154b565b6001600160a01b03165f9081526002602052604090205490565b610253610890565b6101e9600a5481565b61028f600181565b6102536102f0366004611647565b6108a3565b5f546001600160a01b03165b6040516001600160a01b0390911681526020016101f3565b6101e960095481565b6101e960075481565b610253610339366004611519565b610c3c565b61025361034c366004611519565b610d37565b61036461035f366004611519565b610e6e565b6040516101f394939291906116a2565b61025361038236600461170d565b610f27565b6101e961039536600461154b565b60066020525f908152604090205481565b6103b96103b436600461154b565b610f87565b6040516101f39190611735565b6102536103d4366004611778565b610ff0565b6102536103e73660046117ab565b6111da565b6101e960085481565b6101e9683635c9adc5dea0000081565b61044c610413366004611519565b600160208190525f918252604090912080549101546001600160a01b0382169160ff600160a01b8204811692600160a81b909204169084565b604080516001600160a01b03909516855260ff90931660208501529015159183019190915260608201526080016101f3565b6101e961048c36600461170d565b611327565b61025361049f36600461154b565b611352565b6103017f000000000000000000000000280ddb8b67ad8cf791d370fe59227d19e989fb0781565b6102306104d9366004611519565b5f90815260016020526040902054600160a81b900460ff1690565b6104fc61138f565b5f83116105485760405162461bcd60e51b8152602060048201526015602482015274149959da5cdd1c9e4e881e995c9bc8185b5bdd5b9d605a1b60448201526064015b60405180910390fd5b6001600160a01b0384165f908152600560205260409020548311156105af5760405162461bcd60e51b815260206004820152601d60248201527f52656769737472793a20736c6173682065786365656473207374616b65000000604482015260640161053f565b806105fc5760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a20726561736f6e20726571756972656400000000000000604482015260640161053f565b6001600160a01b0384165f90815260056020526040812080548592906106239084906117f5565b9250508190555082600a5f82825461063b91906117f5565b90915550506001600160a01b0384165f90815260066020526040902054600a11610692576001600160a01b0384165f9081526006602052604081208054600a92906106879084906117f5565b909155506106ab9050565b6001600160a01b0384165f908152600660205260408120555b836001600160a01b03167f074c8604eab659bccd1619a91a9588244a2442723fdcb05af0aa39da9fc686578484846040516106e893929190611836565b60405180910390a26001600160a01b0384165f818152600660209081526040918290205491519182527ffc577563f1b9a0461e24abef1e1fcc0d33d3d881f20b5df6dda59de4aae2c821910160405180910390a250505050565b5f81116107895760405162461bcd60e51b8152602060048201526015602482015274149959da5cdd1c9e4e881e995c9bc8185b5bdd5b9d605a1b604482015260640161053f565b335f908152600560205260409020548111156107e75760405162461bcd60e51b815260206004820152601c60248201527f52656769737472793a20696e73756666696369656e74207374616b6500000000604482015260640161053f565b335f90815260056020526040812080548392906108059084906117f5565b9250508190555080600a5f82825461081d91906117f5565b9091555061085790506001600160a01b037f000000000000000000000000280ddb8b67ad8cf791d370fe59227d19e989fb071633836113bb565b60405181815233907f8108595eb6bad3acefa9da467d90cc2217686d5c5ac85460f8b7849c840645fc906020015b60405180910390a250565b61089861138f565b6108a15f61141f565b565b826108e75760405162461bcd60e51b815260206004820152601460248201527352656769737472793a20656d707479206e616d6560601b604482015260640161053f565b8061092b5760405162461bcd60e51b815260206004820152601460248201527352656769737472793a206e6f206465766963657360601b604482015260640161053f565b5f84843360405160200161094193929190611858565b60408051601f1981840301815291815281516020928301205f81815260039093529120600101549091506001600160a01b0316156109c15760405162461bcd60e51b815260206004820152601760248201527f52656769737472793a207363686f6f6c20657869737473000000000000000000604482015260640161053f565b604051806080016040528086868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92018290525093855250503360208085019190915242604080860191909152606090940187905285835260039052502081518190610a35908261190e565b5060208201516001820180546001600160a01b0319166001600160a01b03909216919091179055604082015160028201556060909101516003909101555f5b82811015610be0575f848483818110610a8f57610a8f6119ce565b60200291909101359150819050610ae45760405162461bcd60e51b8152602060048201526019602482015278149959da5cdd1c9e4e88195b5c1d1e4819195d9a58d9481251603a1b604482015260640161053f565b5f818152600160205260409020546001600160a01b031615610b185760405162461bcd60e51b815260040161053f906119e2565b60408051608081018252338082526001602080840182815284860183815242606087019081525f89815285855288812097518854945193511515600160a81b0260ff60a81b1960ff95909516600160a01b026001600160a81b03199096166001600160a01b03929092169190911794909417929092169290921786559051948301949094559183526002825283832080549182018155835281832001849055838252600490529081208490556007805491610bd283611a25565b909155505050600101610a74565b5060098054905f610bf083611a25565b9091555050604051339082907f9d204dba9ec1406faf02a456c0051cdc1ca3aec56bfdb07c6e15ff912f3db88490610c2d90899089908890611a3d565b60405180910390a35050505050565b683635c9adc5dea00000811015610c955760405162461bcd60e51b815260206004820152601d60248201527f52656769737472793a2062656c6f77206d696e696d756d207374616b65000000604482015260640161053f565b610cca6001600160a01b037f000000000000000000000000280ddb8b67ad8cf791d370fe59227d19e989fb071633308461146e565b335f9081526005602052604081208054839290610ce8908490611a60565b9250508190555080600a5f828254610d009190611a60565b909155505060405181815233907f0a7bb2e28cc4698aac06db79cf9163bfcc20719286cf59fa7d492ceda1b8edc290602001610885565b5f81815260016020526040902080546001600160a01b03163314610d9d5760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a206e6f7420796f75722064657669636500000000000000604482015260640161053f565b8054600160a81b900460ff16610df55760405162461bcd60e51b815260206004820152601a60248201527f52656769737472793a20616c726561647920696e616374697665000000000000604482015260640161053f565b805460ff60a81b1916815560078054905f610e0f83611a73565b90915550508054600119600160a01b90910460ff1601610e3e5760088054905f610e3883611a73565b91905055505b604051339083907f754a384455665aa78001cfb183e181f0f5ca7ccbccb296291800ad874663e208905f90a35050565b60036020525f9081526040902080548190610e8890611892565b80601f0160208091040260200160405190810160405280929190818152602001828054610eb490611892565b8015610eff5780601f10610ed657610100808354040283529160200191610eff565b820191905f5260205f20905b815481529060010190602001808311610ee257829003601f168201915b505050506001830154600284015460039094015492936001600160a01b039091169290915084565b610f2f61138f565b6001600160a01b0382165f8181526006602052604090819020839055517ffc577563f1b9a0461e24abef1e1fcc0d33d3d881f20b5df6dda59de4aae2c82190610f7b9084815260200190565b60405180910390a25050565b6001600160a01b0381165f90815260026020908152604091829020805483518184028101840190945280845260609392830182828015610fe457602002820191905f5260205f20905b815481526020019060010190808311610fd0575b50505050509050919050565b816110395760405162461bcd60e51b8152602060048201526019602482015278149959da5cdd1c9e4e88195b5c1d1e4819195d9a58d9481251603a1b604482015260640161053f565b60ff81166001148061104e575060ff81166002145b6110935760405162461bcd60e51b81526020600482015260166024820152752932b3b4b9ba393c9d1034b73b30b634b2103a34b2b960511b604482015260640161053f565b5f828152600160205260409020546001600160a01b0316156110c75760405162461bcd60e51b815260040161053f906119e2565b604080516080810182523380825260ff8085166020808501918252600185870181815242606088019081525f8b815283855289812098518954965193511515600160a81b0260ff60a81b1994909816600160a01b026001600160a81b03199097166001600160a01b039190911617959095179190911694909417865592519483019490945591825260028352928120805493840181558152908120909101839055600780549161117683611a25565b909155505060011960ff82160161119c5760088054905f61119683611a25565b91905055505b60405160ff82168152339083907fab63a41f59db12195348e063acb888e6251960f7686f21c8cdf4c8b82cedadf19060200160405180910390a35050565b6111e261138f565b8281146112315760405162461bcd60e51b815260206004820152601960248201527f52656769737472793a206c656e677468206d69736d6174636800000000000000604482015260640161053f565b5f5b838110156113205782828281811061124d5761124d6119ce565b9050602002013560065f878785818110611269576112696119ce565b905060200201602081019061127e919061154b565b6001600160a01b0316815260208101919091526040015f20558484828181106112a9576112a96119ce565b90506020020160208101906112be919061154b565b6001600160a01b03167ffc577563f1b9a0461e24abef1e1fcc0d33d3d881f20b5df6dda59de4aae2c8218484848181106112fa576112fa6119ce565b9050602002013560405161131091815260200190565b60405180910390a2600101611233565b5050505050565b6002602052815f5260405f208181548110611340575f80fd5b905f5260205f20015f91509150505481565b61135a61138f565b6001600160a01b03811661138357604051631e4fbdf760e01b81525f600482015260240161053f565b61138c8161141f565b50565b5f546001600160a01b031633146108a15760405163118cdaa760e01b815233600482015260240161053f565b6040516001600160a01b0383811660248301526044820183905261141a91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b0383818316178352505050506114ad565b505050565b5f80546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6040516001600160a01b0384811660248301528381166044830152606482018390526114a79186918216906323b872dd906084016113e8565b50505050565b5f8060205f8451602086015f885af1806114cc576040513d5f823e3d81fd5b50505f513d915081156114e35780600114156114f0565b6001600160a01b0384163b155b156114a757604051635274afe760e01b81526001600160a01b038516600482015260240161053f565b5f60208284031215611529575f80fd5b5035919050565b80356001600160a01b0381168114611546575f80fd5b919050565b5f6020828403121561155b575f80fd5b61156482611530565b9392505050565b5f8083601f84011261157b575f80fd5b50813567ffffffffffffffff811115611592575f80fd5b6020830191508360208285010111156115a9575f80fd5b9250929050565b5f805f80606085870312156115c3575f80fd5b6115cc85611530565b935060208501359250604085013567ffffffffffffffff8111156115ee575f80fd5b6115fa8782880161156b565b95989497509550505050565b5f8083601f840112611616575f80fd5b50813567ffffffffffffffff81111561162d575f80fd5b6020830191508360208260051b85010111156115a9575f80fd5b5f805f806040858703121561165a575f80fd5b843567ffffffffffffffff80821115611671575f80fd5b61167d8883890161156b565b90965094506020870135915080821115611695575f80fd5b506115fa87828801611606565b608081525f85518060808401525f5b818110156116ce57602081890181015160a08684010152016116b1565b505f60a08285018101919091526001600160a01b039690961660208401526040830194909452506060810191909152601f909101601f19160101919050565b5f806040838503121561171e575f80fd5b61172783611530565b946020939093013593505050565b602080825282518282018190525f9190848201906040850190845b8181101561176c57835183529284019291840191600101611750565b50909695505050505050565b5f8060408385031215611789575f80fd5b82359150602083013560ff811681146117a0575f80fd5b809150509250929050565b5f805f80604085870312156117be575f80fd5b843567ffffffffffffffff808211156117d5575f80fd5b61167d88838901611606565b634e487b7160e01b5f52601160045260245ffd5b81810381811115611808576118086117e1565b92915050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b838152604060208201525f61184f60408301848661180e565b95945050505050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806118a657607f821691505b6020821081036118c457634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561141a57805f5260205f20601f840160051c810160208510156118ef5750805b601f840160051c820191505b81811015611320575f81556001016118fb565b815167ffffffffffffffff8111156119285761192861187e565b61193c816119368454611892565b846118ca565b602080601f83116001811461196f575f84156119585750858301515b5f19600386901b1c1916600185901b1785556119c6565b5f85815260208120601f198616915b8281101561199d5788860151825594840194600190910190840161197e565b50858210156119ba57878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52603260045260245ffd5b60208082526023908201527f52656769737472793a2064657669636520616c726561647920726567697374656040820152621c995960ea1b606082015260800190565b5f60018201611a3657611a366117e1565b5060010190565b604081525f611a5060408301858761180e565b9050826020830152949350505050565b80820180821115611808576118086117e1565b5f81611a8157611a816117e1565b505f19019056fea26469706673582212201d7d3e3efa9ea87e0856ea18951a47425359675183aaae483aab041c87d676bf64736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000280ddb8b67ad8cf791d370fe59227d19e989fb07
-----Decoded View---------------
Arg [0] : _token (address): 0x280Ddb8b67Ad8cf791D370FE59227d19e989Fb07
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000280ddb8b67ad8cf791d370fe59227d19e989fb07
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 32 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.