Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
NodeRegistry
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 300 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {IERC20, SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol"; import {UUPSUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/proxy/utils/UUPSUpgradeable.sol"; import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol"; import {INodeRegistry, ISignatureUtils} from "./interfaces/INodeRegistry.sol"; import {INodeRegistryOwner} from "./interfaces/INodeRegistryOwner.sol"; import {IController} from "./interfaces/IController.sol"; import {INodeStaking} from "Staking-v0.1/interfaces/INodeStaking.sol"; import {IServiceManager} from "./interfaces/IServiceManager.sol"; import {BLS} from "./libraries/BLS.sol"; import {IERC1271} from "openzeppelin-contracts/contracts/interfaces/IERC1271.sol"; import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol"; import {ECDSA} from "openzeppelin-contracts/contracts/utils/cryptography/ECDSA.sol"; contract NodeRegistry is UUPSUpgradeable, INodeRegistry, INodeRegistryOwner, OwnableUpgradeable { using SafeERC20 for IERC20; // *Constants* /// @notice The EIP-712 typehash for the contract's domain bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)"); /// @notice The EIP-712 typehash for the `Registration` struct used by the contract bytes32 public constant NATIVE_NODE_REGISTRATION_TYPEHASH = keccak256("NativeNodeRegistration(address assetAccountAddress,bytes32 salt,uint256 expiry)"); // bytes4(keccak256("isValidSignature(bytes32,bytes)") bytes4 internal constant _EIP1271_MAGICVALUE = 0x1626ba7e; uint16 private constant _BALANCE_BASE = 1; // *NodeRegistry Config* NodeRegistryConfig private _config; IERC20 private _arpa; // *Node State Variables* mapping(address => Node) private _nodes; // maps node address to Node Struct mapping(address => uint256) private _withdrawableEths; // maps node address to withdrawable eth amount mapping(address => uint256) private _arpaRewards; // maps node address to arpa rewards mapping(address => address) private _assetAccountsToNodes; // maps asset account address to node address mapping(address => address) private _nodesToAssetAccounts; // maps node address to asset account address mapping(address => mapping(bytes32 => bool)) private _assetAccountSaltIsSpent; // maps asset account address to salt // *Events* event NodeRegistered(address indexed nodeAddress, bytes dkgPublicKey, uint256 groupIndex); event NodeActivated(address indexed nodeAddress, uint256 groupIndex); event NodeQuit(address indexed nodeAddress); event DkgPublicKeyChanged(address indexed nodeAddress, bytes dkgPublicKey); event NodeRewarded(address indexed nodeAddress, uint256 ethAmount, uint256 arpaAmount); event NodeSlashed(address indexed nodeIdAddress, uint256 stakingRewardPenalty, uint256 pendingBlock); event AssetAccountSet(address indexed assetAccountAddress, address indexed nodeAddress); // *Errors* error NodeNotRegistered(); error NodeAlreadyRegistered(); error NodeAlreadyActive(); error NodeStillPending(uint256 pendingUntilBlock); error SenderNotController(); error InvalidZeroAddress(); error OperatorUnderStaking(); error EIP1271SignatureVerificationFailed(); error EIP1271SignatureNotFromSigner(); error EIP1271SignatureExpired(); error EIP1271SignatureSaltAlreadySpent(); error InvalidArrayLength(); /// @custom:oz-upgrades-unsafe-allow constructor constructor() { _disableInitializers(); } function initialize(address arpa) public override(INodeRegistryOwner) initializer { _arpa = IERC20(arpa); __Ownable_init(); } // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address) internal override onlyOwner {} function setNodeRegistryConfig( address controllerContractAddress, address stakingContractAddress, address serviceManagerContractAddress, uint256 nativeNodeStakingAmount, uint256 eigenlayerNodeStakingAmount, uint256 pendingBlockAfterQuit ) external override(INodeRegistryOwner) onlyOwner { _config = NodeRegistryConfig( controllerContractAddress, stakingContractAddress, serviceManagerContractAddress, nativeNodeStakingAmount, eigenlayerNodeStakingAmount, pendingBlockAfterQuit ); } function dismissNode(address nodeIdAddress, uint256 pendingBlock) external override(INodeRegistryOwner) onlyOwner { _nodeQuitHelper(nodeIdAddress, pendingBlock); } function setAssetAccount(address[] calldata assetAccountAddresses, address[] calldata nodeAddresses) external override(INodeRegistryOwner) onlyOwner { if (assetAccountAddresses.length != nodeAddresses.length) { revert InvalidArrayLength(); } for (uint256 i = 0; i < assetAccountAddresses.length; i++) { _assetAccountsToNodes[assetAccountAddresses[i]] = nodeAddresses[i]; _nodesToAssetAccounts[nodeAddresses[i]] = assetAccountAddresses[i]; emit AssetAccountSet(assetAccountAddresses[i], nodeAddresses[i]); } } // ============= // INodeRegistry // ============= function nodeRegister( bytes calldata dkgPublicKey, bool isEigenlayerNode, address assetAccountAddress, ISignatureUtils.SignatureWithSaltAndExpiry memory assetAccountSignature ) external override(INodeRegistry) { if (_assetAccountsToNodes[assetAccountAddress] != address(0)) { revert NodeAlreadyRegistered(); } _nodeRegister(dkgPublicKey, isEigenlayerNode); _assetAccountsToNodes[assetAccountAddress] = msg.sender; _nodesToAssetAccounts[msg.sender] = assetAccountAddress; if (isEigenlayerNode) { uint256 share = IServiceManager(_config.serviceManagerContractAddress).getOperatorShare(assetAccountAddress); if (share < _config.eigenlayerNodeStakingAmount) { revert OperatorUnderStaking(); } IServiceManager(_config.serviceManagerContractAddress).registerOperator( assetAccountAddress, assetAccountSignature ); } else { if (msg.sender != assetAccountAddress) { _checkEIP1271SignatureWithSaltAndExpiry(assetAccountAddress, assetAccountSignature); } // Lock staking amount in Staking contract INodeStaking(_config.stakingContractAddress).lock(assetAccountAddress, _config.nativeNodeStakingAmount); } emit AssetAccountSet(assetAccountAddress, msg.sender); } function nodeActivate(ISignatureUtils.SignatureWithSaltAndExpiry memory assetAccountSignature) external override(INodeRegistry) { Node storage node = _nodes[msg.sender]; if (node.idAddress != msg.sender) { revert NodeNotRegistered(); } if (node.state) { revert NodeAlreadyActive(); } if (node.pendingUntilBlock > block.number) { revert NodeStillPending(node.pendingUntilBlock); } node.state = true; uint256 groupIndex = IController(_config.controllerContractAddress).nodeJoin(msg.sender); emit NodeActivated(msg.sender, groupIndex); address assetAccountAddress = _nodesToAssetAccounts[msg.sender]; if (node.isEigenlayerNode) { uint256 share = IServiceManager(_config.serviceManagerContractAddress).getOperatorShare(assetAccountAddress); if (share < _config.eigenlayerNodeStakingAmount) { revert OperatorUnderStaking(); } IServiceManager(_config.serviceManagerContractAddress).registerOperator( assetAccountAddress, assetAccountSignature ); } else { if (msg.sender != assetAccountAddress) { _checkEIP1271SignatureWithSaltAndExpiry(assetAccountAddress, assetAccountSignature); } // lock up to staking amount in Staking contract uint256 lockedAmount = INodeStaking(_config.stakingContractAddress).getLockedAmount(assetAccountAddress); if (lockedAmount < _config.nativeNodeStakingAmount) { INodeStaking(_config.stakingContractAddress).lock( assetAccountAddress, _config.nativeNodeStakingAmount - lockedAmount ); } } } function nodeQuit() external override(INodeRegistry) { _nodeQuitHelper(msg.sender, _config.pendingBlockAfterQuit); } function changeDkgPublicKey(bytes calldata dkgPublicKey) external override(INodeRegistry) { Node storage node = _nodes[msg.sender]; if (node.idAddress != msg.sender) { revert NodeNotRegistered(); } if (node.state) { revert NodeAlreadyActive(); } uint256[4] memory publicKey = BLS.fromBytesPublicKey(dkgPublicKey); if (!BLS.isValidPublicKey(publicKey)) { revert BLS.InvalidPublicKey(); } node.dkgPublicKey = dkgPublicKey; emit DkgPublicKeyChanged(msg.sender, dkgPublicKey); } function nodeWithdraw(address recipient) external override(INodeRegistry) { if (recipient == address(0)) { revert InvalidZeroAddress(); } uint256 ethAmount = _withdrawableEths[msg.sender]; uint256 arpaAmount = _arpaRewards[msg.sender]; if (arpaAmount > _BALANCE_BASE) { _arpaRewards[msg.sender] = _BALANCE_BASE; _arpa.safeTransfer(recipient, arpaAmount - _BALANCE_BASE); } if (ethAmount > _BALANCE_BASE) { _withdrawableEths[msg.sender] = _BALANCE_BASE; IController(_config.controllerContractAddress).nodeWithdrawETH(recipient, ethAmount - _BALANCE_BASE); } } function addReward(address[] memory nodes, uint256 ethAmount, uint256 arpaAmount) public override(INodeRegistry) { if (msg.sender != _config.controllerContractAddress) { revert SenderNotController(); } for (uint256 i = 0; i < nodes.length; i++) { _withdrawableEths[nodes[i]] += ethAmount; _arpaRewards[nodes[i]] += arpaAmount; emit NodeRewarded(nodes[i], ethAmount, arpaAmount); } } // Give node staking reward penalty and freezeNode function slashNode(address nodeIdAddress, uint256 stakingRewardPenalty, uint256 pendingBlock) public override(INodeRegistry) { if (msg.sender != _config.controllerContractAddress) { revert SenderNotController(); } Node storage node = _nodes[nodeIdAddress]; address assetAccountAddress = _nodesToAssetAccounts[nodeIdAddress]; if (node.isEigenlayerNode) { IServiceManager(_config.serviceManagerContractAddress).slashDelegationStaking( assetAccountAddress, stakingRewardPenalty ); IServiceManager(_config.serviceManagerContractAddress).deregisterOperator(assetAccountAddress); } else { // slash staking reward in Staking contract INodeStaking(_config.stakingContractAddress).slashDelegationReward( assetAccountAddress, stakingRewardPenalty ); } _freezeNode(nodeIdAddress, pendingBlock); emit NodeSlashed(nodeIdAddress, stakingRewardPenalty, pendingBlock); } // ============= // View // ============= function getDKGPublicKey(address nodeAddress) public view override(INodeRegistry) returns (bytes memory) { return _nodes[nodeAddress].dkgPublicKey; } function getNode(address nodeAddress) public view override(INodeRegistry) returns (Node memory) { return _nodes[nodeAddress]; } function getNodeWithdrawableTokens(address nodeAddress) public view override(INodeRegistry) returns (uint256, uint256) { return ( _withdrawableEths[nodeAddress] == 0 ? 0 : (_withdrawableEths[nodeAddress] - _BALANCE_BASE), _arpaRewards[nodeAddress] == 0 ? 0 : (_arpaRewards[nodeAddress] - _BALANCE_BASE) ); } function getNodeRegistryConfig() public view override(INodeRegistry) returns ( address controllerContractAddress, address stakingContractAddress, address serviceManagerContractAddress, uint256 nativeNodeStakingAmount, uint256 eigenlayerNodeStakingAmount, uint256 pendingBlockAfterQuit ) { return ( _config.controllerContractAddress, _config.stakingContractAddress, _config.serviceManagerContractAddress, _config.nativeNodeStakingAmount, _config.eigenlayerNodeStakingAmount, _config.pendingBlockAfterQuit ); } function getNodeAddressByAssetAccountAddress(address assetAccountAddress) public view override(INodeRegistry) returns (address) { return _assetAccountsToNodes[assetAccountAddress]; } function getAssetAccountAddressByNodeAddress(address nodeAddress) public view override(INodeRegistry) returns (address) { return _nodesToAssetAccounts[nodeAddress]; } /** * @notice Calculates the digest hash to be signed as a native node * @param assetAccountAddress The asset account address of the staking node * @param salt A unique and single use value associated with the approver signature. * @param expiry Time after which the approver's signature becomes invalid */ function calculateNativeNodeRegistrationDigestHash(address assetAccountAddress, bytes32 salt, uint256 expiry) public view override(INodeRegistry) returns (bytes32) { // calculate the struct hash bytes32 structHash = keccak256(abi.encode(NATIVE_NODE_REGISTRATION_TYPEHASH, assetAccountAddress, salt, expiry)); // calculate the digest hash bytes32 digestHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator(), structHash)); return digestHash; } /** * @notice Getter function for the current EIP-712 domain separator for this contract. */ function domainSeparator() public view override(INodeRegistry) returns (bytes32) { return keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes("ARPANetwork")), block.chainid, address(this))); } function assetAccountSaltIsSpent(address assetAccountAddress, bytes32 salt) public view override(INodeRegistry) returns (bool) { return _assetAccountSaltIsSpent[assetAccountAddress][salt]; } // ============= // Internal // ============= function _nodeRegister(bytes calldata dkgPublicKey, bool isEigenlayerNode) internal { if (_nodes[msg.sender].idAddress != address(0)) { revert NodeAlreadyRegistered(); } uint256[4] memory publicKey = BLS.fromBytesPublicKey(dkgPublicKey); if (!BLS.isValidPublicKey(publicKey)) { revert BLS.InvalidPublicKey(); } // Populate Node struct and insert into nodes Node storage n = _nodes[msg.sender]; n.idAddress = msg.sender; n.dkgPublicKey = dkgPublicKey; n.state = true; n.isEigenlayerNode = isEigenlayerNode; // Initialize withdrawable eths and arpa rewards to save gas for adapter call _withdrawableEths[msg.sender] = _BALANCE_BASE; _arpaRewards[msg.sender] = _BALANCE_BASE; uint256 groupIndex = IController(_config.controllerContractAddress).nodeJoin(msg.sender); emit NodeRegistered(msg.sender, dkgPublicKey, groupIndex); } function _freezeNode(address nodeIdAddress, uint256 pendingBlock) internal { // set node state to false for frozen node _nodes[nodeIdAddress].state = false; uint256 currentBlock = block.number; // if the node is already pending, add the pending block to the current pending block if (_nodes[nodeIdAddress].pendingUntilBlock > currentBlock) { _nodes[nodeIdAddress].pendingUntilBlock += pendingBlock; // else set the pending block to the current block + pending block } else { _nodes[nodeIdAddress].pendingUntilBlock = currentBlock + pendingBlock; } } function _nodeQuitHelper(address nodeIdAddress, uint256 pendingBlock) internal { Node storage node = _nodes[nodeIdAddress]; if (node.idAddress != nodeIdAddress) { revert NodeNotRegistered(); } IController(_config.controllerContractAddress).nodeLeave(nodeIdAddress); _freezeNode(nodeIdAddress, pendingBlock); address assetAccountAddress = _nodesToAssetAccounts[nodeIdAddress]; if (node.isEigenlayerNode) { IServiceManager(_config.serviceManagerContractAddress).deregisterOperator(assetAccountAddress); } else { // unlock staking amount in Staking contract INodeStaking(_config.stakingContractAddress).unlock(assetAccountAddress, _config.nativeNodeStakingAmount); } emit NodeQuit(nodeIdAddress); } function _checkEIP1271SignatureWithSaltAndExpiry( address assetAccountAddress, ISignatureUtils.SignatureWithSaltAndExpiry memory assetAccountSignature ) internal { if (assetAccountSignature.expiry < block.timestamp) { revert EIP1271SignatureExpired(); } if (_assetAccountSaltIsSpent[assetAccountAddress][assetAccountSignature.salt]) { revert EIP1271SignatureSaltAlreadySpent(); } bytes32 nativeNodeRegistrationDigestHash = calculateNativeNodeRegistrationDigestHash( assetAccountAddress, assetAccountSignature.salt, assetAccountSignature.expiry ); _checkEIP1271Signature(assetAccountAddress, nativeNodeRegistrationDigestHash, assetAccountSignature.signature); _assetAccountSaltIsSpent[assetAccountAddress][assetAccountSignature.salt] = true; } /** * @notice Checks @param signature is a valid signature of @param digestHash from @param signer. * If the `signer` contains no code -- i.e. it is not (yet, at least) a contract address, then checks using standard ECDSA logic * Otherwise, passes on the signature to the signer to verify the signature and checks that it returns the `EIP1271_MAGICVALUE`. */ function _checkEIP1271Signature(address signer, bytes32 digestHash, bytes memory signature) internal view { /** * check validity of signature: * 1) if `signer` is an EOA, then `signature` must be a valid ECDSA signature from `signer`, * indicating their intention for this action * 2) if `signer` is a contract, then `signature` must will be checked according to EIP-1271 */ if (Address.isContract(signer)) { if (IERC1271(signer).isValidSignature(digestHash, signature) != _EIP1271_MAGICVALUE) { revert EIP1271SignatureVerificationFailed(); } } else { if (ECDSA.recover(digestHash, signature) != signer) { revert EIP1271SignatureNotFromSigner(); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev 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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.0; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../ERC1967/ERC1967UpgradeUpgradeable.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. * * _Available since v4.1._ */ abstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment address private immutable __self = address(this); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { require(address(this) != __self, "Function must be called through delegatecall"); require(_getImplementation() == __self, "Function must be called through active proxy"); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { require(address(this) == __self, "UUPSUpgradeable: must not be called through delegatecall"); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual override notDelegated returns (bytes32) { return _IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeTo(address newImplementation) public virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, new bytes(0), false); } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data, true); } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeTo} and {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal override onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.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. * * By default, the owner account will be the one that deploys the contract. 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 OwnableUpgradeable is Initializable, ContextUpgradeable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ function __Ownable_init() internal onlyInitializing { __Ownable_init_unchained(); } function __Ownable_init_unchained() internal onlyInitializing { _transferOwnership(_msgSender()); } /** * @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 { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @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 { require(newOwner != address(0), "Ownable: new owner is the zero address"); _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); } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; import {ISignatureUtils} from "./ISignatureUtils.sol"; interface INodeRegistry { struct Node { address idAddress; bytes dkgPublicKey; bool isEigenlayerNode; bool state; uint256 pendingUntilBlock; } struct NodeRegistryConfig { address controllerContractAddress; address stakingContractAddress; address serviceManagerContractAddress; uint256 nativeNodeStakingAmount; uint256 eigenlayerNodeStakingAmount; uint256 pendingBlockAfterQuit; } // node transaction function nodeRegister( bytes calldata dkgPublicKey, bool isEigenlayerNode, address assetAccountAddress, ISignatureUtils.SignatureWithSaltAndExpiry memory assetAccountSignature ) external; function nodeActivate(ISignatureUtils.SignatureWithSaltAndExpiry memory assetAccountSignature) external; function nodeQuit() external; function changeDkgPublicKey(bytes calldata dkgPublicKey) external; function nodeWithdraw(address recipient) external; // controller transaction function slashNode(address nodeIdAddress, uint256 stakingRewardPenalty, uint256 pendingBlock) external; // adapter transaction function addReward(address[] memory nodes, uint256 ethAmount, uint256 arpaAmount) external; // view function getDKGPublicKey(address nodeAddress) external view returns (bytes memory); function getNode(address nodeAddress) external view returns (Node memory); function getNodeWithdrawableTokens(address nodeAddress) external view returns (uint256, uint256); function getNodeRegistryConfig() external view returns ( address controllerContractAddress, address stakingContractAddress, address serviceManagerContractAddress, uint256 nativeNodeStakingAmount, uint256 eigenlayerNodeStakingAmount, uint256 pendingBlockAfterQuit ); function getNodeAddressByAssetAccountAddress(address assetAccountAddress) external view returns (address); function getAssetAccountAddressByNodeAddress(address nodeAddress) external view returns (address); function calculateNativeNodeRegistrationDigestHash(address assetAccountAddress, bytes32 salt, uint256 expiry) external view returns (bytes32); function domainSeparator() external view returns (bytes32); function assetAccountSaltIsSpent(address assetAccountAddress, bytes32 salt) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface INodeRegistryOwner { /** * @notice Sets the configuration of the NodeRegistry * @param controllerContract The address of the controller contract * @param stakingContract The address of the staking contract * @param serviceManagerContract The address of the service manager contract * @param nativeNodeStakingAmount The amount of ARPA must staked by a node * @param eigenlayerNodeStakingAmount The amount of token must restaked by an eigenlayer node * @param pendingBlockAfterQuit The number of blocks a node must wait before joining a group after quitting */ function setNodeRegistryConfig( address controllerContract, address stakingContract, address serviceManagerContract, uint256 nativeNodeStakingAmount, uint256 eigenlayerNodeStakingAmount, uint256 pendingBlockAfterQuit ) external; function initialize(address arpa) external; /** * @notice Dismiss a node from the registry forcefully * @param nodeIdAddress The address of the node * @param pendingBlock The number of blocks the node must wait before activating again */ function dismissNode(address nodeIdAddress, uint256 pendingBlock) external; /** * @notice Set the asset account of the node * @param assetAccountAddresses The addresses of the asset accounts * @param nodeAddresses The addresses of the nodes */ function setAssetAccount(address[] calldata assetAccountAddresses, address[] calldata nodeAddresses) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface IController { struct Group { uint256 index; uint256 epoch; uint256 size; uint256 threshold; Member[] members; address[] committers; CommitCache[] commitCacheList; bool isStrictlyMajorityConsensusReached; uint256[4] publicKey; } struct Member { address nodeIdAddress; uint256[4] partialPublicKey; } struct CommitResult { uint256 groupEpoch; uint256[4] publicKey; address[] disqualifiedNodes; } struct CommitCache { address[] nodeIdAddress; CommitResult commitResult; } struct CommitDkgParams { uint256 groupIndex; uint256 groupEpoch; bytes publicKey; bytes partialPublicKey; address[] disqualifiedNodes; } // node transaction function nodeJoin(address nodeIdAddress) external returns (uint256 groupIndex); function nodeLeave(address nodeIdAddress) external; function commitDkg(CommitDkgParams memory params) external; function postProcessDkg(uint256 groupIndex, uint256 groupEpoch) external; // nodeRegistry transaction function nodeWithdrawETH(address recipient, uint256 ethAmount) external; // adapter transaction function addReward(address[] memory nodes, uint256 ethAmount, uint256 arpaAmount) external; function setLastOutput(uint256 lastOutput) external; // view function getControllerConfig() external view returns ( address nodeRegistryContractAddress, address adapterContractAddress, uint256 disqualifiedNodePenaltyAmount, uint256 defaultNumberOfCommitters, uint256 defaultDkgPhaseDuration, uint256 groupMaxCapacity, uint256 idealNumberOfGroups, uint256 dkgPostProcessReward ); /// @notice Get list of all group indexes where group.isStrictlyMajorityConsensusReached == true /// @return uint256[] List of valid group indexes function getValidGroupIndices() external view returns (uint256[] memory); function getGroupEpoch() external view returns (uint256); function getGroupCount() external view returns (uint256); function getGroup(uint256 index) external view returns (Group memory); function getGroupThreshold(uint256 groupIndex) external view returns (uint256, uint256); function getMember(uint256 groupIndex, uint256 memberIndex) external view returns (Member memory); /// @notice Get the group index and member index of a given node. function getBelongingGroup(address nodeAddress) external view returns (int256, int256); function getCoordinator(uint256 groupIndex) external view returns (address); function getLastOutput() external view returns (uint256); /// @notice Check to see if a group has a partial public key registered for a given node. /// @return bool True if the node has a partial public key registered for the group. function isPartialKeyRegistered(uint256 groupIndex, address nodeIdAddress) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.18; interface INodeStaking { /// @notice This event is emitted when a node locks stake in the pool. /// @param staker Staker address /// @param newLock New principal amount locked event Locked(address staker, uint256 newLock); /// @notice This event is emitted when a node unlocks stake in the pool. /// @param staker Staker address /// @param newUnlock New principal amount unlocked event Unlocked(address staker, uint256 newUnlock); /// @notice This event is emitted when a node gets delegation reward slashed. /// @param staker Staker address /// @param amount Amount slashed event DelegationRewardSlashed(address staker, uint256 amount); /// @notice This error is raised when attempting to unlock with more than the current locked staking amount /// @param currentLockedStakingAmount Current locked staking amount error InadequateOperatorLockedStakingAmount(uint256 currentLockedStakingAmount); /// @notice This function allows controller to lock staking amount for a node. /// @param staker Node address /// @param amount Amount to lock function lock(address staker, uint256 amount) external; /// @notice This function allows controller to unlock staking amount for a node. /// @param staker Node address /// @param amount Amount to unlock function unlock(address staker, uint256 amount) external; /// @notice This function allows controller to slash delegation reward of a node. /// @param staker Node address /// @param amount Amount to slash function slashDelegationReward(address staker, uint256 amount) external; /// @notice This function returns the locked amount of a node. /// @param staker Node address function getLockedAmount(address staker) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.18; import {ISignatureUtils} from "./ISignatureUtils.sol"; interface IServiceManager { function registerOperator(address operator, ISignatureUtils.SignatureWithSaltAndExpiry memory operatorSignature) external; function deregisterOperator(address operator) external; function slashDelegationStaking(address operator, uint256 amount) external; function getOperatorShare(address operator) external view returns (uint256); }
// SPDX-License-Identifier: LGPL 3.0 pragma solidity ^0.8.18; import {BN256G2} from "./BN256G2.sol"; /** * @title BLS operations on bn254 curve * @author ARPA-Network adapted from https://github.com/ChihChengLiang/bls_solidity_python * @dev Homepage: https://github.com/ARPA-Network/BLS-TSS-Network * Signature and Point hashed to G1 are represented by affine coordinate in big-endian order, deserialized from compressed format. * Public key is represented and serialized by affine coordinate Q-x-re(x0), Q-x-im(x1), Q-y-re(y0), Q-y-im(y1) in big-endian order. */ library BLS { // Field order uint256 public constant N = 21888242871839275222246405745257275088696311157297823662689037894645226208583; // Negated genarator of G2 uint256 public constant N_G2_X1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634; uint256 public constant N_G2_X0 = 10857046999023057135944570762232829481370756359578518086990519993285655852781; uint256 public constant N_G2_Y1 = 17805874995975841540914202342111839520379459829704422454583296818431106115052; uint256 public constant N_G2_Y0 = 13392588948715843804641432497768002650278120570034223513918757245338268106653; uint256 public constant FIELD_MASK = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff; error MustNotBeInfinity(); error InvalidPublicKeyEncoding(); error InvalidSignatureFormat(); error InvalidSignature(); error InvalidPartialSignatureFormat(); error InvalidPartialSignatures(); error EmptyPartialSignatures(); error InvalidPublicKey(); error InvalidPartialPublicKey(); function verifySingle(uint256[2] memory signature, uint256[4] memory pubkey, uint256[2] memory message) public view returns (bool) { uint256[12] memory input = [ signature[0], signature[1], N_G2_X1, N_G2_X0, N_G2_Y1, N_G2_Y0, message[0], message[1], pubkey[1], pubkey[0], pubkey[3], pubkey[2] ]; uint256[1] memory out; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 8, input, 384, out, 0x20) switch success case 0 { invalid() } } require(success, ""); return out[0] != 0; } function verifyPartials(uint256[2][] memory partials, uint256[4][] memory pubkeys, uint256[2] memory message) public view returns (bool) { uint256[2] memory aggregatedSignature; uint256[4] memory aggregatedPublicKey; for (uint256 i = 0; i < partials.length; i++) { aggregatedSignature = addPoints(aggregatedSignature, partials[i]); aggregatedPublicKey = BN256G2.ecTwistAdd(aggregatedPublicKey, pubkeys[i]); } uint256[12] memory input = [ aggregatedSignature[0], aggregatedSignature[1], N_G2_X1, N_G2_X0, N_G2_Y1, N_G2_Y0, message[0], message[1], aggregatedPublicKey[1], aggregatedPublicKey[0], aggregatedPublicKey[3], aggregatedPublicKey[2] ]; uint256[1] memory out; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 8, input, 384, out, 0x20) switch success case 0 { invalid() } } require(success, ""); return out[0] != 0; } // TODO a simple hash and increment implementation, can be improved later function hashToPoint(bytes memory data) public view returns (uint256[2] memory p) { bool found; bytes32 candidateHash = keccak256(data); while (true) { (p, found) = mapToPoint(candidateHash); if (found) { break; } candidateHash = keccak256(bytes.concat(candidateHash)); } } // we take the y-coordinate as the lexicographically largest of the two associated with the encoded x-coordinate function mapToPoint(bytes32 _x) internal view returns (uint256[2] memory p, bool found) { uint256 y; uint256 x = uint256(_x) % N; (y, found) = deriveYOnG1(x); if (found) { p[0] = x; p[1] = y > N / 2 ? N - y : y; } } function deriveYOnG1(uint256 x) internal view returns (uint256, bool) { uint256 y; y = mulmod(x, x, N); y = mulmod(y, x, N); y = addmod(y, 3, N); return sqrt(y); } function isValidPublicKey(uint256[4] memory publicKey) public pure returns (bool) { if ((publicKey[0] >= N) || (publicKey[1] >= N) || (publicKey[2] >= N || (publicKey[3] >= N))) { return false; } else { return isOnCurveG2(publicKey); } } function fromBytesPublicKey(bytes memory point) public pure returns (uint256[4] memory pubkey) { if (point.length != 128) { revert InvalidPublicKeyEncoding(); } uint256 x0; uint256 x1; uint256 y0; uint256 y1; // solhint-disable-next-line no-inline-assembly assembly { // look the first 32 bytes of a bytes struct is its length x0 := mload(add(point, 32)) x1 := mload(add(point, 64)) y0 := mload(add(point, 96)) y1 := mload(add(point, 128)) } pubkey = [x0, x1, y0, y1]; } function decompress(uint256 compressedSignature) public view returns (uint256[2] memory uncompressed) { uint256 x = compressedSignature & FIELD_MASK; // The most significant bit, when set, indicates that the y-coordinate of the point // is the lexicographically largest of the two associated values. // The second-most significant bit indicates that the point is at infinity. If this bit is set, // the remaining bits of the group element's encoding should be set to zero. // We don't accept infinity as valid signature. uint256 decision = compressedSignature >> 254; if (decision & 1 == 1) { revert MustNotBeInfinity(); } uint256 y; (y,) = deriveYOnG1(x); // If the following two conditions or their negative forms are not met at the same time, get the negative y. // 1. The most significant bit of compressed signature is set // 2. The y we recovered first is the lexicographically largest if (((decision >> 1) ^ (y > N / 2 ? 1 : 0)) == 1) { y = N - y; } return [x, y]; } function isValid(uint256 compressedSignature) public view returns (bool) { uint256 x = compressedSignature & FIELD_MASK; if (x >= N) { return false; } else if (x == 0) { return false; } return isOnCurveG1(x); } function isOnCurveG1(uint256[2] memory point) internal pure returns (bool _isOnCurve) { // solhint-disable-next-line no-inline-assembly assembly { let t0 := mload(point) let t1 := mload(add(point, 32)) let t2 := mulmod(t0, t0, N) t2 := mulmod(t2, t0, N) t2 := addmod(t2, 3, N) t1 := mulmod(t1, t1, N) _isOnCurve := eq(t1, t2) } } function isOnCurveG1(uint256 x) internal view returns (bool _isOnCurve) { bool callSuccess; // solhint-disable-next-line no-inline-assembly assembly { let t0 := x let t1 := mulmod(t0, t0, N) t1 := mulmod(t1, t0, N) // x ^ 3 + b t1 := addmod(t1, 3, N) let freemem := mload(0x40) mstore(freemem, 0x20) mstore(add(freemem, 0x20), 0x20) mstore(add(freemem, 0x40), 0x20) mstore(add(freemem, 0x60), t1) // (N - 1) / 2 = 0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3 mstore(add(freemem, 0x80), 0x183227397098d014dc2822db40c0ac2ecbc0b548b438e5469e10460b6c3e7ea3) // N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 mstore(add(freemem, 0xA0), 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) callSuccess := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) _isOnCurve := eq(1, mload(freemem)) } } function isOnCurveG2(uint256[4] memory point) internal pure returns (bool _isOnCurve) { // solhint-disable-next-line no-inline-assembly assembly { // x0, x1 let t0 := mload(point) let t1 := mload(add(point, 32)) // x0 ^ 2 let t2 := mulmod(t0, t0, N) // x1 ^ 2 let t3 := mulmod(t1, t1, N) // 3 * x0 ^ 2 let t4 := add(add(t2, t2), t2) // 3 * x1 ^ 2 let t5 := addmod(add(t3, t3), t3, N) // x0 * (x0 ^ 2 - 3 * x1 ^ 2) t2 := mulmod(add(t2, sub(N, t5)), t0, N) // x1 * (3 * x0 ^ 2 - x1 ^ 2) t3 := mulmod(add(t4, sub(N, t3)), t1, N) // x ^ 3 + b t0 := addmod(t2, 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5, N) t1 := addmod(t3, 0x009713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2, N) // y0, y1 t2 := mload(add(point, 64)) t3 := mload(add(point, 96)) // y ^ 2 t4 := mulmod(addmod(t2, t3, N), addmod(t2, sub(N, t3), N), N) t3 := mulmod(shl(1, t2), t3, N) // y ^ 2 == x ^ 3 + b _isOnCurve := and(eq(t0, t4), eq(t1, t3)) } } function sqrt(uint256 xx) internal view returns (uint256 x, bool hasRoot) { bool callSuccess; // solhint-disable-next-line no-inline-assembly assembly { let freemem := mload(0x40) mstore(freemem, 0x20) mstore(add(freemem, 0x20), 0x20) mstore(add(freemem, 0x40), 0x20) mstore(add(freemem, 0x60), xx) // this is enabled by N % 4 = 3 and Fermat's little theorem // (N + 1) / 4 = 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52 mstore(add(freemem, 0x80), 0xc19139cb84c680a6e14116da060561765e05aa45a1c72a34f082305b61f3f52) // N = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 mstore(add(freemem, 0xA0), 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) callSuccess := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) x := mload(freemem) hasRoot := eq(xx, mulmod(x, x, N)) } require(callSuccess, "BLS: sqrt modexp call failed"); } /// @notice Add two points in G1 function addPoints(uint256[2] memory p1, uint256[2] memory p2) internal view returns (uint256[2] memory ret) { uint256[4] memory input; input[0] = p1[0]; input[1] = p1[1]; input[2] = p2[0]; input[3] = p2[1]; bool success; // solhint-disable-next-line no-inline-assembly assembly { success := staticcall(sub(gas(), 2000), 6, input, 0xc0, ret, 0x60) } // solhint-disable-next-line reason-string require(success); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature); } return (signer, RecoverError.NoError); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` 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 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.0; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822ProxiableUpgradeable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol) pragma solidity ^0.8.2; import "../beacon/IBeaconUpgradeable.sol"; import "../../interfaces/IERC1967Upgradeable.sol"; import "../../interfaces/draft-IERC1822Upgradeable.sol"; import "../../utils/AddressUpgradeable.sol"; import "../../utils/StorageSlotUpgradeable.sol"; import {Initializable} from "../utils/Initializable.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. * * _Available since v4.1._ */ abstract contract ERC1967UpgradeUpgradeable is Initializable, IERC1967Upgradeable { // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1 bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143; /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; function __ERC1967Upgrade_init() internal onlyInitializing { } function __ERC1967Upgrade_init_unchained() internal onlyInitializing { } /** * @dev Returns the current implementation address. */ function _getImplementation() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract"); StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Perform implementation upgrade * * Emits an {Upgraded} event. */ function _upgradeTo(address newImplementation) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); } /** * @dev Perform implementation upgrade with additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal { _upgradeTo(newImplementation); if (data.length > 0 || forceCall) { AddressUpgradeable.functionDelegateCall(newImplementation, data); } } /** * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call. * * Emits an {Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal { // Upgrades from old implementations will perform a rollback test. This test requires the new // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing // this special case will break upgrade paths from old UUPS implementation to new ones. if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) { _setImplementation(newImplementation); } else { try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) { require(slot == _IMPLEMENTATION_SLOT, "ERC1967Upgrade: unsupported proxiableUUID"); } catch { revert("ERC1967Upgrade: new implementation is not UUPS"); } _upgradeToAndCall(newImplementation, data, forceCall); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is * validated in the constructor. */ bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. */ function _getAdmin() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { require(newAdmin != address(0), "ERC1967: new admin is the zero address"); StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {AdminChanged} event. */ function _changeAdmin(address newAdmin) internal { emit AdminChanged(_getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor. */ bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function _getBeacon() internal view returns (address) { return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract"); require( AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()), "ERC1967: beacon implementation is not a contract" ); StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon; } /** * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that). * * Emits a {BeaconUpgraded} event. */ function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0 || forceCall) { AddressUpgradeable.functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data); } } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized != type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @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 ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } 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; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[50] private __gap; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.18; /** * @title The interface for common signature utilities. * @author Layr Labs, Inc. * @notice Terms of Service: https://docs.eigenlayer.xyz/overview/terms-of-service */ interface ISignatureUtils { // @notice Struct that bundles together a signature and an expiration time for the signature. Used primarily for stack management. struct SignatureWithExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the expiration timestamp (UTC) of the signature uint256 expiry; } // @notice Struct that bundles together a signature, a salt for uniqueness, and an expiration time for the signature. Used primarily for stack management. struct SignatureWithSaltAndExpiry { // the signature itself, formatted as a single bytes object bytes signature; // the salt used to generate the signature bytes32 salt; // the expiration timestamp (UTC) of the signature uint256 expiry; } }
// SPDX-License-Identifier: LGPL 3.0 pragma solidity ^0.8.18; /** * @title Elliptic curve operations on twist points for alt_bn128 * @author ARPA-Network adapted from https://github.com/musalbas/solidity-BN256G2 * @dev Homepage: https://github.com/ARPA-Network/BLS-TSS-Network */ library BN256G2 { uint256 public constant FIELD_MODULUS = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47; uint256 public constant TWISTBX = 0x2b149d40ceb8aaae81be18991be06ac3b5b4c5e559dbefa33267e6dc24a138e5; uint256 public constant TWISTBY = 0x9713b03af0fed4cd2cafadeed8fdf4a74fa084e52d1852e4a2bd0685c315d2; uint256 public constant PTXX = 0; uint256 public constant PTXY = 1; uint256 public constant PTYX = 2; uint256 public constant PTYY = 3; uint256 public constant PTZX = 4; uint256 public constant PTZY = 5; function ecTwistAdd(uint256[4] memory pt1, uint256[4] memory pt2) internal view returns (uint256[4] memory pt) { (uint256 xx, uint256 xy, uint256 yx, uint256 yy) = ecTwistAdd(pt1[0], pt1[1], pt1[2], pt1[3], pt2[0], pt2[1], pt2[2], pt2[3]); pt = [xx, xy, yx, yy]; } /** * @notice Add two twist points * @param pt1xx Coefficient 1 of x on point 1 * @param pt1xy Coefficient 2 of x on point 1 * @param pt1yx Coefficient 1 of y on point 1 * @param pt1yy Coefficient 2 of y on point 1 * @param pt2xx Coefficient 1 of x on point 2 * @param pt2xy Coefficient 2 of x on point 2 * @param pt2yx Coefficient 1 of y on point 2 * @param pt2yy Coefficient 2 of y on point 2 * @return (pt3xx, pt3xy, pt3yx, pt3yy) */ function ecTwistAdd( uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy ) internal view returns (uint256, uint256, uint256, uint256) { if (pt1xx == 0 && pt1xy == 0 && pt1yx == 0 && pt1yy == 0) { if (!(pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0)) { assert(isOnCurve(pt2xx, pt2xy, pt2yx, pt2yy)); } return (pt2xx, pt2xy, pt2yx, pt2yy); } else if (pt2xx == 0 && pt2xy == 0 && pt2yx == 0 && pt2yy == 0) { assert(isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy)); return (pt1xx, pt1xy, pt1yx, pt1yy); } assert(isOnCurve(pt1xx, pt1xy, pt1yx, pt1yy)); assert(isOnCurve(pt2xx, pt2xy, pt2yx, pt2yy)); uint256[6] memory pt1 = [pt1xx, pt1xy, pt1yx, pt1yy, 1, 0]; uint256[6] memory pt2 = [pt2xx, pt2xy, pt2yx, pt2yy, 1, 0]; uint256[6] memory pt3 = ecTwistAddJacobian(pt1, pt2); return fromJacobian(pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]); } function submod(uint256 a, uint256 b, uint256 n) internal pure returns (uint256) { return addmod(a, n - b, n); } function fq2Mul(uint256 xx, uint256 xy, uint256 yx, uint256 yy) internal pure returns (uint256, uint256) { return ( submod(mulmod(xx, yx, FIELD_MODULUS), mulmod(xy, yy, FIELD_MODULUS), FIELD_MODULUS), addmod(mulmod(xx, yy, FIELD_MODULUS), mulmod(xy, yx, FIELD_MODULUS), FIELD_MODULUS) ); } function fq2Muc(uint256 xx, uint256 xy, uint256 c) internal pure returns (uint256, uint256) { return (mulmod(xx, c, FIELD_MODULUS), mulmod(xy, c, FIELD_MODULUS)); } function fq2Sub(uint256 xx, uint256 xy, uint256 yx, uint256 yy) internal pure returns (uint256 rx, uint256 ry) { return (submod(xx, yx, FIELD_MODULUS), submod(xy, yy, FIELD_MODULUS)); } function fq2Inv(uint256 x, uint256 y) internal view returns (uint256, uint256) { uint256 inv = modInv(addmod(mulmod(y, y, FIELD_MODULUS), mulmod(x, x, FIELD_MODULUS), FIELD_MODULUS), FIELD_MODULUS); return (mulmod(x, inv, FIELD_MODULUS), FIELD_MODULUS - mulmod(y, inv, FIELD_MODULUS)); } function isOnCurve(uint256 xx, uint256 xy, uint256 yx, uint256 yy) internal pure returns (bool) { uint256 yyx; uint256 yyy; uint256 xxxx; uint256 xxxy; (yyx, yyy) = fq2Mul(yx, yy, yx, yy); (xxxx, xxxy) = fq2Mul(xx, xy, xx, xy); (xxxx, xxxy) = fq2Mul(xxxx, xxxy, xx, xy); (yyx, yyy) = fq2Sub(yyx, yyy, xxxx, xxxy); (yyx, yyy) = fq2Sub(yyx, yyy, TWISTBX, TWISTBY); return yyx == 0 && yyy == 0; } function modInv(uint256 a, uint256 n) internal view returns (uint256 result) { bool success; // solhint-disable-next-line no-inline-assembly assembly { let freemem := mload(0x40) mstore(freemem, 0x20) mstore(add(freemem, 0x20), 0x20) mstore(add(freemem, 0x40), 0x20) mstore(add(freemem, 0x60), a) mstore(add(freemem, 0x80), sub(n, 2)) mstore(add(freemem, 0xA0), n) success := staticcall(sub(gas(), 2000), 5, freemem, 0xC0, freemem, 0x20) result := mload(freemem) } // solhint-disable-next-line reason-string require(success); } function fromJacobian(uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt1zx, uint256 pt1zy) internal view returns (uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy) { uint256 invzx; uint256 invzy; (invzx, invzy) = fq2Inv(pt1zx, pt1zy); (pt2xx, pt2xy) = fq2Mul(pt1xx, pt1xy, invzx, invzy); (pt2yx, pt2yy) = fq2Mul(pt1yx, pt1yy, invzx, invzy); } function ecTwistAddJacobian(uint256[6] memory pt1, uint256[6] memory pt2) public pure returns (uint256[6] memory pt3) { if (pt1[4] == 0 && pt1[5] == 0) { (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (pt2[0], pt2[1], pt2[2], pt2[3], pt2[4], pt2[5]); return pt3; } else if (pt2[4] == 0 && pt2[5] == 0) { (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (pt1[0], pt1[1], pt1[2], pt1[3], pt1[4], pt1[5]); return pt3; } (pt2[2], pt2[3]) = fq2Mul(pt2[2], pt2[3], pt1[4], pt1[5]); // U1 = y2 * z1 (pt3[PTYX], pt3[PTYY]) = fq2Mul(pt1[2], pt1[3], pt2[4], pt2[5]); // U2 = y1 * z2 (pt2[0], pt2[1]) = fq2Mul(pt2[0], pt2[1], pt1[4], pt1[5]); // V1 = x2 * z1 (pt3[PTZX], pt3[PTZY]) = fq2Mul(pt1[0], pt1[1], pt2[4], pt2[5]); // V2 = x1 * z2 if (pt2[0] == pt3[PTZX] && pt2[1] == pt3[PTZY]) { if (pt2[2] == pt3[PTYX] && pt2[3] == pt3[PTYY]) { (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = ecTwistDoubleJacobian(pt1[0], pt1[1], pt1[2], pt1[3], pt1[4], pt1[5]); return pt3; } (pt3[PTXX], pt3[PTXY], pt3[PTYX], pt3[PTYY], pt3[PTZX], pt3[PTZY]) = (1, 0, 1, 0, 0, 0); return pt3; } (pt2[4], pt2[5]) = fq2Mul(pt1[4], pt1[5], pt2[4], pt2[5]); // W = z1 * z2 (pt1[0], pt1[1]) = fq2Sub(pt2[2], pt2[3], pt3[PTYX], pt3[PTYY]); // U = U1 - U2 (pt1[2], pt1[3]) = fq2Sub(pt2[0], pt2[1], pt3[PTZX], pt3[PTZY]); // V = V1 - V2 (pt1[4], pt1[5]) = fq2Mul(pt1[2], pt1[3], pt1[2], pt1[3]); // V_squared = V * V (pt2[2], pt2[3]) = fq2Mul(pt1[4], pt1[5], pt3[PTZX], pt3[PTZY]); // V_squared_times_V2 = V_squared * V2 (pt1[4], pt1[5]) = fq2Mul(pt1[4], pt1[5], pt1[2], pt1[3]); // V_cubed = V * V_squared (pt3[PTZX], pt3[PTZY]) = fq2Mul(pt1[4], pt1[5], pt2[4], pt2[5]); // newz = V_cubed * W (pt2[0], pt2[1]) = fq2Mul(pt1[0], pt1[1], pt1[0], pt1[1]); // U * U (pt2[0], pt2[1]) = fq2Mul(pt2[0], pt2[1], pt2[4], pt2[5]); // U * U * W (pt2[0], pt2[1]) = fq2Sub(pt2[0], pt2[1], pt1[4], pt1[5]); // U * U * W - V_cubed (pt2[4], pt2[5]) = fq2Muc(pt2[2], pt2[3], 2); // 2 * V_squared_times_V2 (pt2[0], pt2[1]) = fq2Sub(pt2[0], pt2[1], pt2[4], pt2[5]); // A = U * U * W - V_cubed - 2 * V_squared_times_V2 (pt3[PTXX], pt3[PTXY]) = fq2Mul(pt1[2], pt1[3], pt2[0], pt2[1]); // newx = V * A (pt1[2], pt1[3]) = fq2Sub(pt2[2], pt2[3], pt2[0], pt2[1]); // V_squared_times_V2 - A (pt1[2], pt1[3]) = fq2Mul(pt1[0], pt1[1], pt1[2], pt1[3]); // U * (V_squared_times_V2 - A) (pt1[0], pt1[1]) = fq2Mul(pt1[4], pt1[5], pt3[PTYX], pt3[PTYY]); // V_cubed * U2 (pt3[PTYX], pt3[PTYY]) = fq2Sub(pt1[2], pt1[3], pt1[0], pt1[1]); // newy = U * (V_squared_times_V2 - A) - V_cubed * U2 } function ecTwistDoubleJacobian( uint256 pt1xx, uint256 pt1xy, uint256 pt1yx, uint256 pt1yy, uint256 pt1zx, uint256 pt1zy ) public pure returns (uint256 pt2xx, uint256 pt2xy, uint256 pt2yx, uint256 pt2yy, uint256 pt2zx, uint256 pt2zy) { (pt2xx, pt2xy) = fq2Muc(pt1xx, pt1xy, 3); // 3 * x (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt1xx, pt1xy); // W = 3 * x * x (pt1zx, pt1zy) = fq2Mul(pt1yx, pt1yy, pt1zx, pt1zy); // S = y * z (pt2yx, pt2yy) = fq2Mul(pt1xx, pt1xy, pt1yx, pt1yy); // x * y (pt2yx, pt2yy) = fq2Mul(pt2yx, pt2yy, pt1zx, pt1zy); // B = x * y * S (pt1xx, pt1xy) = fq2Mul(pt2xx, pt2xy, pt2xx, pt2xy); // W * W (pt2zx, pt2zy) = fq2Muc(pt2yx, pt2yy, 8); // 8 * B (pt1xx, pt1xy) = fq2Sub(pt1xx, pt1xy, pt2zx, pt2zy); // H = W * W - 8 * B (pt2zx, pt2zy) = fq2Mul(pt1zx, pt1zy, pt1zx, pt1zy); // S_squared = S * S (pt2yx, pt2yy) = fq2Muc(pt2yx, pt2yy, 4); // 4 * B (pt2yx, pt2yy) = fq2Sub(pt2yx, pt2yy, pt1xx, pt1xy); // 4 * B - H (pt2yx, pt2yy) = fq2Mul(pt2yx, pt2yy, pt2xx, pt2xy); // W * (4 * B - H) (pt2xx, pt2xy) = fq2Muc(pt1yx, pt1yy, 8); // 8 * y (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt1yx, pt1yy); // 8 * y * y (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt2zx, pt2zy); // 8 * y * y * S_squared (pt2yx, pt2yy) = fq2Sub(pt2yx, pt2yy, pt2xx, pt2xy); // newy = W * (4 * B - H) - 8 * y * y * S_squared (pt2xx, pt2xy) = fq2Muc(pt1xx, pt1xy, 2); // 2 * H (pt2xx, pt2xy) = fq2Mul(pt2xx, pt2xy, pt1zx, pt1zy); // newx = 2 * H * S (pt2zx, pt2zy) = fq2Mul(pt1zx, pt1zy, pt2zx, pt2zy); // S * S_squared (pt2zx, pt2zy) = fq2Muc(pt2zx, pt2zy, 8); // newz = 8 * S * S_squared } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.0; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeaconUpgradeable { /** * @dev Must return an address that can be used as a delegate call target. * * {BeaconProxy} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.0; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. * * _Available since v4.8.3._ */ interface IERC1967Upgradeable { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.0; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract"); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` * * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._ * _Available since v4.9 for `string`, `bytes`._ */ library StorageSlotUpgradeable { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "Staking-v0.1/=lib/Staking-v0.1/src/", "Randcast-User-Contract/=lib/Randcast-User-Contract/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "fx-portal/=lib/fx-portal/contracts/", "openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/" ], "optimizer": { "enabled": true, "runs": 300 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "libraries": { "src/libraries/BLS.sol": { "BLS": "0x554816B8C04Fe2Eeab2e9aAbF128d4f759AFE760" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EIP1271SignatureExpired","type":"error"},{"inputs":[],"name":"EIP1271SignatureNotFromSigner","type":"error"},{"inputs":[],"name":"EIP1271SignatureSaltAlreadySpent","type":"error"},{"inputs":[],"name":"EIP1271SignatureVerificationFailed","type":"error"},{"inputs":[],"name":"InvalidArrayLength","type":"error"},{"inputs":[],"name":"InvalidPublicKey","type":"error"},{"inputs":[],"name":"InvalidZeroAddress","type":"error"},{"inputs":[],"name":"NodeAlreadyActive","type":"error"},{"inputs":[],"name":"NodeAlreadyRegistered","type":"error"},{"inputs":[],"name":"NodeNotRegistered","type":"error"},{"inputs":[{"internalType":"uint256","name":"pendingUntilBlock","type":"uint256"}],"name":"NodeStillPending","type":"error"},{"inputs":[],"name":"OperatorUnderStaking","type":"error"},{"inputs":[],"name":"SenderNotController","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"assetAccountAddress","type":"address"},{"indexed":true,"internalType":"address","name":"nodeAddress","type":"address"}],"name":"AssetAccountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nodeAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"dkgPublicKey","type":"bytes"}],"name":"DkgPublicKeyChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nodeAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"groupIndex","type":"uint256"}],"name":"NodeActivated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nodeAddress","type":"address"}],"name":"NodeQuit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nodeAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"dkgPublicKey","type":"bytes"},{"indexed":false,"internalType":"uint256","name":"groupIndex","type":"uint256"}],"name":"NodeRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nodeAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"ethAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"arpaAmount","type":"uint256"}],"name":"NodeRewarded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nodeIdAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"stakingRewardPenalty","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pendingBlock","type":"uint256"}],"name":"NodeSlashed","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":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NATIVE_NODE_REGISTRATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"nodes","type":"address[]"},{"internalType":"uint256","name":"ethAmount","type":"uint256"},{"internalType":"uint256","name":"arpaAmount","type":"uint256"}],"name":"addReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"assetAccountAddress","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"assetAccountSaltIsSpent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"assetAccountAddress","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"name":"calculateNativeNodeRegistrationDigestHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"dkgPublicKey","type":"bytes"}],"name":"changeDkgPublicKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nodeIdAddress","type":"address"},{"internalType":"uint256","name":"pendingBlock","type":"uint256"}],"name":"dismissNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"domainSeparator","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nodeAddress","type":"address"}],"name":"getAssetAccountAddressByNodeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nodeAddress","type":"address"}],"name":"getDKGPublicKey","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nodeAddress","type":"address"}],"name":"getNode","outputs":[{"components":[{"internalType":"address","name":"idAddress","type":"address"},{"internalType":"bytes","name":"dkgPublicKey","type":"bytes"},{"internalType":"bool","name":"isEigenlayerNode","type":"bool"},{"internalType":"bool","name":"state","type":"bool"},{"internalType":"uint256","name":"pendingUntilBlock","type":"uint256"}],"internalType":"struct INodeRegistry.Node","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"assetAccountAddress","type":"address"}],"name":"getNodeAddressByAssetAccountAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNodeRegistryConfig","outputs":[{"internalType":"address","name":"controllerContractAddress","type":"address"},{"internalType":"address","name":"stakingContractAddress","type":"address"},{"internalType":"address","name":"serviceManagerContractAddress","type":"address"},{"internalType":"uint256","name":"nativeNodeStakingAmount","type":"uint256"},{"internalType":"uint256","name":"eigenlayerNodeStakingAmount","type":"uint256"},{"internalType":"uint256","name":"pendingBlockAfterQuit","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nodeAddress","type":"address"}],"name":"getNodeWithdrawableTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"arpa","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct ISignatureUtils.SignatureWithSaltAndExpiry","name":"assetAccountSignature","type":"tuple"}],"name":"nodeActivate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nodeQuit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"dkgPublicKey","type":"bytes"},{"internalType":"bool","name":"isEigenlayerNode","type":"bool"},{"internalType":"address","name":"assetAccountAddress","type":"address"},{"components":[{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"}],"internalType":"struct ISignatureUtils.SignatureWithSaltAndExpiry","name":"assetAccountSignature","type":"tuple"}],"name":"nodeRegister","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"nodeWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"assetAccountAddresses","type":"address[]"},{"internalType":"address[]","name":"nodeAddresses","type":"address[]"}],"name":"setAssetAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controllerContractAddress","type":"address"},{"internalType":"address","name":"stakingContractAddress","type":"address"},{"internalType":"address","name":"serviceManagerContractAddress","type":"address"},{"internalType":"uint256","name":"nativeNodeStakingAmount","type":"uint256"},{"internalType":"uint256","name":"eigenlayerNodeStakingAmount","type":"uint256"},{"internalType":"uint256","name":"pendingBlockAfterQuit","type":"uint256"}],"name":"setNodeRegistryConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nodeIdAddress","type":"address"},{"internalType":"uint256","name":"stakingRewardPenalty","type":"uint256"},{"internalType":"uint256","name":"pendingBlock","type":"uint256"}],"name":"slashNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}]
Contract Creation Code
60a0604052306080523480156200001557600080fd5b506200002062000026565b620000e7565b600054610100900460ff1615620000935760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60005460ff90811614620000e5576000805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b60805161379f6200011f60003960008181610c1a01528181610c6301528181610e2701528181610e670152610efa015261379f6000f3fe6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063c4d66de81161008a578063e275cde611610064578063e275cde614610556578063e40e744b14610576578063f2fde38b146105d6578063f698da25146105f657600080fd5b8063c4d66de8146104cd578063c71e3c78146104ed578063d20cc1521461051d57600080fd5b80639d209048116100c65780639d2090481461042c578063a2cd23e614610459578063add60b4c14610479578063b447f4511461049957600080fd5b80638da5cb5b146103ce5780638ed47008146103ec578063914eb34d1461040c57600080fd5b80634ecea80d116101595780636cc7fb5d116101335780636cc7fb5d14610333578063715018a6146103845780637a2af56e146103995780638d2f3e6b146103ae57600080fd5b80634ecea80d146102eb5780634f1ef2861461030b57806352d1902d1461031e57600080fd5b8063227d0f4611610195578063227d0f461461025657806330d640b21461028b57806333f010a1146102ab5780633659cfe6146102cb57600080fd5b8063081342ba146101bc57806315dac9b2146101de57806320606b7014610214575b600080fd5b3480156101c857600080fd5b506101dc6101d7366004612cd4565b61060b565b005b3480156101ea57600080fd5b506101fe6101f9366004612d5c565b6107e9565b60405161020b9190612dc7565b60405180910390f35b34801561022057600080fd5b506102487f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b60405190815260200161020b565b34801561026257600080fd5b50610276610271366004612d5c565b610898565b6040805192835260208301919091520161020b565b34801561029757600080fd5b506101dc6102a6366004612f5a565b610939565b3480156102b757600080fd5b506101dc6102c6366004612fea565b610b87565b3480156102d757600080fd5b506101dc6102e6366004612d5c565b610c10565b3480156102f757600080fd5b506101dc610306366004612d5c565b610cf8565b6101dc610319366004613049565b610e1d565b34801561032a57600080fd5b50610248610eed565b34801561033f57600080fd5b5061036c61034e366004612d5c565b6001600160a01b03908116600090815260d460205260409020541690565b6040516001600160a01b03909116815260200161020b565b34801561039057600080fd5b506101dc610fa0565b3480156103a557600080fd5b506101dc610fb4565b3480156103ba57600080fd5b506101dc6103c9366004613097565b610fc3565b3480156103da57600080fd5b506097546001600160a01b031661036c565b3480156103f857600080fd5b506101dc6104073660046130cc565b611357565b34801561041857600080fd5b506101dc6104273660046130ff565b61153e565b34801561043857600080fd5b5061044c610447366004612d5c565b611696565b60405161020b91906131bc565b34801561046557600080fd5b506102486104743660046130cc565b6117b0565b34801561048557600080fd5b506101dc610494366004613219565b611865565b3480156104a557600080fd5b506102487fcc09e0f5a503fec4c1d9af748841a9210c73d71fc183762f71c57b2c6977f13681565b3480156104d957600080fd5b506101dc6104e8366004612d5c565b611877565b3480156104f957600080fd5b5061050d610508366004613219565b6119a3565b604051901515815260200161020b565b34801561052957600080fd5b5061036c610538366004612d5c565b6001600160a01b03908116600090815260d360205260409020541690565b34801561056257600080fd5b506101dc610571366004613243565b6119d1565b34801561058257600080fd5b5060c95460ca5460cb5460cc5460cd5460ce54604080516001600160a01b039788168152958716602087015295909316948401949094526060830152608082019290925260a081019190915260c00161020b565b3480156105e257600080fd5b506101dc6105f1366004612d5c565b611ba5565b34801561060257600080fd5b50610248611c1b565b610613611cb3565b82811461063357604051634ec4810560e11b815260040160405180910390fd5b60005b838110156107e25782828281811061065057610650613285565b90506020020160208101906106659190612d5c565b60d3600087878581811061067b5761067b613285565b90506020020160208101906106909190612d5c565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558484828181106106d3576106d3613285565b90506020020160208101906106e89190612d5c565b60d460008585858181106106fe576106fe613285565b90506020020160208101906107139190612d5c565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b0319169290911691909117905582828281811061075657610756613285565b905060200201602081019061076b9190612d5c565b6001600160a01b031685858381811061078657610786613285565b905060200201602081019061079b9190612d5c565b6001600160a01b03167f89ca1a6d1ba2dd7a1222041d072dd6d2e7790f80973456811e834bb9cabedbea60405160405180910390a3806107da816132b1565b915050610636565b5050505050565b6001600160a01b038116600090815260d060205260409020600101805460609190610813906132ca565b80601f016020809104026020016040519081016040528092919081815260200182805461083f906132ca565b801561088c5780601f106108615761010080835404028352916020019161088c565b820191906000526020600020905b81548152906001019060200180831161086f57829003601f168201915b50505050509050919050565b6001600160a01b038116600090815260d160205260408120548190156108e2576001600160a01b038316600090815260d160205260409020546108dd90600190613304565b6108e5565b60005b6001600160a01b038416600090815260d260205260409020541561092d576001600160a01b038416600090815260d2602052604090205461092890600190613304565b610930565b60005b91509150915091565b6001600160a01b03828116600090815260d36020526040902054161561097257604051630eb0d31360e11b815260040160405180910390fd5b61097d858585611d0d565b6001600160a01b038216600081815260d3602090815260408083208054336001600160a01b0319918216811790925590845260d4909252909120805490911690911790558215610ac65760cb54604051637b4ffbbd60e01b81526001600160a01b0384811660048301526000921690637b4ffbbd90602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190613317565b60cd54909150811015610a5c5760405163696aeee160e11b815260040160405180910390fd5b60cb5460405163aa2bcdbd60e01b81526001600160a01b039091169063aa2bcdbd90610a8e9086908690600401613330565b600060405180830381600087803b158015610aa857600080fd5b505af1158015610abc573d6000803e3d6000fd5b5050505050610b4a565b336001600160a01b03831614610ae057610ae08282611f84565b60ca5460cc5460405163282d3fdf60e01b81526001600160a01b038581166004830152602482019290925291169063282d3fdf90604401600060405180830381600087803b158015610b3157600080fd5b505af1158015610b45573d6000803e3d6000fd5b505050505b60405133906001600160a01b038416907f89ca1a6d1ba2dd7a1222041d072dd6d2e7790f80973456811e834bb9cabedbea90600090a35050505050565b610b8f611cb3565b6040805160c0810182526001600160a01b039788168082529688166020820181905295909716908701819052606087018490526080870183905260a090960181905260c980546001600160a01b0319908116909617905560ca8054861690941790935560cb805490941690941790925560cc9190915560cd9190915560ce55565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610c615760405162461bcd60e51b8152600401610c589061337c565b60405180910390fd5b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610caa600080516020613723833981519152546001600160a01b031690565b6001600160a01b031614610cd05760405162461bcd60e51b8152600401610c58906133c8565b610cd98161204b565b60408051600080825260208201909252610cf591839190612053565b50565b6001600160a01b038116610d1f5760405163f6b2911f60e01b815260040160405180910390fd5b33600090815260d1602090815260408083205460d2909252909120546001811115610d7c5733600090815260d260205260409020600190819055610d7c908490610d699084613304565b60cf546001600160a01b031691906121be565b6001821115610e185733600090815260d16020526040902060019081905560c9546001600160a01b031690630ad98f6a908590610db99086613304565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610dff57600080fd5b505af1158015610e13573d6000803e3d6000fd5b505050505b505050565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163003610e655760405162461bcd60e51b8152600401610c589061337c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316610eae600080516020613723833981519152546001600160a01b031690565b6001600160a01b031614610ed45760405162461bcd60e51b8152600401610c58906133c8565b610edd8261204b565b610ee982826001612053565b5050565b6000306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610f8d5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610c58565b5060008051602061372383398151915290565b610fa8611cb3565b610fb26000612210565b565b610fb23360c960050154612262565b33600081815260d060205260409020805490916001600160a01b0390911614610ffe576040516229eaad60e31b815260040160405180910390fd5b6002810154610100900460ff1615611029576040516324a228bb60e21b815260040160405180910390fd5b43816003015411156110565780600301546040516363525acb60e11b8152600401610c5891815260200190565b60028101805461ff00191661010017905560c95460405163ed157c3f60e01b81523360048201526000916001600160a01b03169063ed157c3f906024016020604051808303816000875af11580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d69190613317565b60405181815290915033907ffc97cd9154b40031874ef09a9436a4b60052e4dcf40f21b1258be265fac4a3979060200160405180910390a233600090815260d4602052604090205460028301546001600160a01b039091169060ff16156112365760cb54604051637b4ffbbd60e01b81526001600160a01b0383811660048301526000921690637b4ffbbd90602401602060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a69190613317565b60cd549091508110156111cc5760405163696aeee160e11b815260040160405180910390fd5b60cb5460405163aa2bcdbd60e01b81526001600160a01b039091169063aa2bcdbd906111fe9085908990600401613330565b600060405180830381600087803b15801561121857600080fd5b505af115801561122c573d6000803e3d6000fd5b5050505050611351565b336001600160a01b03821614611250576112508185611f84565b60ca5460405163929ec53760e01b81526001600160a01b038381166004830152600092169063929ec53790602401602060405180830381865afa15801561129b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bf9190613317565b60cc549091508110156107e25760ca5460cc546001600160a01b039091169063282d3fdf9084906112f1908590613304565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561133757600080fd5b505af115801561134b573d6000803e3d6000fd5b50505050505b50505050565b60c9546001600160a01b0316331461138257604051630f5caa3360e41b815260040160405180910390fd5b6001600160a01b03808416600090815260d06020908152604080832060d49092529091205460028201549192169060ff16156114825760cb54604051632955713760e01b81526001600160a01b0383811660048301526024820187905290911690632955713790604401600060405180830381600087803b15801561140657600080fd5b505af115801561141a573d6000803e3d6000fd5b505060cb54604051636c67cc6560e11b81526001600160a01b038581166004830152909116925063d8cf98ca9150602401600060405180830381600087803b15801561146557600080fd5b505af1158015611479573d6000803e3d6000fd5b505050506114e9565b60ca54604051638899fdeb60e01b81526001600160a01b0383811660048301526024820187905290911690638899fdeb90604401600060405180830381600087803b1580156114d057600080fd5b505af11580156114e4573d6000803e3d6000fd5b505050505b6114f38584612438565b60408051858152602081018590526001600160a01b038716917fa8d720d0a0a2e7c96bf9eb87433901ebb6331356c8f3283b2568de34478703cc910160405180910390a25050505050565b60c9546001600160a01b0316331461156957604051630f5caa3360e41b815260040160405180910390fd5b60005b8351811015611351578260d1600086848151811061158c5761158c613285565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546115c39190613414565b925050819055508160d260008684815181106115e1576115e1613285565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546116189190613414565b9250508190555083818151811061163157611631613285565b60200260200101516001600160a01b03167f8353a804115421789f3ab2eeb3f5215943906ce12100c91d40fc865caf742b6f848460405161167c929190918252602082015260400190565b60405180910390a28061168e816132b1565b91505061156c565b6040805160a08082018352600080835260606020808501829052848601839052908401829052608084018290526001600160a01b03868116835260d082529185902085519384019095528454909116825260018401805493949293918401916116fe906132ca565b80601f016020809104026020016040519081016040528092919081815260200182805461172a906132ca565b80156117775780601f1061174c57610100808354040283529160200191611777565b820191906000526020600020905b81548152906001019060200180831161175a57829003601f168201915b5050509183525050600282015460ff80821615156020840152610100909104161515604082015260039091015460609091015292915050565b604080517fcc09e0f5a503fec4c1d9af748841a9210c73d71fc183762f71c57b2c6977f13660208201526001600160a01b038516918101919091526060810183905260808101829052600090819060a0016040516020818303038152906040528051906020012090506000611823611c1b565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f1901815291905280516020909101209695505050505050565b61186d611cb3565b610ee98282612262565b600054610100900460ff16158080156118975750600054600160ff909116105b806118b15750303b1580156118b1575060005460ff166001145b6119145760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c58565b6000805460ff191660011790558015611937576000805461ff0019166101001790555b60cf80546001600160a01b0319166001600160a01b03841617905561195a6124cb565b8015610ee9576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b038216600090815260d56020908152604080832084845290915290205460ff165b92915050565b33600081815260d060205260409020805490916001600160a01b0390911614611a0c576040516229eaad60e31b815260040160405180910390fd5b6002810154610100900460ff1615611a37576040516324a228bb60e21b815260040160405180910390fd5b6040516316f6db8160e01b815260009073554816b8c04fe2eeab2e9aabf128d4f759afe760906316f6db8190611a739087908790600401613450565b608060405180830381865af4158015611a90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab49190613464565b604051636fda2c7960e01b815290915073554816b8c04fe2eeab2e9aabf128d4f759afe76090636fda2c7990611aee9084906004016134e2565b602060405180830381865af4158015611b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2f9190613513565b611b4c5760405163145a1fdd60e31b815260040160405180910390fd5b60018201611b5b84868361357e565b50336001600160a01b03167f4a327ac4843af7a9586b5a2a2c312bd17289ae1d70da32855ed539fe39f86a508585604051611b97929190613450565b60405180910390a250505050565b611bad611cb3565b6001600160a01b038116611c125760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c58565b610cf581612210565b604080518082018252600b81526a415250414e6574776f726b60a81b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc43fa7e3599574b946896342cc7dd655e49b85dcfc1234920ef144a6e4f1f2e581840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b6097546001600160a01b03163314610fb25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c58565b33600090815260d060205260409020546001600160a01b031615611d4457604051630eb0d31360e11b815260040160405180910390fd5b6040516316f6db8160e01b815260009073554816b8c04fe2eeab2e9aabf128d4f759afe760906316f6db8190611d809087908790600401613450565b608060405180830381865af4158015611d9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc19190613464565b604051636fda2c7960e01b815290915073554816b8c04fe2eeab2e9aabf128d4f759afe76090636fda2c7990611dfb9084906004016134e2565b602060405180830381865af4158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c9190613513565b611e595760405163145a1fdd60e31b815260040160405180910390fd5b33600081815260d06020526040902080546001600160a01b031916909117815560018101611e8885878361357e565b5060028101805461010061ffff199091168515151717905533600081815260d16020908152604080832060019081905560d29092528083209190915560c954905163ed157c3f60e01b8152600481019390935290916001600160a01b039091169063ed157c3f906024016020604051808303816000875af1158015611f11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f359190613317565b9050336001600160a01b03167fd4ec586f4f9f417f99e20fe821fbaa10a10a4b95f8712a0c57c6d8ed970e98bd878784604051611f749392919061363e565b60405180910390a2505050505050565b4281604001511015611fa95760405163e3c3dba760e01b815260040160405180910390fd5b6001600160a01b038216600090815260d56020908152604080832084830151845290915290205460ff1615611ff15760405163a6dd314f60e01b815260040160405180910390fd5b600061200683836020015184604001516117b0565b9050612017838284600001516124fa565b506001600160a01b03909116600090815260d56020908152604080832093820151835292905220805460ff19166001179055565b610cf5611cb3565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561208657610e18836125de565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156120e0575060408051601f3d908101601f191682019092526120dd91810190613317565b60015b6121435760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610c58565b60008051602061372383398151915281146121b25760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610c58565b50610e1883838361267a565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610e1890849061269f565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03808316600081815260d06020526040902080549092161461229d576040516229eaad60e31b815260040160405180910390fd5b60c9546040516335fe4a3f60e01b81526001600160a01b038581166004830152909116906335fe4a3f90602401600060405180830381600087803b1580156122e457600080fd5b505af11580156122f8573d6000803e3d6000fd5b505050506123068383612438565b6001600160a01b03808416600090815260d46020526040902054600283015491169060ff16156123945760cb54604051636c67cc6560e11b81526001600160a01b0383811660048301529091169063d8cf98ca90602401600060405180830381600087803b15801561237757600080fd5b505af115801561238b573d6000803e3d6000fd5b505050506123fe565b60ca5460cc54604051637eee288d60e01b81526001600160a01b0384811660048301526024820192909252911690637eee288d90604401600060405180830381600087803b1580156123e557600080fd5b505af11580156123f9573d6000803e3d6000fd5b505050505b6040516001600160a01b038516907f68577adbb6b0647e21353ff032be5797d9fa0879ce7e05fe617e40368441f97d90600090a250505050565b6001600160a01b038216600090815260d06020526040902060028101805461ff00191690556003015443908110156124a0576001600160a01b038316600090815260d0602052604081206003018054849290612495908490613414565b90915550610e189050565b6124aa8282613414565b6001600160a01b038416600090815260d06020526040902060030155505050565b600054610100900460ff166124f25760405162461bcd60e51b8152600401610c5890613662565b610fb2612774565b6001600160a01b0383163b156125a357604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e9061253a90869086906004016136ad565b602060405180830381865afa158015612557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257b91906136c6565b6001600160e01b03191614610e1857604051632c3534d160e11b815260040160405180910390fd5b826001600160a01b03166125b783836127a4565b6001600160a01b031614610e1857604051630825306160e31b815260040160405180910390fd5b6001600160a01b0381163b61264b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610c58565b60008051602061372383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612683836127c8565b6000825111806126905750805b15610e18576113518383612808565b60006126f4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128349092919063ffffffff16565b90508051600014806127155750808060200190518101906127159190613513565b610e185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c58565b600054610100900460ff1661279b5760405162461bcd60e51b8152600401610c5890613662565b610fb233612210565b60008060006127b3858561284b565b915091506127c081612890565b509392505050565b6127d1816125de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061282d8383604051806060016040528060278152602001613743602791396129da565b9392505050565b60606128438484600085612a52565b949350505050565b60008082516041036128815760208301516040840151606085015160001a61287587828585612b2d565b94509450505050612889565b506000905060025b9250929050565b60008160048111156128a4576128a46136f0565b036128ac5750565b60018160048111156128c0576128c06136f0565b0361290d5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c58565b6002816004811115612921576129216136f0565b0361296e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c58565b6003816004811115612982576129826136f0565b03610cf55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c58565b6060600080856001600160a01b0316856040516129f79190613706565b600060405180830381855af49150503d8060008114612a32576040519150601f19603f3d011682016040523d82523d6000602084013e612a37565b606091505b5091509150612a4886838387612bf1565b9695505050505050565b606082471015612ab35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c58565b600080866001600160a01b03168587604051612acf9190613706565b60006040518083038185875af1925050503d8060008114612b0c576040519150601f19603f3d011682016040523d82523d6000602084013e612b11565b606091505b5091509150612b2287838387612bf1565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612b645750600090506003612be8565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612bb8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612be157600060019250925050612be8565b9150600090505b94509492505050565b60608315612c60578251600003612c59576001600160a01b0385163b612c595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c58565b5081612843565b6128438383815115612c755781518083602001fd5b8060405162461bcd60e51b8152600401610c589190612dc7565b60008083601f840112612ca157600080fd5b50813567ffffffffffffffff811115612cb957600080fd5b6020830191508360208260051b850101111561288957600080fd5b60008060008060408587031215612cea57600080fd5b843567ffffffffffffffff80821115612d0257600080fd5b612d0e88838901612c8f565b90965094506020870135915080821115612d2757600080fd5b50612d3487828801612c8f565b95989497509550505050565b80356001600160a01b0381168114612d5757600080fd5b919050565b600060208284031215612d6e57600080fd5b61282d82612d40565b60005b83811015612d92578181015183820152602001612d7a565b50506000910152565b60008151808452612db3816020860160208601612d77565b601f01601f19169290920160200192915050565b60208152600061282d6020830184612d9b565b60008083601f840112612dec57600080fd5b50813567ffffffffffffffff811115612e0457600080fd5b60208301915083602082850101111561288957600080fd5b8015158114610cf557600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e6957612e69612e2a565b604052919050565b600082601f830112612e8257600080fd5b813567ffffffffffffffff811115612e9c57612e9c612e2a565b612eaf601f8201601f1916602001612e40565b818152846020838601011115612ec457600080fd5b816020850160208301376000918101602001919091529392505050565b600060608284031215612ef357600080fd5b6040516060810167ffffffffffffffff8282108183111715612f1757612f17612e2a565b816040528293508435915080821115612f2f57600080fd5b50612f3c85828601612e71565b82525060208301356020820152604083013560408201525092915050565b600080600080600060808688031215612f7257600080fd5b853567ffffffffffffffff80821115612f8a57600080fd5b612f9689838a01612dda565b909750955060208801359150612fab82612e1c565b819450612fba60408901612d40565b93506060880135915080821115612fd057600080fd5b50612fdd88828901612ee1565b9150509295509295909350565b60008060008060008060c0878903121561300357600080fd5b61300c87612d40565b955061301a60208801612d40565b945061302860408801612d40565b9350606087013592506080870135915060a087013590509295509295509295565b6000806040838503121561305c57600080fd5b61306583612d40565b9150602083013567ffffffffffffffff81111561308157600080fd5b61308d85828601612e71565b9150509250929050565b6000602082840312156130a957600080fd5b813567ffffffffffffffff8111156130c057600080fd5b61284384828501612ee1565b6000806000606084860312156130e157600080fd5b6130ea84612d40565b95602085013595506040909401359392505050565b60008060006060848603121561311457600080fd5b833567ffffffffffffffff8082111561312c57600080fd5b818601915086601f83011261314057600080fd5b813560208282111561315457613154612e2a565b8160051b9250613165818401612e40565b828152928401810192818101908a85111561317f57600080fd5b948201945b848610156131a45761319586612d40565b82529482019490820190613184565b9a918901359950506040909701359695505050505050565b602081526001600160a01b0382511660208201526000602083015160a060408401526131eb60c0840182612d9b565b9050604084015115156060840152606084015115156080840152608084015160a08401528091505092915050565b6000806040838503121561322c57600080fd5b61323583612d40565b946020939093013593505050565b6000806020838503121561325657600080fd5b823567ffffffffffffffff81111561326d57600080fd5b61327985828601612dda565b90969095509350505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016132c3576132c361329b565b5060010190565b600181811c908216806132de57607f821691505b6020821081036132fe57634e487b7160e01b600052602260045260246000fd5b50919050565b818103818111156119cb576119cb61329b565b60006020828403121561332957600080fd5b5051919050565b6001600160a01b038316815260406020820152600082516060604084015261335b60a0840182612d9b565b90506020840151606084015260408401516080840152809150509392505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b808201808211156119cb576119cb61329b565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000612843602083018486613427565b60006080828403121561347657600080fd5b82601f83011261348557600080fd5b6040516080810181811067ffffffffffffffff821117156134a8576134a8612e2a565b6040528060808401858111156134bd57600080fd5b845b818110156134d75780518352602092830192016134bf565b509195945050505050565b60808101818360005b600481101561350a5781518352602092830192909101906001016134eb565b50505092915050565b60006020828403121561352557600080fd5b815161282d81612e1c565b601f821115610e1857600081815260208120601f850160051c810160208610156135575750805b601f850160051c820191505b8181101561357657828155600101613563565b505050505050565b67ffffffffffffffff83111561359657613596612e2a565b6135aa836135a483546132ca565b83613530565b6000601f8411600181146135de57600085156135c65750838201355b600019600387901b1c1916600186901b1783556107e2565b600083815260209020601f19861690835b8281101561360f57868501358255602094850194600190920191016135ef565b508682101561362c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b604081526000613652604083018587613427565b9050826020830152949350505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8281526040602082015260006128436040830184612d9b565b6000602082840312156136d857600080fd5b81516001600160e01b03198116811461282d57600080fd5b634e487b7160e01b600052602160045260246000fd5b60008251613718818460208701612d77565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212206686ac35ceeaf9c26964a24bf1be559a37c82b501dc1fa9795f78730e393ede064736f6c63430008120033
Deployed Bytecode
0x6080604052600436106101b75760003560e01c80638da5cb5b116100ec578063c4d66de81161008a578063e275cde611610064578063e275cde614610556578063e40e744b14610576578063f2fde38b146105d6578063f698da25146105f657600080fd5b8063c4d66de8146104cd578063c71e3c78146104ed578063d20cc1521461051d57600080fd5b80639d209048116100c65780639d2090481461042c578063a2cd23e614610459578063add60b4c14610479578063b447f4511461049957600080fd5b80638da5cb5b146103ce5780638ed47008146103ec578063914eb34d1461040c57600080fd5b80634ecea80d116101595780636cc7fb5d116101335780636cc7fb5d14610333578063715018a6146103845780637a2af56e146103995780638d2f3e6b146103ae57600080fd5b80634ecea80d146102eb5780634f1ef2861461030b57806352d1902d1461031e57600080fd5b8063227d0f4611610195578063227d0f461461025657806330d640b21461028b57806333f010a1146102ab5780633659cfe6146102cb57600080fd5b8063081342ba146101bc57806315dac9b2146101de57806320606b7014610214575b600080fd5b3480156101c857600080fd5b506101dc6101d7366004612cd4565b61060b565b005b3480156101ea57600080fd5b506101fe6101f9366004612d5c565b6107e9565b60405161020b9190612dc7565b60405180910390f35b34801561022057600080fd5b506102487f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b60405190815260200161020b565b34801561026257600080fd5b50610276610271366004612d5c565b610898565b6040805192835260208301919091520161020b565b34801561029757600080fd5b506101dc6102a6366004612f5a565b610939565b3480156102b757600080fd5b506101dc6102c6366004612fea565b610b87565b3480156102d757600080fd5b506101dc6102e6366004612d5c565b610c10565b3480156102f757600080fd5b506101dc610306366004612d5c565b610cf8565b6101dc610319366004613049565b610e1d565b34801561032a57600080fd5b50610248610eed565b34801561033f57600080fd5b5061036c61034e366004612d5c565b6001600160a01b03908116600090815260d460205260409020541690565b6040516001600160a01b03909116815260200161020b565b34801561039057600080fd5b506101dc610fa0565b3480156103a557600080fd5b506101dc610fb4565b3480156103ba57600080fd5b506101dc6103c9366004613097565b610fc3565b3480156103da57600080fd5b506097546001600160a01b031661036c565b3480156103f857600080fd5b506101dc6104073660046130cc565b611357565b34801561041857600080fd5b506101dc6104273660046130ff565b61153e565b34801561043857600080fd5b5061044c610447366004612d5c565b611696565b60405161020b91906131bc565b34801561046557600080fd5b506102486104743660046130cc565b6117b0565b34801561048557600080fd5b506101dc610494366004613219565b611865565b3480156104a557600080fd5b506102487fcc09e0f5a503fec4c1d9af748841a9210c73d71fc183762f71c57b2c6977f13681565b3480156104d957600080fd5b506101dc6104e8366004612d5c565b611877565b3480156104f957600080fd5b5061050d610508366004613219565b6119a3565b604051901515815260200161020b565b34801561052957600080fd5b5061036c610538366004612d5c565b6001600160a01b03908116600090815260d360205260409020541690565b34801561056257600080fd5b506101dc610571366004613243565b6119d1565b34801561058257600080fd5b5060c95460ca5460cb5460cc5460cd5460ce54604080516001600160a01b039788168152958716602087015295909316948401949094526060830152608082019290925260a081019190915260c00161020b565b3480156105e257600080fd5b506101dc6105f1366004612d5c565b611ba5565b34801561060257600080fd5b50610248611c1b565b610613611cb3565b82811461063357604051634ec4810560e11b815260040160405180910390fd5b60005b838110156107e25782828281811061065057610650613285565b90506020020160208101906106659190612d5c565b60d3600087878581811061067b5761067b613285565b90506020020160208101906106909190612d5c565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b031916929091169190911790558484828181106106d3576106d3613285565b90506020020160208101906106e89190612d5c565b60d460008585858181106106fe576106fe613285565b90506020020160208101906107139190612d5c565b6001600160a01b039081168252602082019290925260400160002080546001600160a01b0319169290911691909117905582828281811061075657610756613285565b905060200201602081019061076b9190612d5c565b6001600160a01b031685858381811061078657610786613285565b905060200201602081019061079b9190612d5c565b6001600160a01b03167f89ca1a6d1ba2dd7a1222041d072dd6d2e7790f80973456811e834bb9cabedbea60405160405180910390a3806107da816132b1565b915050610636565b5050505050565b6001600160a01b038116600090815260d060205260409020600101805460609190610813906132ca565b80601f016020809104026020016040519081016040528092919081815260200182805461083f906132ca565b801561088c5780601f106108615761010080835404028352916020019161088c565b820191906000526020600020905b81548152906001019060200180831161086f57829003601f168201915b50505050509050919050565b6001600160a01b038116600090815260d160205260408120548190156108e2576001600160a01b038316600090815260d160205260409020546108dd90600190613304565b6108e5565b60005b6001600160a01b038416600090815260d260205260409020541561092d576001600160a01b038416600090815260d2602052604090205461092890600190613304565b610930565b60005b91509150915091565b6001600160a01b03828116600090815260d36020526040902054161561097257604051630eb0d31360e11b815260040160405180910390fd5b61097d858585611d0d565b6001600160a01b038216600081815260d3602090815260408083208054336001600160a01b0319918216811790925590845260d4909252909120805490911690911790558215610ac65760cb54604051637b4ffbbd60e01b81526001600160a01b0384811660048301526000921690637b4ffbbd90602401602060405180830381865afa158015610a12573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a369190613317565b60cd54909150811015610a5c5760405163696aeee160e11b815260040160405180910390fd5b60cb5460405163aa2bcdbd60e01b81526001600160a01b039091169063aa2bcdbd90610a8e9086908690600401613330565b600060405180830381600087803b158015610aa857600080fd5b505af1158015610abc573d6000803e3d6000fd5b5050505050610b4a565b336001600160a01b03831614610ae057610ae08282611f84565b60ca5460cc5460405163282d3fdf60e01b81526001600160a01b038581166004830152602482019290925291169063282d3fdf90604401600060405180830381600087803b158015610b3157600080fd5b505af1158015610b45573d6000803e3d6000fd5b505050505b60405133906001600160a01b038416907f89ca1a6d1ba2dd7a1222041d072dd6d2e7790f80973456811e834bb9cabedbea90600090a35050505050565b610b8f611cb3565b6040805160c0810182526001600160a01b039788168082529688166020820181905295909716908701819052606087018490526080870183905260a090960181905260c980546001600160a01b0319908116909617905560ca8054861690941790935560cb805490941690941790925560cc9190915560cd9190915560ce55565b6001600160a01b037f000000000000000000000000bd7d3a6d1d2d79286c2c859c2881e086748b4956163003610c615760405162461bcd60e51b8152600401610c589061337c565b60405180910390fd5b7f000000000000000000000000bd7d3a6d1d2d79286c2c859c2881e086748b49566001600160a01b0316610caa600080516020613723833981519152546001600160a01b031690565b6001600160a01b031614610cd05760405162461bcd60e51b8152600401610c58906133c8565b610cd98161204b565b60408051600080825260208201909252610cf591839190612053565b50565b6001600160a01b038116610d1f5760405163f6b2911f60e01b815260040160405180910390fd5b33600090815260d1602090815260408083205460d2909252909120546001811115610d7c5733600090815260d260205260409020600190819055610d7c908490610d699084613304565b60cf546001600160a01b031691906121be565b6001821115610e185733600090815260d16020526040902060019081905560c9546001600160a01b031690630ad98f6a908590610db99086613304565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b158015610dff57600080fd5b505af1158015610e13573d6000803e3d6000fd5b505050505b505050565b6001600160a01b037f000000000000000000000000bd7d3a6d1d2d79286c2c859c2881e086748b4956163003610e655760405162461bcd60e51b8152600401610c589061337c565b7f000000000000000000000000bd7d3a6d1d2d79286c2c859c2881e086748b49566001600160a01b0316610eae600080516020613723833981519152546001600160a01b031690565b6001600160a01b031614610ed45760405162461bcd60e51b8152600401610c58906133c8565b610edd8261204b565b610ee982826001612053565b5050565b6000306001600160a01b037f000000000000000000000000bd7d3a6d1d2d79286c2c859c2881e086748b49561614610f8d5760405162461bcd60e51b815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c00000000000000006064820152608401610c58565b5060008051602061372383398151915290565b610fa8611cb3565b610fb26000612210565b565b610fb23360c960050154612262565b33600081815260d060205260409020805490916001600160a01b0390911614610ffe576040516229eaad60e31b815260040160405180910390fd5b6002810154610100900460ff1615611029576040516324a228bb60e21b815260040160405180910390fd5b43816003015411156110565780600301546040516363525acb60e11b8152600401610c5891815260200190565b60028101805461ff00191661010017905560c95460405163ed157c3f60e01b81523360048201526000916001600160a01b03169063ed157c3f906024016020604051808303816000875af11580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d69190613317565b60405181815290915033907ffc97cd9154b40031874ef09a9436a4b60052e4dcf40f21b1258be265fac4a3979060200160405180910390a233600090815260d4602052604090205460028301546001600160a01b039091169060ff16156112365760cb54604051637b4ffbbd60e01b81526001600160a01b0383811660048301526000921690637b4ffbbd90602401602060405180830381865afa158015611182573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a69190613317565b60cd549091508110156111cc5760405163696aeee160e11b815260040160405180910390fd5b60cb5460405163aa2bcdbd60e01b81526001600160a01b039091169063aa2bcdbd906111fe9085908990600401613330565b600060405180830381600087803b15801561121857600080fd5b505af115801561122c573d6000803e3d6000fd5b5050505050611351565b336001600160a01b03821614611250576112508185611f84565b60ca5460405163929ec53760e01b81526001600160a01b038381166004830152600092169063929ec53790602401602060405180830381865afa15801561129b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bf9190613317565b60cc549091508110156107e25760ca5460cc546001600160a01b039091169063282d3fdf9084906112f1908590613304565b6040516001600160e01b031960e085901b1681526001600160a01b0390921660048301526024820152604401600060405180830381600087803b15801561133757600080fd5b505af115801561134b573d6000803e3d6000fd5b50505050505b50505050565b60c9546001600160a01b0316331461138257604051630f5caa3360e41b815260040160405180910390fd5b6001600160a01b03808416600090815260d06020908152604080832060d49092529091205460028201549192169060ff16156114825760cb54604051632955713760e01b81526001600160a01b0383811660048301526024820187905290911690632955713790604401600060405180830381600087803b15801561140657600080fd5b505af115801561141a573d6000803e3d6000fd5b505060cb54604051636c67cc6560e11b81526001600160a01b038581166004830152909116925063d8cf98ca9150602401600060405180830381600087803b15801561146557600080fd5b505af1158015611479573d6000803e3d6000fd5b505050506114e9565b60ca54604051638899fdeb60e01b81526001600160a01b0383811660048301526024820187905290911690638899fdeb90604401600060405180830381600087803b1580156114d057600080fd5b505af11580156114e4573d6000803e3d6000fd5b505050505b6114f38584612438565b60408051858152602081018590526001600160a01b038716917fa8d720d0a0a2e7c96bf9eb87433901ebb6331356c8f3283b2568de34478703cc910160405180910390a25050505050565b60c9546001600160a01b0316331461156957604051630f5caa3360e41b815260040160405180910390fd5b60005b8351811015611351578260d1600086848151811061158c5761158c613285565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546115c39190613414565b925050819055508160d260008684815181106115e1576115e1613285565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060008282546116189190613414565b9250508190555083818151811061163157611631613285565b60200260200101516001600160a01b03167f8353a804115421789f3ab2eeb3f5215943906ce12100c91d40fc865caf742b6f848460405161167c929190918252602082015260400190565b60405180910390a28061168e816132b1565b91505061156c565b6040805160a08082018352600080835260606020808501829052848601839052908401829052608084018290526001600160a01b03868116835260d082529185902085519384019095528454909116825260018401805493949293918401916116fe906132ca565b80601f016020809104026020016040519081016040528092919081815260200182805461172a906132ca565b80156117775780601f1061174c57610100808354040283529160200191611777565b820191906000526020600020905b81548152906001019060200180831161175a57829003601f168201915b5050509183525050600282015460ff80821615156020840152610100909104161515604082015260039091015460609091015292915050565b604080517fcc09e0f5a503fec4c1d9af748841a9210c73d71fc183762f71c57b2c6977f13660208201526001600160a01b038516918101919091526060810183905260808101829052600090819060a0016040516020818303038152906040528051906020012090506000611823611c1b565b60405161190160f01b602082015260228101919091526042810183905260620160408051808303601f1901815291905280516020909101209695505050505050565b61186d611cb3565b610ee98282612262565b600054610100900460ff16158080156118975750600054600160ff909116105b806118b15750303b1580156118b1575060005460ff166001145b6119145760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610c58565b6000805460ff191660011790558015611937576000805461ff0019166101001790555b60cf80546001600160a01b0319166001600160a01b03841617905561195a6124cb565b8015610ee9576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15050565b6001600160a01b038216600090815260d56020908152604080832084845290915290205460ff165b92915050565b33600081815260d060205260409020805490916001600160a01b0390911614611a0c576040516229eaad60e31b815260040160405180910390fd5b6002810154610100900460ff1615611a37576040516324a228bb60e21b815260040160405180910390fd5b6040516316f6db8160e01b815260009073554816b8c04fe2eeab2e9aabf128d4f759afe760906316f6db8190611a739087908790600401613450565b608060405180830381865af4158015611a90573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ab49190613464565b604051636fda2c7960e01b815290915073554816b8c04fe2eeab2e9aabf128d4f759afe76090636fda2c7990611aee9084906004016134e2565b602060405180830381865af4158015611b0b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b2f9190613513565b611b4c5760405163145a1fdd60e31b815260040160405180910390fd5b60018201611b5b84868361357e565b50336001600160a01b03167f4a327ac4843af7a9586b5a2a2c312bd17289ae1d70da32855ed539fe39f86a508585604051611b97929190613450565b60405180910390a250505050565b611bad611cb3565b6001600160a01b038116611c125760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610c58565b610cf581612210565b604080518082018252600b81526a415250414e6574776f726b60a81b60209182015281517f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866818301527fc43fa7e3599574b946896342cc7dd655e49b85dcfc1234920ef144a6e4f1f2e581840152466060820152306080808301919091528351808303909101815260a0909101909252815191012090565b6097546001600160a01b03163314610fb25760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610c58565b33600090815260d060205260409020546001600160a01b031615611d4457604051630eb0d31360e11b815260040160405180910390fd5b6040516316f6db8160e01b815260009073554816b8c04fe2eeab2e9aabf128d4f759afe760906316f6db8190611d809087908790600401613450565b608060405180830381865af4158015611d9d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dc19190613464565b604051636fda2c7960e01b815290915073554816b8c04fe2eeab2e9aabf128d4f759afe76090636fda2c7990611dfb9084906004016134e2565b602060405180830381865af4158015611e18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e3c9190613513565b611e595760405163145a1fdd60e31b815260040160405180910390fd5b33600081815260d06020526040902080546001600160a01b031916909117815560018101611e8885878361357e565b5060028101805461010061ffff199091168515151717905533600081815260d16020908152604080832060019081905560d29092528083209190915560c954905163ed157c3f60e01b8152600481019390935290916001600160a01b039091169063ed157c3f906024016020604051808303816000875af1158015611f11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f359190613317565b9050336001600160a01b03167fd4ec586f4f9f417f99e20fe821fbaa10a10a4b95f8712a0c57c6d8ed970e98bd878784604051611f749392919061363e565b60405180910390a2505050505050565b4281604001511015611fa95760405163e3c3dba760e01b815260040160405180910390fd5b6001600160a01b038216600090815260d56020908152604080832084830151845290915290205460ff1615611ff15760405163a6dd314f60e01b815260040160405180910390fd5b600061200683836020015184604001516117b0565b9050612017838284600001516124fa565b506001600160a01b03909116600090815260d56020908152604080832093820151835292905220805460ff19166001179055565b610cf5611cb3565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff161561208657610e18836125de565b826001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa9250505080156120e0575060408051601f3d908101601f191682019092526120dd91810190613317565b60015b6121435760405162461bcd60e51b815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201526d6f6e206973206e6f74205555505360901b6064820152608401610c58565b60008051602061372383398151915281146121b25760405162461bcd60e51b815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f786044820152681a58589b195555525160ba1b6064820152608401610c58565b50610e1883838361267a565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052610e1890849061269f565b609780546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6001600160a01b03808316600081815260d06020526040902080549092161461229d576040516229eaad60e31b815260040160405180910390fd5b60c9546040516335fe4a3f60e01b81526001600160a01b038581166004830152909116906335fe4a3f90602401600060405180830381600087803b1580156122e457600080fd5b505af11580156122f8573d6000803e3d6000fd5b505050506123068383612438565b6001600160a01b03808416600090815260d46020526040902054600283015491169060ff16156123945760cb54604051636c67cc6560e11b81526001600160a01b0383811660048301529091169063d8cf98ca90602401600060405180830381600087803b15801561237757600080fd5b505af115801561238b573d6000803e3d6000fd5b505050506123fe565b60ca5460cc54604051637eee288d60e01b81526001600160a01b0384811660048301526024820192909252911690637eee288d90604401600060405180830381600087803b1580156123e557600080fd5b505af11580156123f9573d6000803e3d6000fd5b505050505b6040516001600160a01b038516907f68577adbb6b0647e21353ff032be5797d9fa0879ce7e05fe617e40368441f97d90600090a250505050565b6001600160a01b038216600090815260d06020526040902060028101805461ff00191690556003015443908110156124a0576001600160a01b038316600090815260d0602052604081206003018054849290612495908490613414565b90915550610e189050565b6124aa8282613414565b6001600160a01b038416600090815260d06020526040902060030155505050565b600054610100900460ff166124f25760405162461bcd60e51b8152600401610c5890613662565b610fb2612774565b6001600160a01b0383163b156125a357604051630b135d3f60e11b808252906001600160a01b03851690631626ba7e9061253a90869086906004016136ad565b602060405180830381865afa158015612557573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061257b91906136c6565b6001600160e01b03191614610e1857604051632c3534d160e11b815260040160405180910390fd5b826001600160a01b03166125b783836127a4565b6001600160a01b031614610e1857604051630825306160e31b815260040160405180910390fd5b6001600160a01b0381163b61264b5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401610c58565b60008051602061372383398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b612683836127c8565b6000825111806126905750805b15610e18576113518383612808565b60006126f4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166128349092919063ffffffff16565b90508051600014806127155750808060200190518101906127159190613513565b610e185760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610c58565b600054610100900460ff1661279b5760405162461bcd60e51b8152600401610c5890613662565b610fb233612210565b60008060006127b3858561284b565b915091506127c081612890565b509392505050565b6127d1816125de565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606061282d8383604051806060016040528060278152602001613743602791396129da565b9392505050565b60606128438484600085612a52565b949350505050565b60008082516041036128815760208301516040840151606085015160001a61287587828585612b2d565b94509450505050612889565b506000905060025b9250929050565b60008160048111156128a4576128a46136f0565b036128ac5750565b60018160048111156128c0576128c06136f0565b0361290d5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610c58565b6002816004811115612921576129216136f0565b0361296e5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610c58565b6003816004811115612982576129826136f0565b03610cf55760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610c58565b6060600080856001600160a01b0316856040516129f79190613706565b600060405180830381855af49150503d8060008114612a32576040519150601f19603f3d011682016040523d82523d6000602084013e612a37565b606091505b5091509150612a4886838387612bf1565b9695505050505050565b606082471015612ab35760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610c58565b600080866001600160a01b03168587604051612acf9190613706565b60006040518083038185875af1925050503d8060008114612b0c576040519150601f19603f3d011682016040523d82523d6000602084013e612b11565b606091505b5091509150612b2287838387612bf1565b979650505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115612b645750600090506003612be8565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612bb8573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116612be157600060019250925050612be8565b9150600090505b94509492505050565b60608315612c60578251600003612c59576001600160a01b0385163b612c595760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c58565b5081612843565b6128438383815115612c755781518083602001fd5b8060405162461bcd60e51b8152600401610c589190612dc7565b60008083601f840112612ca157600080fd5b50813567ffffffffffffffff811115612cb957600080fd5b6020830191508360208260051b850101111561288957600080fd5b60008060008060408587031215612cea57600080fd5b843567ffffffffffffffff80821115612d0257600080fd5b612d0e88838901612c8f565b90965094506020870135915080821115612d2757600080fd5b50612d3487828801612c8f565b95989497509550505050565b80356001600160a01b0381168114612d5757600080fd5b919050565b600060208284031215612d6e57600080fd5b61282d82612d40565b60005b83811015612d92578181015183820152602001612d7a565b50506000910152565b60008151808452612db3816020860160208601612d77565b601f01601f19169290920160200192915050565b60208152600061282d6020830184612d9b565b60008083601f840112612dec57600080fd5b50813567ffffffffffffffff811115612e0457600080fd5b60208301915083602082850101111561288957600080fd5b8015158114610cf557600080fd5b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612e6957612e69612e2a565b604052919050565b600082601f830112612e8257600080fd5b813567ffffffffffffffff811115612e9c57612e9c612e2a565b612eaf601f8201601f1916602001612e40565b818152846020838601011115612ec457600080fd5b816020850160208301376000918101602001919091529392505050565b600060608284031215612ef357600080fd5b6040516060810167ffffffffffffffff8282108183111715612f1757612f17612e2a565b816040528293508435915080821115612f2f57600080fd5b50612f3c85828601612e71565b82525060208301356020820152604083013560408201525092915050565b600080600080600060808688031215612f7257600080fd5b853567ffffffffffffffff80821115612f8a57600080fd5b612f9689838a01612dda565b909750955060208801359150612fab82612e1c565b819450612fba60408901612d40565b93506060880135915080821115612fd057600080fd5b50612fdd88828901612ee1565b9150509295509295909350565b60008060008060008060c0878903121561300357600080fd5b61300c87612d40565b955061301a60208801612d40565b945061302860408801612d40565b9350606087013592506080870135915060a087013590509295509295509295565b6000806040838503121561305c57600080fd5b61306583612d40565b9150602083013567ffffffffffffffff81111561308157600080fd5b61308d85828601612e71565b9150509250929050565b6000602082840312156130a957600080fd5b813567ffffffffffffffff8111156130c057600080fd5b61284384828501612ee1565b6000806000606084860312156130e157600080fd5b6130ea84612d40565b95602085013595506040909401359392505050565b60008060006060848603121561311457600080fd5b833567ffffffffffffffff8082111561312c57600080fd5b818601915086601f83011261314057600080fd5b813560208282111561315457613154612e2a565b8160051b9250613165818401612e40565b828152928401810192818101908a85111561317f57600080fd5b948201945b848610156131a45761319586612d40565b82529482019490820190613184565b9a918901359950506040909701359695505050505050565b602081526001600160a01b0382511660208201526000602083015160a060408401526131eb60c0840182612d9b565b9050604084015115156060840152606084015115156080840152608084015160a08401528091505092915050565b6000806040838503121561322c57600080fd5b61323583612d40565b946020939093013593505050565b6000806020838503121561325657600080fd5b823567ffffffffffffffff81111561326d57600080fd5b61327985828601612dda565b90969095509350505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016132c3576132c361329b565b5060010190565b600181811c908216806132de57607f821691505b6020821081036132fe57634e487b7160e01b600052602260045260246000fd5b50919050565b818103818111156119cb576119cb61329b565b60006020828403121561332957600080fd5b5051919050565b6001600160a01b038316815260406020820152600082516060604084015261335b60a0840182612d9b565b90506020840151606084015260408401516080840152809150509392505050565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c908201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060408201526b6163746976652070726f787960a01b606082015260800190565b808201808211156119cb576119cb61329b565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b602081526000612843602083018486613427565b60006080828403121561347657600080fd5b82601f83011261348557600080fd5b6040516080810181811067ffffffffffffffff821117156134a8576134a8612e2a565b6040528060808401858111156134bd57600080fd5b845b818110156134d75780518352602092830192016134bf565b509195945050505050565b60808101818360005b600481101561350a5781518352602092830192909101906001016134eb565b50505092915050565b60006020828403121561352557600080fd5b815161282d81612e1c565b601f821115610e1857600081815260208120601f850160051c810160208610156135575750805b601f850160051c820191505b8181101561357657828155600101613563565b505050505050565b67ffffffffffffffff83111561359657613596612e2a565b6135aa836135a483546132ca565b83613530565b6000601f8411600181146135de57600085156135c65750838201355b600019600387901b1c1916600186901b1783556107e2565b600083815260209020601f19861690835b8281101561360f57868501358255602094850194600190920191016135ef565b508682101561362c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b604081526000613652604083018587613427565b9050826020830152949350505050565b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b8281526040602082015260006128436040830184612d9b565b6000602082840312156136d857600080fd5b81516001600160e01b03198116811461282d57600080fd5b634e487b7160e01b600052602160045260246000fd5b60008251613718818460208701612d77565b919091019291505056fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a26469706673582212206686ac35ceeaf9c26964a24bf1be559a37c82b501dc1fa9795f78730e393ede064736f6c63430008120033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.