Source Code
Overview
AVAX Balance
More Info
ContractCreator
Multichain Info
N/A
Latest 7 from a total of 7 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
Amount
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Register L1 | 44160571 | 170 days ago | IN | 0.01 AVAX | 0 | ||||
| Set L1Middleware | 43898292 | 176 days ago | IN | 0 AVAX | 0 | ||||
| Register L1 | 40908085 | 238 days ago | IN | 0.01 AVAX | 0 | ||||
| Set L1Middleware | 40898257 | 238 days ago | IN | 0 AVAX | 0 | ||||
| Register L1 | 40896997 | 238 days ago | IN | 0.01 AVAX | 0 | ||||
| Set L1Middleware | 40629341 | 247 days ago | IN | 0 AVAX | 0 | ||||
| Register L1 | 40372154 | 253 days ago | IN | 0.01 AVAX | 0 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | Amount | ||
|---|---|---|---|---|---|---|
| 44160571 | 170 days ago | 0.01 AVAX | ||||
| 44160571 | 170 days ago | 0 AVAX | ||||
| 44118030 | 171 days ago | 0 AVAX | ||||
| 44116889 | 171 days ago | 0 AVAX | ||||
| 43898334 | 176 days ago | 0 AVAX | ||||
| 43898334 | 176 days ago | 0 AVAX | ||||
| 43898334 | 176 days ago | 0 AVAX | ||||
| 43898292 | 176 days ago | 0 AVAX | ||||
| 41322781 | 227 days ago | 0 AVAX | ||||
| 41322781 | 227 days ago | 0 AVAX | ||||
| 41322781 | 227 days ago | 0 AVAX | ||||
| 41322762 | 227 days ago | 0 AVAX | ||||
| 41322762 | 227 days ago | 0 AVAX | ||||
| 41322762 | 227 days ago | 0 AVAX | ||||
| 41322656 | 227 days ago | 0 AVAX | ||||
| 41322656 | 227 days ago | 0 AVAX | ||||
| 41322656 | 227 days ago | 0 AVAX | ||||
| 40998519 | 235 days ago | 0 AVAX | ||||
| 40998519 | 235 days ago | 0 AVAX | ||||
| 40998519 | 235 days ago | 0 AVAX | ||||
| 40997997 | 235 days ago | 0 AVAX | ||||
| 40997997 | 235 days ago | 0 AVAX | ||||
| 40997997 | 235 days ago | 0 AVAX | ||||
| 40997734 | 235 days ago | 0 AVAX | ||||
| 40997734 | 235 days ago | 0 AVAX |
Loading...
Loading
Contract Name:
L1Registry
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
// SPDX-FileCopyrightText: Copyright 2024 ADDPHO
pragma solidity 0.8.25;
import {IL1Registry} from "../interfaces/IL1Registry.sol";
import {IAvalancheL1Middleware} from "../interfaces/middleware/IAvalancheL1Middleware.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract L1Registry is IL1Registry, Ownable {
using EnumerableSet for EnumerableSet.AddressSet;
EnumerableSet.AddressSet private l1s;
/// @notice The l1Middleware for each L1
mapping(address => address) public l1Middleware;
/// @notice The metadata URL for each L1
mapping(address => string) public l1MetadataURL;
/// @notice The fee collector address (can be changed later).
address payable public feeCollector;
/// @notice The adjustable fee (in wei) for registerL1.
uint256 public registerFee;
/// @notice MAX_FEE is the maximum fee that can be set by the owner.
uint256 immutable MAX_FEE;
/// @notice Tracks the total unclaimed fees in the contract
uint256 public unclaimedFees;
modifier onlyValidatorManagerOwner(
address l1
) {
// Ensure caller owns the validator manager
address vmOwner = Ownable(l1).owner();
if (vmOwner != msg.sender) {
revert L1Registry__NotValidatorManagerOwner(msg.sender, vmOwner);
}
_;
}
modifier isRegisteredL1(
address l1
) {
if (!isRegistered(l1)) {
revert L1Registry__L1NotRegistered();
}
_;
}
modifier notZeroAddress(
address l1
) {
if (l1 == address(0)) {
revert L1Registry__InvalidValidatorManager(l1);
}
_;
}
constructor(address payable feeCollector_, uint256 registerFee_, uint256 MAX_FEE_, address owner) Ownable(owner) {
if (feeCollector_ == address(0)) {
revert L1Registry__ZeroAddress("feeCollector");
}
feeCollector = feeCollector_;
registerFee = registerFee_;
MAX_FEE = MAX_FEE_;
}
/// @inheritdoc IL1Registry
function registerL1(
address l1,
address l1Middleware_,
string calldata metadataURL
) external payable notZeroAddress(l1) onlyValidatorManagerOwner(l1) {
// Only require fee if it's set to non-zero
if (registerFee > 0) {
if (msg.value < registerFee) {
revert L1Registry__InsufficientFee();
}
// Transfer fee to collector (feeCollector is guaranteed to be non-zero)
(bool success,) = feeCollector.call{value: msg.value}("");
if (!success) {
unclaimedFees += msg.value;
}
}
bool registered = l1s.add(l1);
if (!registered) {
revert L1Registry__L1AlreadyRegistered();
}
l1Middleware[l1] = l1Middleware_;
l1MetadataURL[l1] = metadataURL;
emit RegisterL1(l1);
emit SetL1Middleware(l1, l1Middleware_);
emit SetMetadataURL(l1, metadataURL);
}
/// @inheritdoc IL1Registry
function setL1Middleware(
address l1,
address l1Middleware_
) external notZeroAddress(l1Middleware_) isRegisteredL1(l1) onlyValidatorManagerOwner(l1) {
l1Middleware[l1] = l1Middleware_;
emit SetL1Middleware(l1, l1Middleware_);
}
/// @inheritdoc IL1Registry
function setMetadataURL(
address l1,
string calldata metadataURL
) external isRegisteredL1(l1) onlyValidatorManagerOwner(l1) {
// TODO: check that msg.sender is a SecurityModule of the ValidatorManager
l1MetadataURL[l1] = metadataURL;
emit SetMetadataURL(l1, metadataURL);
}
/// @inheritdoc IL1Registry
function isRegistered(
address l1
) public view returns (bool) {
return l1s.contains(l1);
}
// @inheritdoc IL1Registry
function isRegisteredWithMiddleware(address l1, address vaultManager_) external view returns (bool) {
if (!isRegistered(l1)) {
return false;
}
address middleware = l1Middleware[l1];
if (middleware == address(0)) {
return false;
}
address actualVaultManager = IAvalancheL1Middleware(middleware).getVaultManager();
if (actualVaultManager != vaultManager_) {
revert L1Registry__InvalidL1Middleware();
}
return true;
}
/// @inheritdoc IL1Registry
function getL1At(
uint256 index
) public view returns (address, address, string memory) {
address l1 = l1s.at(index);
return (l1, l1Middleware[l1], l1MetadataURL[l1]);
}
/// @inheritdoc IL1Registry
function totalL1s() public view returns (uint256) {
return l1s.length();
}
/// @inheritdoc IL1Registry
function getAllL1s() public view returns (address[] memory, address[] memory, string[] memory) {
address[] memory l1sList = l1s.values();
address[] memory l1Middlewares = new address[](l1sList.length);
string[] memory metadataURLs = new string[](l1sList.length);
for (uint256 i = 0; i < l1sList.length; i++) {
l1Middlewares[i] = l1Middleware[l1sList[i]];
metadataURLs[i] = l1MetadataURL[l1sList[i]];
}
return (l1sList, l1Middlewares, metadataURLs);
}
/// @notice Adjust fee collector. Only owner can change it.
/// @param newFeeCollector The new fee collector address
function setFeeCollector(
address payable newFeeCollector
) external onlyOwner {
if (newFeeCollector == address(0)) {
revert L1Registry__ZeroAddress("feeCollector");
}
// Try to disburse any accumulated fees to the new collector
uint256 feesToSend = unclaimedFees;
if (feesToSend > 0) {
// Reset unclaimed fees before transfer to prevent reentrancy issues
unclaimedFees = 0;
(bool success,) = newFeeCollector.call{value: feesToSend}("");
if (!success) {
// If transfer fails, restore the unclaimed fees amount
// but continue execution so that feeCollector is still updated
unclaimedFees = feesToSend;
}
}
feeCollector = newFeeCollector;
}
/// @notice Adjust fee. Only owner can change it.
function setRegisterFee(
uint256 newFee
) external onlyOwner {
if (newFee > MAX_FEE) {
revert L1Registry__FeeExceedsMaximum(newFee, MAX_FEE);
}
registerFee = newFee;
}
/// @notice Allows the fee collector to withdraw accumulated fees
function withdrawFees() external {
if (msg.sender != feeCollector) {
revert L1Registry__NotFeeCollector(msg.sender);
}
uint256 feesToSend = unclaimedFees;
if (feesToSend == 0) {
revert L1Registry__NoFeesToWithdraw();
}
// Reset unclaimed fees before transfer to prevent reentrancy issues
unclaimedFees = 0;
(bool success,) = feeCollector.call{value: feesToSend}("");
if (!success) {
// If transfer fails, restore the unclaimed fees amount
unclaimedFees = feesToSend;
revert L1Registry__FeeTransferFailed();
}
}
receive() external payable {}
}// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright 2024 ADDPHO
pragma solidity ^0.8.0;
interface IL1Registry {
event RegisterL1(address indexed l1);
event SetL1Middleware(address indexed l1, address indexed l1Middleware);
event SetMetadataURL(address indexed l1, string metadataURL);
error L1Registry__L1AlreadyRegistered();
error L1Registry__L1NotRegistered();
error L1Registry__InvalidValidatorManager(address l1);
error L1Registry__InvalidL1Middleware();
error L1Registry__NotValidatorManagerOwner(address caller, address expectedOwner);
error L1Registry__InsufficientFee();
error L1Registry__FeeTransferFailed();
error L1Registry__FeeExceedsMaximum(uint256 newFee, uint256 maxFee);
error L1Registry__ZeroAddress(string name);
error L1Registry__NotFeeCollector(address caller);
error L1Registry__NoFeesToWithdraw();
/**
* @notice Register an Avalanche L1
* @dev l1 must be the manager of the Avalanche L1
* @dev msg.sender must be a SecurityModule of the l1
* @dev l1Middleware must be a SecurityModule of the Avalanche L1
* @param l1 The Avalanche L1. Should be The ValidatorManager.
* @param l1Middleware The l1Middleware of the Avalanche L1
* @param metadataURL The metadata URL of the Avalanche L1
*/
function registerL1(
address l1,
address l1Middleware,
string calldata metadataURL
)
/*, uint32 messageIndex, SubnetConversionData subnetConversionData*/
external
payable;
/**
* @notice Check if an address is registered as an L1
* @param l1 The Avalanche L1. Should be The ValidatorManager.
* @return True if the address is registered as an L1, false otherwise
*/
function isRegistered(
address l1
) external view returns (bool);
/**
* @notice Check if an address is registered as an L1 and if the Middleware is correct
* @param l1 The Avalanche L1. Should be The ValidatorManager.
* @param l1middleware_ The l1Middleware to check
* @return True if the address is registered as an L1 and the middleware is correct, false otherwise
*/
function isRegisteredWithMiddleware(address l1, address l1middleware_) external view returns (bool);
/**
* @notice Get the L1 at a specific index
* @param index The index of the L1 to get
* @return The address of the L1 at the specified index
* @return The l1Middleware of the L1 at the specified index
* @return The metadata URL of the L1 at the specified index
*/
function getL1At(
uint256 index
) external view returns (address, address, string memory);
/**
* @notice Get the total number of L1s
* @return Total number of L1s
*/
function totalL1s() external view returns (uint256);
/**
* @notice Get all L1s
* @return Array of all L1s
* @return Array of all L1s' l1Middlewares
* @return Array of all L1s' metadata URLs
*/
function getAllL1s() external view returns (address[] memory, address[] memory, string[] memory);
/**
* @notice Set the l1Middleware of an L1
* @param l1 The Avalanche L1. Should be The ValidatorManager.
* @param l1Middleware_ The new l1Middleware
*/
function setL1Middleware(address l1, address l1Middleware_) external;
/**
* @notice Set the metadata URL of an L1
* @param l1 The Avalanche L1. Should be The ValidatorManager.
* @param metadataURL The new metadata URL
*/
function setMetadataURL(address l1, string calldata metadataURL) external;
}// SPDX-License-Identifier: MIT
// SPDX-FileCopyrightText: Copyright 2024 ADDPHO
pragma solidity 0.8.25;
import {
IValidatorManager,
Validator,
ValidatorStatus,
ValidatorRegistrationInput,
PChainOwner
} from "@avalabs/teleporter/validator-manager/interfaces/IValidatorManager.sol";
/**
* @title IAvalancheL1Middleware
* @notice Manages operator registration, asset classes, stake accounting, and slashing for Avalanche L1
*/
interface IAvalancheL1Middleware {
// Errors
error AvalancheL1Middleware__ActiveSecondaryAssetCLass(uint256 assetClassId);
error AvalancheL1Middleware__AssetClassNotActive(uint256 assetClassId);
error AvalancheL1Middleware__AssetStillInUse(uint256 assetClassId);
error AvalancheL1Middleware__AlreadyRebalanced(address operator, uint48 epoch);
error AvalancheL1Middleware__WeightUpdateNotPending(bytes32 validationId);
error AvalancheL1Middleware__CollateralNotInAssetClass(address collateral, uint96 assetClassId);
error AvalancheL1Middleware__EpochError(uint48 epochStartTs);
error AvalancheL1Middleware__MaxL1LimitZero();
error AvalancheL1Middleware__NoSlasher();
error AvalancheL1Middleware__NotEnoughFreeStakeSecondaryAssetClasses();
error AvalancheL1Middleware__NodeNotActive();
error AvalancheL1Middleware__NotEnoughFreeStake(uint256 newStake);
error AvalancheL1Middleware__StakeTooHigh(uint256 newStake, uint256 maxStake);
error AvalancheL1Middleware__StakeTooLow(uint256 newStake, uint256 minStake);
error AvalancheL1Middleware__OperatorGracePeriodNotPassed(uint48 disabledTime, uint48 slashingWindow);
error AvalancheL1Middleware__OperatorAlreadyRegistered(address operator);
error AvalancheL1Middleware__OperatorNotOptedIn(address operator, address l1ValidatorManager);
error AvalancheL1Middleware__OperatorNotRegistered(address operator);
error AvalancheL1Middleware__SlashingWindowTooShort(uint48 slashingWindow, uint48 epochDuration);
error AvalancheL1Middleware__TooBigSlashAmount();
error AvalancheL1Middleware__NodeNotFound(bytes32 nodeId);
error AvalancheL1Middleware__SecurityModuleCapacityNotEnough(uint256 securityModuleCapacity, uint256 minStake);
error AvalancheL1Middleware__WeightUpdatePending(bytes32 validationID);
error AvalancheL1Middleware__NodeStateNotUpdated(bytes32 validationID);
error AvalancheL1Middleware__NotEpochUpdatePeriod(uint48 timeNow, uint48 epochUpdatePeriod);
error AvalancheL1Middleware__NotImplemented();
error AvalancheL1Middleware__NodePendingRemoval(bytes32 nodeId);
error AvalancheL1Middleware__NodePendingUpdate(bytes32 nodeId);
error AvalancheL1Middleware__ZeroAddress(string name);
error AvalancheL1Middleware__InvalidScaleFactor();
// Events
/**
* @notice Emitted when a node is added
* @param operator The operator who added the node
* @param nodeId The ID of the node
* @param stake The stake assigned to the node
* @param validationID The validation identifier from BalancerValidatorManager
*/
event NodeAdded(address indexed operator, bytes32 indexed nodeId, uint256 stake, bytes32 indexed validationID);
/**
* @notice Emitted when a node is removed
* @param operator The operator who removed the node
* @param nodeId The ID of the node
* @param validationID The validation identifier from BalancerValidatorManager
*/
event NodeRemoved(address indexed operator, bytes32 indexed nodeId, bytes32 indexed validationID);
/**
* @notice Emitted when a single node's stake is updated
* @param operator The operator who owns the node
* @param nodeId The ID of the node
* @param newStake The new stake of the node
* @param validationID The validation identifier from BalancerValidatorManager
*/
event NodeStakeUpdated(
address indexed operator, bytes32 indexed nodeId, uint256 newStake, bytes32 indexed validationID
);
/**
* @notice Emitted when the operator has leftover stake after rebalancing
* @param operator The operator who has leftover stake
* @param leftoverStake The amount of leftover stake
*/
event OperatorHasLeftoverStake(address indexed operator, uint256 leftoverStake);
/**
* @notice Emitted when all node stakes are updated for an operator
* @param operator The operator
* @param newStake The total new stake for the operator
*/
event AllNodeStakesUpdated(address indexed operator, uint256 newStake);
/**
* @notice Emitted when the Vault Manager is updated
* @param oldVaultManager The old Vault Manager address
* @param newVaultManager The new Vault Manager address
*/
event VaultManagerUpdated(address indexed oldVaultManager, address indexed newVaultManager);
/**
* @dev Simple struct to return operator stake and key.
*/
struct OperatorData {
uint256 stake;
bytes32 key;
}
// External functions
/**
* @notice Activates a secondary asset class
* @param assetClassId The asset class ID to activate
*/
function activateSecondaryAssetClass(
uint256 assetClassId
) external;
/**
* @notice Deactivates a secondary asset class
* @param assetClassId The asset class ID to deactivate
*/
function deactivateSecondaryAssetClass(
uint256 assetClassId
) external;
/**
* @notice Registers a new operator and enables it
* @param operator The operator address
*/
function registerOperator(
address operator
) external;
/**
* @notice Disables an operator
* @param operator The operator address
*/
function disableOperator(
address operator
) external;
/**
* @notice Enables an operator
* @param operator The operator address
*/
function enableOperator(
address operator
) external;
/**
* @notice Removes an operator if grace period has passed
* @param operator The operator address
*/
function removeOperator(
address operator
) external;
/**
* @notice Add a new node => create a new validator.
* Check the new node stake also ensure security module capacity.
* @param nodeId The node ID
* @param blsKey The BLS key
* @param registrationExpiry The Unix timestamp after which the reigistration is no longer valid on the P-Chain
* @param remainingBalanceOwner The owner of a validator's remaining balance
* @param disableOwner The owner of a validator's disable owner on the P-Chain
* @param stakeAmount The initial stake of the node to be added(optional)
*/
function addNode(
bytes32 nodeId,
bytes calldata blsKey,
uint64 registrationExpiry,
PChainOwner calldata remainingBalanceOwner,
PChainOwner calldata disableOwner,
uint256 stakeAmount
) external;
/**
* @notice Remove a node => remove a validator.
* @param nodeId The node ID
*/
function removeNode(
bytes32 nodeId
) external;
/**
* @notice Rebalance node stakes once per epoch for an operator.
* @param operator The operator address
* @param limitStake The maximum stake adjustment (add or remove) allowed per node per call.
*/
function forceUpdateNodes(address operator, uint256 limitStake) external;
/**
* @notice Update the stake of a validator.
* @param nodeId The node ID.
* @param stakeAmount The new stake.
*/
function initializeValidatorStakeUpdate(bytes32 nodeId, uint256 stakeAmount) external;
/**
* @notice Finalize a pending validator registration
* @param operator The operator address
* @param nodeId The node ID
* @param messageIndex The message index
*/
function completeValidatorRegistration(address operator, bytes32 nodeId, uint32 messageIndex) external;
/**
* @notice Finalize a pending stake update
* @param nodeId The node ID
* @param messageIndex The message index
*/
function completeStakeUpdate(bytes32 nodeId, uint32 messageIndex) external;
/**
* @notice Finalize a pending validator removal
* @param messageIndex The message index
*/
function completeValidatorRemoval(
uint32 messageIndex
) external;
/**
* @notice Slashes an operator's stake
* @param epoch The epoch of the slash
* @param operator The operator being slashed
* @param amount The slash amount
* @param assetClassId The asset class ID
*/
function slash(uint48 epoch, address operator, uint256 amount, uint96 assetClassId) external;
/**
* @notice Calculates and caches total stake for an epoch
* @param epoch The epoch number
* @param assetClassId The asset class ID
* @return totalStake The total stake calculated and cached
*/
function calcAndCacheStakes(uint48 epoch, uint96 assetClassId) external returns (uint256);
/**
* @notice Calculates and caches node stakes for all operators retroactively for all epochs
*/
function calcAndCacheNodeStakeForAllOperators() external;
/**
* @notice Fetches the primary and secondary asset classes
* @return primary The primary asset class
* @return secondaries An array of secondary asset classes
*/
function getActiveAssetClasses() external view returns (uint256 primary, uint256[] memory secondaries);
/**
* @notice Checks if the classId is active
* @param assetClassId The asset class ID
* @return bool True if active
*/
function isActiveAssetClass(
uint96 assetClassId
) external view returns (bool);
/**
* @notice Gets the start timestamp for a given epoch
* @param epoch The epoch number
* @return timestamp The start time of that epoch
*/
function getEpochStartTs(
uint48 epoch
) external view returns (uint48);
/**
* @notice Gets the epoch number at a given timestamp
* @param timestamp The timestamp
* @return epoch The epoch at that time
*/
function getEpochAtTs(
uint48 timestamp
) external view returns (uint48);
/**
* @notice Gets the current epoch based on the current block time
* @return epoch The current epoch
*/
function getCurrentEpoch() external view returns (uint48);
/**
* @notice Returns an operator's stake at a given epoch for a specific asset class
* @param operator The operator address
* @param epoch The epoch number
* @param assetClassId The asset class ID
* @return stake The operator's stake
*/
function getOperatorStake(address operator, uint48 epoch, uint96 assetClassId) external view returns (uint256);
/**
* @notice Returns total stake across all operators in a specific epoch
* @param epoch The epoch number
* @param assetClassId The asset class ID
* @return The total stake in that epoch
*/
function getTotalStake(uint48 epoch, uint96 assetClassId) external view returns (uint256);
/**
* @notice Returns all operators
*/
function getAllOperators() external view returns (address[] memory);
/**
* @notice Returns the cached stake for a given node in the specified epoch, based on its Validation ID.
* @param epoch The target Not enough free stake to add nodeepoch.
* @param validationId The node ID.
* @return The node stake from the cache.
*/
function getNodeStake(uint48 epoch, bytes32 validationId) external view returns (uint256);
/**
* @notice Returns the current epoch number
* @param operator The operator address
* @param epoch The epoch number
* @return activeNodeIds The list of nodes
*/
function getActiveNodesForEpoch(address operator, uint48 epoch) external view returns (bytes32[] memory);
/**
* @notice Returns the available stake for an operator
* @param operator The operator address
* @return The available stake
*/
function getOperatorAvailableStake(
address operator
) external view returns (uint256);
/**
* @notice Summation of node stakes from the nodeStakeCache.
* @param operator The operator address.
* @return registeredStake The sum of node stakes.
*/
function getOperatorUsedStakeCached(
address operator
) external view returns (uint256);
/**
* @notice Returns the Vault Manager address associated to this middleware
* @return Address Vault Manager
*/
function getVaultManager() external view returns (address);
/**
* @notice Returns the true active stake for an operator in a given epoch and asset class
* @param epoch The epoch number
* @param operator The operator address
* @param assetClass The asset class ID
* @return The true active stake
*/
function getOperatorUsedStakeCachedPerEpoch(
uint48 epoch,
address operator,
uint96 assetClass
) external view returns (uint256);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// 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);
}
}// (c) 2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// SPDX-License-Identifier: Ecosystem
pragma solidity 0.8.25;
/**
* @dev Validator status
*/
enum ValidatorStatus {
Unknown,
PendingAdded,
Active,
PendingRemoved,
Completed,
Invalidated
}
/**
* @dev Specifies the owner of a validator's remaining balance or disable owner on the P-Chain.
* P-Chain addresses are also 20-bytes, so we use the address type to represent them.
*/
struct PChainOwner {
uint32 threshold;
address[] addresses;
}
/**
* @dev Contains the active state of a Validator
*/
struct Validator {
ValidatorStatus status;
bytes nodeID;
uint64 startingWeight;
uint64 messageNonce;
uint64 weight;
uint64 startedAt;
uint64 endedAt;
}
/**
* @dev Describes the current churn period
*/
struct ValidatorChurnPeriod {
uint256 startedAt;
uint64 initialWeight;
uint64 totalWeight;
uint64 churnAmount;
}
/**
* @notice Validator Manager settings, used to initialize the Validator Manager
* @notice The l1ID is the ID of the L1 that the Validator Manager is managing
* @notice The churnPeriodSeconds is the duration of the churn period in seconds
* @notice The maximumChurnPercentage is the maximum percentage of the total weight that can be added or removed in a single churn period
*/
struct ValidatorManagerSettings {
bytes32 l1ID;
uint64 churnPeriodSeconds;
uint8 maximumChurnPercentage;
}
/**
* @dev Description of the conversion data used to convert
* a subnet to an L1 on the P-Chain.
* This data is the pre-image of a hash that is authenticated by the P-Chain
* and verified by the Validator Manager.
*/
struct ConversionData {
bytes32 l1ID;
bytes32 validatorManagerBlockchainID;
address validatorManagerAddress;
InitialValidator[] initialValidators;
}
/**
* @dev Specifies an initial validator, used in the conversion data.
*/
struct InitialValidator {
bytes nodeID;
bytes blsPublicKey;
uint64 weight;
}
/**
* @dev Specifies a validator to register.
*/
struct ValidatorRegistrationInput {
bytes nodeID;
bytes blsPublicKey;
uint64 registrationExpiry;
PChainOwner remainingBalanceOwner;
PChainOwner disableOwner;
}
/**
* @notice Interface for Validator Manager contracts that implement Subnet-only Validator management.
*/
interface IValidatorManager {
/**
* @notice Emitted when a new validation period is created by locking stake in the manager contract.
* Note: This event does not mean that the validation period has been successfully registered on the P-Chain,
* and rewards for this validation period will not begin accruing until the {ValidationPeriodRegistered} event is
* emitted.
* @param validationID The ID of the validation period being created.
* @param nodeID The node ID of the validator being registered.
* @param registerValidationMessageID The ID of the ICM message that will be sent to the P-Chain to register the
* validation period.
* @param weight The weight of the validator being registered.
* @param registrationExpiry The Unix timestamp after which the reigistration is no longer valid on the P-Chain.
*/
event ValidationPeriodCreated(
bytes32 indexed validationID,
bytes indexed nodeID,
bytes32 indexed registerValidationMessageID,
uint64 weight,
uint64 registrationExpiry
);
event InitialValidatorCreated(
bytes32 indexed validationID, bytes indexed nodeID, uint64 weight
);
/**
* @notice Emitted when the staking manager learns that the validation period has been successfully registered
* on the P-Chain. Rewards for this validation period will begin accruing when this event is emitted.
* @param validationID The ID of the validation period being registered.
* @param weight The weight of the validator being registered.
* @param timestamp The time at which the validation period was registered with the contract.
*/
event ValidationPeriodRegistered(
bytes32 indexed validationID, uint64 weight, uint256 timestamp
);
/**
* @notice Emitted when the process of ending a registered validation period is started by calling
* {initializeEndValidation}.
* Note: The stake for this validation period remains locked until a {ValidationPeriodRemoved} event is emitted.
* @param validationID The ID of the validation period being removed.
* @param setWeightMessageID The ID of the ICM message that updates the validator's weight on the P-Chain.
* @param weight The weight of the validator being removed.
* @param endTime The time at which the removal was initiated.
*/
event ValidatorRemovalInitialized(
bytes32 indexed validationID,
bytes32 indexed setWeightMessageID,
uint64 weight,
uint256 endTime
);
/**
* @notice Emitted when the stake for a validation period is unlocked and returned to the staker.
* This is done by calling {completeEndValidation}, which provides proof from the P-Chain that the
* validation period is not active and will never be active in the future.
* @param validationID The ID of the validation period being removed.
*/
event ValidationPeriodEnded(bytes32 indexed validationID, ValidatorStatus indexed status);
/**
* @notice Event emitted when validator weight is updated.
* @param validationID The ID of the validation period being updated
* @param nonce The message nonce used to update the validator weight
* @param weight The updated validator weight that is sent to the P-Chain
* @param setWeightMessageID The ID of the ICM message that updates the validator's weight on the P-Chain
*/
event ValidatorWeightUpdate(
bytes32 indexed validationID,
uint64 indexed nonce,
uint64 weight,
bytes32 setWeightMessageID
);
/**
* @notice Verifies and sets the initial validator set for the chain through a P-Chain SubnetToL1ConversionMessage.
* @param conversionData The subnet conversion message data used to recompute and verify against the conversionID.
* @param messsageIndex The index that contains the SubnetToL1ConversionMessage ICM message containing the conversionID to be verified against the provided {ConversionData}
*/
function initializeValidatorSet(
ConversionData calldata conversionData,
uint32 messsageIndex
) external;
/**
* @notice Resubmits a validator registration message to be sent to the P-Chain.
* Only necessary if the original message can't be delivered due to validator churn.
* @param validationID The ID of the validation period being registered.
*/
function resendRegisterValidatorMessage(bytes32 validationID) external;
/**
* @notice Completes the validator registration process by returning an acknowledgement of the registration of a
* validationID from the P-Chain.
* @param messageIndex The index of the ICM message to be received providing the acknowledgement.
*/
function completeValidatorRegistration(uint32 messageIndex) external;
/**
* @notice Resubmits a validator end message to be sent to the P-Chain.
* Only necessary if the original message can't be delivered due to validator churn.
* @param validationID The ID of the validation period being ended.
*/
function resendEndValidatorMessage(bytes32 validationID) external;
/**
* @notice Completes the process of ending a validation period by receiving an acknowledgement from the P-Chain
* that the validation ID is not active and will never be active in the future. Returns the the stake associated
* with the validation.
* Note: This function can be used for successful validation periods that have been explicitly ended by calling
* {initializeEndValidation} or for validation periods that never began on the P-Chain due to the {registrationExpiry} being reached.
* @param messageIndex The index of the ICM message to be received providing the proof the validation is not active
* and never will be active on the P-Chain.
*/
function completeEndValidation(uint32 messageIndex) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (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;
}
}{
"remappings": [
"@suzaku/collateral/=lib/collateral/src/",
"@suzaku/core/=lib/suzaku-core/",
"@suzaku/contracts-lib/=lib/suzaku-contracts-library/",
"@suzaku/contracts-library/=lib/suzaku-contracts-library/src/",
"@avalabs/teleporter/=lib/suzaku-contracts-library/lib/icm-contracts/contracts/",
"@avalabs/icm-contracts/=lib/suzaku-contracts-library/lib/icm-contracts/contracts/",
"@avalabs/subnet-evm-contracts/=lib/suzaku-core/lib/suzaku-contracts-library/lib/icm-contracts/lib/subnet-evm/contracts/contracts/",
"@avalabs/[email protected]/=lib/suzaku-contracts-library/lib/icm-contracts/lib/subnet-evm/contracts/",
"@forge-std/=lib/suzaku-contracts-library/lib/icm-contracts/lib/forge-std/src/",
"@mocks/=lib/suzaku-contracts-library/lib/icm-contracts/contracts/mocks/",
"@openzeppelin/contracts-upgradeable/=lib/collateral/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/[email protected]/=lib/suzaku-contracts-library/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/collateral/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/[email protected]/=lib/suzaku-contracts-library/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/foundry-upgrades/=lib/suzaku-core/lib/openzeppelin-foundry-upgrades/src/",
"@symbiotic/core/=lib/suzaku-core/lib/core/src/",
"@teleporter/=lib/suzaku-contracts-library/lib/icm-contracts/contracts/teleporter/",
"@utilities/=lib/suzaku-contracts-library/lib/icm-contracts/contracts/utilities/",
"collateral/=lib/collateral/",
"core/=lib/suzaku-core/lib/core/",
"ds-test/=lib/collateral/lib/permit2/lib/solmate/lib/ds-test/src/",
"erc4626-tests/=lib/collateral/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-gas-snapshot/=lib/collateral/lib/permit2/lib/forge-gas-snapshot/src/",
"forge-std/=lib/forge-std/src/",
"icm-contracts/=lib/suzaku-contracts-library/lib/icm-contracts/contracts/",
"openzeppelin-contracts-upgradeable/=lib/collateral/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/collateral/lib/openzeppelin-contracts/",
"openzeppelin-foundry-upgrades/=lib/suzaku-core/lib/openzeppelin-foundry-upgrades/src/",
"permit2/=lib/collateral/lib/permit2/",
"solidity-stringutils/=lib/suzaku-core/lib/openzeppelin-foundry-upgrades/lib/solidity-stringutils/",
"solmate/=lib/collateral/lib/permit2/lib/solmate/",
"subnet-evm/=lib/suzaku-contracts-library/lib/icm-contracts/lib/subnet-evm/",
"suzaku-contracts-library/=lib/suzaku-contracts-library/",
"suzaku-core/=lib/suzaku-core/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": true,
"libraries": {}
}Contract ABI
API[{"inputs":[{"internalType":"address payable","name":"feeCollector_","type":"address"},{"internalType":"uint256","name":"registerFee_","type":"uint256"},{"internalType":"uint256","name":"MAX_FEE_","type":"uint256"},{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"},{"internalType":"uint256","name":"maxFee","type":"uint256"}],"name":"L1Registry__FeeExceedsMaximum","type":"error"},{"inputs":[],"name":"L1Registry__FeeTransferFailed","type":"error"},{"inputs":[],"name":"L1Registry__InsufficientFee","type":"error"},{"inputs":[],"name":"L1Registry__InvalidL1Middleware","type":"error"},{"inputs":[{"internalType":"address","name":"l1","type":"address"}],"name":"L1Registry__InvalidValidatorManager","type":"error"},{"inputs":[],"name":"L1Registry__L1AlreadyRegistered","type":"error"},{"inputs":[],"name":"L1Registry__L1NotRegistered","type":"error"},{"inputs":[],"name":"L1Registry__NoFeesToWithdraw","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"L1Registry__NotFeeCollector","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"expectedOwner","type":"address"}],"name":"L1Registry__NotValidatorManagerOwner","type":"error"},{"inputs":[{"internalType":"string","name":"name","type":"string"}],"name":"L1Registry__ZeroAddress","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"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":"l1","type":"address"}],"name":"RegisterL1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1","type":"address"},{"indexed":true,"internalType":"address","name":"l1Middleware","type":"address"}],"name":"SetL1Middleware","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"l1","type":"address"},{"indexed":false,"internalType":"string","name":"metadataURL","type":"string"}],"name":"SetMetadataURL","type":"event"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAllL1s","outputs":[{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"address[]","name":"","type":"address[]"},{"internalType":"string[]","name":"","type":"string[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getL1At","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"l1","type":"address"}],"name":"isRegistered","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"l1","type":"address"},{"internalType":"address","name":"vaultManager_","type":"address"}],"name":"isRegisteredWithMiddleware","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"l1MetadataURL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"l1Middleware","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registerFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"l1","type":"address"},{"internalType":"address","name":"l1Middleware_","type":"address"},{"internalType":"string","name":"metadataURL","type":"string"}],"name":"registerL1","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newFeeCollector","type":"address"}],"name":"setFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"l1","type":"address"},{"internalType":"address","name":"l1Middleware_","type":"address"}],"name":"setL1Middleware","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"l1","type":"address"},{"internalType":"string","name":"metadataURL","type":"string"}],"name":"setMetadataURL","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"setRegisterFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalL1s","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":[],"name":"unclaimedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a03461012757601f6113b838819003918201601f19168301916001600160401b0383118484101761012b578084926080946040528339810103126101275780516001600160a01b039081811690819003610127576020830151916060604085015194015181811680910361012757801561010f575f549060018060a01b03199281848416175f5560405192167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a382156100dd5750600554161760055560065560805260405161127890816101408239608051816108dc0152f35b635a0bc64760e01b815260206004820152600c60248201526b3332b2a1b7b63632b1ba37b960a11b6044820152606490fd5b604051631e4fbdf760e01b81525f6004820152602490fd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe608060409080825260049081361015610022575b5050503615610020575f80fd5b005b5f3560e01c90816303f187ea14610e295750806334ebec3014610df05780633a98187b14610cb35780634049596a14610c86578063476343ee14610c08578063715018a614610bb1578063720057c4146109b4578063734d8287146109965780638c36aa1c1461094b5780638da5cb5b1461092457806392be2ab8146108bd5780639ec60b41146105ae578063a42dce8014610502578063bffcb7e814610461578063c3c5a5471461041e578063c40e2880146101cf578063c415b95c146101a7578063d96f3599146101895763f2fde38b146100ff5780610013565b3461018557602036600319011261018557610118610e43565b90610121611181565b6001600160a01b0391821692831561016f5750505f54826001600160601b0360a01b8216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b905f6024925191631e4fbdf760e01b8352820152fd5b5f80fd5b8234610185575f366003190112610185576020906001549051908152f35b8234610185575f3660031901126101855760055490516001600160a01b039091168152602090f35b50346101855781600319360112610185576101e8610e43565b67ffffffffffffffff90602435828111610185576102099036908501610fdf565b92909160018060a01b038091169461022c865f52600260205260405f2054151590565b15610410578651638da5cb5b60e01b8152602092838284818b5afa918215610406575f926103d7575b5033908216036103aa5750855f52808252865f20928511610397575061027b8254610ecf565b601f8111610354575b505f90601f85116001146102dd5750946102cd91845f8051602061122383398151915296975f916102d2575b508560011b905f198760031b1c19161790555b519283928361115a565b0390a2005b90508401355f6102b0565b90601f198516835f52825f20925f905b82821061033c575050916102cd9391865f8051602061122383398151915298999410610323575b5050600185811b0190556102c3565b8501355f19600388901b60f8161c191690555f80610314565b80600185968294968a013581550195019301906102ed565b825f52815f20601f860160051c81019183871061038d575b601f0160051c01905b8181106103825750610284565b5f8155600101610375565b909150819061036c565b604190634e487b7160e01b5f525260245ffd5b8751630f42d82560e21b8152339281019283526001600160a01b0390911660208301529081906040010390fd5b6103f8919250843d86116103ff575b6103f08183610f07565b81019061100d565b905f610255565b503d6103e6565b89513d5f823e3d90fd5b86516332814c1960e01b8152fd5b8234610185576020366003190112610185576020906104586001600160a01b03610446610e43565b165f52600260205260405f2054151590565b90519015158152f35b509034610185576020366003190112610185578135906001548210156104ef576104eb9060018060a01b0380937fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601541692835f526003602052815f2054169360205260606104d1825f20610f3d565b918051958695865260208601528401526060830190610eab565b0390f35b603283634e487b7160e01b5f525260245ffd5b50346101855760203660031901126101855780356001600160a01b038116929083900361018557610531611181565b821561057b578260075480610559575b506001600160601b0360a01b60055416176005555f80f35b5f6007555f80808084865af161056d6110db565b506105415760075581610541565b9060206064925191635a0bc64760e01b8352820152600c60248201526b3332b2a1b7b63632b1ba37b960a11b6044820152fd5b506060366003190112610185576105c3610e43565b6105cb610e59565b67ffffffffffffffff93604435858111610185576105ec9036908601610fdf565b956001600160a01b03948516959194909186156108a6578351638da5cb5b60e01b815260209290838184818c5afa90811561089c575f9161087f575b5033828216036108525750600654806107f4575b50610646886111ac565b156107e557875f5260038352845f20951694856001600160601b0360a01b825416179055808252835f2092881161039757506106828254610ecf565b601f81116107a2575b505f90601f881160011461072a57509186915f8051602061122383398151915296976102cd945f9161071f575b508360011b905f198560031b1c19161790555b51938493877fec03e7641f2ddabb96aad9433e5ecdce879559cf693804cc5891626950fd006a5f80a2877fc4bfddda2d4796aa99cbc1d81e2732dcbb467734f776699113fb7bafbff8d56f5f80a38361115a565b90508601355f6106b8565b90601f198816835f52825f20925f905b82821061078a575050918893915f8051602061122383398151915298996102cd969410610771575b5050600183811b0190556106cb565b8701355f19600386901b60f8161c191690555f80610762565b80600185968294968c0135815501950193019061073a565b825f52815f20601f890160051c810191838a106107db575b601f0160051c01905b8181106107d0575061068b565b5f81556001016107c3565b90915081906107ba565b50835163030fa68760e51b8152fd5b3410610843575f8080803485600554165af161080e6110db565b501561081b575b5f61063c565b60075434810180911161083057600755610815565b601183634e487b7160e01b5f525260245ffd5b508351631fab2c7d60e01b8152fd5b8551630f42d82560e21b8152338185019081526001600160a01b0390921660208301529081906040010390fd5b6108969150843d86116103ff576103f08183610f07565b5f610628565b86513d5f823e3d90fd5b8351632f286dff60e01b8152908101879052602490fd5b5034610185576020366003190112610185578035916108da611181565b7f00000000000000000000000000000000000000000000000000000000000000009081841161090a576006849055005b926044935192633fb535d560e11b84528301526024820152fd5b8234610185575f366003190112610185575f5490516001600160a01b039091168152602090f35b509034610185576020366003190112610185576104eb916001600160a01b03610972610e43565b165f52602052610983815f20610f3d565b9051918291602083526020830190610eab565b8234610185575f366003190112610185576020906007549051908152f35b509034610185575f36600319011261018557805190816001918254808352602080930190845f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6905f5b818110610b9e5750505084610a15910385610f07565b835191610a39610a248461111a565b93610a3184519586610f07565b80855261111a565b601f1993908401368383013785519684610a6a610a558a61111a565b99610a6287519b8c610f07565b808b5261111a565b015f5b818110610b8f575050855f905b610b02575b5050610aa690610a99845197606089526060890190610e6f565b9087820384890152610e6f565b918583039086015285519182815281810182808560051b8401019801945f925b858410610ad357888a0389f35b909192939495968580610aef8c8686869f030188528b51610eab565b9b99019796959190910193019190610ac6565b9086989691889694959651811015610b825782906001600160a01b0380610b29838d611132565b51165f526003885280895f205416610b418388611132565b52610b4c828c611132565b51165f52828752610b5e885f20610f3d565b610b68828b611132565b52610b73818a611132565b50019091969895949395610a7a565b5097959794939294610a7f565b60608a82018601528401610a6d565b82548452928501929186019186016109ff565b34610185575f36600319011261018557610bc9611181565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b509034610185575f366003190112610185576005546001600160a01b031633819003610c7057600754908115610c61575f8080938193826007555af1610c4c6110db565b5015610c5457005b5163eaa7352f60e01b8152fd5b50505163134b502360e01b8152fd5b815163e548a2dd60e01b81523381850152602490fd5b8234610185578060031936011261018557602090610458610ca5610e43565b610cad610e59565b9061102c565b5034610185578160031936011261018557610ccc610e43565b916001600160a01b0380610cde610e59565b16938415610dd957811692610cfe845f52600260205260405f2054151590565b15610dcb578251638da5cb5b60e01b8152916020838381885afa928315610dc1575f93610da0575b503390831603610d74575050815f5260036020525f20826001600160601b0360a01b8254161790557fc4bfddda2d4796aa99cbc1d81e2732dcbb467734f776699113fb7bafbff8d56f5f80a3005b8251630f42d82560e21b8152339181019182526001600160a01b03909216602082015281906040010390fd5b610dba91935060203d6020116103ff576103f08183610f07565b915f610d26565b84513d5f823e3d90fd5b82516332814c1960e01b8152fd5b8251632f286dff60e01b8152808501869052602490fd5b8234610185576020366003190112610185576020906001600160a01b0380610e16610e43565b165f5260038352815f2054169051908152f35b34610185575f366003190112610185576020906006548152f35b600435906001600160a01b038216820361018557565b602435906001600160a01b038216820361018557565b9081518082526020808093019301915f5b828110610e8e575050505090565b83516001600160a01b031685529381019392810192600101610e80565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90600182811c92168015610efd575b6020831014610ee957565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ede565b90601f8019910116810190811067ffffffffffffffff821117610f2957604052565b634e487b7160e01b5f52604160045260245ffd5b9060405191825f8254610f4f81610ecf565b908184526020946001916001811690815f14610fbd5750600114610f7f575b505050610f7d92500383610f07565b565b5f90815285812095935091905b818310610fa5575050610f7d93508201015f8080610f6e565b85548884018501529485019487945091830191610f8c565b92505050610f7d94925060ff191682840152151560051b8201015f8080610f6e565b9181601f840112156101855782359167ffffffffffffffff8311610185576020838186019501011161018557565b9081602091031261018557516001600160a01b03811681036101855790565b6001600160a01b039081165f81815260026020526040902054156110d4575f5260036020528060405f2054169182156110d45760206004936040519485809263b9bbb6f560e01b82525afa9283156110c9575f936110a6575b50811691160361109457600190565b604051631363c09760e31b8152600490fd5b829193506110c29060203d6020116103ff576103f08183610f07565b9290611085565b6040513d5f823e3d90fd5b5050505f90565b3d15611115573d9067ffffffffffffffff8211610f29576040519161110a601f8201601f191660200184610f07565b82523d5f602084013e565b606090565b67ffffffffffffffff8111610f295760051b60200190565b80518210156111465760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b90918060409360208452816020850152848401375f828201840152601f01601f1916010190565b5f546001600160a01b0316330361119457565b60405163118cdaa760e01b8152336004820152602490fd5b805f52600260205260405f2054155f1461121d5760015468010000000000000000811015610f295760018101806001558110156111465781907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155600154905f52600260205260405f2055600190565b505f9056fef8dac27f20d622a0759394313683066cb713a406633a3a7dde8799654015ea64a264697066735822122037e9b2d1d530821a921e7af3795e0509281a80561f2352bf3ef1ca77ce6876cd64736f6c634300081900330000000000000000000000002811086bd8962c536264e711470f7ef9a783a5eb000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000002811086bd8962c536264e711470f7ef9a783a5eb
Deployed Bytecode
0x608060409080825260049081361015610022575b5050503615610020575f80fd5b005b5f3560e01c90816303f187ea14610e295750806334ebec3014610df05780633a98187b14610cb35780634049596a14610c86578063476343ee14610c08578063715018a614610bb1578063720057c4146109b4578063734d8287146109965780638c36aa1c1461094b5780638da5cb5b1461092457806392be2ab8146108bd5780639ec60b41146105ae578063a42dce8014610502578063bffcb7e814610461578063c3c5a5471461041e578063c40e2880146101cf578063c415b95c146101a7578063d96f3599146101895763f2fde38b146100ff5780610013565b3461018557602036600319011261018557610118610e43565b90610121611181565b6001600160a01b0391821692831561016f5750505f54826001600160601b0360a01b8216175f55167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3005b905f6024925191631e4fbdf760e01b8352820152fd5b5f80fd5b8234610185575f366003190112610185576020906001549051908152f35b8234610185575f3660031901126101855760055490516001600160a01b039091168152602090f35b50346101855781600319360112610185576101e8610e43565b67ffffffffffffffff90602435828111610185576102099036908501610fdf565b92909160018060a01b038091169461022c865f52600260205260405f2054151590565b15610410578651638da5cb5b60e01b8152602092838284818b5afa918215610406575f926103d7575b5033908216036103aa5750855f52808252865f20928511610397575061027b8254610ecf565b601f8111610354575b505f90601f85116001146102dd5750946102cd91845f8051602061122383398151915296975f916102d2575b508560011b905f198760031b1c19161790555b519283928361115a565b0390a2005b90508401355f6102b0565b90601f198516835f52825f20925f905b82821061033c575050916102cd9391865f8051602061122383398151915298999410610323575b5050600185811b0190556102c3565b8501355f19600388901b60f8161c191690555f80610314565b80600185968294968a013581550195019301906102ed565b825f52815f20601f860160051c81019183871061038d575b601f0160051c01905b8181106103825750610284565b5f8155600101610375565b909150819061036c565b604190634e487b7160e01b5f525260245ffd5b8751630f42d82560e21b8152339281019283526001600160a01b0390911660208301529081906040010390fd5b6103f8919250843d86116103ff575b6103f08183610f07565b81019061100d565b905f610255565b503d6103e6565b89513d5f823e3d90fd5b86516332814c1960e01b8152fd5b8234610185576020366003190112610185576020906104586001600160a01b03610446610e43565b165f52600260205260405f2054151590565b90519015158152f35b509034610185576020366003190112610185578135906001548210156104ef576104eb9060018060a01b0380937fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf601541692835f526003602052815f2054169360205260606104d1825f20610f3d565b918051958695865260208601528401526060830190610eab565b0390f35b603283634e487b7160e01b5f525260245ffd5b50346101855760203660031901126101855780356001600160a01b038116929083900361018557610531611181565b821561057b578260075480610559575b506001600160601b0360a01b60055416176005555f80f35b5f6007555f80808084865af161056d6110db565b506105415760075581610541565b9060206064925191635a0bc64760e01b8352820152600c60248201526b3332b2a1b7b63632b1ba37b960a11b6044820152fd5b506060366003190112610185576105c3610e43565b6105cb610e59565b67ffffffffffffffff93604435858111610185576105ec9036908601610fdf565b956001600160a01b03948516959194909186156108a6578351638da5cb5b60e01b815260209290838184818c5afa90811561089c575f9161087f575b5033828216036108525750600654806107f4575b50610646886111ac565b156107e557875f5260038352845f20951694856001600160601b0360a01b825416179055808252835f2092881161039757506106828254610ecf565b601f81116107a2575b505f90601f881160011461072a57509186915f8051602061122383398151915296976102cd945f9161071f575b508360011b905f198560031b1c19161790555b51938493877fec03e7641f2ddabb96aad9433e5ecdce879559cf693804cc5891626950fd006a5f80a2877fc4bfddda2d4796aa99cbc1d81e2732dcbb467734f776699113fb7bafbff8d56f5f80a38361115a565b90508601355f6106b8565b90601f198816835f52825f20925f905b82821061078a575050918893915f8051602061122383398151915298996102cd969410610771575b5050600183811b0190556106cb565b8701355f19600386901b60f8161c191690555f80610762565b80600185968294968c0135815501950193019061073a565b825f52815f20601f890160051c810191838a106107db575b601f0160051c01905b8181106107d0575061068b565b5f81556001016107c3565b90915081906107ba565b50835163030fa68760e51b8152fd5b3410610843575f8080803485600554165af161080e6110db565b501561081b575b5f61063c565b60075434810180911161083057600755610815565b601183634e487b7160e01b5f525260245ffd5b508351631fab2c7d60e01b8152fd5b8551630f42d82560e21b8152338185019081526001600160a01b0390921660208301529081906040010390fd5b6108969150843d86116103ff576103f08183610f07565b5f610628565b86513d5f823e3d90fd5b8351632f286dff60e01b8152908101879052602490fd5b5034610185576020366003190112610185578035916108da611181565b7f0000000000000000000000000000000000000000000000000de0b6b3a76400009081841161090a576006849055005b926044935192633fb535d560e11b84528301526024820152fd5b8234610185575f366003190112610185575f5490516001600160a01b039091168152602090f35b509034610185576020366003190112610185576104eb916001600160a01b03610972610e43565b165f52602052610983815f20610f3d565b9051918291602083526020830190610eab565b8234610185575f366003190112610185576020906007549051908152f35b509034610185575f36600319011261018557805190816001918254808352602080930190845f527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6905f5b818110610b9e5750505084610a15910385610f07565b835191610a39610a248461111a565b93610a3184519586610f07565b80855261111a565b601f1993908401368383013785519684610a6a610a558a61111a565b99610a6287519b8c610f07565b808b5261111a565b015f5b818110610b8f575050855f905b610b02575b5050610aa690610a99845197606089526060890190610e6f565b9087820384890152610e6f565b918583039086015285519182815281810182808560051b8401019801945f925b858410610ad357888a0389f35b909192939495968580610aef8c8686869f030188528b51610eab565b9b99019796959190910193019190610ac6565b9086989691889694959651811015610b825782906001600160a01b0380610b29838d611132565b51165f526003885280895f205416610b418388611132565b52610b4c828c611132565b51165f52828752610b5e885f20610f3d565b610b68828b611132565b52610b73818a611132565b50019091969895949395610a7a565b5097959794939294610a7f565b60608a82018601528401610a6d565b82548452928501929186019186016109ff565b34610185575f36600319011261018557610bc9611181565b5f80546001600160a01b0319811682556001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b509034610185575f366003190112610185576005546001600160a01b031633819003610c7057600754908115610c61575f8080938193826007555af1610c4c6110db565b5015610c5457005b5163eaa7352f60e01b8152fd5b50505163134b502360e01b8152fd5b815163e548a2dd60e01b81523381850152602490fd5b8234610185578060031936011261018557602090610458610ca5610e43565b610cad610e59565b9061102c565b5034610185578160031936011261018557610ccc610e43565b916001600160a01b0380610cde610e59565b16938415610dd957811692610cfe845f52600260205260405f2054151590565b15610dcb578251638da5cb5b60e01b8152916020838381885afa928315610dc1575f93610da0575b503390831603610d74575050815f5260036020525f20826001600160601b0360a01b8254161790557fc4bfddda2d4796aa99cbc1d81e2732dcbb467734f776699113fb7bafbff8d56f5f80a3005b8251630f42d82560e21b8152339181019182526001600160a01b03909216602082015281906040010390fd5b610dba91935060203d6020116103ff576103f08183610f07565b915f610d26565b84513d5f823e3d90fd5b82516332814c1960e01b8152fd5b8251632f286dff60e01b8152808501869052602490fd5b8234610185576020366003190112610185576020906001600160a01b0380610e16610e43565b165f5260038352815f2054169051908152f35b34610185575f366003190112610185576020906006548152f35b600435906001600160a01b038216820361018557565b602435906001600160a01b038216820361018557565b9081518082526020808093019301915f5b828110610e8e575050505090565b83516001600160a01b031685529381019392810192600101610e80565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b90600182811c92168015610efd575b6020831014610ee957565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610ede565b90601f8019910116810190811067ffffffffffffffff821117610f2957604052565b634e487b7160e01b5f52604160045260245ffd5b9060405191825f8254610f4f81610ecf565b908184526020946001916001811690815f14610fbd5750600114610f7f575b505050610f7d92500383610f07565b565b5f90815285812095935091905b818310610fa5575050610f7d93508201015f8080610f6e565b85548884018501529485019487945091830191610f8c565b92505050610f7d94925060ff191682840152151560051b8201015f8080610f6e565b9181601f840112156101855782359167ffffffffffffffff8311610185576020838186019501011161018557565b9081602091031261018557516001600160a01b03811681036101855790565b6001600160a01b039081165f81815260026020526040902054156110d4575f5260036020528060405f2054169182156110d45760206004936040519485809263b9bbb6f560e01b82525afa9283156110c9575f936110a6575b50811691160361109457600190565b604051631363c09760e31b8152600490fd5b829193506110c29060203d6020116103ff576103f08183610f07565b9290611085565b6040513d5f823e3d90fd5b5050505f90565b3d15611115573d9067ffffffffffffffff8211610f29576040519161110a601f8201601f191660200184610f07565b82523d5f602084013e565b606090565b67ffffffffffffffff8111610f295760051b60200190565b80518210156111465760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b90918060409360208452816020850152848401375f828201840152601f01601f1916010190565b5f546001600160a01b0316330361119457565b60405163118cdaa760e01b8152336004820152602490fd5b805f52600260205260405f2054155f1461121d5760015468010000000000000000811015610f295760018101806001558110156111465781907fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60155600154905f52600260205260405f2055600190565b505f9056fef8dac27f20d622a0759394313683066cb713a406633a3a7dde8799654015ea64a264697066735822122037e9b2d1d530821a921e7af3795e0509281a80561f2352bf3ef1ca77ce6876cd64736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000002811086bd8962c536264e711470f7ef9a783a5eb000000000000000000000000000000000000000000000000002386f26fc100000000000000000000000000000000000000000000000000000de0b6b3a76400000000000000000000000000002811086bd8962c536264e711470f7ef9a783a5eb
-----Decoded View---------------
Arg [0] : feeCollector_ (address): 0x2811086Bd8962C536264e711470f7ef9A783a5eB
Arg [1] : registerFee_ (uint256): 10000000000000000
Arg [2] : MAX_FEE_ (uint256): 1000000000000000000
Arg [3] : owner (address): 0x2811086Bd8962C536264e711470f7ef9A783a5eB
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000002811086bd8962c536264e711470f7ef9a783a5eb
Arg [1] : 000000000000000000000000000000000000000000000000002386f26fc10000
Arg [2] : 0000000000000000000000000000000000000000000000000de0b6b3a7640000
Arg [3] : 0000000000000000000000002811086bd8962c536264e711470f7ef9a783a5eb
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.