Source Code
Overview
HYPE Balance
HYPE Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 17005099 | 99 days ago | Contract Creation | 0 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
TokenTableMerkleMultitokenDistributorBatched
Compiler Version
v0.8.29+commit.ab55807c
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL v3
pragma solidity ^0.8.24;
import { BaseMerkleDistributor } from "../BaseMerkleDistributor.sol";
import { IERC20 } from "@openzeppelin-contracts/interfaces/IERC20.sol";
import { SafeERC20 } from "../../../common/utils/MinimalSafeERC20.sol";
import { MinimalPausable } from "../../../common/utils/MinimalPausable.sol";
/// @notice Data structure for group-based batched claims with optimized bit packing
/// @dev Uses bit packing for calldata optimization: recipient(160) + timestamp(40) + tokenIndex(56) = 256 bits
/// @dev Group hash is derived from claim parameters, single proof validates entire group
struct BatchClaimData {
/// @notice Packed data containing recipient address, claimable timestamp, and token index
uint256 packedRecipientTimeToken;
/// @notice Amount of tokens claimable
uint256 claimableAmount;
}
/// @title TokenTable Merkle Multitoken Distributor with Batched Claims
/// @notice A merkle-tree based token distributor supporting multiple tokens and batched claims
/// @dev Extends BaseMerkleDistributor with multi-token support and gas-optimized batch processing
/// @author TokenTable Team
contract TokenTableMerkleMultitokenDistributorBatched is BaseMerkleDistributor, MinimalPausable {
using SafeERC20 for IERC20;
/// @notice Array of supported tokens, where address(0) represents native ETH
address[] public tokens;
mapping(address => bool) public whitelist;
error OutsideClaimableTimeRange();
error ETHTransferFailed();
error IndividualClaimNotAllowed();
error InvalidTokenIndex();
error InvalidTimestamp();
error EmptyTokensArray();
error ClaimsAlreadyActive();
/// @notice Allows the contract to receive native ETH for distribution
receive() external payable { }
/// @notice Pauses all claim operations
/// @dev Only callable by the contract owner
function pause() external onlyOwner {
_pause();
}
/// @notice Unpauses all claim operations
/// @dev Only callable by the contract owner
function unpause() external onlyOwner {
_unpause();
}
/// @notice Sets the supported tokens for distribution
/// @dev Clears existing tokens and sets new ones. Can only be called before claims are active
/// @param _tokens Array of token addresses (use address(0) for native ETH)
function setTokens(address[] calldata _tokens) external onlyOwner {
if (_tokens.length == 0) revert EmptyTokensArray();
// Check if claims are already active (merkle root is set)
if (
_getBaseMerkleDistributorStorage().root != bytes32(0)
&& _getBaseMerkleDistributorStorage().startTime <= block.timestamp
) {
revert ClaimsAlreadyActive();
}
// Clear existing tokens and set new ones
tokens = new address[](_tokens.length);
for (uint256 i = 0; i < _tokens.length;) {
tokens[i] = _tokens[i];
unchecked {
++i;
}
}
}
function setWhitelist(address[] calldata addresses, bool status) external onlyOwner {
for (uint256 i = 0; i < addresses.length;) {
whitelist[addresses[i]] = status;
unchecked {
++i;
}
}
}
function batchClaimAdmin(
BatchClaimData[] calldata batchData,
bytes32[] calldata
)
external
virtual
onlyActive
whenNotPaused
nonReentrant
{
require(whitelist[msg.sender], Unauthorized());
BaseMerkleDistributorStorage storage $ = _getBaseMerkleDistributorStorage();
// Generate group hash from all claim parameters - this becomes our leaf directly
bytes32 leaf = generateGroupHash(batchData);
// Verify the group hash directly against the merkle tree with single proof
require(!$.usedLeafs[leaf], Unauthorized());
$.usedLeafs[leaf] = true;
// Process all claims in the group
for (uint256 i = 0; i < batchData.length;) {
BatchClaimData calldata claimData = batchData[i];
// Unpack the data
(address recipient, uint256 claimableTimestamp, uint256 tokenIndex) =
unpackRecipientTimeToken(claimData.packedRecipientTimeToken);
// Validate timestamp
if (claimableTimestamp > block.timestamp || claimableTimestamp < $.startTime) {
revert OutsideClaimableTimeRange();
}
// Send tokens
_sendByIndex(recipient, tokenIndex, claimData.claimableAmount);
unchecked {
++i;
}
}
}
/// @notice Individual claim function - disabled in favor of batch claims
/// @dev Always reverts as this contract only supports batch claiming
function claim(bytes32[] calldata, bytes32, bytes calldata, bytes calldata) external payable virtual override {
revert IndividualClaimNotAllowed();
}
/// @notice Withdraws tokens from the contract to the owner
/// @dev If extraData is empty, withdraws all registered tokens. Otherwise, withdraws specific token
/// @param extraData Optional encoded address of specific token to withdraw
function withdraw(bytes memory extraData) external virtual override onlyOwner {
if (extraData.length == 0) {
// Withdraw all registered tokens (including ETH if registered)
for (uint256 i = 0; i < tokens.length;) {
_withdrawByIndex(i);
unchecked {
++i;
}
}
} else {
// Withdraw specific token by address only
address tokenToWithdraw = abi.decode(extraData, (address));
_withdrawByAddress(tokenToWithdraw);
}
}
/// @notice Returns the array of supported token addresses
/// @return Array of token addresses, where address(0) represents native ETH
function getTokens() external view returns (address[] memory) {
return tokens;
}
/// @notice Sets the base distribution parameters
/// @dev Overrides base implementation to deprecate single token support
/// @param startTime When claiming becomes active
/// @param endTime When claiming ends
/// @param root Merkle root of the distribution tree
function setBaseParams(
address,
uint256 startTime,
uint256 endTime,
bytes32 root
)
public
virtual
override
onlyOwner
{
// Deprecate base token - always set to address(0)
super.setBaseParams(address(0), startTime, endTime, root);
}
/// @notice Packs recipient address, timestamp, and token index into a single uint256
/// @dev Bit layout: recipient(160) + timestamp(40) + tokenIndex(56) = 256 bits
/// @param recipient The address that can claim the tokens
/// @param claimableTimestamp When the tokens become claimable (max 2^40-1)
/// @param tokenIndex Index of the token in the tokens array (max 2^56-1)
/// @return Packed uint256 containing all three values
function packRecipientTimeToken(
address recipient,
uint256 claimableTimestamp,
uint256 tokenIndex
)
external
pure
returns (uint256)
{
if (claimableTimestamp >= (1 << 40)) revert InvalidTimestamp();
if (tokenIndex >= (1 << 56)) revert InvalidTokenIndex();
return uint256(uint160(recipient)) | (claimableTimestamp << 160) | (tokenIndex << 200);
}
/// @notice Unpacks recipient address, timestamp, and token index from a packed uint256
/// @dev Reverses the bit packing performed by packRecipientTimeToken
/// @param packed The packed uint256 value
/// @return recipient The address that can claim the tokens
/// @return claimableTimestamp When the tokens become claimable
/// @return tokenIndex Index of the token in the tokens array
function unpackRecipientTimeToken(uint256 packed)
public
pure
returns (address recipient, uint256 claimableTimestamp, uint256 tokenIndex)
{
recipient = address(uint160(packed));
claimableTimestamp = (packed >> 160) & ((1 << 40) - 1);
tokenIndex = packed >> 200;
}
/// @notice Generates a unique group hash from all claim parameters for off-chain integration
/// @param batchData Array of claim data to hash
/// @return Group hash derived from all claim parameters
function generateGroupHash(BatchClaimData[] calldata batchData) public pure returns (bytes32) {
return keccak256(abi.encode(batchData));
}
/// @notice Returns the version string of this contract
/// @return Version string combining base version with contract-specific identifier
function version() public pure virtual override returns (string memory) {
return string.concat(BaseMerkleDistributor.version(), "-TokenTableMerkleMultitokenDistributorBatched-Admin-2");
}
function _withdrawByIndex(uint256 tokenIndex) internal {
_withdrawToken(tokens[tokenIndex]);
}
function _withdrawByAddress(address tokenToWithdraw) internal {
_withdrawToken(tokenToWithdraw);
}
function _withdrawToken(address token) internal {
if (token == address(0)) {
// ETH withdrawal
uint256 balance = address(this).balance;
if (balance > 0) {
(bool success,) = payable(owner()).call{ value: balance }("");
if (!success) revert ETHTransferFailed();
}
} else {
// ERC20 withdrawal
IERC20 erc20Token = IERC20(token);
uint256 balance = erc20Token.balanceOf(address(this));
if (balance > 0) {
erc20Token.safeTransfer(owner(), balance);
}
}
}
function _verifyAndClaim(
address,
bytes32[] calldata,
bytes32,
bytes calldata
)
internal
virtual
override
returns (uint256)
{
// This function should not be used - only batchClaim is supported
revert IndividualClaimNotAllowed();
}
function _send(address, address, uint256) internal virtual override {
// This function should not be used - only _sendByIndex is supported
revert IndividualClaimNotAllowed();
}
function _sendByIndex(address recipient, uint256 tokenIndex, uint256 amount) internal {
address token = tokens[tokenIndex];
if (token == address(0)) {
// Native ETH transfer
(bool success,) = payable(recipient).call{ value: amount }("");
if (!success) revert ETHTransferFailed();
} else {
// ERC20 transfer
IERC20(token).safeTransfer(recipient, amount);
}
}
}// SPDX-License-Identifier: AGPL v3
pragma solidity ^0.8.24;
import { Ownable } from "solady/auth/Ownable.sol";
import { ReentrancyGuard } from "solady/utils/ReentrancyGuard.sol";
import { MerkleProofLib } from "solady/utils/MerkleProofLib.sol";
import { IVersionable } from "../../common/interfaces/IVersionable.sol";
import { IClaimHook } from "../interfaces/IClaimHook.sol";
import { ITTFeeCollector } from "../../common/interfaces/ITTFeeCollector.sol";
import { IERC20 } from "@openzeppelin-contracts/interfaces/IERC20.sol";
import { SafeERC20 } from "../../common/utils/MinimalSafeERC20.sol";
import { ITTADeployer } from "../../TTADeployer.sol";
import { Initializable } from "solady/utils/Initializable.sol";
import { ITTCreate3Initializable } from "../../common/interfaces/ITTCreate3Initializable.sol";
abstract contract BaseMerkleDistributor is
Initializable,
ITTCreate3Initializable,
Ownable,
ReentrancyGuard,
IVersionable
{
using MerkleProofLib for bytes32[];
using SafeERC20 for IERC20;
/// @custom:storage-location erc7201:ethsign.misc.BaseMerkleDistributor
struct BaseMerkleDistributorStorage {
mapping(bytes32 leaf => bool used) usedLeafs;
bytes32 root;
address deployer;
address token;
address claimDelegate;
uint256 startTime;
uint256 endTime;
address claimHook;
}
// keccak256(abi.encode(uint256(keccak256("ethsign.misc.BaseMerkleDistributor")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant BaseMerkleDistributorStorageLocation =
0x452bdf2c9fe836ad357e55ed0859c19d2ac2a2c151d216523e3d37a8b9a03f00;
event ClaimDelegateSet(address delegate);
event Claimed(address recipient, bytes32 group, bytes data);
error UnsupportedOperation();
error TimeInactive();
error InvalidProof();
error LeafUsed();
error IncorrectFees();
modifier onlyDelegate() {
require(msg.sender == _getBaseMerkleDistributorStorage().claimDelegate, Unauthorized());
_;
}
modifier onlyActive() {
if (
block.timestamp < _getBaseMerkleDistributorStorage().startTime
|| block.timestamp > _getBaseMerkleDistributorStorage().endTime
) revert TimeInactive();
_;
}
/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
if (block.chainid != 31_337) {
_disableInitializers();
}
}
function initialize(address owner_) public initializer {
_initializeOwner(owner_);
_getBaseMerkleDistributorStorage().deployer = msg.sender;
}
function setClaimDelegate(address delegate) external virtual onlyOwner {
_getBaseMerkleDistributorStorage().claimDelegate = delegate;
emit ClaimDelegateSet(delegate);
}
function claim(
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
bytes calldata extraData
)
external
payable
virtual
onlyActive
nonReentrant
{
_beforeClaim(msg.sender, proof, group, data, extraData);
uint256 claimedAmount = _verifyAndClaim(msg.sender, proof, group, data);
_afterClaim(msg.sender, proof, group, data, claimedAmount, extraData);
emit Claimed(msg.sender, group, data);
}
function delegateClaim(
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
bytes calldata extraData
)
public
payable
virtual
onlyDelegate
onlyActive
nonReentrant
{
_beforeDelegateClaim(msg.sender, recipient, proof, group, data, extraData);
uint256 claimedAmount = _verifyAndClaim(recipient, proof, group, data);
_afterDelegateClaim(msg.sender, recipient, proof, group, data, claimedAmount, extraData);
emit Claimed(recipient, group, data);
}
// solhint-disable no-empty-blocks
// solhint-disable ordering
function withdraw(bytes memory extraData) external virtual;
function getClaimDelegate() external view returns (address) {
return _getBaseMerkleDistributorStorage().claimDelegate;
}
function getRoot() external view returns (bytes32) {
return _getBaseMerkleDistributorStorage().root;
}
function getTime() external view returns (uint256, uint256) {
return (_getBaseMerkleDistributorStorage().startTime, _getBaseMerkleDistributorStorage().endTime);
}
function getToken() external view returns (address) {
return _getBaseMerkleDistributorStorage().token;
}
function getDeployer() external view returns (address) {
return _getBaseMerkleDistributorStorage().deployer;
}
function getClaimHook() external view returns (address) {
return _getBaseMerkleDistributorStorage().claimHook;
}
function version() public pure virtual returns (string memory) {
return "0.4.5";
}
function setBaseParams(address token, uint256 startTime, uint256 endTime, bytes32 root) public virtual onlyOwner {
if (startTime >= endTime) revert UnsupportedOperation();
_getBaseMerkleDistributorStorage().token = token;
_getBaseMerkleDistributorStorage().startTime = startTime;
_getBaseMerkleDistributorStorage().endTime = endTime;
_getBaseMerkleDistributorStorage().root = root;
}
function setClaimHook(address hook) public virtual onlyOwner {
_getBaseMerkleDistributorStorage().claimHook = hook;
}
function encodeLeaf(address user, bytes32 group, bytes memory data) public view virtual returns (bytes32) {
return keccak256(abi.encode(block.chainid, address(this), user, group, data));
}
function verify(bytes32[] calldata proof, bytes32 leaf) public view virtual {
if (isLeafUsed(leaf)) revert LeafUsed();
if (!proof.verifyCalldata(_getBaseMerkleDistributorStorage().root, leaf)) revert InvalidProof();
}
function isLeafUsed(bytes32 leaf) public view virtual returns (bool) {
return _getBaseMerkleDistributorStorage().usedLeafs[leaf];
}
function _verifyAndClaim(
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data
)
internal
virtual
returns (uint256 claimedAmount);
function _send(address recipient, address token, uint256 amount) internal virtual;
function _chargeFees(address payer, uint256 claimedAmount) internal virtual {
BaseMerkleDistributorStorage storage $ = _getBaseMerkleDistributorStorage();
ITTADeployer deployer = ITTADeployer($.deployer);
address feeCollector = deployer.feeCollectors(address(this));
if (feeCollector == address(0)) {
if (msg.value > 0) revert IncorrectFees();
return;
}
uint256 amountToCharge = ITTFeeCollector(feeCollector).getFee(address(this), claimedAmount);
if (amountToCharge == 0) {
if (msg.value > 0) revert IncorrectFees();
return;
}
address feeToken = deployer.feeTokens(address(this));
if (feeToken == address(0)) {
if (msg.value != amountToCharge) revert IncorrectFees();
(bool success, bytes memory data) = feeCollector.call{ value: amountToCharge }("");
// solhint-disable-next-line custom-errors
require(success, string(data));
} else {
if (msg.value > 0) revert IncorrectFees();
IERC20(feeToken).safeTransferFrom(payer, feeCollector, amountToCharge);
}
}
function _beforeClaim(
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
bytes calldata extraData
)
internal
virtual
{
_tryCallClaimHook(address(0), recipient, proof, group, data, 0, true, extraData);
}
function _afterClaim(
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
uint256 claimedAmount,
bytes calldata extraData
)
internal
virtual
{
_tryCallClaimHook(address(0), recipient, proof, group, data, claimedAmount, false, extraData);
_chargeFees(recipient, claimedAmount);
}
function _beforeDelegateClaim(
address delegate,
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
bytes calldata extraData
)
internal
virtual
{
_tryCallClaimHook(delegate, recipient, proof, group, data, 0, true, extraData);
}
function _afterDelegateClaim(
address delegate,
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
uint256 claimedAmount,
bytes calldata extraData
)
internal
virtual
{
_tryCallClaimHook(delegate, recipient, proof, group, data, claimedAmount, false, extraData);
_chargeFees(delegate, claimedAmount);
}
function _getBaseMerkleDistributorStorage() internal pure returns (BaseMerkleDistributorStorage storage $) {
assembly {
$.slot := BaseMerkleDistributorStorageLocation
}
}
function _tryCallClaimHook(
address delegate,
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
uint256 claimedAmount,
bool isBeforeClaim,
bytes calldata extraData
)
private
{
address claimHook = _getBaseMerkleDistributorStorage().claimHook;
if (claimHook != address(0)) {
isBeforeClaim
? IClaimHook(claimHook).beforeClaim(delegate, recipient, proof, group, data, extraData)
: IClaimHook(claimHook).afterClaim(delegate, recipient, proof, group, data, claimedAmount, extraData);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../token/ERC20/IERC20.sol";// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
// Minimized by Jack @ Sign
pragma solidity ^0.8.20;
import { IERC20 } from "@openzeppelin-contracts/interfaces/IERC20.sol";
library SafeERC20 {
error SafeERC20FailedOperation(address token);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
// bubble errors
if iszero(success) {
let ptr := mload(0x40)
returndatacopy(ptr, 0, returndatasize())
revert(ptr, returndatasize())
}
returnSize := returndatasize()
returnValue := mload(0)
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
revert SafeERC20FailedOperation(address(token));
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.29;
abstract contract MinimalPausable {
/// @custom:storage-location erc7201:sign.utils.MinimalPausable
struct PausableStorage {
bool _paused;
}
// keccak256(abi.encode(uint256(keccak256("sign.utils.MinimalPausable")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant PausableStorageLocation =
0x159a745eaf9f69c9f8685f5357fc5c3fc24330eca10f86813ccbd1db89bdb000;
function _getPausableStorage() private pure returns (PausableStorage storage $) {
assembly {
$.slot := PausableStorageLocation
}
}
error Paused();
error NotPaused();
modifier whenNotPaused() {
_requireNotPaused();
_;
}
modifier whenPaused() {
_requirePaused();
_;
}
function paused() public view virtual returns (bool) {
PausableStorage storage $ = _getPausableStorage();
return $._paused;
}
function _requireNotPaused() internal view virtual {
if (paused()) {
revert Paused();
}
}
function _requirePaused() internal view virtual {
if (!paused()) {
revert NotPaused();
}
}
function _pause() internal virtual whenNotPaused {
PausableStorage storage $ = _getPausableStorage();
$._paused = true;
}
function _unpause() internal virtual whenPaused {
PausableStorage storage $ = _getPausableStorage();
$._paused = false;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
revert(0x1c, 0x04)
}
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(_OWNER_SLOT, newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(_OWNER_SLOT)
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Reentrancy guard mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unauthorized reentrant call.
error Reentrancy();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Equivalent to: `uint72(bytes9(keccak256("_REENTRANCY_GUARD_SLOT")))`.
/// 9 bytes is large enough to avoid collisions with lower slots,
/// but not too large to result in excessive bytecode bloat.
uint256 private constant _REENTRANCY_GUARD_SLOT = 0x929eee149b4bd21268;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* REENTRANCY GUARD */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Guards a function from reentrancy.
modifier nonReentrant() virtual {
/// @solidity memory-safe-assembly
assembly {
if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
mstore(0x00, 0xab143c06) // `Reentrancy()`.
revert(0x1c, 0x04)
}
sstore(_REENTRANCY_GUARD_SLOT, address())
}
_;
/// @solidity memory-safe-assembly
assembly {
sstore(_REENTRANCY_GUARD_SLOT, codesize())
}
}
/// @dev Guards a view function from read-only reentrancy.
modifier nonReadReentrant() virtual {
/// @solidity memory-safe-assembly
assembly {
if eq(sload(_REENTRANCY_GUARD_SLOT), address()) {
mstore(0x00, 0xab143c06) // `Reentrancy()`.
revert(0x1c, 0x04)
}
}
_;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Gas optimized verification of proof of inclusion for a leaf in a Merkle tree.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/MerkleProof.sol)
library MerkleProofLib {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MERKLE PROOF VERIFICATION OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf)
internal
pure
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
if mload(proof) {
// Initialize `offset` to the offset of `proof` elements in memory.
let offset := add(proof, 0x20)
// Left shift by 5 is equivalent to multiplying by 0x20.
let end := add(offset, shl(5, mload(proof)))
// Iterate over proof elements to compute root hash.
for {} 1 {} {
// Slot of `leaf` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(leaf, mload(offset)))
// Store elements to hash contiguously in scratch space.
// Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
mstore(scratch, leaf)
mstore(xor(scratch, 0x20), mload(offset))
// Reuse `leaf` to store the hash to reduce stack operations.
leaf := keccak256(0x00, 0x40)
offset := add(offset, 0x20)
if iszero(lt(offset, end)) { break }
}
}
isValid := eq(leaf, root)
}
}
/// @dev Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`.
function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf)
internal
pure
returns (bool isValid)
{
/// @solidity memory-safe-assembly
assembly {
if proof.length {
// Left shift by 5 is equivalent to multiplying by 0x20.
let end := add(proof.offset, shl(5, proof.length))
// Initialize `offset` to the offset of `proof` in the calldata.
let offset := proof.offset
// Iterate over proof elements to compute root hash.
for {} 1 {} {
// Slot of `leaf` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(leaf, calldataload(offset)))
// Store elements to hash contiguously in scratch space.
// Scratch space is 64 bytes (0x00 - 0x3f) and both elements are 32 bytes.
mstore(scratch, leaf)
mstore(xor(scratch, 0x20), calldataload(offset))
// Reuse `leaf` to store the hash to reduce stack operations.
leaf := keccak256(0x00, 0x40)
offset := add(offset, 0x20)
if iszero(lt(offset, end)) { break }
}
}
isValid := eq(leaf, root)
}
}
/// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
/// given `proof` and `flags`.
///
/// Note:
/// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
/// will always return false.
/// - The sum of the lengths of `proof` and `leaves` must never overflow.
/// - Any non-zero word in the `flags` array is treated as true.
/// - The memory offset of `proof` must be non-zero
/// (i.e. `proof` is not pointing to the scratch space).
function verifyMultiProof(
bytes32[] memory proof,
bytes32 root,
bytes32[] memory leaves,
bool[] memory flags
) internal pure returns (bool isValid) {
// Rebuilds the root by consuming and producing values on a queue.
// The queue starts with the `leaves` array, and goes into a `hashes` array.
// After the process, the last element on the queue is verified
// to be equal to the `root`.
//
// The `flags` array denotes whether the sibling
// should be popped from the queue (`flag == true`), or
// should be popped from the `proof` (`flag == false`).
/// @solidity memory-safe-assembly
assembly {
// Cache the lengths of the arrays.
let leavesLength := mload(leaves)
let proofLength := mload(proof)
let flagsLength := mload(flags)
// Advance the pointers of the arrays to point to the data.
leaves := add(0x20, leaves)
proof := add(0x20, proof)
flags := add(0x20, flags)
// If the number of flags is correct.
for {} eq(add(leavesLength, proofLength), add(flagsLength, 1)) {} {
// For the case where `proof.length + leaves.length == 1`.
if iszero(flagsLength) {
// `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
isValid := eq(mload(xor(leaves, mul(xor(proof, leaves), proofLength))), root)
break
}
// The required final proof offset if `flagsLength` is not zero, otherwise zero.
let proofEnd := add(proof, shl(5, proofLength))
// We can use the free memory space for the queue.
// We don't need to allocate, since the queue is temporary.
let hashesFront := mload(0x40)
// Copy the leaves into the hashes.
// Sometimes, a little memory expansion costs less than branching.
// Should cost less, even with a high free memory offset of 0x7d00.
leavesLength := shl(5, leavesLength)
for { let i := 0 } iszero(eq(i, leavesLength)) { i := add(i, 0x20) } {
mstore(add(hashesFront, i), mload(add(leaves, i)))
}
// Compute the back of the hashes.
let hashesBack := add(hashesFront, leavesLength)
// This is the end of the memory for the queue.
// We recycle `flagsLength` to save on stack variables (sometimes save gas).
flagsLength := add(hashesBack, shl(5, flagsLength))
for {} 1 {} {
// Pop from `hashes`.
let a := mload(hashesFront)
// Pop from `hashes`.
let b := mload(add(hashesFront, 0x20))
hashesFront := add(hashesFront, 0x40)
// If the flag is false, load the next proof,
// else, pops from the queue.
if iszero(mload(flags)) {
// Loads the next proof.
b := mload(proof)
proof := add(proof, 0x20)
// Unpop from `hashes`.
hashesFront := sub(hashesFront, 0x20)
}
// Advance to the next flag.
flags := add(flags, 0x20)
// Slot of `a` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(a, b))
// Hash the scratch space and push the result onto the queue.
mstore(scratch, a)
mstore(xor(scratch, 0x20), b)
mstore(hashesBack, keccak256(0x00, 0x40))
hashesBack := add(hashesBack, 0x20)
if iszero(lt(hashesBack, flagsLength)) { break }
}
isValid :=
and(
// Checks if the last value in the queue is same as the root.
eq(mload(sub(hashesBack, 0x20)), root),
// And whether all the proofs are used, if required.
eq(proofEnd, proof)
)
break
}
}
}
/// @dev Returns whether all `leaves` exist in the Merkle tree with `root`,
/// given `proof` and `flags`.
///
/// Note:
/// - Breaking the invariant `flags.length == (leaves.length - 1) + proof.length`
/// will always return false.
/// - Any non-zero word in the `flags` array is treated as true.
/// - The calldata offset of `proof` must be non-zero
/// (i.e. `proof` is from a regular Solidity function with a 4-byte selector).
function verifyMultiProofCalldata(
bytes32[] calldata proof,
bytes32 root,
bytes32[] calldata leaves,
bool[] calldata flags
) internal pure returns (bool isValid) {
// Rebuilds the root by consuming and producing values on a queue.
// The queue starts with the `leaves` array, and goes into a `hashes` array.
// After the process, the last element on the queue is verified
// to be equal to the `root`.
//
// The `flags` array denotes whether the sibling
// should be popped from the queue (`flag == true`), or
// should be popped from the `proof` (`flag == false`).
/// @solidity memory-safe-assembly
assembly {
// If the number of flags is correct.
for {} eq(add(leaves.length, proof.length), add(flags.length, 1)) {} {
// For the case where `proof.length + leaves.length == 1`.
if iszero(flags.length) {
// `isValid = (proof.length == 1 ? proof[0] : leaves[0]) == root`.
// forgefmt: disable-next-item
isValid := eq(
calldataload(
xor(leaves.offset, mul(xor(proof.offset, leaves.offset), proof.length))
),
root
)
break
}
// The required final proof offset if `flagsLength` is not zero, otherwise zero.
let proofEnd := add(proof.offset, shl(5, proof.length))
// We can use the free memory space for the queue.
// We don't need to allocate, since the queue is temporary.
let hashesFront := mload(0x40)
// Copy the leaves into the hashes.
// Sometimes, a little memory expansion costs less than branching.
// Should cost less, even with a high free memory offset of 0x7d00.
calldatacopy(hashesFront, leaves.offset, shl(5, leaves.length))
// Compute the back of the hashes.
let hashesBack := add(hashesFront, shl(5, leaves.length))
// This is the end of the memory for the queue.
// We recycle `flagsLength` to save on stack variables (sometimes save gas).
flags.length := add(hashesBack, shl(5, flags.length))
// We don't need to make a copy of `proof.offset` or `flags.offset`,
// as they are pass-by-value (this trick may not always save gas).
for {} 1 {} {
// Pop from `hashes`.
let a := mload(hashesFront)
// Pop from `hashes`.
let b := mload(add(hashesFront, 0x20))
hashesFront := add(hashesFront, 0x40)
// If the flag is false, load the next proof,
// else, pops from the queue.
if iszero(calldataload(flags.offset)) {
// Loads the next proof.
b := calldataload(proof.offset)
proof.offset := add(proof.offset, 0x20)
// Unpop from `hashes`.
hashesFront := sub(hashesFront, 0x20)
}
// Advance to the next flag offset.
flags.offset := add(flags.offset, 0x20)
// Slot of `a` in scratch space.
// If the condition is true: 0x20, otherwise: 0x00.
let scratch := shl(5, gt(a, b))
// Hash the scratch space and push the result onto the queue.
mstore(scratch, a)
mstore(xor(scratch, 0x20), b)
mstore(hashesBack, keccak256(0x00, 0x40))
hashesBack := add(hashesBack, 0x20)
if iszero(lt(hashesBack, flags.length)) { break }
}
isValid :=
and(
// Checks if the last value in the queue is same as the root.
eq(mload(sub(hashesBack, 0x20)), root),
// And whether all the proofs are used, if required.
eq(proofEnd, proof.offset)
)
break
}
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes32 array.
function emptyProof() internal pure returns (bytes32[] calldata proof) {
/// @solidity memory-safe-assembly
assembly {
proof.length := 0
}
}
/// @dev Returns an empty calldata bytes32 array.
function emptyLeaves() internal pure returns (bytes32[] calldata leaves) {
/// @solidity memory-safe-assembly
assembly {
leaves.length := 0
}
}
/// @dev Returns an empty calldata bool array.
function emptyFlags() internal pure returns (bool[] calldata flags) {
/// @solidity memory-safe-assembly
assembly {
flags.length := 0
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title IVersionable
* @author Jack Xu @ EthSign
* @dev This interface is implemented by all major TokenTable contracts to keep track of their versioning for upgrade
* compatibility checks.
*/
interface IVersionable {
function version() external pure returns (string memory);
}// SPDX-License-Identifier: AGPL v3
pragma solidity ^0.8.24;
interface IClaimHook {
function beforeClaim(
address delegate,
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
bytes calldata extraData
)
external;
function afterClaim(
address delegate,
address recipient,
bytes32[] calldata proof,
bytes32 group,
bytes calldata data,
uint256 claimedAmount,
bytes calldata extraData
)
external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title ITTFeeCollector
* @author Jack Xu @ Sign
* @dev This contract handles TokenTable service fee calculation.
*/
interface ITTFeeCollector {
event DefaultFeeSetBips(uint256 bips);
event DefaultFeeSet(uint256 fee);
event CustomFeeSetBips(address unlockerAddress, uint256 bips);
event CustomFeeSetFixed(address unlockerAddress, uint256 fixedFee);
/**
* @dev 0xc9034e18
*/
error FeesTooHigh();
/**
* @notice Returns the amount of fees to collect. A fixed fee will always override a dynamic fee.
* @param unlockerAddress The address of the Unlocker (or any contract that uses the fee collector). Used to fetch
* pricing.
* @param tokenTransferred The number of tokens transferred.
* @return tokensCollected The number of tokens to collect as fees.
*/
function getFee(
address unlockerAddress,
uint256 tokenTransferred
)
external
view
returns (uint256 tokensCollected);
/**
* @notice Returns the fee token address.
* @param unlockerAddress The address of the Unlocker (or any contract that uses the fee collector). Used to fetch
* pricing.
*/
function getFeeToken(address unlockerAddress) external view returns (address tokenAddress);
}// SPDX-License-Identifier: AGPL v3
pragma solidity ^0.8.24;
import { Ownable } from "solady/auth/Ownable.sol";
import { LibClone } from "solady/utils/LibClone.sol";
import { IVersionable } from "./common/interfaces/IVersionable.sol";
import { ITTFeeCollector } from "./common/interfaces/ITTFeeCollector.sol";
import { Initializable } from "solady/utils/Initializable.sol";
import { ITTCreate3Initializable } from "./common/interfaces/ITTCreate3Initializable.sol";
interface ITTADeployer {
function feeTokens(address deployment) external view returns (address);
function feeCollectors(address deployment) external view returns (address);
}
// solhint-disable max-line-length
contract TTADeployer is ITTADeployer, ITTCreate3Initializable, Ownable, IVersionable, Initializable {
address public defaultFeeCollector;
mapping(string projectId => address deployment) public deployments;
mapping(uint8 mdType => address implementation) public implementations;
mapping(address deployment => address feeCollectors) internal _feeCollectors;
event DidDeploy(uint8 mdType, string projectId, address instance);
error UnsupportedOperation();
function initialize(address newOwner) external initializer {
_setOwner(newOwner);
}
function setDefaultFeeParams(address feeCollector) external onlyOwner {
defaultFeeCollector = feeCollector;
}
function setDeploymentFeeParams(address deployment, address feeCollector) external onlyOwner {
_feeCollectors[deployment] = feeCollector;
}
function setImplementation(uint8 mdType, address implementation) external onlyOwner {
implementations[mdType] = implementation;
}
function deploy(uint8 mdType, string calldata projectId) external returns (address instance) {
if (deployments[projectId] != address(0)) revert UnsupportedOperation();
instance = LibClone.cloneDeterministic(implementations[mdType], keccak256(abi.encode(projectId)));
ITTCreate3Initializable(instance).initialize(msg.sender);
deployments[projectId] = instance;
emit DidDeploy(mdType, projectId, instance);
}
function simulateDeploy(uint8 mdType, string calldata projectId) external view returns (address) {
return LibClone.predictDeterministicAddress(
implementations[mdType], keccak256(abi.encode(projectId)), address(this)
);
}
function feeTokens(address deployment) external view returns (address) {
return ITTFeeCollector(feeCollectors(deployment)).getFeeToken(deployment);
}
function version() external pure override returns (string memory) {
return "0.5.4-TTADeployer";
}
function feeCollectors(address deployment) public view returns (address) {
return _feeCollectors[deployment] == address(0) ? defaultFeeCollector : _feeCollectors[deployment];
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Initializable mixin for the upgradeable contracts.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/Initializable.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/proxy/utils/Initializable.sol)
abstract contract Initializable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The contract is already initialized.
error InvalidInitialization();
/// @dev The contract is not initializing.
error NotInitializing();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Triggered when the contract has been initialized.
event Initialized(uint64 version);
/// @dev `keccak256(bytes("Initialized(uint64)"))`.
bytes32 private constant _INITIALIZED_EVENT_SIGNATURE =
0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The default initializable slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_INITIALIZABLE_SLOT")))))`.
///
/// Bits Layout:
/// - [0] `initializing`
/// - [1..64] `initializedVersion`
bytes32 private constant _INITIALIZABLE_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf601132;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTRUCTOR */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
constructor() {
// Construction time check to ensure that `_initializableSlot()` is not
// overridden to zero. Will be optimized away if there is no revert.
require(_initializableSlot() != bytes32(0));
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return a non-zero custom storage slot if required.
function _initializableSlot() internal pure virtual returns (bytes32) {
return _INITIALIZABLE_SLOT;
}
/// @dev Guards an initializer function so that it can be invoked at most once.
///
/// You can guard a function with `onlyInitializing` such that it can be called
/// through a function guarded with `initializer`.
///
/// This is similar to `reinitializer(1)`, except that in the context of a constructor,
/// an `initializer` guarded function can be invoked multiple times.
/// This can be useful during testing and is not expected to be used in production.
///
/// Emits an {Initialized} event.
modifier initializer() virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
let i := sload(s)
// Set `initializing` to 1, `initializedVersion` to 1.
sstore(s, 3)
// If `!(initializing == 0 && initializedVersion == 0)`.
if i {
// If `!(address(this).code.length == 0 && initializedVersion == 1)`.
if iszero(lt(extcodesize(address()), eq(shr(1, i), 1))) {
mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`.
revert(0x1c, 0x04)
}
s := shl(shl(255, i), s) // Skip initializing if `initializing == 1`.
}
}
_;
/// @solidity memory-safe-assembly
assembly {
if s {
// Set `initializing` to 0, `initializedVersion` to 1.
sstore(s, 2)
// Emit the {Initialized} event.
mstore(0x20, 1)
log1(0x20, 0x20, _INITIALIZED_EVENT_SIGNATURE)
}
}
}
/// @dev Guards a reinitializer function so that it can be invoked at most once.
///
/// You can guard a function with `onlyInitializing` such that it can be called
/// through a function guarded with `reinitializer`.
///
/// Emits an {Initialized} event.
modifier reinitializer(uint64 version) virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
// Clean upper bits, and shift left by 1 to make space for the initializing bit.
version := shl(1, and(version, 0xffffffffffffffff))
let i := sload(s)
// If `initializing == 1 || initializedVersion >= version`.
if iszero(lt(and(i, 1), lt(i, version))) {
mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`.
revert(0x1c, 0x04)
}
// Set `initializing` to 1, `initializedVersion` to `version`.
sstore(s, or(1, version))
}
_;
/// @solidity memory-safe-assembly
assembly {
// Set `initializing` to 0, `initializedVersion` to `version`.
sstore(s, version)
// Emit the {Initialized} event.
mstore(0x20, shr(1, version))
log1(0x20, 0x20, _INITIALIZED_EVENT_SIGNATURE)
}
}
/// @dev Guards a function such that it can only be called in the scope
/// of a function guarded with `initializer` or `reinitializer`.
modifier onlyInitializing() virtual {
_checkInitializing();
_;
}
/// @dev Reverts if the contract is not initializing.
function _checkInitializing() internal view virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
if iszero(and(1, sload(s))) {
mstore(0x00, 0xd7e6bcf8) // `NotInitializing()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Locks any future initializations by setting the initialized version to `2**64 - 1`.
///
/// Calling this in the constructor will prevent the contract from being initialized
/// or reinitialized. 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 called.
function _disableInitializers() internal virtual {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
let i := sload(s)
if and(i, 1) {
mstore(0x00, 0xf92ee8a9) // `InvalidInitialization()`.
revert(0x1c, 0x04)
}
let uint64max := 0xffffffffffffffff
if iszero(eq(shr(1, i), uint64max)) {
// Set `initializing` to 0, `initializedVersion` to `2**64 - 1`.
sstore(s, shl(1, uint64max))
// Emit the {Initialized} event.
mstore(0x20, uint64max)
log1(0x20, 0x20, _INITIALIZED_EVENT_SIGNATURE)
}
}
}
/// @dev Returns the highest version that has been initialized.
function _getInitializedVersion() internal view virtual returns (uint64 version) {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
version := shr(1, sload(s))
}
}
/// @dev Returns whether the contract is currently initializing.
function _isInitializing() internal view virtual returns (bool result) {
bytes32 s = _initializableSlot();
/// @solidity memory-safe-assembly
assembly {
result := and(1, sload(s))
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title ITTCreate3Initializable
* @author Jack Xu @ Sign
* @dev This interface enforces an initializer for contracts that are directly deployed by Create3.
*/
interface ITTCreate3Initializable {
function initialize(address owner) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Minimal proxy library.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol)
/// @author Minimal proxy by 0age (https://github.com/0age)
/// @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie
/// (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args)
/// @author Minimal ERC1967 proxy by jtriley-eth (https://github.com/jtriley-eth/minimum-viable-proxy)
///
/// @dev Minimal proxy:
/// Although the sw0nt pattern saves 5 gas over the ERC1167 pattern during runtime,
/// it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern,
/// which saves 4 gas over the ERC1167 pattern during runtime, and has the smallest bytecode.
/// - Automatically verified on Etherscan.
///
/// @dev Minimal proxy (PUSH0 variant):
/// This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai.
/// It is optimized first for minimal runtime gas, then for minimal bytecode.
/// The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as
/// many EVM chains may not support the PUSH0 opcode in the early months after Shanghai.
/// Please use with caution.
/// - Automatically verified on Etherscan.
///
/// @dev Clones with immutable args (CWIA):
/// The implementation of CWIA here does NOT append the immutable args into the calldata
/// passed into delegatecall. It is simply an ERC1167 minimal proxy with the immutable arguments
/// appended to the back of the runtime bytecode.
/// - Uses the identity precompile (0x4) to copy args during deployment.
///
/// @dev Minimal ERC1967 proxy:
/// A minimal ERC1967 proxy, intended to be upgraded with UUPS.
/// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.
/// - Automatically verified on Etherscan.
///
/// @dev Minimal ERC1967 proxy with immutable args:
/// - Uses the identity precompile (0x4) to copy args during deployment.
/// - Automatically verified on Etherscan.
///
/// @dev ERC1967I proxy:
/// A variant of the minimal ERC1967 proxy, with a special code path that activates
/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
/// `implementation` address. The returned implementation is guaranteed to be valid if the
/// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.
///
/// @dev ERC1967I proxy with immutable args:
/// A variant of the minimal ERC1967 proxy, with a special code path that activates
/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
/// - Uses the identity precompile (0x4) to copy args during deployment.
///
/// @dev Minimal ERC1967 beacon proxy:
/// A minimal beacon proxy, intended to be upgraded with an upgradable beacon.
/// - Automatically verified on Etherscan.
///
/// @dev Minimal ERC1967 beacon proxy with immutable args:
/// - Uses the identity precompile (0x4) to copy args during deployment.
/// - Automatically verified on Etherscan.
///
/// @dev ERC1967I beacon proxy:
/// A variant of the minimal ERC1967 beacon proxy, with a special code path that activates
/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
/// `implementation` address. The returned implementation is guaranteed to be valid if the
/// keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`.
///
/// @dev ERC1967I proxy with immutable args:
/// A variant of the minimal ERC1967 beacon proxy, with a special code path that activates
/// if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the
/// - Uses the identity precompile (0x4) to copy args during deployment.
library LibClone {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The keccak256 of deployed code for the clone proxy,
/// with the implementation set to `address(0)`.
bytes32 internal constant CLONE_CODE_HASH =
0x48db2cfdb2853fce0b464f1f93a1996469459df3ab6c812106074c4106a1eb1f;
/// @dev The keccak256 of deployed code for the PUSH0 proxy,
/// with the implementation set to `address(0)`.
bytes32 internal constant PUSH0_CLONE_CODE_HASH =
0x67bc6bde1b84d66e267c718ba44cf3928a615d29885537955cb43d44b3e789dc;
/// @dev The keccak256 of deployed code for the ERC-1167 CWIA proxy,
/// with the implementation set to `address(0)`.
bytes32 internal constant CWIA_CODE_HASH =
0x3cf92464268225a4513da40a34d967354684c32cd0edd67b5f668dfe3550e940;
/// @dev The keccak256 of the deployed code for the ERC1967 proxy.
bytes32 internal constant ERC1967_CODE_HASH =
0xaaa52c8cc8a0e3fd27ce756cc6b4e70c51423e9b597b11f32d3e49f8b1fc890d;
/// @dev The keccak256 of the deployed code for the ERC1967I proxy.
bytes32 internal constant ERC1967I_CODE_HASH =
0xce700223c0d4cea4583409accfc45adac4a093b3519998a9cbbe1504dadba6f7;
/// @dev The keccak256 of the deployed code for the ERC1967 beacon proxy.
bytes32 internal constant ERC1967_BEACON_PROXY_CODE_HASH =
0x14044459af17bc4f0f5aa2f658cb692add77d1302c29fe2aebab005eea9d1162;
/// @dev The keccak256 of the deployed code for the ERC1967 beacon proxy.
bytes32 internal constant ERC1967I_BEACON_PROXY_CODE_HASH =
0xf8c46d2793d5aa984eb827aeaba4b63aedcab80119212fce827309788735519a;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unable to deploy the clone.
error DeploymentFailed();
/// @dev The salt must start with either the zero address or `by`.
error SaltDoesNotStartWith();
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL PROXY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a clone of `implementation`.
function clone(address implementation) internal returns (address instance) {
instance = clone(0, implementation);
}
/// @dev Deploys a clone of `implementation`.
/// Deposits `value` ETH during deployment.
function clone(uint256 value, address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
/**
* --------------------------------------------------------------------------+
* CREATION (9 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* --------------------------------------------------------------------------|
* RUNTIME (44 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* |
* ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | |
* 3d | RETURNDATASIZE | 0 0 | |
* 3d | RETURNDATASIZE | 0 0 0 | |
* 3d | RETURNDATASIZE | 0 0 0 0 | |
* |
* ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 0 0 | |
* 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | |
* 3d | RETURNDATASIZE | 0 0 cds 0 0 0 0 | |
* 37 | CALLDATACOPY | 0 0 0 0 | [0..cds): calldata |
* |
* ::: delegate call to the implementation contract :::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |
* 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |
* 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |
* f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |
* |
* ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata |
* 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata |
* 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata |
* 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata |
* |
* 60 0x2a | PUSH1 0x2a | 0x2a success 0 rds | [0..rds): returndata |
* 57 | JUMPI | 0 rds | [0..rds): returndata |
* |
* ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* fd | REVERT | | [0..rds): returndata |
* |
* ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | 0 rds | [0..rds): returndata |
* f3 | RETURN | | [0..rds): returndata |
* --------------------------------------------------------------------------+
*/
mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
mstore(0x14, implementation)
mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
instance := create(value, 0x0c, 0x35)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Deploys a deterministic clone of `implementation` with `salt`.
function cloneDeterministic(address implementation, bytes32 salt)
internal
returns (address instance)
{
instance = cloneDeterministic(0, implementation, salt);
}
/// @dev Deploys a deterministic clone of `implementation` with `salt`.
/// Deposits `value` ETH during deployment.
function cloneDeterministic(uint256 value, address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
mstore(0x14, implementation)
mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
instance := create2(value, 0x0c, 0x35, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the clone of `implementation`.
function initCode(address implementation) internal pure returns (bytes memory c) {
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x40), 0x5af43d3d93803e602a57fd5bf30000000000000000000000)
mstore(add(c, 0x28), implementation)
mstore(add(c, 0x14), 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
mstore(c, 0x35) // Store the length.
mstore(0x40, add(c, 0x60)) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the clone of `implementation`.
function initCodeHash(address implementation) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x21, 0x5af43d3d93803e602a57fd5bf3)
mstore(0x14, implementation)
mstore(0x00, 0x602c3d8160093d39f33d3d3d3d363d3d37363d73)
hash := keccak256(0x0c, 0x35)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the address of the clone of `implementation`, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddress(address implementation, bytes32 salt, address deployer)
internal
pure
returns (address predicted)
{
bytes32 hash = initCodeHash(implementation);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL PROXY OPERATIONS (PUSH0 VARIANT) */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a PUSH0 clone of `implementation`.
function clone_PUSH0(address implementation) internal returns (address instance) {
instance = clone_PUSH0(0, implementation);
}
/// @dev Deploys a PUSH0 clone of `implementation`.
/// Deposits `value` ETH during deployment.
function clone_PUSH0(uint256 value, address implementation)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
/**
* --------------------------------------------------------------------------+
* CREATION (9 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 5f | PUSH0 | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 5f | PUSH0 | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* --------------------------------------------------------------------------|
* RUNTIME (45 bytes) |
* --------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* --------------------------------------------------------------------------|
* |
* ::: keep some values in stack ::::::::::::::::::::::::::::::::::::::::::: |
* 5f | PUSH0 | 0 | |
* 5f | PUSH0 | 0 0 | |
* |
* ::: copy calldata to memory ::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 | |
* 5f | PUSH0 | 0 cds 0 0 | |
* 5f | PUSH0 | 0 0 cds 0 0 | |
* 37 | CALLDATACOPY | 0 0 | [0..cds): calldata |
* |
* ::: delegate call to the implementation contract :::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds 0 0 | [0..cds): calldata |
* 5f | PUSH0 | 0 cds 0 0 | [0..cds): calldata |
* 73 addr | PUSH20 addr | addr 0 cds 0 0 | [0..cds): calldata |
* 5a | GAS | gas addr 0 cds 0 0 | [0..cds): calldata |
* f4 | DELEGATECALL | success | [0..cds): calldata |
* |
* ::: copy return data to memory :::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds success | [0..cds): calldata |
* 5f | PUSH0 | 0 rds success | [0..cds): calldata |
* 5f | PUSH0 | 0 0 rds success | [0..cds): calldata |
* 3e | RETURNDATACOPY | success | [0..rds): returndata |
* |
* 60 0x29 | PUSH1 0x29 | 0x29 success | [0..rds): returndata |
* 57 | JUMPI | | [0..rds): returndata |
* |
* ::: revert :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds | [0..rds): returndata |
* 5f | PUSH0 | 0 rds | [0..rds): returndata |
* fd | REVERT | | [0..rds): returndata |
* |
* ::: return :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | [0..rds): returndata |
* 3d | RETURNDATASIZE | rds | [0..rds): returndata |
* 5f | PUSH0 | 0 rds | [0..rds): returndata |
* f3 | RETURN | | [0..rds): returndata |
* --------------------------------------------------------------------------+
*/
mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
mstore(0x14, implementation) // 20
mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
instance := create(value, 0x0e, 0x36)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
function cloneDeterministic_PUSH0(address implementation, bytes32 salt)
internal
returns (address instance)
{
instance = cloneDeterministic_PUSH0(0, implementation, salt);
}
/// @dev Deploys a deterministic PUSH0 clone of `implementation` with `salt`.
/// Deposits `value` ETH during deployment.
function cloneDeterministic_PUSH0(uint256 value, address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
mstore(0x14, implementation) // 20
mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
instance := create2(value, 0x0e, 0x36, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the PUSH0 clone of `implementation`.
function initCode_PUSH0(address implementation) internal pure returns (bytes memory c) {
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x40), 0x5af43d5f5f3e6029573d5ffd5b3d5ff300000000000000000000) // 16
mstore(add(c, 0x26), implementation) // 20
mstore(add(c, 0x12), 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
mstore(c, 0x36) // Store the length.
mstore(0x40, add(c, 0x60)) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the PUSH0 clone of `implementation`.
function initCodeHash_PUSH0(address implementation) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x24, 0x5af43d5f5f3e6029573d5ffd5b3d5ff3) // 16
mstore(0x14, implementation) // 20
mstore(0x00, 0x602d5f8160095f39f35f5f365f5f37365f73) // 9 + 9
hash := keccak256(0x0e, 0x36)
mstore(0x24, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the address of the PUSH0 clone of `implementation`, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddress_PUSH0(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHash_PUSH0(implementation);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CLONES WITH IMMUTABLE ARGS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a clone of `implementation` with immutable arguments encoded in `args`.
function clone(address implementation, bytes memory args) internal returns (address instance) {
instance = clone(0, implementation, args);
}
/// @dev Deploys a clone of `implementation` with immutable arguments encoded in `args`.
/// Deposits `value` ETH during deployment.
function clone(uint256 value, address implementation, bytes memory args)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
/**
* ---------------------------------------------------------------------------+
* CREATION (10 bytes) |
* ---------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------|
* 61 runSize | PUSH2 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* ---------------------------------------------------------------------------|
* RUNTIME (45 bytes + extraLength) |
* ---------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------|
* |
* ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..cds): calldata |
* |
* ::: delegate call to the implementation contract ::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata |
* 36 | CALLDATASIZE | cds 0 0 0 | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 0 0 | [0..cds): calldata |
* 73 addr | PUSH20 addr | addr 0 cds 0 0 0 0 | [0..cds): calldata |
* 5a | GAS | gas addr 0 cds 0 0 0 0 | [0..cds): calldata |
* f4 | DELEGATECALL | success 0 0 | [0..cds): calldata |
* |
* ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds success 0 | [0..cds): calldata |
* 82 | DUP3 | 0 rds success 0 | [0..cds): calldata |
* 80 | DUP1 | 0 0 rds success 0 | [0..cds): calldata |
* 3e | RETURNDATACOPY | success 0 | [0..rds): returndata |
* 90 | SWAP1 | 0 success | [0..rds): returndata |
* 3d | RETURNDATASIZE | rds 0 success | [0..rds): returndata |
* 91 | SWAP2 | success 0 rds | [0..rds): returndata |
* |
* 60 0x2b | PUSH1 0x2b | 0x2b success 0 rds | [0..rds): returndata |
* 57 | JUMPI | 0 rds | [0..rds): returndata |
* |
* ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* fd | REVERT | | [0..rds): returndata |
* |
* ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | 0 rds | [0..rds): returndata |
* f3 | RETURN | | [0..rds): returndata |
* ---------------------------------------------------------------------------+
*/
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))
mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(m, 0x14), implementation)
mstore(m, add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
instance := create(value, add(m, add(0x0b, lt(n, 0xffd3))), add(n, 0x37))
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic clone of `implementation`
/// with immutable arguments encoded in `args` and `salt`.
function cloneDeterministic(address implementation, bytes memory args, bytes32 salt)
internal
returns (address instance)
{
instance = cloneDeterministic(0, implementation, args, salt);
}
/// @dev Deploys a deterministic clone of `implementation`
/// with immutable arguments encoded in `args` and `salt`.
function cloneDeterministic(
uint256 value,
address implementation,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))
mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(m, 0x14), implementation)
mstore(m, add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
instance := create2(value, add(m, add(0x0b, lt(n, 0xffd3))), add(n, 0x37), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic clone of `implementation`
/// with immutable arguments encoded in `args` and `salt`.
/// This method does not revert if the clone has already been deployed.
function createDeterministicClone(address implementation, bytes memory args, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicClone(0, implementation, args, salt);
}
/// @dev Deploys a deterministic clone of `implementation`
/// with immutable arguments encoded in `args` and `salt`.
/// This method does not revert if the clone has already been deployed.
function createDeterministicClone(
uint256 value,
address implementation,
bytes memory args,
bytes32 salt
) internal returns (bool alreadyDeployed, address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x43), n))
mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(m, 0x14), implementation)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
// forgefmt: disable-next-item
mstore(add(m, gt(n, 0xffd2)), add(0xfe61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, keccak256(add(m, 0x0c), add(n, 0x37)))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
instance := keccak256(0x00, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, add(m, 0x0c), add(n, 0x37), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the clone of `implementation`
/// using immutable arguments encoded in `args`.
function initCode(address implementation, bytes memory args)
internal
pure
returns (bytes memory c)
{
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffd2))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(c, 0x57), i), mload(add(add(args, 0x20), i)))
}
mstore(add(c, 0x37), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(c, 0x28), implementation)
mstore(add(c, 0x14), add(0x61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))
mstore(c, add(0x37, n)) // Store the length.
mstore(add(c, add(n, 0x57)), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(c, add(n, 0x77))) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the clone of `implementation`
/// using immutable arguments encoded in `args`.
function initCodeHash(address implementation, bytes memory args)
internal
pure
returns (bytes32 hash)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x2d = 0xffd2`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffd2))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(m, 0x43), i), mload(add(add(args, 0x20), i)))
}
mstore(add(m, 0x23), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(m, 0x14), implementation)
mstore(m, add(0x61002d3d81600a3d39f3363d3d373d3d3d363d73, shl(136, n)))
hash := keccak256(add(m, 0x0c), add(n, 0x37))
}
}
/// @dev Returns the address of the clone of
/// `implementation` using immutable arguments encoded in `args`, with `salt`, by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddress(
address implementation,
bytes memory data,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHash(implementation, data);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/// @dev Equivalent to `argsOnClone(instance, 0, 2 ** 256 - 1)`.
function argsOnClone(address instance) internal view returns (bytes memory args) {
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x2d))) // Store the length.
extcodecopy(instance, add(args, 0x20), 0x2d, add(mload(args), 0x20))
mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
}
}
/// @dev Equivalent to `argsOnClone(instance, start, 2 ** 256 - 1)`.
function argsOnClone(address instance, uint256 start)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
let n := and(0xffffffffff, sub(extcodesize(instance), 0x2d))
let l := sub(n, and(0xffffff, mul(lt(start, n), start)))
extcodecopy(instance, args, add(start, 0x0d), add(l, 0x40))
mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
}
}
/// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
/// `start` and `end` will be clamped to the range `[0, args.length]`.
/// The `instance` MUST be deployed via the clone with immutable args functions.
/// Otherwise, the behavior is undefined.
/// Out-of-gas reverts if `instance` does not have any code.
function argsOnClone(address instance, uint256 start, uint256 end)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
if iszero(lt(end, 0xffff)) { end := 0xffff }
let d := mul(sub(end, start), lt(start, end))
extcodecopy(instance, args, add(start, 0x0d), add(d, 0x20))
if iszero(and(0xff, mload(add(args, d)))) {
let n := sub(extcodesize(instance), 0x2d)
returndatacopy(returndatasize(), returndatasize(), shr(40, n))
d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
}
mstore(args, d) // Store the length.
mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL ERC1967 PROXY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Note: The ERC1967 proxy here is intended to be upgraded with UUPS.
// This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic.
/// @dev Deploys a minimal ERC1967 proxy with `implementation`.
function deployERC1967(address implementation) internal returns (address instance) {
instance = deployERC1967(0, implementation);
}
/// @dev Deploys a minimal ERC1967 proxy with `implementation`.
/// Deposits `value` ETH during deployment.
function deployERC1967(uint256 value, address implementation)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
/**
* ---------------------------------------------------------------------------------+
* CREATION (34 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* 73 impl | PUSH20 impl | impl 0 r | [0..runSize): runtime code |
* 60 slotPos | PUSH1 slotPos | slotPos impl 0 r | [0..runSize): runtime code |
* 51 | MLOAD | slot impl 0 r | [0..runSize): runtime code |
* 55 | SSTORE | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* ---------------------------------------------------------------------------------|
* RUNTIME (61 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* |
* ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..calldatasize): calldata |
* |
* ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | |
* 3d | RETURNDATASIZE | 0 0 | |
* 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |
* 7f slot | PUSH32 slot | s 0 cds 0 0 | [0..calldatasize): calldata |
* 54 | SLOAD | i 0 cds 0 0 | [0..calldatasize): calldata |
* 5a | GAS | g i 0 cds 0 0 | [0..calldatasize): calldata |
* f4 | DELEGATECALL | succ | [0..calldatasize): calldata |
* |
* ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |
* 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |
* 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata |
* 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata |
* |
* ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
* 60 0x38 | PUSH1 0x38 | dest succ | [0..returndatasize): returndata |
* 57 | JUMPI | | [0..returndatasize): returndata |
* |
* ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |
* 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |
* fd | REVERT | | [0..returndatasize): returndata |
* |
* ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | [0..returndatasize): returndata |
* 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |
* 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |
* f3 | RETURN | | [0..returndatasize): returndata |
* ---------------------------------------------------------------------------------+
*/
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x20, 0x6009)
mstore(0x1e, implementation)
mstore(0x0a, 0x603d3d8160223d3973)
instance := create(value, 0x21, 0x5f)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
function deployDeterministicERC1967(address implementation, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967(0, implementation, salt);
}
/// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x20, 0x6009)
mstore(0x1e, implementation)
mstore(0x0a, 0x603d3d8160223d3973)
instance := create2(value, 0x21, 0x5f, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967(address implementation, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967(0, implementation, salt);
}
/// @dev Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967(uint256 value, address implementation, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x20, 0x6009)
mstore(0x1e, implementation)
mstore(0x0a, 0x603d3d8160223d3973)
// Compute and store the bytecode hash.
mstore(add(m, 0x35), keccak256(0x21, 0x5f))
mstore(m, shl(88, address()))
mstore8(m, 0xff) // Write the prefix.
mstore(add(m, 0x15), salt)
instance := keccak256(m, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, 0x21, 0x5f, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation`.
function initCodeERC1967(address implementation) internal pure returns (bytes memory c) {
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x60), 0x3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f300)
mstore(add(c, 0x40), 0x55f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076cc)
mstore(add(c, 0x20), or(shl(24, implementation), 0x600951))
mstore(add(c, 0x09), 0x603d3d8160223d3973)
mstore(c, 0x5f) // Store the length.
mstore(0x40, add(c, 0x80)) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`.
function initCodeHashERC1967(address implementation) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(0x40, 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x20, 0x6009)
mstore(0x1e, implementation)
mstore(0x0a, 0x603d3d8160223d3973)
hash := keccak256(0x21, 0x5f)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the address of the ERC1967 proxy of `implementation`, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967(implementation);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL ERC1967 PROXY WITH IMMUTABLE ARGS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a minimal ERC1967 proxy with `implementation` and `args`.
function deployERC1967(address implementation, bytes memory args)
internal
returns (address instance)
{
instance = deployERC1967(0, implementation, args);
}
/// @dev Deploys a minimal ERC1967 proxy with `implementation` and `args`.
/// Deposits `value` ETH during deployment.
function deployERC1967(uint256 value, address implementation, bytes memory args)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))
mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x16, 0x6009)
mstore(0x14, implementation)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))
mstore(m, mload(0x16))
instance := create(value, m, add(n, 0x60))
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
function deployDeterministicERC1967(address implementation, bytes memory args, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967(0, implementation, args, salt);
}
/// @dev Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967(
uint256 value,
address implementation,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))
mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x16, 0x6009)
mstore(0x14, implementation)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))
mstore(m, mload(0x16))
instance := create2(value, m, add(n, 0x60), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967(address implementation, bytes memory args, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967(0, implementation, args, salt);
}
/// @dev Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967(
uint256 value,
address implementation,
bytes memory args,
bytes32 salt
) internal returns (bool alreadyDeployed, address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x60), n))
mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x16, 0x6009)
mstore(0x14, implementation)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
mstore(gt(n, 0xffc2), add(0xfe61003d3d8160233d3973, shl(56, n)))
mstore(m, mload(0x16))
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, keccak256(m, add(n, 0x60)))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
instance := keccak256(0x00, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, m, add(n, 0x60), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the minimal ERC1967 proxy of `implementation` and `args`.
function initCodeERC1967(address implementation, bytes memory args)
internal
pure
returns (bytes memory c)
{
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffc2))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(c, 0x80), i), mload(add(add(args, 0x20), i)))
}
mstore(add(c, 0x60), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(add(c, 0x40), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(add(c, 0x20), 0x6009)
mstore(add(c, 0x1e), implementation)
mstore(add(c, 0x0a), add(0x61003d3d8160233d3973, shl(56, n)))
mstore(c, add(n, 0x60)) // Store the length.
mstore(add(c, add(n, 0x80)), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(c, add(n, 0xa0))) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the minimal ERC1967 proxy of `implementation` and `args`.
function initCodeHashERC1967(address implementation, bytes memory args)
internal
pure
returns (bytes32 hash)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x3d = 0xffc2`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffc2))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(m, 0x60), i), mload(add(add(args, 0x20), i)))
}
mstore(add(m, 0x40), 0xcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f3)
mstore(add(m, 0x20), 0x5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076)
mstore(0x16, 0x6009)
mstore(0x14, implementation)
mstore(0x00, add(0x61003d3d8160233d3973, shl(56, n)))
mstore(m, mload(0x16))
hash := keccak256(m, add(n, 0x60))
}
}
/// @dev Returns the address of the ERC1967 proxy of `implementation`, `args`, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967(
address implementation,
bytes memory args,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967(implementation, args);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/// @dev Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967(address instance) internal view returns (bytes memory args) {
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x3d))) // Store the length.
extcodecopy(instance, add(args, 0x20), 0x3d, add(mload(args), 0x20))
mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
}
}
/// @dev Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967(address instance, uint256 start)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
let n := and(0xffffffffff, sub(extcodesize(instance), 0x3d))
let l := sub(n, and(0xffffff, mul(lt(start, n), start)))
extcodecopy(instance, args, add(start, 0x1d), add(l, 0x40))
mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
}
}
/// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
/// `start` and `end` will be clamped to the range `[0, args.length]`.
/// The `instance` MUST be deployed via the ERC1967 with immutable args functions.
/// Otherwise, the behavior is undefined.
/// Out-of-gas reverts if `instance` does not have any code.
function argsOnERC1967(address instance, uint256 start, uint256 end)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
if iszero(lt(end, 0xffff)) { end := 0xffff }
let d := mul(sub(end, start), lt(start, end))
extcodecopy(instance, args, add(start, 0x1d), add(d, 0x20))
if iszero(and(0xff, mload(add(args, d)))) {
let n := sub(extcodesize(instance), 0x3d)
returndatacopy(returndatasize(), returndatasize(), shr(40, n))
d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
}
mstore(args, d) // Store the length.
mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1967I PROXY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Note: This proxy has a special code path that activates if `calldatasize() == 1`.
// This code path skips the delegatecall and directly returns the `implementation` address.
// The returned implementation is guaranteed to be valid if the keccak256 of the
// proxy's code is equal to `ERC1967I_CODE_HASH`.
/// @dev Deploys a ERC1967I proxy with `implementation`.
function deployERC1967I(address implementation) internal returns (address instance) {
instance = deployERC1967I(0, implementation);
}
/// @dev Deploys a ERC1967I proxy with `implementation`.
/// Deposits `value` ETH during deployment.
function deployERC1967I(uint256 value, address implementation)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
/**
* ---------------------------------------------------------------------------------+
* CREATION (34 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* 73 impl | PUSH20 impl | impl 0 r | [0..runSize): runtime code |
* 60 slotPos | PUSH1 slotPos | slotPos impl 0 r | [0..runSize): runtime code |
* 51 | MLOAD | slot impl 0 r | [0..runSize): runtime code |
* 55 | SSTORE | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* ---------------------------------------------------------------------------------|
* RUNTIME (82 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* |
* ::: check calldatasize ::::::::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 58 | PC | 1 cds | |
* 14 | EQ | eqs | |
* 60 0x43 | PUSH1 0x43 | dest eqs | |
* 57 | JUMPI | | |
* |
* ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..calldatasize): calldata |
* |
* ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | |
* 3d | RETURNDATASIZE | 0 0 | |
* 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |
* 7f slot | PUSH32 slot | s 0 cds 0 0 | [0..calldatasize): calldata |
* 54 | SLOAD | i 0 cds 0 0 | [0..calldatasize): calldata |
* 5a | GAS | g i 0 cds 0 0 | [0..calldatasize): calldata |
* f4 | DELEGATECALL | succ | [0..calldatasize): calldata |
* |
* ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |
* 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |
* 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata |
* 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata |
* |
* ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
* 60 0x3E | PUSH1 0x3E | dest succ | [0..returndatasize): returndata |
* 57 | JUMPI | | [0..returndatasize): returndata |
* |
* ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |
* 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |
* fd | REVERT | | [0..returndatasize): returndata |
* |
* ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | [0..returndatasize): returndata |
* 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |
* 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |
* f3 | RETURN | | [0..returndatasize): returndata |
* |
* ::: implementation , return :::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | |
* 60 0x20 | PUSH1 0x20 | 32 | |
* 60 0x0F | PUSH1 0x0F | o 32 | |
* 3d | RETURNDATASIZE | 0 o 32 | |
* 39 | CODECOPY | | [0..32): implementation slot |
* 3d | RETURNDATASIZE | 0 | [0..32): implementation slot |
* 51 | MLOAD | slot | [0..32): implementation slot |
* 54 | SLOAD | impl | [0..32): implementation slot |
* 3d | RETURNDATASIZE | 0 impl | [0..32): implementation slot |
* 52 | MSTORE | | [0..32): implementation address |
* 59 | MSIZE | 32 | [0..32): implementation address |
* 3d | RETURNDATASIZE | 0 32 | [0..32): implementation address |
* f3 | RETURN | | [0..32): implementation address |
* ---------------------------------------------------------------------------------+
*/
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
instance := create(value, 0x0c, 0x74)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
function deployDeterministicERC1967I(address implementation, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967I(0, implementation, salt);
}
/// @dev Deploys a deterministic ERC1967I proxy with `implementation` and `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
instance := create2(value, 0x0c, 0x74, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967I(address implementation, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967I(0, implementation, salt);
}
/// @dev Creates a deterministic ERC1967I proxy with `implementation` and `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967I(uint256 value, address implementation, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
// Compute and store the bytecode hash.
mstore(add(m, 0x35), keccak256(0x0c, 0x74))
mstore(m, shl(88, address()))
mstore8(m, 0xff) // Write the prefix.
mstore(add(m, 0x15), salt)
instance := keccak256(m, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, 0x0c, 0x74, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the initialization code of the ERC1967I proxy of `implementation`.
function initCodeERC1967I(address implementation) internal pure returns (bytes memory c) {
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x74), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(add(c, 0x54), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(add(c, 0x34), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(add(c, 0x1d), implementation)
mstore(add(c, 0x09), 0x60523d8160223d3973)
mstore(add(c, 0x94), 0)
mstore(c, 0x74) // Store the length.
mstore(0x40, add(c, 0xa0)) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the ERC1967I proxy of `implementation`.
function initCodeHashERC1967I(address implementation) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(0x40, 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(0x20, 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, implementation))))
hash := keccak256(0x0c, 0x74)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the address of the ERC1967I proxy of `implementation`, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967I(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967I(implementation);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1967I PROXY WITH IMMUTABLE ARGS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a minimal ERC1967I proxy with `implementation` and `args`.
function deployERC1967I(address implementation, bytes memory args) internal returns (address) {
return deployERC1967I(0, implementation, args);
}
/// @dev Deploys a minimal ERC1967I proxy with `implementation` and `args`.
/// Deposits `value` ETH during deployment.
function deployERC1967I(uint256 value, address implementation, bytes memory args)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
mstore(add(m, 0x6b), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(add(m, 0x4b), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(add(m, 0x2b), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(add(m, 0x14), implementation)
mstore(m, add(0xfe6100523d8160233d3973, shl(56, n)))
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
instance := create(value, add(m, add(0x15, lt(n, 0xffae))), add(0x75, n))
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`.
function deployDeterministicERC1967I(address implementation, bytes memory args, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967I(0, implementation, args, salt);
}
/// @dev Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967I(
uint256 value,
address implementation,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
mstore(add(m, 0x6b), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(add(m, 0x4b), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(add(m, 0x2b), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(add(m, 0x14), implementation)
mstore(m, add(0xfe6100523d8160233d3973, shl(56, n)))
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
instance := create2(value, add(m, add(0x15, lt(n, 0xffae))), add(0x75, n), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967I(address implementation, bytes memory args, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967I(0, implementation, args, salt);
}
/// @dev Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967I(
uint256 value,
address implementation,
bytes memory args,
bytes32 salt
) internal returns (bool alreadyDeployed, address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x75), n))
mstore(add(m, 0x55), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(add(m, 0x35), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(add(m, 0x15), 0x5155f3365814604357363d3d373d3d363d7f360894)
mstore(0x16, 0x600f)
mstore(0x14, implementation)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
mstore(gt(n, 0xffad), add(0xfe6100523d8160233d3973, shl(56, n)))
mstore(m, mload(0x16))
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, keccak256(m, add(n, 0x75)))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
instance := keccak256(0x00, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, m, add(0x75, n), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the ERC1967I proxy of `implementation` and `args`.
function initCodeERC1967I(address implementation, bytes memory args)
internal
pure
returns (bytes memory c)
{
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(c, 0x95), i), mload(add(add(args, 0x20), i)))
}
mstore(add(c, 0x75), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(add(c, 0x55), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(add(c, 0x35), 0x600f5155f3365814604357363d3d373d3d363d7f360894)
mstore(add(c, 0x1e), implementation)
mstore(add(c, 0x0a), add(0x6100523d8160233d3973, shl(56, n)))
mstore(add(c, add(n, 0x95)), 0)
mstore(c, add(0x75, n)) // Store the length.
mstore(0x40, add(c, add(n, 0xb5))) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the ERC1967I proxy of `implementation` and `args.
function initCodeHashERC1967I(address implementation, bytes memory args)
internal
pure
returns (bytes32 hash)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(m, 0x75), i), mload(add(add(args, 0x20), i)))
}
mstore(add(m, 0x55), 0x3d6000803e603e573d6000fd5b3d6000f35b6020600f3d393d51543d52593df3)
mstore(add(m, 0x35), 0xa13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545af4)
mstore(add(m, 0x15), 0x5155f3365814604357363d3d373d3d363d7f360894)
mstore(0x16, 0x600f)
mstore(0x14, implementation)
mstore(0x00, add(0x6100523d8160233d3973, shl(56, n)))
mstore(m, mload(0x16))
hash := keccak256(m, add(0x75, n))
}
}
/// @dev Returns the address of the ERC1967I proxy of `implementation`, `args` with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967I(
address implementation,
bytes memory args,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967I(implementation, args);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/// @dev Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967I(address instance) internal view returns (bytes memory args) {
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x52))) // Store the length.
extcodecopy(instance, add(args, 0x20), 0x52, add(mload(args), 0x20))
mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
}
}
/// @dev Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967I(address instance, uint256 start)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
let n := and(0xffffffffff, sub(extcodesize(instance), 0x52))
let l := sub(n, and(0xffffff, mul(lt(start, n), start)))
extcodecopy(instance, args, add(start, 0x32), add(l, 0x40))
mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
}
}
/// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
/// `start` and `end` will be clamped to the range `[0, args.length]`.
/// The `instance` MUST be deployed via the ERC1967 with immutable args functions.
/// Otherwise, the behavior is undefined.
/// Out-of-gas reverts if `instance` does not have any code.
function argsOnERC1967I(address instance, uint256 start, uint256 end)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
if iszero(lt(end, 0xffff)) { end := 0xffff }
let d := mul(sub(end, start), lt(start, end))
extcodecopy(instance, args, add(start, 0x32), add(d, 0x20))
if iszero(and(0xff, mload(add(args, d)))) {
let n := sub(extcodesize(instance), 0x52)
returndatacopy(returndatasize(), returndatasize(), shr(40, n))
d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
}
mstore(args, d) // Store the length.
mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1967 BOOTSTRAP OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// A bootstrap is a minimal UUPS implementation that allows an ERC1967 proxy
// pointing to it to be upgraded. The ERC1967 proxy can then be deployed to a
// deterministic address independent of the implementation:
// ```
// address bootstrap = LibClone.erc1967Bootstrap();
// address instance = LibClone.deployDeterministicERC1967(0, bootstrap, salt);
// LibClone.bootstrapERC1967(bootstrap, implementation);
// ```
/// @dev Deploys the ERC1967 bootstrap if it has not been deployed.
function erc1967Bootstrap() internal returns (address) {
return erc1967Bootstrap(address(this));
}
/// @dev Deploys the ERC1967 bootstrap if it has not been deployed.
function erc1967Bootstrap(address authorizedUpgrader) internal returns (address bootstrap) {
bytes memory c = initCodeERC1967Bootstrap(authorizedUpgrader);
bootstrap = predictDeterministicAddress(keccak256(c), bytes32(0), address(this));
/// @solidity memory-safe-assembly
assembly {
if iszero(extcodesize(bootstrap)) {
if iszero(create2(0, add(c, 0x20), mload(c), 0)) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Replaces the implementation at `instance`.
function bootstrapERC1967(address instance, address implementation) internal {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, implementation)
if iszero(call(gas(), instance, 0, 0x0c, 0x14, codesize(), 0x00)) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Replaces the implementation at `instance`, and then call it with `data`.
function bootstrapERC1967AndCall(address instance, address implementation, bytes memory data)
internal
{
/// @solidity memory-safe-assembly
assembly {
let n := mload(data)
mstore(data, implementation)
if iszero(call(gas(), instance, 0, add(data, 0x0c), add(n, 0x14), codesize(), 0x00)) {
if iszero(returndatasize()) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
returndatacopy(mload(0x40), 0x00, returndatasize())
revert(mload(0x40), returndatasize())
}
mstore(data, n) // Restore the length of `data`.
}
}
/// @dev Returns the implementation address of the ERC1967 bootstrap for this contract.
function predictDeterministicAddressERC1967Bootstrap() internal view returns (address) {
return predictDeterministicAddressERC1967Bootstrap(address(this), address(this));
}
/// @dev Returns the implementation address of the ERC1967 bootstrap for this contract.
function predictDeterministicAddressERC1967Bootstrap(
address authorizedUpgrader,
address deployer
) internal pure returns (address) {
bytes32 hash = initCodeHashERC1967Bootstrap(authorizedUpgrader);
return predictDeterministicAddress(hash, bytes32(0), deployer);
}
/// @dev Returns the initialization code of the ERC1967 bootstrap.
function initCodeERC1967Bootstrap(address authorizedUpgrader)
internal
pure
returns (bytes memory c)
{
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x80), 0x3d3560601c5af46047573d6000383e3d38fd0000000000000000000000000000)
mstore(add(c, 0x60), 0xa920a3ca505d382bbc55601436116049575b005b363d3d373d3d601436036014)
mstore(add(c, 0x40), 0x0338573d3560601c7f360894a13ba1a3210667c828492db98dca3e2076cc3735)
mstore(add(c, 0x20), authorizedUpgrader)
mstore(add(c, 0x0c), 0x606880600a3d393df3fe3373)
mstore(c, 0x72)
mstore(0x40, add(c, 0xa0))
}
}
/// @dev Returns the initialization code hash of the ERC1967 bootstrap.
function initCodeHashERC1967Bootstrap(address authorizedUpgrader)
internal
pure
returns (bytes32)
{
return keccak256(initCodeERC1967Bootstrap(authorizedUpgrader));
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MINIMAL ERC1967 BEACON PROXY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Note: If you use this proxy, you MUST make sure that the beacon is a
// valid ERC1967 beacon. This means that the beacon must always return a valid
// address upon a staticcall to `implementation()`, given sufficient gas.
// For performance, the deployment operations and the proxy assumes that the
// beacon is always valid and will NOT validate it.
/// @dev Deploys a minimal ERC1967 beacon proxy.
function deployERC1967BeaconProxy(address beacon) internal returns (address instance) {
instance = deployERC1967BeaconProxy(0, beacon);
}
/// @dev Deploys a minimal ERC1967 beacon proxy.
/// Deposits `value` ETH during deployment.
function deployERC1967BeaconProxy(uint256 value, address beacon)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
/**
* ---------------------------------------------------------------------------------+
* CREATION (34 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* 73 beac | PUSH20 beac | beac 0 r | [0..runSize): runtime code |
* 60 slotPos | PUSH1 slotPos | slotPos beac 0 r | [0..runSize): runtime code |
* 51 | MLOAD | slot beac 0 r | [0..runSize): runtime code |
* 55 | SSTORE | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* ---------------------------------------------------------------------------------|
* RUNTIME (82 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* |
* ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..calldatasize): calldata |
* |
* ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | |
* 3d | RETURNDATASIZE | 0 0 | |
* 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |
* |
* ~~~~~~~ beacon staticcall sub procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
* 60 0x20 | PUSH1 0x20 | 32 | |
* 36 | CALLDATASIZE | cds 32 | |
* 60 0x04 | PUSH1 0x04 | 4 cds 32 | |
* 36 | CALLDATASIZE | cds 4 cds 32 | |
* 63 0x5c60da1b | PUSH4 0x5c60da1b | 0x5c60da1b cds 4 cds 32 | |
* 60 0xe0 | PUSH1 0xe0 | 224 0x5c60da1b cds 4 cds 32 | |
* 1b | SHL | sel cds 4 cds 32 | |
* 36 | CALLDATASIZE | cds sel cds 4 cds 32 | |
* 52 | MSTORE | cds 4 cds 32 | sel |
* 7f slot | PUSH32 slot | s cds 4 cds 32 | sel |
* 54 | SLOAD | beac cds 4 cds 32 | sel |
* 5a | GAS | g beac cds 4 cds 32 | sel |
* fa | STATICCALL | succ | impl |
* 50 | POP | | impl |
* 36 | CALLDATASIZE | cds | impl |
* 51 | MLOAD | impl | impl |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
* 5a | GAS | g impl 0 cds 0 0 | [0..calldatasize): calldata |
* f4 | DELEGATECALL | succ | [0..calldatasize): calldata |
* |
* ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |
* 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |
* 80 | DUP1 | 0 0 rds succ | [0..calldatasize): calldata |
* 3e | RETURNDATACOPY | succ | [0..returndatasize): returndata |
* |
* ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
* 60 0x4d | PUSH1 0x4d | dest succ | [0..returndatasize): returndata |
* 57 | JUMPI | | [0..returndatasize): returndata |
* |
* ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |
* 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |
* fd | REVERT | | [0..returndatasize): returndata |
* |
* ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | [0..returndatasize): returndata |
* 3d | RETURNDATASIZE | rds | [0..returndatasize): returndata |
* 60 0x00 | PUSH1 0x00 | 0 rds | [0..returndatasize): returndata |
* f3 | RETURN | | [0..returndatasize): returndata |
* ---------------------------------------------------------------------------------+
*/
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
instance := create(value, 0x0c, 0x74)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `salt`.
function deployDeterministicERC1967BeaconProxy(address beacon, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967BeaconProxy(0, beacon, salt);
}
/// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967BeaconProxy(uint256 value, address beacon, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
instance := create2(value, 0x0c, 0x74, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Creates a deterministic minimal ERC1967 beacon proxy with `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967BeaconProxy(address beacon, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967BeaconProxy(0, beacon, salt);
}
/// @dev Creates a deterministic minimal ERC1967 beacon proxy with `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967BeaconProxy(uint256 value, address beacon, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
// Compute and store the bytecode hash.
mstore(add(m, 0x35), keccak256(0x0c, 0x74))
mstore(m, shl(88, address()))
mstore8(m, 0xff) // Write the prefix.
mstore(add(m, 0x15), salt)
instance := keccak256(m, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, 0x0c, 0x74, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the initialization code of the minimal ERC1967 beacon proxy.
function initCodeERC1967BeaconProxy(address beacon) internal pure returns (bytes memory c) {
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x74), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(add(c, 0x54), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(add(c, 0x34), 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(add(c, 0x1d), beacon)
mstore(add(c, 0x09), 0x60523d8160223d3973)
mstore(add(c, 0x94), 0)
mstore(c, 0x74) // Store the length.
mstore(0x40, add(c, 0xa0)) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the minimal ERC1967 beacon proxy.
function initCodeHashERC1967BeaconProxy(address beacon) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(0x40, 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(0x09, or(shl(160, 0x60523d8160223d3973), shr(96, shl(96, beacon))))
hash := keccak256(0x0c, 0x74)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the address of the ERC1967 beacon proxy, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967BeaconProxy(
address beacon,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967BeaconProxy(beacon);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1967 BEACON PROXY WITH IMMUTABLE ARGS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a minimal ERC1967 beacon proxy with `args`.
function deployERC1967BeaconProxy(address beacon, bytes memory args)
internal
returns (address instance)
{
instance = deployERC1967BeaconProxy(0, beacon, args);
}
/// @dev Deploys a minimal ERC1967 beacon proxy with `args`.
/// Deposits `value` ETH during deployment.
function deployERC1967BeaconProxy(uint256 value, address beacon, bytes memory args)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(add(m, 0x14), beacon)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))
instance := create(value, add(m, 0x16), add(n, 0x75))
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
function deployDeterministicERC1967BeaconProxy(address beacon, bytes memory args, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967BeaconProxy(0, beacon, args, salt);
}
/// @dev Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967BeaconProxy(
uint256 value,
address beacon,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(add(m, 0x14), beacon)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))
instance := create2(value, add(m, 0x16), add(n, 0x75), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967BeaconProxy(address beacon, bytes memory args, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967BeaconProxy(0, beacon, args, salt);
}
/// @dev Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967BeaconProxy(
uint256 value,
address beacon,
bytes memory args,
bytes32 salt
) internal returns (bool alreadyDeployed, address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x8b), n))
mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(add(m, 0x14), beacon)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
mstore(add(m, gt(n, 0xffad)), add(0xfe6100523d8160233d3973, shl(56, n)))
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, keccak256(add(m, 0x16), add(n, 0x75)))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
instance := keccak256(0x00, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, add(m, 0x16), add(n, 0x75), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the minimal ERC1967 beacon proxy.
function initCodeERC1967BeaconProxy(address beacon, bytes memory args)
internal
pure
returns (bytes memory c)
{
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(c, 0x95), i), mload(add(add(args, 0x20), i)))
}
mstore(add(c, 0x75), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(add(c, 0x55), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(add(c, 0x35), 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(add(c, 0x1e), beacon)
mstore(add(c, 0x0a), add(0x6100523d8160233d3973, shl(56, n)))
mstore(c, add(n, 0x75)) // Store the length.
mstore(add(c, add(n, 0x95)), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(c, add(n, 0xb5))) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the minimal ERC1967 beacon proxy with `args`.
function initCodeHashERC1967BeaconProxy(address beacon, bytes memory args)
internal
pure
returns (bytes32 hash)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x52 = 0xffad`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffad))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(m, 0x8b), i), mload(add(add(args, 0x20), i)))
}
mstore(add(m, 0x6b), 0xb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3)
mstore(add(m, 0x4b), 0x1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c)
mstore(add(m, 0x2b), 0x60195155f3363d3d373d3d363d602036600436635c60da)
mstore(add(m, 0x14), beacon)
mstore(m, add(0x6100523d8160233d3973, shl(56, n)))
hash := keccak256(add(m, 0x16), add(n, 0x75))
}
}
/// @dev Returns the address of the ERC1967 beacon proxy with `args`, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967BeaconProxy(
address beacon,
bytes memory args,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967BeaconProxy(beacon, args);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/// @dev Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967BeaconProxy(address instance) internal view returns (bytes memory args) {
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x52))) // Store the length.
extcodecopy(instance, add(args, 0x20), 0x52, add(mload(args), 0x20))
mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
}
}
/// @dev Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967BeaconProxy(address instance, uint256 start)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
let n := and(0xffffffffff, sub(extcodesize(instance), 0x52))
let l := sub(n, and(0xffffff, mul(lt(start, n), start)))
extcodecopy(instance, args, add(start, 0x32), add(l, 0x40))
mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
}
}
/// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
/// `start` and `end` will be clamped to the range `[0, args.length]`.
/// The `instance` MUST be deployed via the ERC1967 beacon proxy with immutable args functions.
/// Otherwise, the behavior is undefined.
/// Out-of-gas reverts if `instance` does not have any code.
function argsOnERC1967BeaconProxy(address instance, uint256 start, uint256 end)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
if iszero(lt(end, 0xffff)) { end := 0xffff }
let d := mul(sub(end, start), lt(start, end))
extcodecopy(instance, args, add(start, 0x32), add(d, 0x20))
if iszero(and(0xff, mload(add(args, d)))) {
let n := sub(extcodesize(instance), 0x52)
returndatacopy(returndatasize(), returndatasize(), shr(40, n))
d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
}
mstore(args, d) // Store the length.
mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1967I BEACON PROXY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// Note: This proxy has a special code path that activates if `calldatasize() == 1`.
// This code path skips the delegatecall and directly returns the `implementation` address.
// The returned implementation is guaranteed to be valid if the keccak256 of the
// proxy's code is equal to `ERC1967_BEACON_PROXY_CODE_HASH`.
//
// If you use this proxy, you MUST make sure that the beacon is a
// valid ERC1967 beacon. This means that the beacon must always return a valid
// address upon a staticcall to `implementation()`, given sufficient gas.
// For performance, the deployment operations and the proxy assumes that the
// beacon is always valid and will NOT validate it.
/// @dev Deploys a ERC1967I beacon proxy.
function deployERC1967IBeaconProxy(address beacon) internal returns (address instance) {
instance = deployERC1967IBeaconProxy(0, beacon);
}
/// @dev Deploys a ERC1967I beacon proxy.
/// Deposits `value` ETH during deployment.
function deployERC1967IBeaconProxy(uint256 value, address beacon)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
/**
* ---------------------------------------------------------------------------------+
* CREATION (34 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* 60 runSize | PUSH1 runSize | r | |
* 3d | RETURNDATASIZE | 0 r | |
* 81 | DUP2 | r 0 r | |
* 60 offset | PUSH1 offset | o r 0 r | |
* 3d | RETURNDATASIZE | 0 o r 0 r | |
* 39 | CODECOPY | 0 r | [0..runSize): runtime code |
* 73 beac | PUSH20 beac | beac 0 r | [0..runSize): runtime code |
* 60 slotPos | PUSH1 slotPos | slotPos beac 0 r | [0..runSize): runtime code |
* 51 | MLOAD | slot beac 0 r | [0..runSize): runtime code |
* 55 | SSTORE | 0 r | [0..runSize): runtime code |
* f3 | RETURN | | [0..runSize): runtime code |
* ---------------------------------------------------------------------------------|
* RUNTIME (87 bytes) |
* ---------------------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* ---------------------------------------------------------------------------------|
* |
* ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::: |
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..calldatasize): calldata |
* |
* ::: delegatecall to implementation ::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | 0 | |
* 3d | RETURNDATASIZE | 0 0 | |
* 36 | CALLDATASIZE | cds 0 0 | [0..calldatasize): calldata |
* 3d | RETURNDATASIZE | 0 cds 0 0 | [0..calldatasize): calldata |
* |
* ~~~~~~~ beacon staticcall sub procedure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
* 60 0x20 | PUSH1 0x20 | 32 | |
* 36 | CALLDATASIZE | cds 32 | |
* 60 0x04 | PUSH1 0x04 | 4 cds 32 | |
* 36 | CALLDATASIZE | cds 4 cds 32 | |
* 63 0x5c60da1b | PUSH4 0x5c60da1b | 0x5c60da1b cds 4 cds 32 | |
* 60 0xe0 | PUSH1 0xe0 | 224 0x5c60da1b cds 4 cds 32 | |
* 1b | SHL | sel cds 4 cds 32 | |
* 36 | CALLDATASIZE | cds sel cds 4 cds 32 | |
* 52 | MSTORE | cds 4 cds 32 | sel |
* 7f slot | PUSH32 slot | s cds 4 cds 32 | sel |
* 54 | SLOAD | beac cds 4 cds 32 | sel |
* 5a | GAS | g beac cds 4 cds 32 | sel |
* fa | STATICCALL | succ | impl |
* ~~~~~~ check calldatasize ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
* 36 | CALLDATASIZE | cds succ | |
* 14 | EQ | | impl |
* 60 0x52 | PUSH1 0x52 | | impl |
* 57 | JUMPI | | impl |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
* 36 | CALLDATASIZE | cds | impl |
* 51 | MLOAD | impl | impl |
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
* 5a | GAS | g impl 0 cds 0 0 | [0..calldatasize): calldata |
* f4 | DELEGATECALL | succ | [0..calldatasize): calldata |
* |
* ::: copy returndata to memory :::::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds succ | [0..calldatasize): calldata |
* 60 0x00 | PUSH1 0x00 | 0 rds succ | [0..calldatasize): calldata |
* 60 0x01 | PUSH1 0x01 | 1 0 rds succ | [0..calldatasize): calldata |
* 3e | RETURNDATACOPY | succ | [1..returndatasize): returndata |
* |
* ::: branch on delegatecall status :::::::::::::::::::::::::::::::::::::::::::::: |
* 60 0x52 | PUSH1 0x52 | dest succ | [1..returndatasize): returndata |
* 57 | JUMPI | | [1..returndatasize): returndata |
* |
* ::: delegatecall failed, revert :::::::::::::::::::::::::::::::::::::::::::::::: |
* 3d | RETURNDATASIZE | rds | [1..returndatasize): returndata |
* 60 0x01 | PUSH1 0x01 | 1 rds | [1..returndatasize): returndata |
* fd | REVERT | | [1..returndatasize): returndata |
* |
* ::: delegatecall succeeded, return ::::::::::::::::::::::::::::::::::::::::::::: |
* 5b | JUMPDEST | | [1..returndatasize): returndata |
* 3d | RETURNDATASIZE | rds | [1..returndatasize): returndata |
* 60 0x01 | PUSH1 0x01 | 1 rds | [1..returndatasize): returndata |
* f3 | RETURN | | [1..returndatasize): returndata |
* ---------------------------------------------------------------------------------+
*/
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
instance := create(value, 0x07, 0x79)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Deploys a deterministic ERC1967I beacon proxy with `salt`.
function deployDeterministicERC1967IBeaconProxy(address beacon, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967IBeaconProxy(0, beacon, salt);
}
/// @dev Deploys a deterministic ERC1967I beacon proxy with `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967IBeaconProxy(uint256 value, address beacon, bytes32 salt)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
instance := create2(value, 0x07, 0x79, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Creates a deterministic ERC1967I beacon proxy with `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967IBeaconProxy(address beacon, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967IBeaconProxy(0, beacon, salt);
}
/// @dev Creates a deterministic ERC1967I beacon proxy with `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967IBeaconProxy(uint256 value, address beacon, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
// Compute and store the bytecode hash.
mstore(add(m, 0x35), keccak256(0x07, 0x79))
mstore(m, shl(88, address()))
mstore8(m, 0xff) // Write the prefix.
mstore(add(m, 0x15), salt)
instance := keccak256(m, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, 0x07, 0x79, salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the initialization code of the ERC1967I beacon proxy.
function initCodeERC1967IBeaconProxy(address beacon) internal pure returns (bytes memory c) {
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
mstore(add(c, 0x79), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(add(c, 0x59), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(add(c, 0x39), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(add(c, 0x1d), beacon)
mstore(add(c, 0x09), 0x60573d8160223d3973)
mstore(add(c, 0x99), 0)
mstore(c, 0x79) // Store the length.
mstore(0x40, add(c, 0xa0)) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the ERC1967I beacon proxy.
function initCodeHashERC1967IBeaconProxy(address beacon) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x60, 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(0x40, 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(0x20, 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(0x04, or(shl(160, 0x60573d8160223d3973), shr(96, shl(96, beacon))))
hash := keccak256(0x07, 0x79)
mstore(0x40, m) // Restore the free memory pointer.
mstore(0x60, 0) // Restore the zero slot.
}
}
/// @dev Returns the address of the ERC1967I beacon proxy, with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967IBeaconProxy(
address beacon,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967IBeaconProxy(beacon);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ERC1967I BEACON PROXY WITH IMMUTABLE ARGS OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys a ERC1967I beacon proxy with `args.
function deployERC1967IBeaconProxy(address beacon, bytes memory args)
internal
returns (address instance)
{
instance = deployERC1967IBeaconProxy(0, beacon, args);
}
/// @dev Deploys a ERC1967I beacon proxy with `args.
/// Deposits `value` ETH during deployment.
function deployERC1967IBeaconProxy(uint256 value, address beacon, bytes memory args)
internal
returns (address instance)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))
mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(add(m, 0x14), beacon)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))
instance := create(value, add(m, 0x16), add(n, 0x7a))
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`.
function deployDeterministicERC1967IBeaconProxy(address beacon, bytes memory args, bytes32 salt)
internal
returns (address instance)
{
instance = deployDeterministicERC1967IBeaconProxy(0, beacon, args, salt);
}
/// @dev Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`.
/// Deposits `value` ETH during deployment.
function deployDeterministicERC1967IBeaconProxy(
uint256 value,
address beacon,
bytes memory args,
bytes32 salt
) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))
mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(add(m, 0x14), beacon)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))
instance := create2(value, add(m, 0x16), add(n, 0x7a), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Creates a deterministic ERC1967I beacon proxy with `args` and `salt`.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967IBeaconProxy(address beacon, bytes memory args, bytes32 salt)
internal
returns (bool alreadyDeployed, address instance)
{
return createDeterministicERC1967IBeaconProxy(0, beacon, args, salt);
}
/// @dev Creates a deterministic ERC1967I beacon proxy with `args` and `salt`.
/// Deposits `value` ETH during deployment.
/// Note: This method is intended for use in ERC4337 factories,
/// which are expected to NOT revert if the proxy is already deployed.
function createDeterministicERC1967IBeaconProxy(
uint256 value,
address beacon,
bytes memory args,
bytes32 salt
) internal returns (bool alreadyDeployed, address instance) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40)
let n := mload(args)
pop(staticcall(gas(), 4, add(args, 0x20), n, add(m, 0x90), n))
mstore(add(m, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(add(m, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(add(m, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(add(m, 0x14), beacon)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
mstore(add(m, gt(n, 0xffa8)), add(0xfe6100573d8160233d3973, shl(56, n)))
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, keccak256(add(m, 0x16), add(n, 0x7a)))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
instance := keccak256(0x00, 0x55)
for {} 1 {} {
if iszero(extcodesize(instance)) {
instance := create2(value, add(m, 0x16), add(n, 0x7a), salt)
if iszero(instance) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
break
}
alreadyDeployed := 1
if iszero(value) { break }
if iszero(call(gas(), instance, value, codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
revert(0x1c, 0x04)
}
break
}
mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the initialization code of the ERC1967I beacon proxy with `args`.
function initCodeERC1967IBeaconProxy(address beacon, bytes memory args)
internal
pure
returns (bytes memory c)
{
/// @solidity memory-safe-assembly
assembly {
c := mload(0x40)
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffa8))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(c, 0x9a), i), mload(add(add(args, 0x20), i)))
}
mstore(add(c, 0x7a), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(add(c, 0x5a), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(add(c, 0x3a), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(add(c, 0x1e), beacon)
mstore(add(c, 0x0a), add(0x6100573d8160233d3973, shl(56, n)))
mstore(add(c, add(n, 0x9a)), 0)
mstore(c, add(n, 0x7a)) // Store the length.
mstore(0x40, add(c, add(n, 0xba))) // Allocate memory.
}
}
/// @dev Returns the initialization code hash of the ERC1967I beacon proxy with `args`.
function initCodeHashERC1967IBeaconProxy(address beacon, bytes memory args)
internal
pure
returns (bytes32 hash)
{
/// @solidity memory-safe-assembly
assembly {
let c := mload(0x40) // Cache the free memory pointer.
let n := mload(args)
// Do a out-of-gas revert if `n` is greater than `0xffff - 0x57 = 0xffa8`.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0xffa8))
for { let i := 0 } lt(i, n) { i := add(i, 0x20) } {
mstore(add(add(c, 0x90), i), mload(add(add(args, 0x20), i)))
}
mstore(add(c, 0x70), 0x3d50545afa361460525736515af43d600060013e6052573d6001fd5b3d6001f3)
mstore(add(c, 0x50), 0x527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b3513)
mstore(add(c, 0x30), 0x60195155f3363d3d373d3d363d602036600436635c60da1b60e01b36)
mstore(add(c, 0x14), beacon)
mstore(c, add(0x6100573d8160233d3973, shl(56, n)))
hash := keccak256(add(c, 0x16), add(n, 0x7a))
}
}
/// @dev Returns the address of the ERC1967I beacon proxy, with `args` and salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddressERC1967IBeaconProxy(
address beacon,
bytes memory args,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
bytes32 hash = initCodeHashERC1967IBeaconProxy(beacon, args);
predicted = predictDeterministicAddress(hash, salt, deployer);
}
/// @dev Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967IBeaconProxy(address instance)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
mstore(args, and(0xffffffffff, sub(extcodesize(instance), 0x57))) // Store the length.
extcodecopy(instance, add(args, 0x20), 0x57, add(mload(args), 0x20))
mstore(0x40, add(mload(args), add(args, 0x40))) // Allocate memory.
}
}
/// @dev Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`.
function argsOnERC1967IBeaconProxy(address instance, uint256 start)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
let n := and(0xffffffffff, sub(extcodesize(instance), 0x57))
let l := sub(n, and(0xffffff, mul(lt(start, n), start)))
extcodecopy(instance, args, add(start, 0x37), add(l, 0x40))
mstore(args, mul(sub(n, start), lt(start, n))) // Store the length.
mstore(0x40, add(args, add(0x40, mload(args)))) // Allocate memory.
}
}
/// @dev Returns a slice of the immutable arguments on `instance` from `start` to `end`.
/// `start` and `end` will be clamped to the range `[0, args.length]`.
/// The `instance` MUST be deployed via the ERC1967I beacon proxy with immutable args functions.
/// Otherwise, the behavior is undefined.
/// Out-of-gas reverts if `instance` does not have any code.
function argsOnERC1967IBeaconProxy(address instance, uint256 start, uint256 end)
internal
view
returns (bytes memory args)
{
/// @solidity memory-safe-assembly
assembly {
args := mload(0x40)
if iszero(lt(end, 0xffff)) { end := 0xffff }
let d := mul(sub(end, start), lt(start, end))
extcodecopy(instance, args, add(start, 0x37), add(d, 0x20))
if iszero(and(0xff, mload(add(args, d)))) {
let n := sub(extcodesize(instance), 0x57)
returndatacopy(returndatasize(), returndatasize(), shr(40, n))
d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
}
mstore(args, d) // Store the length.
mstore(add(add(args, 0x20), d), 0) // Zeroize the slot after the bytes.
mstore(0x40, add(add(args, 0x40), d)) // Allocate memory.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* OTHER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns `address(0)` if the implementation address cannot be determined.
function implementationOf(address instance) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
for { extcodecopy(instance, 0x00, 0x00, 0x57) } 1 {} {
if mload(0x2d) {
// ERC1967I and ERC1967IBeaconProxy detection.
if or(
eq(keccak256(0x00, 0x52), ERC1967I_CODE_HASH),
eq(keccak256(0x00, 0x57), ERC1967I_BEACON_PROXY_CODE_HASH)
) {
pop(staticcall(gas(), instance, 0x00, 0x01, 0x00, 0x20))
result := mload(0x0c)
break
}
}
// 0age clone detection.
result := mload(0x0b)
codecopy(0x0b, codesize(), 0x14) // Zeroize the 20 bytes for the address.
if iszero(xor(keccak256(0x00, 0x2c), CLONE_CODE_HASH)) { break }
mstore(0x0b, result) // Restore the zeroized memory.
// CWIA detection.
result := mload(0x0a)
codecopy(0x0a, codesize(), 0x14) // Zeroize the 20 bytes for the address.
if iszero(xor(keccak256(0x00, 0x2d), CWIA_CODE_HASH)) { break }
mstore(0x0a, result) // Restore the zeroized memory.
// PUSH0 clone detection.
result := mload(0x09)
codecopy(0x09, codesize(), 0x14) // Zeroize the 20 bytes for the address.
result := shr(xor(keccak256(0x00, 0x2d), PUSH0_CLONE_CODE_HASH), result)
break
}
result := shr(96, result)
mstore(0x37, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the address when a contract with initialization code hash,
/// `hash`, is deployed with `salt`, by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer)
internal
pure
returns (address predicted)
{
/// @solidity memory-safe-assembly
assembly {
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, hash)
mstore(0x01, shl(96, deployer))
mstore(0x15, salt)
predicted := keccak256(0x00, 0x55)
mstore(0x35, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Requires that `salt` starts with either the zero address or `by`.
function checkStartsWith(bytes32 salt, address by) internal pure {
/// @solidity memory-safe-assembly
assembly {
// If the salt does not start with the zero address or `by`.
if iszero(or(iszero(shr(96, salt)), eq(shr(96, shl(96, by)), shr(96, salt)))) {
mstore(0x00, 0x0c4549ef) // `SaltDoesNotStartWith()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns the `bytes32` at `offset` in `args`, without any bounds checks.
/// To load an address, you can use `address(bytes20(argLoad(args, offset)))`.
function argLoad(bytes memory args, uint256 offset) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
result := mload(add(add(args, 0x20), offset))
}
}
}{
"remappings": [
"@openzeppelin-contracts/=dependencies/@openzeppelin-contracts-5.3.0/",
"createx-forge/=dependencies/createx-forge/",
"erc721a-upgradeable/=dependencies/ERC721A-Upgradeable/",
"forge-std/=dependencies/forge-std-1.9.7/src/",
"solady/=dependencies/solady-0.1.19/src/",
"@openzeppelin-contracts-5.3.0/=dependencies/@openzeppelin-contracts-5.3.0/",
"ERC721A-Upgradeable/=dependencies/ERC721A-Upgradeable/contracts/",
"ds-test/=dependencies/createx-forge/lib/forge-std/lib/ds-test/src/",
"forge-std-1.9.7/=dependencies/forge-std-1.9.7/src/",
"solady-0.1.19/=dependencies/solady-0.1.19/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "none",
"appendCBOR": false
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"evmVersion": "prague",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"ClaimsAlreadyActive","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"EmptyTokensArray","type":"error"},{"inputs":[],"name":"IncorrectFees","type":"error"},{"inputs":[],"name":"IndividualClaimNotAllowed","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"InvalidTimestamp","type":"error"},{"inputs":[],"name":"InvalidTokenIndex","type":"error"},{"inputs":[],"name":"LeafUsed","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NotPaused","type":"error"},{"inputs":[],"name":"OutsideClaimableTimeRange","type":"error"},{"inputs":[],"name":"Paused","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TimeInactive","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsupportedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"delegate","type":"address"}],"name":"ClaimDelegateSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"bytes32","name":"group","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"Claimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[{"components":[{"internalType":"uint256","name":"packedRecipientTimeToken","type":"uint256"},{"internalType":"uint256","name":"claimableAmount","type":"uint256"}],"internalType":"struct BatchClaimData[]","name":"batchData","type":"tuple[]"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"name":"batchClaimAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"claim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"group","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"delegateClaim","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes32","name":"group","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"encodeLeaf","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"packedRecipientTimeToken","type":"uint256"},{"internalType":"uint256","name":"claimableAmount","type":"uint256"}],"internalType":"struct BatchClaimData[]","name":"batchData","type":"tuple[]"}],"name":"generateGroupHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getClaimDelegate","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getClaimHook","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeployer","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"isLeafUsed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"claimableTimestamp","type":"uint256"},{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"name":"packRecipientTimeToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"root","type":"bytes32"}],"name":"setBaseParams","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegate","type":"address"}],"name":"setClaimDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"hook","type":"address"}],"name":"setClaimHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"setTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"bool","name":"status","type":"bool"}],"name":"setWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tokens","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"packed","type":"uint256"}],"name":"unpackRecipientTimeToken","outputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"claimableTimestamp","type":"uint256"},{"internalType":"uint256","name":"tokenIndex","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"proof","type":"bytes32[]"},{"internalType":"bytes32","name":"leaf","type":"bytes32"}],"name":"verify","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"extraData","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6080604052348015600e575f5ffd5b5046617a6914601d57601d6021565b6084565b63409feecd1980546001811615603e5763f92ee8a95f526004601cfd5b6001600160401b03808260011c14607f578060011b8355806020527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602080a15b505050565b6122ad806100915f395ff3fe60806040526004361061020a575f3560e01c80636c043a33116101135780639b19251a1161009d578063c4d66de81161006d578063c4d66de8146105b5578063e1696957146105d4578063f04e283e146105f3578063f2fde38b14610606578063fee81cf414610619575f5ffd5b80639b19251a14610528578063a8b5129914610556578063aa6ca80814610575578063b131ec9714610596575f5ffd5b806372630531116100e357806372630531146104b657806372abac54146104ca5780638456cb59146104dd5780638da5cb5b146104f1578063972a2a6214610509575f5ffd5b80636c043a33146104685780636cadf5ad1461047b5780636e98be7f1461048f578063715018a6146104ae575f5ffd5b80634c41909111610194578063557ed1ba11610164578063557ed1ba146103be5780635c975abb146103e75780635ca1e1651461041657806361b3c9f21461042a578063625adaf214610449575f5ffd5b80634c419091146103215780634f64b2be1461037657806354d1f13d1461039557806354fd4d501461039d575f5ffd5b806325692962116101da57806325692962146102a85780633c271a05146102b05780633c8949b3146102cf5780633f4ba83a146102ee57806347efc03814610302575f5ffd5b806308ddeb45146102155780630968f2641461024757806321df0da71461026857806322e0ab1614610294575f5ffd5b3661021157005b5f5ffd5b348015610220575f5ffd5b5061023461022f366004611a48565b61064a565b6040519081526020015b60405180910390f35b348015610252575f5ffd5b50610266610261366004611b23565b61067c565b005b348015610273575f5ffd5b5061027c6106cf565b6040516001600160a01b03909116815260200161023e565b34801561029f575f5ffd5b5061027c6106ea565b610266610705565b3480156102bb575f5ffd5b506102666102ca366004611b9c565b610751565b3480156102da575f5ffd5b506102666102e9366004611c06565b6107c3565b3480156102f9575f5ffd5b50610266610829565b34801561030d575f5ffd5b5061023461031c366004611c28565b61083b565b34801561032c575f5ffd5b5061035161033b366004611c5a565b9064ffffffffff60a083901c169060c883901c90565b604080516001600160a01b03909416845260208401929092529082015260600161023e565b348015610381575f5ffd5b5061027c610390366004611c5a565b6108a8565b6102666108cf565b3480156103a8575f5ffd5b506103b1610908565b60405161023e9190611c9f565b3480156103c9575f5ffd5b506103d2610950565b6040805192835260208301919091520161023e565b3480156103f2575f5ffd5b505f51602061228d5f395f51905f525460ff165b604051901515815260200161023e565b348015610421575f5ffd5b50610234610972565b348015610435575f5ffd5b50610266610444366004611c06565b610984565b348015610454575f5ffd5b50610266610463366004611cb1565b6109b9565b610266610476366004611d20565b610af4565b348015610486575f5ffd5b5061027c610b0d565b34801561049a575f5ffd5b506104066104a9366004611c5a565b610b28565b610266610b44565b3480156104c1575f5ffd5b5061027c610b55565b6102666104d8366004611dc5565b610b70565b3480156104e8575f5ffd5b50610266610c96565b3480156104fc575f5ffd5b50638b78c6d8195461027c565b348015610514575f5ffd5b50610266610523366004611e7c565b610ca6565b348015610533575f5ffd5b50610406610542366004611c06565b60016020525f908152604090205460ff1681565b348015610561575f5ffd5b50610266610570366004611ec3565b610d03565b348015610580575f5ffd5b50610589610d17565b60405161023e9190611efb565b3480156105a1575f5ffd5b506102666105b0366004611f46565b610d76565b3480156105c0575f5ffd5b506102666105cf366004611c06565b610f11565b3480156105df575f5ffd5b506102346105ee366004611fb0565b610fb3565b610266610601366004611c06565b610fec565b610266610614366004611c06565b611026565b348015610624575f5ffd5b50610234610633366004611c06565b63389a75e1600c9081525f91909152602090205490565b5f828260405160200161065e929190612004565b60405160208183030381529060405280519060200120905092915050565b61068461104c565b80515f036106ac575f5b5f548110156106a8576106a081611066565b60010161068e565b5050565b5f818060200190518101906106c19190612048565b90506106a881611094565b50565b5f6106d861109d565b600301546001600160a01b0316919050565b5f6106f361109d565b600401546001600160a01b0316919050565b5f6202a3006001600160401b03164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f5fa250565b61075961104c565b5f5b828110156107bd578160015f86868581811061077957610779612063565b905060200201602081019061078e9190611c06565b6001600160a01b0316815260208101919091526040015f20805460ff191691151591909117905560010161075b565b50505050565b6107cb61104c565b806107d461109d565b60040180546001600160a01b0319166001600160a01b0392831617905560405190821681527f9ca1bfcac82ee1107a485dd1336f6b73e33bdd7f01445200703a0a6d79f5d4e59060200160405180910390a150565b61083161104c565b6108396110c1565b565b5f6501000000000083106108625760405163b7d0949760e01b815260040160405180910390fd5b670100000000000000821061088a5760405163609f982f60e01b815260040160405180910390fd5b506001600160a01b03831660a083901b1760c882901b179392505050565b5f81815481106108b6575f80fd5b5f918252602090912001546001600160a01b0316905081565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f5fa2565b606061092c604080518082019091526005815264302e342e3560d81b602082015290565b60405160200161093c9190612077565b604051602081830303815290604052905090565b5f5f61095a61109d565b6005015461096661109d565b60060154915091509091565b5f61097b61109d565b60010154905090565b61098c61104c565b8061099561109d565b60070180546001600160a01b0319166001600160a01b039290921691909117905550565b6109c161104c565b5f8190036109e2576040516339d75f4360e21b815260040160405180910390fd5b5f6109eb61109d565b6001015414158015610a08575042610a0161109d565b6005015411155b15610a2657604051631ce71ac160e31b815260040160405180910390fd5b806001600160401b03811115610a3e57610a3e611a86565b604051908082528060200260200182016040528015610a67578160200160208202803683370190505b508051610a7b915f9160209091019061198a565b505f5b81811015610aef57828282818110610a9857610a98612063565b9050602002016020810190610aad9190611c06565b5f8281548110610abf57610abf612063565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600101610a7e565b505050565b6040516316d8614d60e01b815260040160405180910390fd5b5f610b1661109d565b600701546001600160a01b0316919050565b5f610b3161109d565b5f92835260205250604090205460ff1690565b610b4c61104c565b6108395f6110e1565b5f610b5e61109d565b600201546001600160a01b0316919050565b610b7861109d565b600401546001600160a01b03163314610ba3576040516282b42960e81b815260040160405180910390fd5b610bab61109d565b60050154421080610bc65750610bbf61109d565b6006015442115b15610be45760405163018287d760e31b815260040160405180910390fd5b3068929eee149b4bd212685403610c025763ab143c065f526004601cfd5b3068929eee149b4bd2126855610c1f33898989898989898961111e565b5f610c2e89898989898961113d565b9050610c42338a8a8a8a8a8a888b8b611157565b7f597a291bf8dedc18fe24ac7ca5fc092b5108111be5a87280cf758b19396941d189878787604051610c7794939291906120f6565b60405180910390a1503868929eee149b4bd21268555050505050505050565b610c9e61104c565b610839611180565b610caf81610b28565b15610ccd57604051630725855960e11b815260040160405180910390fd5b610ce6610cd861109d565b6001015484908490846111a5565b610aef576040516309bde33960e01b815260040160405180910390fd5b610d0b61104c565b6107bd5f8484846111dd565b60605f805480602002602001604051908101604052809291908181526020018280548015610d6c57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610d4e575b5050505050905090565b610d7e61109d565b60050154421080610d995750610d9261109d565b6006015442115b15610db75760405163018287d760e31b815260040160405180910390fd5b610dbf61125c565b3068929eee149b4bd212685403610ddd5763ab143c065f526004601cfd5b3068929eee149b4bd2126855335f9081526001602052604090205460ff16610e17576040516282b42960e81b815260040160405180910390fd5b5f610e2061109d565b90505f610e2d868661064a565b5f8181526020849052604090205490915060ff1615610e5e576040516282b42960e81b815260040160405180910390fd5b5f818152602083905260408120805460ff191660011790555b85811015610efc5736878783818110610e9257610e92612063565b60400291909101915050803564ffffffffff60a082901c1660c882901c42821180610ec05750866005015482105b15610ede5760405163f5d66d0560e01b815260040160405180910390fd5b610eed8382866020013561128c565b84600101945050505050610e77565b5050503868929eee149b4bd212685550505050565b63409feecd198054600382558015610f475760018160011c14303b10610f3e5763f92ee8a95f526004601cfd5b818160ff1b1b91505b50610f5182611344565b33610f5a61109d565b60020180546001600160a01b0319166001600160a01b039290921691909117905580156106a8576002815560016020527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602080a15050565b5f4630858585604051602001610fcd959493929190612127565b6040516020818303038152906040528051906020012090509392505050565b610ff461104c565b63389a75e1600c52805f526020600c20805442111561101a57636f5e88185f526004601cfd5b5f90556106cc816110e1565b61102e61104c565b8060601b61104357637448fbae5f526004601cfd5b6106cc816110e1565b638b78c6d819543314610839576382b429005f526004601cfd5b6106cc5f828154811061107b5761107b612063565b5f918252602090912001546001600160a01b031661137f565b6106cc8161137f565b7f452bdf2c9fe836ad357e55ed0859c19d2ac2a2c151d216523e3d37a8b9a03f0090565b6110c96114a3565b5f51602061228d5f395f51905f52805460ff19169055565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b611132898989898989895f60018b8b6114d2565b505050505050505050565b5f6040516316d8614d60e01b815260040160405180910390fd5b61116a8a8a8a8a8a8a8a8a5f8b8b6114d2565b6111748a846115dd565b50505050505050505050565b61118861125c565b5f5f51602061228d5f395f51905f52805460ff1916600117905550565b5f83156111d5578360051b8501855b803580851160051b94855260209485185260405f2093018181106111b45750505b501492915050565b6111e561104c565b81831061120557604051639ba6061b60e01b815260040160405180910390fd5b8361120e61109d565b60030180546001600160a01b0319166001600160a01b03929092169190911790558261123861109d565b600501558161124561109d565b600601558061125261109d565b6001015550505050565b5f51602061228d5f395f51905f525460ff1615610839576040516313d0ff5960e31b815260040160405180910390fd5b5f5f838154811061129f5761129f612063565b5f918252602090912001546001600160a01b0316905080611330575f846001600160a01b0316836040515f6040518083038185875af1925050503d805f8114611303576040519150601f19603f3d011682016040523d82523d5f602084013e611308565b606091505b505090508061132a5760405163b12d13eb60e01b815260040160405180910390fd5b506107bd565b6107bd6001600160a01b0382168584611886565b6001600160a01b0316638b78c6d819819055805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6001600160a01b038116611410574780156106a8575f6113a2638b78c6d8195490565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f81146113e9576040519150601f19603f3d011682016040523d82523d5f602084013e6113ee565b606091505b5050905080610aef5760405163b12d13eb60e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015281905f906001600160a01b038316906370a0823190602401602060405180830381865afa158015611456573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061147a919061216a565b90508015610aef57610aef611492638b78c6d8195490565b6001600160a01b0384169083611886565b5f51602061228d5f395f51905f525460ff1661083957604051636cd6020160e01b815260040160405180910390fd5b5f6114db61109d565b600701546001600160a01b0316905080156115cf57836115655760405163040482f360e21b81526001600160a01b038216906310120bcc90611533908f908f908f908f908f908f908f908f908e908e906004016121b1565b5f604051808303815f87803b15801561154a575f5ffd5b505af115801561155c573d5f5f3e3d5ffd5b505050506115cf565b60405163b1020e1960e01b81526001600160a01b0382169063b1020e19906115a1908f908f908f908f908f908f908f908d908d90600401612222565b5f604051808303815f87803b1580156115b8575f5ffd5b505af11580156115ca573d5f5f3e3d5ffd5b505050505b505050505050505050505050565b5f6115e661109d565b600281015460405163cb5cd39160e01b81523060048201529192506001600160a01b0316905f90829063cb5cd39190602401602060405180830381865afa158015611633573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116579190612048565b90506001600160a01b03811661168d57341561168657604051631669aa8360e01b815260040160405180910390fd5b5050505050565b6040516313b7ae0d60e21b8152306004820152602481018590525f906001600160a01b03831690634edeb83490604401602060405180830381865afa1580156116d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116fc919061216a565b9050805f0361172c57341561172457604051631669aa8360e01b815260040160405180910390fd5b505050505050565b6040516316605a0d60e01b81523060048201525f906001600160a01b038516906316605a0d90602401602060405180830381865afa158015611770573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117949190612048565b90506001600160a01b038116611849578134146117c457604051631669aa8360e01b815260040160405180910390fd5b5f5f846001600160a01b0316846040515f6040518083038185875af1925050503d805f811461180e576040519150601f19603f3d011682016040523d82523d5f602084013e611813565b606091505b50915091508181906118415760405162461bcd60e51b81526004016118389190611c9f565b60405180910390fd5b50505061187d565b341561186857604051631669aa8360e01b815260040160405180910390fd5b61187d6001600160a01b0382168885856118e5565b50505050505050565b6040516001600160a01b03838116602483015260448201839052610aef91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061191e565b6040516001600160a01b0384811660248301528381166044830152606482018390526107bd9186918216906323b872dd906084016118b3565b5f5f60205f8451602086015f885af18061193d576040513d5f823e3d81fd5b50505f513d91508115611954578060011415611961565b6001600160a01b0384163b155b156107bd57604051635274afe760e01b81526001600160a01b0385166004820152602401611838565b828054828255905f5260205f209081019282156119dd579160200282015b828111156119dd57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906119a8565b506119e99291506119ed565b5090565b5b808211156119e9575f81556001016119ee565b5f5f83601f840112611a11575f5ffd5b5081356001600160401b03811115611a27575f5ffd5b6020830191508360208260061b8501011115611a41575f5ffd5b9250929050565b5f5f60208385031215611a59575f5ffd5b82356001600160401b03811115611a6e575f5ffd5b611a7a85828601611a01565b90969095509350505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112611aa9575f5ffd5b81356001600160401b03811115611ac257611ac2611a86565b604051601f8201601f19908116603f011681016001600160401b0381118282101715611af057611af0611a86565b604052818152838201602001851015611b07575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215611b33575f5ffd5b81356001600160401b03811115611b48575f5ffd5b611b5484828501611a9a565b949350505050565b5f5f83601f840112611b6c575f5ffd5b5081356001600160401b03811115611b82575f5ffd5b6020830191508360208260051b8501011115611a41575f5ffd5b5f5f5f60408486031215611bae575f5ffd5b83356001600160401b03811115611bc3575f5ffd5b611bcf86828701611b5c565b90945092505060208401358015158114611be7575f5ffd5b809150509250925092565b6001600160a01b03811681146106cc575f5ffd5b5f60208284031215611c16575f5ffd5b8135611c2181611bf2565b9392505050565b5f5f5f60608486031215611c3a575f5ffd5b8335611c4581611bf2565b95602085013595506040909401359392505050565b5f60208284031215611c6a575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611c216020830184611c71565b5f5f60208385031215611cc2575f5ffd5b82356001600160401b03811115611cd7575f5ffd5b611a7a85828601611b5c565b5f5f83601f840112611cf3575f5ffd5b5081356001600160401b03811115611d09575f5ffd5b602083019150836020828501011115611a41575f5ffd5b5f5f5f5f5f5f5f6080888a031215611d36575f5ffd5b87356001600160401b03811115611d4b575f5ffd5b611d578a828b01611b5c565b9098509650506020880135945060408801356001600160401b03811115611d7c575f5ffd5b611d888a828b01611ce3565b90955093505060608801356001600160401b03811115611da6575f5ffd5b611db28a828b01611ce3565b989b979a50959850939692959293505050565b5f5f5f5f5f5f5f5f60a0898b031215611ddc575f5ffd5b8835611de781611bf2565b975060208901356001600160401b03811115611e01575f5ffd5b611e0d8b828c01611b5c565b9098509650506040890135945060608901356001600160401b03811115611e32575f5ffd5b611e3e8b828c01611ce3565b90955093505060808901356001600160401b03811115611e5c575f5ffd5b611e688b828c01611ce3565b999c989b5096995094979396929594505050565b5f5f5f60408486031215611e8e575f5ffd5b83356001600160401b03811115611ea3575f5ffd5b611eaf86828701611b5c565b909790965060209590950135949350505050565b5f5f5f5f60808587031215611ed6575f5ffd5b8435611ee181611bf2565b966020860135965060408601359560600135945092505050565b602080825282518282018190525f918401906040840190835b81811015611f3b5783516001600160a01b0316835260209384019390920191600101611f14565b509095945050505050565b5f5f5f5f60408587031215611f59575f5ffd5b84356001600160401b03811115611f6e575f5ffd5b611f7a87828801611a01565b90955093505060208501356001600160401b03811115611f98575f5ffd5b611fa487828801611b5c565b95989497509550505050565b5f5f5f60608486031215611fc2575f5ffd5b8335611fcd81611bf2565b92506020840135915060408401356001600160401b03811115611fee575f5ffd5b611ffa86828701611a9a565b9150509250925092565b602080825281018290525f8360408301825b8581101561203e57823582526020808401359083015260409283019290910190600101612016565b5095945050505050565b5f60208284031215612058575f5ffd5b8151611c2181611bf2565b634e487b7160e01b5f52603260045260245ffd5b5f82518060208501845e7f2d546f6b656e5461626c654d65726b6c654d756c7469746f6b656e44697374729201918252507434b13aba37b92130ba31b432b216a0b236b4b7169960591b6020820152603501919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b0385168152836020820152606060408201525f61211d6060830184866120ce565b9695505050505050565b8581526001600160a01b038581166020830152841660408201526060810183905260a0608082018190525f9061215f90830184611c71565b979650505050505050565b5f6020828403121561217a575f5ffd5b5051919050565b8183525f6001600160fb1b03831115612198575f5ffd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038b811682528a16602082015260e0604082018190525f906121dd9083018a8c612181565b88606084015282810360808401526121f681888a6120ce565b90508560a084015282810360c08401526122118185876120ce565b9d9c50505050505050505050505050565b6001600160a01b038a811682528916602082015260c0604082018190525f9061224e908301898b612181565b87606084015282810360808401526122678187896120ce565b905082810360a084015261227c8185876120ce565b9c9b50505050505050505050505056fe159a745eaf9f69c9f8685f5357fc5c3fc24330eca10f86813ccbd1db89bdb000
Deployed Bytecode
0x60806040526004361061020a575f3560e01c80636c043a33116101135780639b19251a1161009d578063c4d66de81161006d578063c4d66de8146105b5578063e1696957146105d4578063f04e283e146105f3578063f2fde38b14610606578063fee81cf414610619575f5ffd5b80639b19251a14610528578063a8b5129914610556578063aa6ca80814610575578063b131ec9714610596575f5ffd5b806372630531116100e357806372630531146104b657806372abac54146104ca5780638456cb59146104dd5780638da5cb5b146104f1578063972a2a6214610509575f5ffd5b80636c043a33146104685780636cadf5ad1461047b5780636e98be7f1461048f578063715018a6146104ae575f5ffd5b80634c41909111610194578063557ed1ba11610164578063557ed1ba146103be5780635c975abb146103e75780635ca1e1651461041657806361b3c9f21461042a578063625adaf214610449575f5ffd5b80634c419091146103215780634f64b2be1461037657806354d1f13d1461039557806354fd4d501461039d575f5ffd5b806325692962116101da57806325692962146102a85780633c271a05146102b05780633c8949b3146102cf5780633f4ba83a146102ee57806347efc03814610302575f5ffd5b806308ddeb45146102155780630968f2641461024757806321df0da71461026857806322e0ab1614610294575f5ffd5b3661021157005b5f5ffd5b348015610220575f5ffd5b5061023461022f366004611a48565b61064a565b6040519081526020015b60405180910390f35b348015610252575f5ffd5b50610266610261366004611b23565b61067c565b005b348015610273575f5ffd5b5061027c6106cf565b6040516001600160a01b03909116815260200161023e565b34801561029f575f5ffd5b5061027c6106ea565b610266610705565b3480156102bb575f5ffd5b506102666102ca366004611b9c565b610751565b3480156102da575f5ffd5b506102666102e9366004611c06565b6107c3565b3480156102f9575f5ffd5b50610266610829565b34801561030d575f5ffd5b5061023461031c366004611c28565b61083b565b34801561032c575f5ffd5b5061035161033b366004611c5a565b9064ffffffffff60a083901c169060c883901c90565b604080516001600160a01b03909416845260208401929092529082015260600161023e565b348015610381575f5ffd5b5061027c610390366004611c5a565b6108a8565b6102666108cf565b3480156103a8575f5ffd5b506103b1610908565b60405161023e9190611c9f565b3480156103c9575f5ffd5b506103d2610950565b6040805192835260208301919091520161023e565b3480156103f2575f5ffd5b505f51602061228d5f395f51905f525460ff165b604051901515815260200161023e565b348015610421575f5ffd5b50610234610972565b348015610435575f5ffd5b50610266610444366004611c06565b610984565b348015610454575f5ffd5b50610266610463366004611cb1565b6109b9565b610266610476366004611d20565b610af4565b348015610486575f5ffd5b5061027c610b0d565b34801561049a575f5ffd5b506104066104a9366004611c5a565b610b28565b610266610b44565b3480156104c1575f5ffd5b5061027c610b55565b6102666104d8366004611dc5565b610b70565b3480156104e8575f5ffd5b50610266610c96565b3480156104fc575f5ffd5b50638b78c6d8195461027c565b348015610514575f5ffd5b50610266610523366004611e7c565b610ca6565b348015610533575f5ffd5b50610406610542366004611c06565b60016020525f908152604090205460ff1681565b348015610561575f5ffd5b50610266610570366004611ec3565b610d03565b348015610580575f5ffd5b50610589610d17565b60405161023e9190611efb565b3480156105a1575f5ffd5b506102666105b0366004611f46565b610d76565b3480156105c0575f5ffd5b506102666105cf366004611c06565b610f11565b3480156105df575f5ffd5b506102346105ee366004611fb0565b610fb3565b610266610601366004611c06565b610fec565b610266610614366004611c06565b611026565b348015610624575f5ffd5b50610234610633366004611c06565b63389a75e1600c9081525f91909152602090205490565b5f828260405160200161065e929190612004565b60405160208183030381529060405280519060200120905092915050565b61068461104c565b80515f036106ac575f5b5f548110156106a8576106a081611066565b60010161068e565b5050565b5f818060200190518101906106c19190612048565b90506106a881611094565b50565b5f6106d861109d565b600301546001600160a01b0316919050565b5f6106f361109d565b600401546001600160a01b0316919050565b5f6202a3006001600160401b03164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f5fa250565b61075961104c565b5f5b828110156107bd578160015f86868581811061077957610779612063565b905060200201602081019061078e9190611c06565b6001600160a01b0316815260208101919091526040015f20805460ff191691151591909117905560010161075b565b50505050565b6107cb61104c565b806107d461109d565b60040180546001600160a01b0319166001600160a01b0392831617905560405190821681527f9ca1bfcac82ee1107a485dd1336f6b73e33bdd7f01445200703a0a6d79f5d4e59060200160405180910390a150565b61083161104c565b6108396110c1565b565b5f6501000000000083106108625760405163b7d0949760e01b815260040160405180910390fd5b670100000000000000821061088a5760405163609f982f60e01b815260040160405180910390fd5b506001600160a01b03831660a083901b1760c882901b179392505050565b5f81815481106108b6575f80fd5b5f918252602090912001546001600160a01b0316905081565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f5fa2565b606061092c604080518082019091526005815264302e342e3560d81b602082015290565b60405160200161093c9190612077565b604051602081830303815290604052905090565b5f5f61095a61109d565b6005015461096661109d565b60060154915091509091565b5f61097b61109d565b60010154905090565b61098c61104c565b8061099561109d565b60070180546001600160a01b0319166001600160a01b039290921691909117905550565b6109c161104c565b5f8190036109e2576040516339d75f4360e21b815260040160405180910390fd5b5f6109eb61109d565b6001015414158015610a08575042610a0161109d565b6005015411155b15610a2657604051631ce71ac160e31b815260040160405180910390fd5b806001600160401b03811115610a3e57610a3e611a86565b604051908082528060200260200182016040528015610a67578160200160208202803683370190505b508051610a7b915f9160209091019061198a565b505f5b81811015610aef57828282818110610a9857610a98612063565b9050602002016020810190610aad9190611c06565b5f8281548110610abf57610abf612063565b5f91825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600101610a7e565b505050565b6040516316d8614d60e01b815260040160405180910390fd5b5f610b1661109d565b600701546001600160a01b0316919050565b5f610b3161109d565b5f92835260205250604090205460ff1690565b610b4c61104c565b6108395f6110e1565b5f610b5e61109d565b600201546001600160a01b0316919050565b610b7861109d565b600401546001600160a01b03163314610ba3576040516282b42960e81b815260040160405180910390fd5b610bab61109d565b60050154421080610bc65750610bbf61109d565b6006015442115b15610be45760405163018287d760e31b815260040160405180910390fd5b3068929eee149b4bd212685403610c025763ab143c065f526004601cfd5b3068929eee149b4bd2126855610c1f33898989898989898961111e565b5f610c2e89898989898961113d565b9050610c42338a8a8a8a8a8a888b8b611157565b7f597a291bf8dedc18fe24ac7ca5fc092b5108111be5a87280cf758b19396941d189878787604051610c7794939291906120f6565b60405180910390a1503868929eee149b4bd21268555050505050505050565b610c9e61104c565b610839611180565b610caf81610b28565b15610ccd57604051630725855960e11b815260040160405180910390fd5b610ce6610cd861109d565b6001015484908490846111a5565b610aef576040516309bde33960e01b815260040160405180910390fd5b610d0b61104c565b6107bd5f8484846111dd565b60605f805480602002602001604051908101604052809291908181526020018280548015610d6c57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610d4e575b5050505050905090565b610d7e61109d565b60050154421080610d995750610d9261109d565b6006015442115b15610db75760405163018287d760e31b815260040160405180910390fd5b610dbf61125c565b3068929eee149b4bd212685403610ddd5763ab143c065f526004601cfd5b3068929eee149b4bd2126855335f9081526001602052604090205460ff16610e17576040516282b42960e81b815260040160405180910390fd5b5f610e2061109d565b90505f610e2d868661064a565b5f8181526020849052604090205490915060ff1615610e5e576040516282b42960e81b815260040160405180910390fd5b5f818152602083905260408120805460ff191660011790555b85811015610efc5736878783818110610e9257610e92612063565b60400291909101915050803564ffffffffff60a082901c1660c882901c42821180610ec05750866005015482105b15610ede5760405163f5d66d0560e01b815260040160405180910390fd5b610eed8382866020013561128c565b84600101945050505050610e77565b5050503868929eee149b4bd212685550505050565b63409feecd198054600382558015610f475760018160011c14303b10610f3e5763f92ee8a95f526004601cfd5b818160ff1b1b91505b50610f5182611344565b33610f5a61109d565b60020180546001600160a01b0319166001600160a01b039290921691909117905580156106a8576002815560016020527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602080a15050565b5f4630858585604051602001610fcd959493929190612127565b6040516020818303038152906040528051906020012090509392505050565b610ff461104c565b63389a75e1600c52805f526020600c20805442111561101a57636f5e88185f526004601cfd5b5f90556106cc816110e1565b61102e61104c565b8060601b61104357637448fbae5f526004601cfd5b6106cc816110e1565b638b78c6d819543314610839576382b429005f526004601cfd5b6106cc5f828154811061107b5761107b612063565b5f918252602090912001546001600160a01b031661137f565b6106cc8161137f565b7f452bdf2c9fe836ad357e55ed0859c19d2ac2a2c151d216523e3d37a8b9a03f0090565b6110c96114a3565b5f51602061228d5f395f51905f52805460ff19169055565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b611132898989898989895f60018b8b6114d2565b505050505050505050565b5f6040516316d8614d60e01b815260040160405180910390fd5b61116a8a8a8a8a8a8a8a8a5f8b8b6114d2565b6111748a846115dd565b50505050505050505050565b61118861125c565b5f5f51602061228d5f395f51905f52805460ff1916600117905550565b5f83156111d5578360051b8501855b803580851160051b94855260209485185260405f2093018181106111b45750505b501492915050565b6111e561104c565b81831061120557604051639ba6061b60e01b815260040160405180910390fd5b8361120e61109d565b60030180546001600160a01b0319166001600160a01b03929092169190911790558261123861109d565b600501558161124561109d565b600601558061125261109d565b6001015550505050565b5f51602061228d5f395f51905f525460ff1615610839576040516313d0ff5960e31b815260040160405180910390fd5b5f5f838154811061129f5761129f612063565b5f918252602090912001546001600160a01b0316905080611330575f846001600160a01b0316836040515f6040518083038185875af1925050503d805f8114611303576040519150601f19603f3d011682016040523d82523d5f602084013e611308565b606091505b505090508061132a5760405163b12d13eb60e01b815260040160405180910390fd5b506107bd565b6107bd6001600160a01b0382168584611886565b6001600160a01b0316638b78c6d819819055805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b6001600160a01b038116611410574780156106a8575f6113a2638b78c6d8195490565b6001600160a01b0316826040515f6040518083038185875af1925050503d805f81146113e9576040519150601f19603f3d011682016040523d82523d5f602084013e6113ee565b606091505b5050905080610aef5760405163b12d13eb60e01b815260040160405180910390fd5b6040516370a0823160e01b815230600482015281905f906001600160a01b038316906370a0823190602401602060405180830381865afa158015611456573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061147a919061216a565b90508015610aef57610aef611492638b78c6d8195490565b6001600160a01b0384169083611886565b5f51602061228d5f395f51905f525460ff1661083957604051636cd6020160e01b815260040160405180910390fd5b5f6114db61109d565b600701546001600160a01b0316905080156115cf57836115655760405163040482f360e21b81526001600160a01b038216906310120bcc90611533908f908f908f908f908f908f908f908f908e908e906004016121b1565b5f604051808303815f87803b15801561154a575f5ffd5b505af115801561155c573d5f5f3e3d5ffd5b505050506115cf565b60405163b1020e1960e01b81526001600160a01b0382169063b1020e19906115a1908f908f908f908f908f908f908f908d908d90600401612222565b5f604051808303815f87803b1580156115b8575f5ffd5b505af11580156115ca573d5f5f3e3d5ffd5b505050505b505050505050505050505050565b5f6115e661109d565b600281015460405163cb5cd39160e01b81523060048201529192506001600160a01b0316905f90829063cb5cd39190602401602060405180830381865afa158015611633573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116579190612048565b90506001600160a01b03811661168d57341561168657604051631669aa8360e01b815260040160405180910390fd5b5050505050565b6040516313b7ae0d60e21b8152306004820152602481018590525f906001600160a01b03831690634edeb83490604401602060405180830381865afa1580156116d8573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116fc919061216a565b9050805f0361172c57341561172457604051631669aa8360e01b815260040160405180910390fd5b505050505050565b6040516316605a0d60e01b81523060048201525f906001600160a01b038516906316605a0d90602401602060405180830381865afa158015611770573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117949190612048565b90506001600160a01b038116611849578134146117c457604051631669aa8360e01b815260040160405180910390fd5b5f5f846001600160a01b0316846040515f6040518083038185875af1925050503d805f811461180e576040519150601f19603f3d011682016040523d82523d5f602084013e611813565b606091505b50915091508181906118415760405162461bcd60e51b81526004016118389190611c9f565b60405180910390fd5b50505061187d565b341561186857604051631669aa8360e01b815260040160405180910390fd5b61187d6001600160a01b0382168885856118e5565b50505050505050565b6040516001600160a01b03838116602483015260448201839052610aef91859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180516001600160e01b03838183161783525050505061191e565b6040516001600160a01b0384811660248301528381166044830152606482018390526107bd9186918216906323b872dd906084016118b3565b5f5f60205f8451602086015f885af18061193d576040513d5f823e3d81fd5b50505f513d91508115611954578060011415611961565b6001600160a01b0384163b155b156107bd57604051635274afe760e01b81526001600160a01b0385166004820152602401611838565b828054828255905f5260205f209081019282156119dd579160200282015b828111156119dd57825182546001600160a01b0319166001600160a01b039091161782556020909201916001909101906119a8565b506119e99291506119ed565b5090565b5b808211156119e9575f81556001016119ee565b5f5f83601f840112611a11575f5ffd5b5081356001600160401b03811115611a27575f5ffd5b6020830191508360208260061b8501011115611a41575f5ffd5b9250929050565b5f5f60208385031215611a59575f5ffd5b82356001600160401b03811115611a6e575f5ffd5b611a7a85828601611a01565b90969095509350505050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112611aa9575f5ffd5b81356001600160401b03811115611ac257611ac2611a86565b604051601f8201601f19908116603f011681016001600160401b0381118282101715611af057611af0611a86565b604052818152838201602001851015611b07575f5ffd5b816020850160208301375f918101602001919091529392505050565b5f60208284031215611b33575f5ffd5b81356001600160401b03811115611b48575f5ffd5b611b5484828501611a9a565b949350505050565b5f5f83601f840112611b6c575f5ffd5b5081356001600160401b03811115611b82575f5ffd5b6020830191508360208260051b8501011115611a41575f5ffd5b5f5f5f60408486031215611bae575f5ffd5b83356001600160401b03811115611bc3575f5ffd5b611bcf86828701611b5c565b90945092505060208401358015158114611be7575f5ffd5b809150509250925092565b6001600160a01b03811681146106cc575f5ffd5b5f60208284031215611c16575f5ffd5b8135611c2181611bf2565b9392505050565b5f5f5f60608486031215611c3a575f5ffd5b8335611c4581611bf2565b95602085013595506040909401359392505050565b5f60208284031215611c6a575f5ffd5b5035919050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f611c216020830184611c71565b5f5f60208385031215611cc2575f5ffd5b82356001600160401b03811115611cd7575f5ffd5b611a7a85828601611b5c565b5f5f83601f840112611cf3575f5ffd5b5081356001600160401b03811115611d09575f5ffd5b602083019150836020828501011115611a41575f5ffd5b5f5f5f5f5f5f5f6080888a031215611d36575f5ffd5b87356001600160401b03811115611d4b575f5ffd5b611d578a828b01611b5c565b9098509650506020880135945060408801356001600160401b03811115611d7c575f5ffd5b611d888a828b01611ce3565b90955093505060608801356001600160401b03811115611da6575f5ffd5b611db28a828b01611ce3565b989b979a50959850939692959293505050565b5f5f5f5f5f5f5f5f60a0898b031215611ddc575f5ffd5b8835611de781611bf2565b975060208901356001600160401b03811115611e01575f5ffd5b611e0d8b828c01611b5c565b9098509650506040890135945060608901356001600160401b03811115611e32575f5ffd5b611e3e8b828c01611ce3565b90955093505060808901356001600160401b03811115611e5c575f5ffd5b611e688b828c01611ce3565b999c989b5096995094979396929594505050565b5f5f5f60408486031215611e8e575f5ffd5b83356001600160401b03811115611ea3575f5ffd5b611eaf86828701611b5c565b909790965060209590950135949350505050565b5f5f5f5f60808587031215611ed6575f5ffd5b8435611ee181611bf2565b966020860135965060408601359560600135945092505050565b602080825282518282018190525f918401906040840190835b81811015611f3b5783516001600160a01b0316835260209384019390920191600101611f14565b509095945050505050565b5f5f5f5f60408587031215611f59575f5ffd5b84356001600160401b03811115611f6e575f5ffd5b611f7a87828801611a01565b90955093505060208501356001600160401b03811115611f98575f5ffd5b611fa487828801611b5c565b95989497509550505050565b5f5f5f60608486031215611fc2575f5ffd5b8335611fcd81611bf2565b92506020840135915060408401356001600160401b03811115611fee575f5ffd5b611ffa86828701611a9a565b9150509250925092565b602080825281018290525f8360408301825b8581101561203e57823582526020808401359083015260409283019290910190600101612016565b5095945050505050565b5f60208284031215612058575f5ffd5b8151611c2181611bf2565b634e487b7160e01b5f52603260045260245ffd5b5f82518060208501845e7f2d546f6b656e5461626c654d65726b6c654d756c7469746f6b656e44697374729201918252507434b13aba37b92130ba31b432b216a0b236b4b7169960591b6020820152603501919050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b60018060a01b0385168152836020820152606060408201525f61211d6060830184866120ce565b9695505050505050565b8581526001600160a01b038581166020830152841660408201526060810183905260a0608082018190525f9061215f90830184611c71565b979650505050505050565b5f6020828403121561217a575f5ffd5b5051919050565b8183525f6001600160fb1b03831115612198575f5ffd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038b811682528a16602082015260e0604082018190525f906121dd9083018a8c612181565b88606084015282810360808401526121f681888a6120ce565b90508560a084015282810360c08401526122118185876120ce565b9d9c50505050505050505050505050565b6001600160a01b038a811682528916602082015260c0604082018190525f9061224e908301898b612181565b87606084015282810360808401526122678187896120ce565b905082810360a084015261227c8185876120ce565b9c9b50505050505050505050505056fe159a745eaf9f69c9f8685f5357fc5c3fc24330eca10f86813ccbd1db89bdb000
Deployed Bytecode Sourcemap
1168:9756:14:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8563:150;;;;;;;;;;-1:-1:-1;8563:150:14;;;;;:::i;:::-;;:::i;:::-;;;1054:25:16;;;1042:2;1027:18;8563:150:14;;;;;;;;5286:578;;;;;;;;;;-1:-1:-1;5286:578:14;;;;;:::i;:::-;;:::i;:::-;;4525:116:13;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;2441:32:16;;;2423:51;;2411:2;2396:18;4525:116:13;2277:203:16;4087:132:13;;;;;;;;;;;;;:::i;9021:617:2:-;;;:::i;3061:259:14:-;;;;;;;;;;-1:-1:-1;3061:259:14;;;;;:::i;:::-;;:::i;2629:188:13:-;;;;;;;;;;-1:-1:-1;2629:188:13;;;;;:::i;:::-;;:::i;2062:65:14:-;;;;;;;;;;;;;:::i;7179:430::-;;;;;;;;;;-1:-1:-1;7179:430:14;;;;;:::i;:::-;;:::i;8026:319::-;;;;;;;;;;-1:-1:-1;8026:319:14;;;;;:::i;:::-;8230:6;8288:13;8280:3;8270:13;;;8269:33;;8335:3;8325:13;;;;8026:319;;;;;-1:-1:-1;;;;;4973:32:16;;;4955:51;;5037:2;5022:18;;5015:34;;;;5065:18;;;5058:34;4943:2;4928:18;8026:319:14;4753:345:16;1385:23:14;;;;;;;;;;-1:-1:-1;1385:23:14;;;;;:::i;:::-;;:::i;9720:456:2:-;;;:::i;8867:199:14:-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;4345:174:13:-;;;;;;;;;;;;;:::i;:::-;;;;5796:25:16;;;5852:2;5837:18;;5830:34;;;;5769:18;4345:174:13;5622:248:16;827:145:11;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;956:9:11;;;827:145;;;6040:14:16;;6033:22;6015:41;;6003:2;5988:18;827:145:11;5875:187:16;4225:114:13;;;;;;;;;;;;;:::i;5438:129::-;;;;;;;;;;-1:-1:-1;5438:129:13;;;;;:::i;:::-;;:::i;2371:684:14:-;;;;;;;;;;-1:-1:-1;2371:684:14;;;;;:::i;:::-;;:::i;4870:161::-;;;;;;:::i;:::-;;:::i;4775:124:13:-;;;;;;;;;;;;;:::i;6022:143::-;;;;;;;;;;-1:-1:-1;6022:143:13;;;;;:::i;:::-;;:::i;8762:100:2:-;;;:::i;4647:122:13:-;;;;;;;;;;;;;:::i;3342:603::-;;;;;;:::i;:::-;;:::i;1900:61:14:-;;;;;;;;;;;;;:::i;11408:182:2:-;;;;;;;;;;-1:-1:-1;;;11556:18:2;11408:182;;5779:237:13;;;;;;;;;;-1:-1:-1;5779:237:13;;;;;:::i;:::-;;:::i;1414:41:14:-;;;;;;;;;;-1:-1:-1;1414:41:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;6396:323;;;;;;;;;;-1:-1:-1;6396:323:14;;;;;:::i;:::-;;:::i;6014:92::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;3326:1386::-;;;;;;;;;;-1:-1:-1;3326:1386:14;;;;;:::i;:::-;;:::i;2461:162:13:-;;;;;;;;;;-1:-1:-1;2461:162:13;;;;;:::i;:::-;;:::i;5573:200::-;;;;;;;;;;-1:-1:-1;5573:200:13;;;;;:::i;:::-;;:::i;10363:708:2:-;;;;;;:::i;:::-;;:::i;8348:349::-;;;;;;:::i;:::-;;:::i;11693:435::-;;;;;;;;;;-1:-1:-1;11693:435:2;;;;;:::i;:::-;11963:19;11957:4;11950:33;;;11812:14;11996:26;;;;12106:4;12090:21;;12084:28;;11693:435;8563:150:14;8648:7;8695:9;;8684:21;;;;;;;;;:::i;:::-;;;;;;;;;;;;;8674:32;;;;;;8667:39;;8563:150;;;;:::o;5286:578::-;12517:13:2;:11;:13::i;:::-;5378:9:14::1;:16;5398:1;5378:21:::0;5374:484:::1;;5496:9;5491:164;5515:6;:13:::0;5511:17;::::1;5491:164;;;5549:19;5566:1;5549:16;:19::i;:::-;5619:3;;5491:164;;;;5286:578:::0;:::o;5374:484::-:1;5740:23;5777:9;5766:32;;;;;;;;;;;;:::i;:::-;5740:58;;5812:35;5831:15;5812:18;:35::i;5374:484::-;5286:578:::0;:::o;4525:116:13:-;4568:7;4594:34;:32;:34::i;:::-;:40;;;-1:-1:-1;;;;;4594:40:13;;4525:116;-1:-1:-1;4525:116:13:o;4087:132::-;4138:7;4164:34;:32;:34::i;:::-;:48;;;-1:-1:-1;;;;;4164:48:13;;4087:132;-1:-1:-1;4087:132:13:o;9021:617:2:-;9114:15;7972:9;-1:-1:-1;;;;;9132:46:2;:15;:46;9114:64;;9346:19;9340:4;9333:33;9396:8;9390:4;9383:22;9452:7;9445:4;9439;9429:21;9422:38;9599:8;9552:45;9549:1;9546;9541:67;9248:374;9021:617::o;3061:259:14:-;12517:13:2;:11;:13::i;:::-;3160:9:14::1;3155:159;3175:20:::0;;::::1;3155:159;;;3238:6;3212:9;:23;3222:9;;3232:1;3222:12;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;3212:23:14::1;::::0;;::::1;::::0;::::1;::::0;;;;;;-1:-1:-1;3212:23:14;:32;;-1:-1:-1;;3212:32:14::1;::::0;::::1;;::::0;;;::::1;::::0;;-1:-1:-1;3286:3:14::1;3155:159;;;;3061:259:::0;;;:::o;2629:188:13:-;12517:13:2;:11;:13::i;:::-;2761:8:13::1;2710:34;:32;:34::i;:::-;:48;;:59:::0;;-1:-1:-1;;;;;;2710:59:13::1;-1:-1:-1::0;;;;;2710:59:13;;::::1;;::::0;;2784:26:::1;::::0;2441:32:16;;;2423:51;;2784:26:13::1;::::0;2411:2:16;2396:18;2784:26:13::1;;;;;;;2629:188:::0;:::o;2062:65:14:-;12517:13:2;:11;:13::i;:::-;2110:10:14::1;:8;:10::i;:::-;2062:65::o:0;7179:430::-;7355:7;7405;7382:18;:31;7378:62;;7422:18;;-1:-1:-1;;;7422:18:14;;;;;;;;;;;7378:62;7469:7;7454:10;:23;7450:55;;7486:19;;-1:-1:-1;;;7486:19:14;;;;;;;;;;;7450:55;-1:-1:-1;;;;;;7523:27:14;;7576:3;7554:25;;;7523:57;7598:3;7584:17;;;7523:79;7179:430;;;;;:::o;1385:23::-;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1385:23:14;;-1:-1:-1;1385:23:14;:::o;9720:456:2:-;9922:19;9916:4;9909:33;9968:8;9962:4;9955:22;10020:1;10013:4;10007;9997:21;9990:32;10151:8;10105:44;10102:1;10099;10094:66;9720:456::o;8867:199:14:-;8924:13;8970:31;4978:14:13;;;;;;;;;;;;-1:-1:-1;;;4978:14:13;;;;;4905:94;8970:31:14;8956:103;;;;;;;;:::i;:::-;;;;;;;;;;;;;8949:110;;8867:199;:::o;4345:174:13:-;4387:7;4396;4423:34;:32;:34::i;:::-;:44;;;4469:34;:32;:34::i;:::-;:42;;;4415:97;;;;4345:174;;:::o;4225:114::-;4267:7;4293:34;:32;:34::i;:::-;:39;;;4286:46;;4225:114;:::o;5438:129::-;12517:13:2;:11;:13::i;:::-;5556:4:13::1;5509:34;:32;:34::i;:::-;:44;;:51:::0;;-1:-1:-1;;;;;;5509:51:13::1;-1:-1:-1::0;;;;;5509:51:13;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;5438:129:13:o;2371:684:14:-;12517:13:2;:11;:13::i;:::-;2469:1:14::1;2451:19:::0;;;2447:50:::1;;2479:18;;-1:-1:-1::0;;;2479:18:14::1;;;;;;;;;;;2447:50;2643:1;2592:34;:32;:34::i;:::-;:39;;;:53;;:136;;;;;2713:15;2665:34;:32;:34::i;:::-;:44;;;:63;;2592:136;2575:217;;;2760:21;;-1:-1:-1::0;;;2760:21:14::1;;;;;;;;;;;2575:217;2875:7:::0;-1:-1:-1;;;;;2861:29:14;::::1;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;-1:-1:-1;2861:29:14::1;-1:-1:-1::0;2852:38:14;;::::1;::::0;:6:::1;::::0;:38:::1;::::0;;::::1;::::0;::::1;:::i;:::-;-1:-1:-1::0;2906:9:14::1;2901:148;2921:18:::0;;::::1;2901:148;;;2968:7;;2976:1;2968:10;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2956:6;2963:1;2956:9;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;::::1;:22:::0;;-1:-1:-1;;;;;;2956:22:14::1;-1:-1:-1::0;;;;;2956:22:14;;;::::1;::::0;;;::::1;::::0;;-1:-1:-1;3021:3:14::1;2901:148;;;;2371:684:::0;;:::o;4870:161::-;4997:27;;-1:-1:-1;;;4997:27:14;;;;;;;;;;;4775:124:13;4822:7;4848:34;:32;:34::i;:::-;:44;;;-1:-1:-1;;;;;4848:44:13;;4775:124;-1:-1:-1;4775:124:13:o;6022:143::-;6085:4;6108:34;:32;:34::i;:::-;:44;:50;;;;;-1:-1:-1;6108:50:13;;;;;;;6022:143::o;8762:100:2:-;12517:13;:11;:13::i;:::-;8834:21:::1;8852:1;8834:9;:21::i;4647:122:13:-:0;4693:7;4719:34;:32;:34::i;:::-;:43;;;-1:-1:-1;;;;;4719:43:13;;4647:122;-1:-1:-1;4647:122:13:o;3342:603::-;1960:34;:32;:34::i;:::-;:48;;;-1:-1:-1;;;;;1960:48:13;1946:10;:62;1938:87;;;;-1:-1:-1;;;1938:87:13;;;;;;;;;;;;2116:34:::1;:32;:34::i;:::-;:44;;;2098:15;:62;:142;;;;2198:34;:32;:34::i;:::-;:42;;;2180:15;:60;2098:142;2081:191;;;2258:14;;-1:-1:-1::0;;;2258:14:13::1;;;;;;;;;;;2081:191;1635:9:6::2;1610:22;1604:29;1601:44:::0;1598:158:::2;;1677:10;1671:4;1664:24;1737:4;1731;1724:18;1598:158;1800:9;1776:22;1769:41;3640:74:13::3;3661:10;3673:9;3684:5;;3691;3698:4;;3704:9;;3640:20;:74::i;:::-;3724:21;3748:46;3764:9;3775:5;;3782;3789:4;;3748:15;:46::i;:::-;3724:70;;3804:88;3824:10;3836:9;3847:5;;3854;3861:4;;3867:13;3882:9;;3804:19;:88::i;:::-;3907:31;3915:9;3926:5;3933:4;;3907:31;;;;;;;;;:::i;:::-;;;;;;;;3630:315;1937:10:6::2;1913:22;1906:42;3342:603:13::0;;;;;;;;:::o;1900:61:14:-;12517:13:2;:11;:13::i;:::-;1946:8:14::1;:6;:8::i;5779:237:13:-:0;5869:16;5880:4;5869:10;:16::i;:::-;5865:39;;;5894:10;;-1:-1:-1;;;5894:10:13;;;;;;;;;;;5865:39;5919:67;5940:34;:32;:34::i;:::-;:39;;;5919:5;;;;5981:4;5919:20;:67::i;:::-;5914:95;;5995:14;;-1:-1:-1;;;5995:14:13;;;;;;;;;;;6396:323:14;12517:13:2;:11;:13::i;:::-;6655:57:14::1;6683:1;6687:9;6698:7;6707:4;6655:19;:57::i;6014:92::-:0;6058:16;6093:6;6086:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;6086:13:14;;;;;;;;;;;;;;;;;;;;;;;6014:92;:::o;3326:1386::-;2116:34:13;:32;:34::i;:::-;:44;;;2098:15;:62;:142;;;;2198:34;:32;:34::i;:::-;:42;;;2180:15;:60;2098:142;2081:191;;;2258:14;;-1:-1:-1;;;2258:14:13;;;;;;;;;;;2081:191;712:19:11::1;:17;:19::i;:::-;1635:9:6::2;1610:22;1604:29;1601:44:::0;1598:158:::2;;1677:10;1671:4;1664:24;1737:4;1731;1724:18;1598:158;1800:9;1776:22;1769:41:::0;3557:10:14::3;3547:21;::::0;;;:9:::3;:21;::::0;;;;;::::3;;3539:46;;;;-1:-1:-1::0;;;3539:46:14::3;;;;;;;;;;;;3596:38;3637:34;:32;:34::i;:::-;3596:75;;3772:12;3787:28;3805:9;;3787:17;:28::i;:::-;3919:11;:17:::0;;;::::3;::::0;;;;;;;3772:43;;-1:-1:-1;3919:17:14::3;;3918:18;3910:43;;;;-1:-1:-1::0;;;3910:43:14::3;;;;;;;;;;;;3963:11;:17:::0;;;::::3;::::0;;;;;;:24;;-1:-1:-1;;3963:24:14::3;3983:4;3963:24;::::0;;4041:665:::3;4061:20:::0;;::::3;4041:665;;;4098:33;4134:9;;4144:1;4134:12;;;;;;;:::i;:::-;;;::::0;;;::::3;::::0;-1:-1:-1;;4303:34:14;::::3;8288:13:::0;8280:3;8270:13;;;8269:33;8335:3;8325:13;;;4412:15:::3;4391:36:::0;::::3;::::0;:72:::3;;;4452:1;:11;;;4431:18;:32;4391:72;4387:145;;;4490:27;;-1:-1:-1::0;;;4490:27:14::3;;;;;;;;;;;4387:145;4573:62;4586:9;4597:10;4609:9;:25;;;4573:12;:62::i;:::-;4678:3;;;;;4084:622;;;;4041:665;;;;3529:1183;;1937:10:6::2;1913:22;1906:42;3326:1386:14::0;;;;:::o;2461:162:13:-;-1:-1:-1;;3769:8:3;;3867:1;3857:12;;3951:398;;;;4111:1;4107;4104;4100:9;4097:16;4085:9;4073:22;4070:44;4060:189;;4151:10;4145:4;4138:24;4226:4;4220;4213:18;4060:189;4288:1;4284;4279:3;4275:11;4271:19;4266:24;;3951:398;;2526:24:13::1;2543:6;2526:16;:24::i;:::-;2606:10;2560:34;:32;:34::i;:::-;:43;;:56:::0;;-1:-1:-1;;;;;;2560:56:13::1;-1:-1:-1::0;;;;;2560:56:13;;;::::1;::::0;;;::::1;::::0;;4445:264:3;;;;4549:1;4546;4539:12;4630:1;4624:4;4617:15;4666:28;4660:4;4654;4649:46;4431:288;2461:162:13;:::o;5573:200::-;5670:7;5717:13;5740:4;5747;5753:5;5760:4;5706:59;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;5696:70;;;;;;5689:77;;5573:200;;;;;:::o;10363:708:2:-;12517:13;:11;:13::i;:::-;10597:19:::1;10591:4;10584:33;10643:12;10637:4;10630:26;10705:4;10699;10689:21;10811:12;10805:19;10792:11;10789:36;10786:157;;;10857:10;10851:4;10844:24;10924:4;10918;10911:18;10786:157;11020:1;10999:23:::0;;11041::::1;11051:12:::0;11041:9:::1;:23::i;8348:349::-:0;12517:13;:11;:13::i;:::-;8520:8:::1;8516:2;8512:17;8502:150;;8562:10;8556:4;8549:24;8633:4;8627;8620:18;8502:150;8671:19;8681:8;8671:9;:19::i;7292:355::-:0;-1:-1:-1;;7498:18:2;7488:8;7485:32;7475:156;;7550:10;7544:4;7537:24;7612:4;7606;7599:18;9072:106:14;9137:34;9152:6;9159:10;9152:18;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;9152:18:14;9137:14;:34::i;9184:110::-;9256:31;9271:15;9256:14;:31::i;9165:202:13:-;9315:36;;9165:202::o;1380:141:11:-;787:16;:14;:16::i;:::-;-1:-1:-1;;;;;;;;;;;1497:17:11;;-1:-1:-1;;1497:17:11::1;::::0;;1380:141::o;6145:1089:2:-;-1:-1:-1;;7093:16:2;;-1:-1:-1;;;;;6941:26:2;;;;;;7053:38;7050:1;;7042:78;7177:27;6145:1089::o;8382:341:13:-;8638:78;8656:8;8666:9;8677:5;;8684;8691:4;;8697:1;8700:4;8706:9;;8638:17;:78::i;:::-;8382:341;;;;;;;;;:::o;9938:323:14:-;10122:7;10227:27;;-1:-1:-1;;;10227:27:14;;;;;;;;;;;8729:430:13;9015:91;9033:8;9043:9;9054:5;;9061;9068:4;;9074:13;9089:5;9096:9;;9015:17;:91::i;:::-;9116:36;9128:8;9138:13;9116:11;:36::i;:::-;8729:430;;;;;;;;;;:::o;1233:141:11:-;712:19;:17;:19::i;:::-;1292:25:::1;-1:-1:-1::0;;;;;;;;;;;1351:16:11;;-1:-1:-1;;1351:16:11::1;1363:4;1351:16;::::0;;-1:-1:-1;1233:141:11:o;2397:1407:5:-;2522:12;2619;2616:1134;;;2759:12;2756:1;2752:20;2738:12;2734:39;2885:12;2983:753;3176:20;;3167:30;;;3164:1;3160:38;3391:21;;;3453:4;3440:18;;;3433:48;3608:4;3602;3592:21;;3644:17;3692:15;;;2983:753;3682:36;2987:2;;2616:1134;-1:-1:-1;3774:14:5;;2397:1407;-1:-1:-1;;2397:1407:5:o;5005:427:13:-;12517:13:2;:11;:13::i;:::-;5145:7:13::1;5132:9;:20;5128:55;;5161:22;;-1:-1:-1::0;;;5161:22:13::1;;;;;;;;;;;5128:55;5236:5;5193:34;:32;:34::i;:::-;:40;;:48:::0;;-1:-1:-1;;;;;;5193:48:13::1;-1:-1:-1::0;;;;;5193:48:13;;;::::1;::::0;;;::::1;::::0;;5298:9;5251:34:::1;:32;:34::i;:::-;:44;;:56:::0;5362:7;5317:34:::1;:32;:34::i;:::-;:42;;:52:::0;5421:4;5379:34:::1;:32;:34::i;:::-;:39;;:46:::0;-1:-1:-1;;;;5005:427:13:o;978:121:11:-;-1:-1:-1;;;;;;;;;;;956:9:11;;;1039:54;;;1074:8;;-1:-1:-1;;;1074:8:11;;;;;;;;;;;10469:453:14;10565:13;10581:6;10588:10;10581:18;;;;;;;;:::i;:::-;;;;;;;;;;;-1:-1:-1;;;;;10581:18:14;;-1:-1:-1;10581:18:14;10609:307;;10684:12;10709:9;-1:-1:-1;;;;;10701:23:14;10733:6;10701:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;10683:62;;;10764:7;10759:40;;10780:19;;-1:-1:-1;;;10780:19:14;;;;;;;;;;;10759:40;10634:176;10609:307;;;10860:45;-1:-1:-1;;;;;10860:26:14;;10887:9;10898:6;10860:26;:45::i;4883:1190:2:-;-1:-1:-1;;;;;5793:26:2;-1:-1:-1;;5876:29:2;;;5793:26;6031:1;5991:38;6031:1;;5980:63;4883:1190;:::o;9300:632:14:-;-1:-1:-1;;;;;9362:19:14;;9358:568;;9445:21;9484:11;;9480:169;;9516:12;9541:7;-1:-1:-1;;11556:18:2;;11408:182;9541:7:14;-1:-1:-1;;;;;9533:21:14;9563:7;9533:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9515:61;;;9599:7;9594:40;;9615:19;;-1:-1:-1;;;9615:19:14;;;;;;;;;;;9358:568;9776:35;;-1:-1:-1;;;9776:35:14;;9805:4;9776:35;;;2423:51:16;9738:5:14;;9711:17;;-1:-1:-1;;;;;9776:20:14;;;;;2396:18:16;;9776:35:14;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;9758:53;-1:-1:-1;9829:11:14;;9825:91;;9860:41;9884:7;-1:-1:-1;;11556:18:2;;11408:182;9884:7:14;-1:-1:-1;;;;;9860:23:14;;;9893:7;9860:23;:41::i;1105:122:11:-;-1:-1:-1;;;;;;;;;;;956:9:11;;;1163:58;;1199:11;;-1:-1:-1;;;1199:11:11;;;;;;;;;;;9373:664:13;9668:17;9688:34;:32;:34::i;:::-;:44;;;-1:-1:-1;;;;;9688:44:13;;-1:-1:-1;9746:23:13;;9742:289;;9785:13;:235;;9921:99;;-1:-1:-1;;;9921:99:13;;-1:-1:-1;;;;;9921:32:13;;;;;:99;;9954:8;;9964:9;;9975:5;;;;9982;;9989:4;;;;9995:13;;10010:9;;;;9921:99;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9785:235;;;9817:85;;-1:-1:-1;;;9817:85:13;;-1:-1:-1;;;;;9817:33:13;;;;;:85;;9851:8;;9861:9;;9872:5;;;;9879;;9886:4;;;;9892:9;;;;9817:85;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9785:235;9658:379;9373:664;;;;;;;;;;;:::o;6482:1174::-;6568:38;6609:34;:32;:34::i;:::-;6690:10;;;;6734:37;;-1:-1:-1;;;6734:37:13;;6765:4;6734:37;;;2423:51:16;6690:10:13;;-1:-1:-1;;;;;;6690:10:13;;6653:21;;6690:10;;6734:22;;2396:18:16;;6734:37:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6711:60;-1:-1:-1;;;;;;6785:26:13;;6781:118;;6831:9;:13;6827:41;;6853:15;;-1:-1:-1;;;6853:15:13;;;;;;;;;;;6827:41;6882:7;;;6482:1174;;:::o;6781:118::-;6933:66;;-1:-1:-1;;;6933:66:13;;6978:4;6933:66;;;18854:51:16;18921:18;;;18914:34;;;6908:22:13;;-1:-1:-1;;;;;6933:36:13;;;;;18827:18:16;;6933:66:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6908:91;;7013:14;7031:1;7013:19;7009:111;;7052:9;:13;7048:41;;7074:15;;-1:-1:-1;;;7074:15:13;;;;;;;;;;;7048:41;7103:7;;;;6482:1174;;:::o;7009:111::-;7148:33;;-1:-1:-1;;;7148:33:13;;7175:4;7148:33;;;2423:51:16;7129:16:13;;-1:-1:-1;;;;;7148:18:13;;;;;2396::16;;7148:33:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7129:52;-1:-1:-1;;;;;;7195:22:13;;7191:459;;7250:14;7237:9;:27;7233:55;;7273:15;;-1:-1:-1;;;7273:15:13;;;;;;;;;;;7233:55;7303:12;7317:17;7338:12;-1:-1:-1;;;;;7338:17:13;7364:14;7338:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7302:82;;;;7461:7;7477:4;7453:30;;;;;-1:-1:-1;;;7453:30:13;;;;;;;;:::i;:::-;;;;;;;;;;7219:275;;7191:459;;;7518:9;:13;7514:41;;7540:15;;-1:-1:-1;;;7540:15:13;;;;;;;;;;;7514:41;7569:70;-1:-1:-1;;;;;7569:33:13;;7603:5;7610:12;7624:14;7569:33;:70::i;:::-;6558:1098;;;;;6482:1174;;:::o;317:160:12:-;426:43;;-1:-1:-1;;;;;18872:32:16;;;426:43:12;;;18854:51:16;18921:18;;;18914:34;;;399:71:12;;419:5;;441:14;;;;;18827:18:16;;426:43:12;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;426:43:12;;;;;;;;;;;399:19;:71::i;483:188::-;610:53;;-1:-1:-1;;;;;19179:32:16;;;610:53:12;;;19161:51:16;19248:32;;;19228:18;;;19221:60;19297:18;;;19290:34;;;583:81:12;;603:5;;625:18;;;;;19134::16;;610:53:12;18959:371:16;677:720:12;757:18;785:19;923:4;920:1;913:4;907:11;900:4;894;890:15;887:1;880:5;873;868:60;980:7;970:176;;1024:4;1018:11;1069:16;1066:1;1061:3;1046:40;1115:16;1110:3;1103:29;970:176;-1:-1:-1;;1223:1:12;1217:8;1173:16;;-1:-1:-1;1249:15:12;;:68;;1301:11;1316:1;1301:16;;1249:68;;;-1:-1:-1;;;;;1267:26:12;;;:31;1249:68;1245:146;;;1340:40;;-1:-1:-1;;;1340:40:12;;-1:-1:-1;;;;;2441:32:16;;1340:40:12;;;2423:51:16;2396:18;;1340:40:12;2277:203:16;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;;;;;;;;;14:390:16;100:8;110:6;164:3;157:4;149:6;145:17;141:27;131:55;;182:1;179;172:12;131:55;-1:-1:-1;205:20:16;;-1:-1:-1;;;;;237:30:16;;234:50;;;280:1;277;270:12;234:50;317:4;309:6;305:17;293:29;;377:3;370:4;360:6;357:1;353:14;345:6;341:27;337:38;334:47;331:67;;;394:1;391;384:12;331:67;14:390;;;;;:::o;409:494::-;529:6;537;590:2;578:9;569:7;565:23;561:32;558:52;;;606:1;603;596:12;558:52;646:9;633:23;-1:-1:-1;;;;;671:6:16;668:30;665:50;;;711:1;708;701:12;665:50;750:93;835:7;826:6;815:9;811:22;750:93;:::i;:::-;862:8;;724:119;;-1:-1:-1;409:494:16;-1:-1:-1;;;;409:494:16:o;1090:127::-;1151:10;1146:3;1142:20;1139:1;1132:31;1182:4;1179:1;1172:15;1206:4;1203:1;1196:15;1222:725;1264:5;1317:3;1310:4;1302:6;1298:17;1294:27;1284:55;;1335:1;1332;1325:12;1284:55;1375:6;1362:20;-1:-1:-1;;;;;1397:6:16;1394:30;1391:56;;;1427:18;;:::i;:::-;1476:2;1470:9;1568:2;1530:17;;-1:-1:-1;;1526:31:16;;;1559:2;1522:40;1518:54;1506:67;;-1:-1:-1;;;;;1588:34:16;;1624:22;;;1585:62;1582:88;;;1650:18;;:::i;:::-;1686:2;1679:22;1710;;;1751:19;;;1772:4;1747:30;1744:39;-1:-1:-1;1741:59:16;;;1796:1;1793;1786:12;1741:59;1860:6;1853:4;1845:6;1841:17;1834:4;1826:6;1822:17;1809:58;1915:1;1887:19;;;1908:4;1883:30;1876:41;;;;1891:6;1222:725;-1:-1:-1;;;1222:725:16:o;1952:320::-;2020:6;2073:2;2061:9;2052:7;2048:23;2044:32;2041:52;;;2089:1;2086;2079:12;2041:52;2129:9;2116:23;-1:-1:-1;;;;;2154:6:16;2151:30;2148:50;;;2194:1;2191;2184:12;2148:50;2217:49;2258:7;2249:6;2238:9;2234:22;2217:49;:::i;:::-;2207:59;1952:320;-1:-1:-1;;;;1952:320:16:o;2485:367::-;2548:8;2558:6;2612:3;2605:4;2597:6;2593:17;2589:27;2579:55;;2630:1;2627;2620:12;2579:55;-1:-1:-1;2653:20:16;;-1:-1:-1;;;;;2685:30:16;;2682:50;;;2728:1;2725;2718:12;2682:50;2765:4;2757:6;2753:17;2741:29;;2825:3;2818:4;2808:6;2805:1;2801:14;2793:6;2789:27;2785:38;2782:47;2779:67;;;2842:1;2839;2832:12;2857:598;2949:6;2957;2965;3018:2;3006:9;2997:7;2993:23;2989:32;2986:52;;;3034:1;3031;3024:12;2986:52;3074:9;3061:23;-1:-1:-1;;;;;3099:6:16;3096:30;3093:50;;;3139:1;3136;3129:12;3093:50;3178:70;3240:7;3231:6;3220:9;3216:22;3178:70;:::i;:::-;3267:8;;-1:-1:-1;3152:96:16;-1:-1:-1;;3352:2:16;3337:18;;3324:32;3392:13;;3385:21;3375:32;;3365:60;;3421:1;3418;3411:12;3365:60;3444:5;3434:15;;;2857:598;;;;;:::o;3460:131::-;-1:-1:-1;;;;;3535:31:16;;3525:42;;3515:70;;3581:1;3578;3571:12;3596:247;3655:6;3708:2;3696:9;3687:7;3683:23;3679:32;3676:52;;;3724:1;3721;3714:12;3676:52;3763:9;3750:23;3782:31;3807:5;3782:31;:::i;:::-;3832:5;3596:247;-1:-1:-1;;;3596:247:16:o;3848:487::-;3925:6;3933;3941;3994:2;3982:9;3973:7;3969:23;3965:32;3962:52;;;4010:1;4007;4000:12;3962:52;4049:9;4036:23;4068:31;4093:5;4068:31;:::i;:::-;4118:5;4196:2;4181:18;;4168:32;;-1:-1:-1;4299:2:16;4284:18;;;4271:32;;3848:487;-1:-1:-1;;;3848:487:16:o;4522:226::-;4581:6;4634:2;4622:9;4613:7;4609:23;4605:32;4602:52;;;4650:1;4647;4640:12;4602:52;-1:-1:-1;4695:23:16;;4522:226;-1:-1:-1;4522:226:16:o;5103:289::-;5145:3;5183:5;5177:12;5210:6;5205:3;5198:19;5266:6;5259:4;5252:5;5248:16;5241:4;5236:3;5232:14;5226:47;5318:1;5311:4;5302:6;5297:3;5293:16;5289:27;5282:38;5381:4;5374:2;5370:7;5365:2;5357:6;5353:15;5349:29;5344:3;5340:39;5336:50;5329:57;;;5103:289;;;;:::o;5397:220::-;5546:2;5535:9;5528:21;5509:4;5566:45;5607:2;5596:9;5592:18;5584:6;5566:45;:::i;6067:437::-;6153:6;6161;6214:2;6202:9;6193:7;6189:23;6185:32;6182:52;;;6230:1;6227;6220:12;6182:52;6270:9;6257:23;-1:-1:-1;;;;;6295:6:16;6292:30;6289:50;;;6335:1;6332;6325:12;6289:50;6374:70;6436:7;6427:6;6416:9;6412:22;6374:70;:::i;6509:347::-;6560:8;6570:6;6624:3;6617:4;6609:6;6605:17;6601:27;6591:55;;6642:1;6639;6632:12;6591:55;-1:-1:-1;6665:20:16;;-1:-1:-1;;;;;6697:30:16;;6694:50;;;6740:1;6737;6730:12;6694:50;6777:4;6769:6;6765:17;6753:29;;6829:3;6822:4;6813:6;6805;6801:19;6797:30;6794:39;6791:59;;;6846:1;6843;6836:12;6861:1158;6996:6;7004;7012;7020;7028;7036;7044;7097:3;7085:9;7076:7;7072:23;7068:33;7065:53;;;7114:1;7111;7104:12;7065:53;7154:9;7141:23;-1:-1:-1;;;;;7179:6:16;7176:30;7173:50;;;7219:1;7216;7209:12;7173:50;7258:70;7320:7;7311:6;7300:9;7296:22;7258:70;:::i;:::-;7347:8;;-1:-1:-1;7232:96:16;-1:-1:-1;;7451:2:16;7436:18;;7423:32;;-1:-1:-1;7532:2:16;7517:18;;7504:32;-1:-1:-1;;;;;7548:32:16;;7545:52;;;7593:1;7590;7583:12;7545:52;7632:60;7684:7;7673:8;7662:9;7658:24;7632:60;:::i;:::-;7711:8;;-1:-1:-1;7606:86:16;-1:-1:-1;;7799:2:16;7784:18;;7771:32;-1:-1:-1;;;;;7815:32:16;;7812:52;;;7860:1;7857;7850:12;7812:52;7899:60;7951:7;7940:8;7929:9;7925:24;7899:60;:::i;:::-;6861:1158;;;;-1:-1:-1;6861:1158:16;;-1:-1:-1;6861:1158:16;;;;7873:86;;-1:-1:-1;;;6861:1158:16:o;8255:1300::-;8399:6;8407;8415;8423;8431;8439;8447;8455;8508:3;8496:9;8487:7;8483:23;8479:33;8476:53;;;8525:1;8522;8515:12;8476:53;8564:9;8551:23;8583:31;8608:5;8583:31;:::i;:::-;8633:5;-1:-1:-1;8689:2:16;8674:18;;8661:32;-1:-1:-1;;;;;8705:30:16;;8702:50;;;8748:1;8745;8738:12;8702:50;8787:70;8849:7;8840:6;8829:9;8825:22;8787:70;:::i;:::-;8876:8;;-1:-1:-1;8761:96:16;-1:-1:-1;;8984:2:16;8969:18;;8956:32;;-1:-1:-1;9067:2:16;9052:18;;9039:32;-1:-1:-1;;;;;9083:32:16;;9080:52;;;9128:1;9125;9118:12;9080:52;9167:60;9219:7;9208:8;9197:9;9193:24;9167:60;:::i;:::-;9246:8;;-1:-1:-1;9141:86:16;-1:-1:-1;;9334:3:16;9319:19;;9306:33;-1:-1:-1;;;;;9351:32:16;;9348:52;;;9396:1;9393;9386:12;9348:52;9435:60;9487:7;9476:8;9465:9;9461:24;9435:60;:::i;:::-;8255:1300;;;;-1:-1:-1;8255:1300:16;;-1:-1:-1;8255:1300:16;;;;;;9514:8;-1:-1:-1;;;8255:1300:16:o;9560:551::-;9655:6;9663;9671;9724:2;9712:9;9703:7;9699:23;9695:32;9692:52;;;9740:1;9737;9730:12;9692:52;9780:9;9767:23;-1:-1:-1;;;;;9805:6:16;9802:30;9799:50;;;9845:1;9842;9835:12;9799:50;9884:70;9946:7;9937:6;9926:9;9922:22;9884:70;:::i;:::-;9973:8;;9858:96;;-1:-1:-1;10077:2:16;10062:18;;;;10049:32;;9560:551;-1:-1:-1;;;;9560:551:16:o;10116:608::-;10202:6;10210;10218;10226;10279:3;10267:9;10258:7;10254:23;10250:33;10247:53;;;10296:1;10293;10286:12;10247:53;10335:9;10322:23;10354:31;10379:5;10354:31;:::i;:::-;10404:5;10482:2;10467:18;;10454:32;;-1:-1:-1;10585:2:16;10570:18;;10557:32;;10688:2;10673:18;10660:32;;-1:-1:-1;10116:608:16;-1:-1:-1;;;10116:608:16:o;10729:637::-;10919:2;10931:21;;;11001:13;;10904:18;;;11023:22;;;10871:4;;11102:15;;;11076:2;11061:18;;;10871:4;11145:195;11159:6;11156:1;11153:13;11145:195;;;11224:13;;-1:-1:-1;;;;;11220:39:16;11208:52;;11289:2;11315:15;;;;11280:12;;;;11256:1;11174:9;11145:195;;;-1:-1:-1;11357:3:16;;10729:637;-1:-1:-1;;;;;10729:637:16:o;11371:825::-;11527:6;11535;11543;11551;11604:2;11592:9;11583:7;11579:23;11575:32;11572:52;;;11620:1;11617;11610:12;11572:52;11660:9;11647:23;-1:-1:-1;;;;;11685:6:16;11682:30;11679:50;;;11725:1;11722;11715:12;11679:50;11764:93;11849:7;11840:6;11829:9;11825:22;11764:93;:::i;:::-;11876:8;;-1:-1:-1;11738:119:16;-1:-1:-1;;11964:2:16;11949:18;;11936:32;-1:-1:-1;;;;;11980:32:16;;11977:52;;;12025:1;12022;12015:12;11977:52;12064:72;12128:7;12117:8;12106:9;12102:24;12064:72;:::i;:::-;11371:825;;;;-1:-1:-1;12155:8:16;-1:-1:-1;;;;11371:825:16:o;12201:575::-;12287:6;12295;12303;12356:2;12344:9;12335:7;12331:23;12327:32;12324:52;;;12372:1;12369;12362:12;12324:52;12411:9;12398:23;12430:31;12455:5;12430:31;:::i;:::-;12480:5;-1:-1:-1;12558:2:16;12543:18;;12530:32;;-1:-1:-1;12639:2:16;12624:18;;12611:32;-1:-1:-1;;;;;12655:30:16;;12652:50;;;12698:1;12695;12688:12;12652:50;12721:49;12762:7;12753:6;12742:9;12738:22;12721:49;:::i;:::-;12711:59;;;12201:575;;;;;:::o;12781:827::-;13047:2;13059:21;;;13032:18;;13115:22;;;12999:4;13194:6;13168:2;13153:18;;12999:4;13228:354;13242:6;13239:1;13236:13;13228:354;;;13327:20;;13360:18;;13456:2;13444:15;;;13431:29;13480:12;;;13473:29;13531:2;13557:15;;;;13522:12;;;;13264:1;13257:9;13228:354;;;-1:-1:-1;13599:3:16;12781:827;-1:-1:-1;;;;;12781:827:16:o;13613:259::-;13691:6;13744:2;13732:9;13723:7;13719:23;13715:32;13712:52;;;13760:1;13757;13750:12;13712:52;13792:9;13786:16;13811:31;13836:5;13811:31;:::i;13877:127::-;13938:10;13933:3;13929:20;13926:1;13919:31;13969:4;13966:1;13959:15;13993:4;13990:1;13983:15;14009:501;14241:3;14279:6;14273:13;14325:6;14318:4;14310:6;14306:17;14301:3;14295:37;14387:34;14351:16;;14376:46;;;-1:-1:-1;;;;14446:4:16;14438:13;;14431:46;14501:2;14493:11;;14009:501;-1:-1:-1;14009:501:16:o;14515:266::-;14603:6;14598:3;14591:19;14655:6;14648:5;14641:4;14636:3;14632:14;14619:43;-1:-1:-1;14707:1:16;14682:16;;;14700:4;14678:27;;;14671:38;;;;14763:2;14742:15;;;-1:-1:-1;;14738:29:16;14729:39;;;14725:50;;14515:266::o;14786:412::-;15028:1;15024;15019:3;15015:11;15011:19;15003:6;14999:32;14988:9;14981:51;15068:6;15063:2;15052:9;15048:18;15041:34;15111:2;15106;15095:9;15091:18;15084:30;14962:4;15131:61;15188:2;15177:9;15173:18;15165:6;15157;15131:61;:::i;:::-;15123:69;14786:412;-1:-1:-1;;;;;;14786:412:16:o;15203:557::-;15444:25;;;-1:-1:-1;;;;;15505:32:16;;;15500:2;15485:18;;15478:60;15574:32;;15569:2;15554:18;;15547:60;15638:2;15623:18;;15616:34;;;15525:3;15681;15666:19;;15659:32;;;-1:-1:-1;;15708:46:16;;15734:19;;15726:6;15708:46;:::i;:::-;15700:54;15203:557;-1:-1:-1;;;;;;;15203:557:16:o;15975:184::-;16045:6;16098:2;16086:9;16077:7;16073:23;16069:32;16066:52;;;16114:1;16111;16104:12;16066:52;-1:-1:-1;16137:16:16;;15975:184;-1:-1:-1;15975:184:16:o;16164:311::-;16252:19;;;16234:3;-1:-1:-1;;;;;16283:31:16;;16280:51;;;16327:1;16324;16317:12;16280:51;16363:6;16360:1;16356:14;16415:8;16408:5;16401:4;16396:3;16392:14;16379:45;16444:18;;;;16464:4;16440:29;;16164:311;-1:-1:-1;;;16164:311:16:o;16480:1003::-;-1:-1:-1;;;;;16893:32:16;;;16875:51;;16962:32;;16957:2;16942:18;;16935:60;17031:3;17026:2;17011:18;;17004:31;;;-1:-1:-1;;17058:74:16;;17112:19;;17104:6;17096;17058:74;:::i;:::-;17168:6;17163:2;17152:9;17148:18;17141:34;17224:9;17216:6;17212:22;17206:3;17195:9;17191:19;17184:51;17258:49;17300:6;17292;17284;17258:49;:::i;:::-;17244:63;;17344:6;17338:3;17327:9;17323:19;17316:35;17400:9;17392:6;17388:22;17382:3;17371:9;17367:19;17360:51;17428:49;17470:6;17462;17454;17428:49;:::i;:::-;17420:57;16480:1003;-1:-1:-1;;;;;;;;;;;;;16480:1003:16:o;17488:931::-;-1:-1:-1;;;;;17873:32:16;;;17855:51;;17942:32;;17937:2;17922:18;;17915:60;18011:3;18006:2;17991:18;;17984:31;;;-1:-1:-1;;18038:74:16;;18092:19;;18084:6;18076;18038:74;:::i;:::-;18148:6;18143:2;18132:9;18128:18;18121:34;18204:9;18196:6;18192:22;18186:3;18175:9;18171:19;18164:51;18238:49;18280:6;18272;18264;18238:49;:::i;:::-;18224:63;;18336:9;18328:6;18324:22;18318:3;18307:9;18303:19;18296:51;18364:49;18406:6;18398;18390;18364:49;:::i;:::-;18356:57;17488:931;-1:-1:-1;;;;;;;;;;;;17488:931:16:o
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in HYPE
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.