Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 29479055 | 49 days ago | Contract Creation | 0 FRAX | |||
| 29479051 | 49 days ago | Contract Creation | 0 FRAX | |||
| 29479046 | 49 days ago | Contract Creation | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
ContractFactory
Compiler Version
v0.8.30+commit.73712a01
Optimization Enabled:
Yes with 100000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.30;
import {OwnableRoles} from "solady/auth/OwnableRoles.sol";
import {CREATE3} from "solady/utils/CREATE3.sol";
import {ECDSA} from "solady/utils/ECDSA.sol";
import {LibClone} from "solady/utils/LibClone.sol";
/**
* @title ContractFactory
* @notice Contract factory with version tracking
* @dev Inherits Ownable for flexible deployment management
*/
contract ContractFactory is OwnableRoles {
uint256 internal constant MANAGER_ROLE = _ROLE_0;
// Errors
error DeploymentFailed();
error InvalidDeploymentType();
error InvalidImplementation();
error InvalidSignature();
error SignatureExpired();
error InvalidNonce();
// Events
event ContractDeployed(bytes32 id, uint256 version, address contractAddress, bytes32 salt);
event ProxyDeployed(bytes32 id, uint256 version, address proxyAddress, address implementation, bytes32 salt);
event NonceUsed(address account, uint256 nonce);
// Enums for contract deployment (bytecode-based)
enum ContractDeploymentType {
CREATE, // Standard CREATE deployment
CREATE2, // CREATE2 deterministic deployment
CREATE3 // CREATE3 deterministic deployment (via proxy)
}
// Enums for proxy deployment (address-based)
enum ProxyDeploymentType {
CLONE, // Deterministic minimal proxy
CLONE_IMMUTABLE_ARGS, // Deterministic proxy with immutable args
ERC1967, // ERC1967 upgradeable proxy
ERC1967_IMMUTABLE_ARGS, // ERC1967 proxy with immutable args
ERC1967_BEACON, // ERC1967 beacon proxy
ERC1967_BEACON_IMMUTABLE_ARGS // ERC1967 beacon proxy with immutable args
}
// State
// Mapping from contract ID to version to deployed address
mapping(bytes32 => mapping(uint256 => address)) internal deployments;
// Mapping from contract ID to latest version
mapping(bytes32 => uint256) public latestVersion;
// Mapping from account to nonce to used status for replay protection
mapping(address => mapping(uint256 => bool)) public nonceUsed;
// Structs for signature-based deployment
struct ContractDeploymentRequest {
bytes32 id;
ContractDeploymentType deployType;
bytes bytecode;
bytes constructorArgs;
bytes32 salt;
bytes[] postDeployCalls;
uint256 nonce;
uint256 deadline;
}
struct ProxyDeploymentRequest {
bytes32 id;
ProxyDeploymentType deployType;
address implementation;
bytes data;
bytes32 salt;
bytes[] postDeployCalls;
uint256 nonce;
uint256 deadline;
}
constructor(address owner, address manager) {
_initializeOwner(owner);
_grantRoles(manager, MANAGER_ROLE);
}
/**
* @notice Deploy a contract using bytecode
* @param id Unique identifier for the contract type
* @param deployType Contract deployment type
* @param bytecode Contract bytecode
* @param constructorArgs Constructor arguments
* @param salt Salt for deterministic deployment (used as nonce for CREATE)
* @param postDeployCalls Array of calls to execute after deployment
* @return deployed The deployed contract address
*/
function deployContract(
bytes32 id,
ContractDeploymentType deployType,
bytes calldata bytecode,
bytes calldata constructorArgs,
bytes32 salt,
bytes[] calldata postDeployCalls
) external onlyRolesOrOwner(MANAGER_ROLE) returns (address deployed) {
return _deployContractInternal(id, deployType, bytecode, constructorArgs, salt, postDeployCalls);
}
/**
* @notice Deploy a proxy or clone
* @param id Unique identifier for the contract type
* @param deployType Proxy/clone deployment type
* @param implementation Implementation address (or beacon address for beacon proxies)
* @param data Immutable args or initialization data
* @param salt Salt for deterministic deployment (ignored for CREATE)
* @param postDeployCalls Array of calls to execute after deployment
* @return deployed The deployed proxy address
*/
function deployProxy(
bytes32 id,
ProxyDeploymentType deployType,
address implementation,
bytes calldata data,
bytes32 salt,
bytes[] calldata postDeployCalls
) external onlyRolesOrOwner(MANAGER_ROLE) returns (address deployed) {
return _deployProxyInternal(id, deployType, implementation, data, salt, postDeployCalls);
}
/**
* @notice Deploy using CREATE
* @param bytecode The contract bytecode with constructor args
* @return deployed The deployed contract address
*/
function _deployCreate(bytes memory bytecode) internal returns (address deployed) {
assembly {
deployed := create(0, add(bytecode, 0x20), mload(bytecode))
}
if (deployed == address(0)) {
revert DeploymentFailed();
}
}
/**
* @notice Deploy using CREATE2
* @param bytecode The contract bytecode with constructor args
* @param salt The salt for deterministic deployment
* @return deployed The deployed contract address
*/
function _deployCreate2(bytes memory bytecode, bytes32 salt) internal returns (address deployed) {
assembly {
deployed := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
}
if (deployed == address(0)) {
revert DeploymentFailed();
}
}
/**
* @notice Get deployment address for a specific version
* @param id Contract identifier
* @param version Version number (0 for latest)
* @return The deployed contract address
*/
function getDeployment(bytes32 id, uint256 version) external view returns (address) {
if (version == 0) {
version = latestVersion[id];
}
return deployments[id][version];
}
/**
* @notice Compute deployment address for contracts
* @param deployType The contract deployment type
* @param bytecode The contract bytecode
* @param constructorArgs The constructor arguments
* @param salt The salt for deployment (ignored for CREATE)
* @return The computed address
*/
function computeDeployAddress(
ContractDeploymentType deployType,
bytes calldata bytecode,
bytes calldata constructorArgs,
bytes32 salt
) external view returns (address) {
if (deployType == ContractDeploymentType.CREATE2) {
bytes memory creationCode =
constructorArgs.length > 0 ? abi.encodePacked(bytecode, constructorArgs) : bytecode;
return address(
uint160(
uint256(keccak256(abi.encodePacked(bytes1(0xff), address(this), salt, keccak256(creationCode))))
)
);
} else if (deployType == ContractDeploymentType.CREATE3) {
return CREATE3.predictDeterministicAddress(salt, address(this));
} else {
revert InvalidDeploymentType();
}
}
/**
* @notice Compute deployment address for proxies and clones
* @param deployType The deployment type
* @param implementation The implementation address (or beacon address for beacon proxies)
* @param data The data (immutable args or init data)
* @param salt The salt for deterministic deployment
* @return The computed address
*/
function computeProxyAddress(
ProxyDeploymentType deployType,
address implementation,
bytes calldata data,
bytes32 salt
) external view returns (address) {
if (deployType == ProxyDeploymentType.CLONE) {
return LibClone.predictDeterministicAddress(implementation, salt, address(this));
} else if (deployType == ProxyDeploymentType.CLONE_IMMUTABLE_ARGS) {
return LibClone.predictDeterministicAddress(
implementation,
data, // immutable args
salt,
address(this)
);
} else if (deployType == ProxyDeploymentType.ERC1967) {
return LibClone.predictDeterministicAddressERC1967(implementation, salt, address(this));
} else if (deployType == ProxyDeploymentType.ERC1967_IMMUTABLE_ARGS) {
return LibClone.predictDeterministicAddressERC1967(
implementation,
data, // args
salt,
address(this)
);
} else if (deployType == ProxyDeploymentType.ERC1967_BEACON) {
return LibClone.predictDeterministicAddressERC1967BeaconProxy(
implementation, // beacon address
salt,
address(this)
);
} else if (deployType == ProxyDeploymentType.ERC1967_BEACON_IMMUTABLE_ARGS) {
return LibClone.predictDeterministicAddressERC1967BeaconProxy(
implementation, // beacon address
data, // args
salt,
address(this)
);
} else {
revert InvalidDeploymentType();
}
}
/**
* @notice Deploy a contract using a signature for authorization
* @param request The deployment request containing all parameters
* @param signature The ECDSA signature from an authorized manager
* @return deployed The deployed contract address
*/
function deployContractWithSignature(ContractDeploymentRequest calldata request, bytes calldata signature)
external
returns (address deployed)
{
// Verify signature
_verifyContractDeploymentSignature(request, signature);
// Deploy using internal function
return _deployContractInternal(
request.id,
request.deployType,
request.bytecode,
request.constructorArgs,
request.salt,
request.postDeployCalls
);
}
/**
* @notice Deploy a proxy using a signature for authorization
* @param request The deployment request containing all parameters
* @param signature The ECDSA signature from an authorized manager
* @return deployed The deployed proxy address
*/
function deployProxyWithSignature(ProxyDeploymentRequest calldata request, bytes calldata signature)
external
returns (address deployed)
{
// Verify signature
_verifyProxyDeploymentSignature(request, signature);
// Deploy using internal function
return _deployProxyInternal(
request.id, request.deployType, request.implementation, request.data, request.salt, request.postDeployCalls
);
}
/**
* @notice Recover signer address from contract deployment request signature
* @param request The deployment request
* @param signature The ECDSA signature
* @return The recovered signer address
*/
function _recoverSigner(ContractDeploymentRequest calldata request, bytes calldata signature)
internal
view
returns (address)
{
bytes32 structHash = keccak256(
abi.encode(
keccak256(
"ContractDeploymentRequest(bytes32 id,uint8 deployType,bytes bytecode,bytes constructorArgs,bytes32 salt,bytes[] postDeployCalls,uint256 nonce,uint256 deadline)"
),
request.id,
request.deployType,
keccak256(request.bytecode),
keccak256(request.constructorArgs),
request.salt,
_hashBytesArray(request.postDeployCalls),
request.nonce,
request.deadline
)
);
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", _domainSeparator(), structHash));
return ECDSA.recover(digest, signature);
}
/**
* @notice Recover signer address from proxy deployment request signature
* @param request The deployment request
* @param signature The ECDSA signature
* @return The recovered signer address
*/
function _recoverProxySigner(ProxyDeploymentRequest calldata request, bytes calldata signature)
internal
view
returns (address)
{
bytes32 structHash = keccak256(
abi.encode(
keccak256(
"ProxyDeploymentRequest(bytes32 id,uint8 deployType,address implementation,bytes data,bytes32 salt,bytes[] postDeployCalls,uint256 nonce,uint256 deadline)"
),
request.id,
request.deployType,
request.implementation,
keccak256(request.data),
request.salt,
_hashBytesArray(request.postDeployCalls),
request.nonce,
request.deadline
)
);
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", _domainSeparator(), structHash));
return ECDSA.recover(digest, signature);
}
/**
* @notice Hash an array of bytes for EIP-712 encoding
* @param data Array of bytes to hash
* @return Hash of the array
*/
function _hashBytesArray(bytes[] calldata data) internal pure returns (bytes32) {
bytes32[] memory hashes = new bytes32[](data.length);
for (uint256 i = 0; i < data.length; i++) {
hashes[i] = keccak256(data[i]);
}
return keccak256(abi.encodePacked(hashes));
}
/**
* @notice Get the EIP-712 domain separator
* @return The domain separator
*/
function _domainSeparator() internal view returns (bytes32) {
return keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256("ContractFactory"),
keccak256("1"),
block.chainid,
address(this)
)
);
}
/**
* @notice Internal function to deploy a contract
* @param id Unique identifier for the contract type
* @param deployType Contract deployment type
* @param bytecode Contract bytecode
* @param constructorArgs Constructor arguments
* @param salt Salt for deterministic deployment
* @param postDeployCalls Array of calls to execute after deployment
* @return deployed The deployed contract address
*/
function _deployContractInternal(
bytes32 id,
ContractDeploymentType deployType,
bytes calldata bytecode,
bytes calldata constructorArgs,
bytes32 salt,
bytes[] calldata postDeployCalls
) internal returns (address deployed) {
uint256 newVersion = latestVersion[id] + 1;
bytes memory creationCode = constructorArgs.length > 0 ? abi.encodePacked(bytecode, constructorArgs) : bytecode;
if (deployType == ContractDeploymentType.CREATE) {
deployed = _deployCreate(creationCode);
} else if (deployType == ContractDeploymentType.CREATE2) {
deployed = _deployCreate2(creationCode, salt);
} else if (deployType == ContractDeploymentType.CREATE3) {
deployed = CREATE3.deployDeterministic(creationCode, salt);
} else {
revert InvalidDeploymentType();
}
// Execute post-deployment calls
_executePostDeployCalls(deployed, postDeployCalls);
// Update state and emit event
deployments[id][newVersion] = deployed;
latestVersion[id] = newVersion;
emit ContractDeployed(id, newVersion, deployed, salt);
return deployed;
}
/**
* @notice Internal function to deploy a proxy
* @param id Unique identifier for the contract type
* @param deployType Proxy deployment type
* @param implementation Implementation address
* @param data Immutable args or initialization data
* @param salt Salt for deterministic deployment
* @param postDeployCalls Array of calls to execute after deployment
* @return deployed The deployed proxy address
*/
function _deployProxyInternal(
bytes32 id,
ProxyDeploymentType deployType,
address implementation,
bytes calldata data,
bytes32 salt,
bytes[] calldata postDeployCalls
) internal returns (address deployed) {
// Validate implementation
if (implementation.code.length == 0) {
revert InvalidImplementation();
}
uint256 newVersion = latestVersion[id] + 1;
if (deployType == ProxyDeploymentType.CLONE) {
deployed = LibClone.cloneDeterministic(implementation, salt);
} else if (deployType == ProxyDeploymentType.CLONE_IMMUTABLE_ARGS) {
deployed = LibClone.cloneDeterministic(implementation, data, salt);
} else if (deployType == ProxyDeploymentType.ERC1967) {
deployed = LibClone.deployDeterministicERC1967(implementation, salt);
} else if (deployType == ProxyDeploymentType.ERC1967_IMMUTABLE_ARGS) {
deployed = LibClone.deployDeterministicERC1967(implementation, data, salt);
} else if (deployType == ProxyDeploymentType.ERC1967_BEACON) {
deployed = LibClone.deployDeterministicERC1967BeaconProxy(implementation, salt);
} else if (deployType == ProxyDeploymentType.ERC1967_BEACON_IMMUTABLE_ARGS) {
deployed = LibClone.deployDeterministicERC1967BeaconProxy(implementation, data, salt);
} else {
revert InvalidDeploymentType();
}
// Execute post-deployment calls
_executePostDeployCalls(deployed, postDeployCalls);
// Update state and emit event
deployments[id][newVersion] = deployed;
latestVersion[id] = newVersion;
emit ProxyDeployed(id, newVersion, deployed, implementation, salt);
return deployed;
}
/**
* @notice Execute post-deployment calls
* @param target The target address for the calls
* @param calls Array of encoded function calls
*/
function _executePostDeployCalls(address target, bytes[] calldata calls) internal {
for (uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory result) = target.call(calls[i]);
if (!success) {
assembly {
revert(add(result, 32), mload(result))
}
}
}
}
/**
* @notice Verify contract deployment signature
* @param request The deployment request
* @param signature The ECDSA signature
*/
function _verifyContractDeploymentSignature(ContractDeploymentRequest calldata request, bytes calldata signature)
internal
{
// Verify deadline
if (block.timestamp > request.deadline) {
revert SignatureExpired();
}
// Verify nonce and authorization
address signer = _recoverSigner(request, signature);
if (nonceUsed[signer][request.nonce]) {
revert InvalidNonce();
}
if (!hasAnyRole(signer, MANAGER_ROLE) && signer != owner()) {
revert InvalidSignature();
}
// Mark nonce as used to prevent replay
nonceUsed[signer][request.nonce] = true;
emit NonceUsed(signer, request.nonce);
}
/**
* @notice Verify proxy deployment signature
* @param request The deployment request
* @param signature The ECDSA signature
*/
function _verifyProxyDeploymentSignature(ProxyDeploymentRequest calldata request, bytes calldata signature)
internal
{
// Verify deadline
if (block.timestamp > request.deadline) {
revert SignatureExpired();
}
// Verify nonce and authorization
address signer = _recoverProxySigner(request, signature);
if (nonceUsed[signer][request.nonce]) {
revert InvalidNonce();
}
if (!hasAnyRole(signer, MANAGER_ROLE) && signer != owner()) {
revert InvalidSignature();
}
// Mark nonce as used to prevent replay
nonceUsed[signer][request.nonce] = true;
emit NonceUsed(signer, request.nonce);
}
}// 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;
import {Ownable} from "./Ownable.sol";
/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/OwnableRoles.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 OwnableRoles is Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The `user`'s roles is updated to `roles`.
/// Each bit of `roles` represents whether the role is set.
event RolesUpdated(address indexed user, uint256 indexed roles);
/// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The role slot of `user` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
/// let roleSlot := keccak256(0x00, 0x20)
/// ```
/// This automatically ignores the upper bits of the `user` in case
/// they are not clean, as well as keep the `keccak256` under 32-bytes.
///
/// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Overwrite the roles directly without authorization guard.
function _setRoles(address user, uint256 roles) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Store the new value.
sstore(keccak256(0x0c, 0x20), roles)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
}
}
/// @dev Updates the roles directly without authorization guard.
/// If `on` is true, each set bit of `roles` will be turned on,
/// otherwise, each set bit of `roles` will be turned off.
function _updateRoles(address user, uint256 roles, bool on) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
let roleSlot := keccak256(0x0c, 0x20)
// Load the current value.
let current := sload(roleSlot)
// Compute the updated roles if `on` is true.
let updated := or(current, roles)
// Compute the updated roles if `on` is false.
// Use `and` to compute the intersection of `current` and `roles`,
// `xor` it with `current` to flip the bits in the intersection.
if iszero(on) { updated := xor(current, and(current, roles)) }
// Then, store the new value.
sstore(roleSlot, updated)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
}
}
/// @dev Grants the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn on.
function _grantRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, true);
}
/// @dev Removes the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn off.
function _removeRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, false);
}
/// @dev Throws if the sender does not have any of the `roles`.
function _checkRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Throws if the sender is not the owner,
/// and does not have any of the `roles`.
/// Checks for ownership first, then lazily checks for roles.
function _checkOwnerOrRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Throws if the sender does not have any of the `roles`,
/// and is not the owner.
/// Checks for roles first, then lazily checks for ownership.
function _checkRolesOrOwner(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
// We don't need to mask the values of `ordinals`, as Solidity
// cleans dirty upper bits when storing variables into memory.
roles := or(shl(mload(add(ordinals, i)), 1), roles)
}
}
}
/// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
/// @solidity memory-safe-assembly
assembly {
// Grab the pointer to the free memory.
ordinals := mload(0x40)
let ptr := add(ordinals, 0x20)
let o := 0
// The absence of lookup tables, De Bruijn, etc., here is intentional for
// smaller bytecode, as this function is not meant to be called on-chain.
for { let t := roles } 1 {} {
mstore(ptr, o)
// `shr` 5 is equivalent to multiplying by 0x20.
// Push back into the ordinals array if the bit is set.
ptr := add(ptr, shl(5, and(t, 1)))
o := add(o, 1)
t := shr(o, roles)
if iszero(t) { break }
}
// Store the length of `ordinals`.
mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
// Allocate the memory.
mstore(0x40, ptr)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to grant `user` `roles`.
/// If the `user` already has a role, then it will be an no-op for the role.
function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
_grantRoles(user, roles);
}
/// @dev Allows the owner to remove `user` `roles`.
/// If the `user` does not have a role, then it will be an no-op for the role.
function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
_removeRoles(user, roles);
}
/// @dev Allow the caller to remove their own roles.
/// If the caller does not have a role, then it will be an no-op for the role.
function renounceRoles(uint256 roles) public payable virtual {
_removeRoles(msg.sender, roles);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the roles of `user`.
function rolesOf(address user) public view virtual returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Load the stored value.
roles := sload(keccak256(0x0c, 0x20))
}
}
/// @dev Returns whether `user` has any of `roles`.
function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles != 0;
}
/// @dev Returns whether `user` has all of `roles`.
function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles == roles;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by an account with `roles`.
modifier onlyRoles(uint256 roles) virtual {
_checkRoles(roles);
_;
}
/// @dev Marks a function as only callable by the owner or by an account
/// with `roles`. Checks for ownership first, then lazily checks for roles.
modifier onlyOwnerOrRoles(uint256 roles) virtual {
_checkOwnerOrRoles(roles);
_;
}
/// @dev Marks a function as only callable by an account with `roles`
/// or the owner. Checks for roles first, then lazily checks for ownership.
modifier onlyRolesOrOwner(uint256 roles) virtual {
_checkRolesOrOwner(roles);
_;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ROLE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// IYKYK
uint256 internal constant _ROLE_0 = 1 << 0;
uint256 internal constant _ROLE_1 = 1 << 1;
uint256 internal constant _ROLE_2 = 1 << 2;
uint256 internal constant _ROLE_3 = 1 << 3;
uint256 internal constant _ROLE_4 = 1 << 4;
uint256 internal constant _ROLE_5 = 1 << 5;
uint256 internal constant _ROLE_6 = 1 << 6;
uint256 internal constant _ROLE_7 = 1 << 7;
uint256 internal constant _ROLE_8 = 1 << 8;
uint256 internal constant _ROLE_9 = 1 << 9;
uint256 internal constant _ROLE_10 = 1 << 10;
uint256 internal constant _ROLE_11 = 1 << 11;
uint256 internal constant _ROLE_12 = 1 << 12;
uint256 internal constant _ROLE_13 = 1 << 13;
uint256 internal constant _ROLE_14 = 1 << 14;
uint256 internal constant _ROLE_15 = 1 << 15;
uint256 internal constant _ROLE_16 = 1 << 16;
uint256 internal constant _ROLE_17 = 1 << 17;
uint256 internal constant _ROLE_18 = 1 << 18;
uint256 internal constant _ROLE_19 = 1 << 19;
uint256 internal constant _ROLE_20 = 1 << 20;
uint256 internal constant _ROLE_21 = 1 << 21;
uint256 internal constant _ROLE_22 = 1 << 22;
uint256 internal constant _ROLE_23 = 1 << 23;
uint256 internal constant _ROLE_24 = 1 << 24;
uint256 internal constant _ROLE_25 = 1 << 25;
uint256 internal constant _ROLE_26 = 1 << 26;
uint256 internal constant _ROLE_27 = 1 << 27;
uint256 internal constant _ROLE_28 = 1 << 28;
uint256 internal constant _ROLE_29 = 1 << 29;
uint256 internal constant _ROLE_30 = 1 << 30;
uint256 internal constant _ROLE_31 = 1 << 31;
uint256 internal constant _ROLE_32 = 1 << 32;
uint256 internal constant _ROLE_33 = 1 << 33;
uint256 internal constant _ROLE_34 = 1 << 34;
uint256 internal constant _ROLE_35 = 1 << 35;
uint256 internal constant _ROLE_36 = 1 << 36;
uint256 internal constant _ROLE_37 = 1 << 37;
uint256 internal constant _ROLE_38 = 1 << 38;
uint256 internal constant _ROLE_39 = 1 << 39;
uint256 internal constant _ROLE_40 = 1 << 40;
uint256 internal constant _ROLE_41 = 1 << 41;
uint256 internal constant _ROLE_42 = 1 << 42;
uint256 internal constant _ROLE_43 = 1 << 43;
uint256 internal constant _ROLE_44 = 1 << 44;
uint256 internal constant _ROLE_45 = 1 << 45;
uint256 internal constant _ROLE_46 = 1 << 46;
uint256 internal constant _ROLE_47 = 1 << 47;
uint256 internal constant _ROLE_48 = 1 << 48;
uint256 internal constant _ROLE_49 = 1 << 49;
uint256 internal constant _ROLE_50 = 1 << 50;
uint256 internal constant _ROLE_51 = 1 << 51;
uint256 internal constant _ROLE_52 = 1 << 52;
uint256 internal constant _ROLE_53 = 1 << 53;
uint256 internal constant _ROLE_54 = 1 << 54;
uint256 internal constant _ROLE_55 = 1 << 55;
uint256 internal constant _ROLE_56 = 1 << 56;
uint256 internal constant _ROLE_57 = 1 << 57;
uint256 internal constant _ROLE_58 = 1 << 58;
uint256 internal constant _ROLE_59 = 1 << 59;
uint256 internal constant _ROLE_60 = 1 << 60;
uint256 internal constant _ROLE_61 = 1 << 61;
uint256 internal constant _ROLE_62 = 1 << 62;
uint256 internal constant _ROLE_63 = 1 << 63;
uint256 internal constant _ROLE_64 = 1 << 64;
uint256 internal constant _ROLE_65 = 1 << 65;
uint256 internal constant _ROLE_66 = 1 << 66;
uint256 internal constant _ROLE_67 = 1 << 67;
uint256 internal constant _ROLE_68 = 1 << 68;
uint256 internal constant _ROLE_69 = 1 << 69;
uint256 internal constant _ROLE_70 = 1 << 70;
uint256 internal constant _ROLE_71 = 1 << 71;
uint256 internal constant _ROLE_72 = 1 << 72;
uint256 internal constant _ROLE_73 = 1 << 73;
uint256 internal constant _ROLE_74 = 1 << 74;
uint256 internal constant _ROLE_75 = 1 << 75;
uint256 internal constant _ROLE_76 = 1 << 76;
uint256 internal constant _ROLE_77 = 1 << 77;
uint256 internal constant _ROLE_78 = 1 << 78;
uint256 internal constant _ROLE_79 = 1 << 79;
uint256 internal constant _ROLE_80 = 1 << 80;
uint256 internal constant _ROLE_81 = 1 << 81;
uint256 internal constant _ROLE_82 = 1 << 82;
uint256 internal constant _ROLE_83 = 1 << 83;
uint256 internal constant _ROLE_84 = 1 << 84;
uint256 internal constant _ROLE_85 = 1 << 85;
uint256 internal constant _ROLE_86 = 1 << 86;
uint256 internal constant _ROLE_87 = 1 << 87;
uint256 internal constant _ROLE_88 = 1 << 88;
uint256 internal constant _ROLE_89 = 1 << 89;
uint256 internal constant _ROLE_90 = 1 << 90;
uint256 internal constant _ROLE_91 = 1 << 91;
uint256 internal constant _ROLE_92 = 1 << 92;
uint256 internal constant _ROLE_93 = 1 << 93;
uint256 internal constant _ROLE_94 = 1 << 94;
uint256 internal constant _ROLE_95 = 1 << 95;
uint256 internal constant _ROLE_96 = 1 << 96;
uint256 internal constant _ROLE_97 = 1 << 97;
uint256 internal constant _ROLE_98 = 1 << 98;
uint256 internal constant _ROLE_99 = 1 << 99;
uint256 internal constant _ROLE_100 = 1 << 100;
uint256 internal constant _ROLE_101 = 1 << 101;
uint256 internal constant _ROLE_102 = 1 << 102;
uint256 internal constant _ROLE_103 = 1 << 103;
uint256 internal constant _ROLE_104 = 1 << 104;
uint256 internal constant _ROLE_105 = 1 << 105;
uint256 internal constant _ROLE_106 = 1 << 106;
uint256 internal constant _ROLE_107 = 1 << 107;
uint256 internal constant _ROLE_108 = 1 << 108;
uint256 internal constant _ROLE_109 = 1 << 109;
uint256 internal constant _ROLE_110 = 1 << 110;
uint256 internal constant _ROLE_111 = 1 << 111;
uint256 internal constant _ROLE_112 = 1 << 112;
uint256 internal constant _ROLE_113 = 1 << 113;
uint256 internal constant _ROLE_114 = 1 << 114;
uint256 internal constant _ROLE_115 = 1 << 115;
uint256 internal constant _ROLE_116 = 1 << 116;
uint256 internal constant _ROLE_117 = 1 << 117;
uint256 internal constant _ROLE_118 = 1 << 118;
uint256 internal constant _ROLE_119 = 1 << 119;
uint256 internal constant _ROLE_120 = 1 << 120;
uint256 internal constant _ROLE_121 = 1 << 121;
uint256 internal constant _ROLE_122 = 1 << 122;
uint256 internal constant _ROLE_123 = 1 << 123;
uint256 internal constant _ROLE_124 = 1 << 124;
uint256 internal constant _ROLE_125 = 1 << 125;
uint256 internal constant _ROLE_126 = 1 << 126;
uint256 internal constant _ROLE_127 = 1 << 127;
uint256 internal constant _ROLE_128 = 1 << 128;
uint256 internal constant _ROLE_129 = 1 << 129;
uint256 internal constant _ROLE_130 = 1 << 130;
uint256 internal constant _ROLE_131 = 1 << 131;
uint256 internal constant _ROLE_132 = 1 << 132;
uint256 internal constant _ROLE_133 = 1 << 133;
uint256 internal constant _ROLE_134 = 1 << 134;
uint256 internal constant _ROLE_135 = 1 << 135;
uint256 internal constant _ROLE_136 = 1 << 136;
uint256 internal constant _ROLE_137 = 1 << 137;
uint256 internal constant _ROLE_138 = 1 << 138;
uint256 internal constant _ROLE_139 = 1 << 139;
uint256 internal constant _ROLE_140 = 1 << 140;
uint256 internal constant _ROLE_141 = 1 << 141;
uint256 internal constant _ROLE_142 = 1 << 142;
uint256 internal constant _ROLE_143 = 1 << 143;
uint256 internal constant _ROLE_144 = 1 << 144;
uint256 internal constant _ROLE_145 = 1 << 145;
uint256 internal constant _ROLE_146 = 1 << 146;
uint256 internal constant _ROLE_147 = 1 << 147;
uint256 internal constant _ROLE_148 = 1 << 148;
uint256 internal constant _ROLE_149 = 1 << 149;
uint256 internal constant _ROLE_150 = 1 << 150;
uint256 internal constant _ROLE_151 = 1 << 151;
uint256 internal constant _ROLE_152 = 1 << 152;
uint256 internal constant _ROLE_153 = 1 << 153;
uint256 internal constant _ROLE_154 = 1 << 154;
uint256 internal constant _ROLE_155 = 1 << 155;
uint256 internal constant _ROLE_156 = 1 << 156;
uint256 internal constant _ROLE_157 = 1 << 157;
uint256 internal constant _ROLE_158 = 1 << 158;
uint256 internal constant _ROLE_159 = 1 << 159;
uint256 internal constant _ROLE_160 = 1 << 160;
uint256 internal constant _ROLE_161 = 1 << 161;
uint256 internal constant _ROLE_162 = 1 << 162;
uint256 internal constant _ROLE_163 = 1 << 163;
uint256 internal constant _ROLE_164 = 1 << 164;
uint256 internal constant _ROLE_165 = 1 << 165;
uint256 internal constant _ROLE_166 = 1 << 166;
uint256 internal constant _ROLE_167 = 1 << 167;
uint256 internal constant _ROLE_168 = 1 << 168;
uint256 internal constant _ROLE_169 = 1 << 169;
uint256 internal constant _ROLE_170 = 1 << 170;
uint256 internal constant _ROLE_171 = 1 << 171;
uint256 internal constant _ROLE_172 = 1 << 172;
uint256 internal constant _ROLE_173 = 1 << 173;
uint256 internal constant _ROLE_174 = 1 << 174;
uint256 internal constant _ROLE_175 = 1 << 175;
uint256 internal constant _ROLE_176 = 1 << 176;
uint256 internal constant _ROLE_177 = 1 << 177;
uint256 internal constant _ROLE_178 = 1 << 178;
uint256 internal constant _ROLE_179 = 1 << 179;
uint256 internal constant _ROLE_180 = 1 << 180;
uint256 internal constant _ROLE_181 = 1 << 181;
uint256 internal constant _ROLE_182 = 1 << 182;
uint256 internal constant _ROLE_183 = 1 << 183;
uint256 internal constant _ROLE_184 = 1 << 184;
uint256 internal constant _ROLE_185 = 1 << 185;
uint256 internal constant _ROLE_186 = 1 << 186;
uint256 internal constant _ROLE_187 = 1 << 187;
uint256 internal constant _ROLE_188 = 1 << 188;
uint256 internal constant _ROLE_189 = 1 << 189;
uint256 internal constant _ROLE_190 = 1 << 190;
uint256 internal constant _ROLE_191 = 1 << 191;
uint256 internal constant _ROLE_192 = 1 << 192;
uint256 internal constant _ROLE_193 = 1 << 193;
uint256 internal constant _ROLE_194 = 1 << 194;
uint256 internal constant _ROLE_195 = 1 << 195;
uint256 internal constant _ROLE_196 = 1 << 196;
uint256 internal constant _ROLE_197 = 1 << 197;
uint256 internal constant _ROLE_198 = 1 << 198;
uint256 internal constant _ROLE_199 = 1 << 199;
uint256 internal constant _ROLE_200 = 1 << 200;
uint256 internal constant _ROLE_201 = 1 << 201;
uint256 internal constant _ROLE_202 = 1 << 202;
uint256 internal constant _ROLE_203 = 1 << 203;
uint256 internal constant _ROLE_204 = 1 << 204;
uint256 internal constant _ROLE_205 = 1 << 205;
uint256 internal constant _ROLE_206 = 1 << 206;
uint256 internal constant _ROLE_207 = 1 << 207;
uint256 internal constant _ROLE_208 = 1 << 208;
uint256 internal constant _ROLE_209 = 1 << 209;
uint256 internal constant _ROLE_210 = 1 << 210;
uint256 internal constant _ROLE_211 = 1 << 211;
uint256 internal constant _ROLE_212 = 1 << 212;
uint256 internal constant _ROLE_213 = 1 << 213;
uint256 internal constant _ROLE_214 = 1 << 214;
uint256 internal constant _ROLE_215 = 1 << 215;
uint256 internal constant _ROLE_216 = 1 << 216;
uint256 internal constant _ROLE_217 = 1 << 217;
uint256 internal constant _ROLE_218 = 1 << 218;
uint256 internal constant _ROLE_219 = 1 << 219;
uint256 internal constant _ROLE_220 = 1 << 220;
uint256 internal constant _ROLE_221 = 1 << 221;
uint256 internal constant _ROLE_222 = 1 << 222;
uint256 internal constant _ROLE_223 = 1 << 223;
uint256 internal constant _ROLE_224 = 1 << 224;
uint256 internal constant _ROLE_225 = 1 << 225;
uint256 internal constant _ROLE_226 = 1 << 226;
uint256 internal constant _ROLE_227 = 1 << 227;
uint256 internal constant _ROLE_228 = 1 << 228;
uint256 internal constant _ROLE_229 = 1 << 229;
uint256 internal constant _ROLE_230 = 1 << 230;
uint256 internal constant _ROLE_231 = 1 << 231;
uint256 internal constant _ROLE_232 = 1 << 232;
uint256 internal constant _ROLE_233 = 1 << 233;
uint256 internal constant _ROLE_234 = 1 << 234;
uint256 internal constant _ROLE_235 = 1 << 235;
uint256 internal constant _ROLE_236 = 1 << 236;
uint256 internal constant _ROLE_237 = 1 << 237;
uint256 internal constant _ROLE_238 = 1 << 238;
uint256 internal constant _ROLE_239 = 1 << 239;
uint256 internal constant _ROLE_240 = 1 << 240;
uint256 internal constant _ROLE_241 = 1 << 241;
uint256 internal constant _ROLE_242 = 1 << 242;
uint256 internal constant _ROLE_243 = 1 << 243;
uint256 internal constant _ROLE_244 = 1 << 244;
uint256 internal constant _ROLE_245 = 1 << 245;
uint256 internal constant _ROLE_246 = 1 << 246;
uint256 internal constant _ROLE_247 = 1 << 247;
uint256 internal constant _ROLE_248 = 1 << 248;
uint256 internal constant _ROLE_249 = 1 << 249;
uint256 internal constant _ROLE_250 = 1 << 250;
uint256 internal constant _ROLE_251 = 1 << 251;
uint256 internal constant _ROLE_252 = 1 << 252;
uint256 internal constant _ROLE_253 = 1 << 253;
uint256 internal constant _ROLE_254 = 1 << 254;
uint256 internal constant _ROLE_255 = 1 << 255;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Deterministic deployments agnostic to the initialization code.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/CREATE3.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/CREATE3.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/create3/blob/master/contracts/Create3.sol)
library CREATE3 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unable to deploy the contract.
error DeploymentFailed();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* BYTECODE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/**
* -------------------------------------------------------------------+
* Opcode | Mnemonic | Stack | Memory |
* -------------------------------------------------------------------|
* 36 | CALLDATASIZE | cds | |
* 3d | RETURNDATASIZE | 0 cds | |
* 3d | RETURNDATASIZE | 0 0 cds | |
* 37 | CALLDATACOPY | | [0..cds): calldata |
* 36 | CALLDATASIZE | cds | [0..cds): calldata |
* 3d | RETURNDATASIZE | 0 cds | [0..cds): calldata |
* 34 | CALLVALUE | value 0 cds | [0..cds): calldata |
* f0 | CREATE | newContract | [0..cds): calldata |
* -------------------------------------------------------------------|
* Opcode | Mnemonic | Stack | Memory |
* -------------------------------------------------------------------|
* 67 bytecode | PUSH8 bytecode | bytecode | |
* 3d | RETURNDATASIZE | 0 bytecode | |
* 52 | MSTORE | | [0..8): bytecode |
* 60 0x08 | PUSH1 0x08 | 0x08 | [0..8): bytecode |
* 60 0x18 | PUSH1 0x18 | 0x18 0x08 | [0..8): bytecode |
* f3 | RETURN | | [0..8): bytecode |
* -------------------------------------------------------------------+
*/
/// @dev The proxy initialization code.
uint256 private constant _PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3;
/// @dev Hash of the `_PROXY_INITCODE`.
/// Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`.
bytes32 internal constant PROXY_INITCODE_HASH =
0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CREATE3 OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Deploys `initCode` deterministically with a `salt`.
/// Returns the deterministic address of the deployed contract,
/// which solely depends on `salt`.
function deployDeterministic(bytes memory initCode, bytes32 salt)
internal
returns (address deployed)
{
deployed = deployDeterministic(0, initCode, salt);
}
/// @dev Deploys `initCode` deterministically with a `salt`.
/// The deployed contract is funded with `value` (in wei) ETH.
/// Returns the deterministic address of the deployed contract,
/// which solely depends on `salt`.
function deployDeterministic(uint256 value, bytes memory initCode, bytes32 salt)
internal
returns (address deployed)
{
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, _PROXY_INITCODE) // Store the `_PROXY_INITCODE`.
let proxy := create2(0, 0x10, 0x10, salt)
if iszero(proxy) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
mstore(0x14, proxy) // Store the proxy's address.
// 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).
// 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).
mstore(0x00, 0xd694)
mstore8(0x34, 0x01) // Nonce of the proxy contract (1).
deployed := keccak256(0x1e, 0x17)
if iszero(
mul( // The arguments of `mul` are evaluated last to first.
extcodesize(deployed),
call(gas(), proxy, value, add(initCode, 0x20), mload(initCode), 0x00, 0x00)
)
) {
mstore(0x00, 0x30116425) // `DeploymentFailed()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns the deterministic address for `salt`.
function predictDeterministicAddress(bytes32 salt) internal view returns (address deployed) {
deployed = predictDeterministicAddress(salt, address(this));
}
/// @dev Returns the deterministic address for `salt` with `deployer`.
function predictDeterministicAddress(bytes32 salt, address deployer)
internal
pure
returns (address deployed)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, deployer) // Store `deployer`.
mstore8(0x0b, 0xff) // Store the prefix.
mstore(0x20, salt) // Store the salt.
mstore(0x40, PROXY_INITCODE_HASH) // Store the bytecode hash.
mstore(0x14, keccak256(0x0b, 0x55)) // Store the proxy's address.
mstore(0x40, m) // Restore the free memory pointer.
// 0xd6 = 0xc0 (short RLP prefix) + 0x16 (length of: 0x94 ++ proxy ++ 0x01).
// 0x94 = 0x80 + 0x14 (0x14 = the length of an address, 20 bytes, in hex).
mstore(0x00, 0xd694)
mstore8(0x34, 0x01) // Nonce of the proxy contract (1).
deployed := keccak256(0x1e, 0x17)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
/// This is for more safety by default.
/// Use the `tryRecover` variants if you need to get the zero address back
/// upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
/// See: https://eips.ethereum.org/EIPS/eip-2098
/// This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT directly use signatures as unique identifiers:
/// - The recovery operations do NOT check if a signature is non-malleable.
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
/// EIP-712 also enables readable signing of typed data for better user safety.
/// - If you need a unique hash from a signature, please use the `canonicalHash` functions.
library ECDSA {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The order of the secp256k1 elliptic curve.
uint256 internal constant N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141;
/// @dev `N/2 + 1`. Used for checking the malleability of the signature.
uint256 private constant _HALF_N_PLUS_1 =
0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The signature is invalid.
error InvalidSignature();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RECOVERY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
} {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { continue }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if returndatasize() { break }
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
} {
switch signature.length
case 64 {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
}
default { continue }
mstore(0x00, hash)
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if returndatasize() { break }
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TRY-RECOVER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// WARNING!
// These functions will NOT revert upon recovery failure.
// Instead, they will return the zero address upon recovery failure.
// It is critical that the returned address is NEVER compared against
// a zero address (e.g. an uninitialized address variable).
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecover(bytes32 hash, bytes memory signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {} {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { break }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {} {
switch signature.length
case 64 {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
}
default { break }
mstore(0x00, hash)
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an Ethereum Signed Message, created from a `hash`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
/// JSON-RPC method as part of EIP-191.
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x20, hash) // Store into scratch space for keccak256.
mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
}
}
/// @dev Returns an Ethereum Signed Message, created from `s`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
/// JSON-RPC method as part of EIP-191.
/// Note: Supports lengths of `s` up to 999999 bytes.
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let sLength := mload(s)
let o := 0x20
mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
mstore(0x00, 0x00)
// Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
for { let temp := sLength } 1 {} {
o := sub(o, 1)
mstore8(o, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
// Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
mstore(s, sLength) // Restore the length.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CANONICAL HASH FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// The following functions return the hash of the signature in its canonicalized format,
// which is the 65-byte `abi.encodePacked(r, s, uint8(v))`, where `v` is either 27 or 28.
// If `s` is greater than `N / 2` then it will be converted to `N - s`
// and the `v` value will be flipped.
// If the signature has an invalid length, or if `v` is invalid,
// a uniquely corrupt hash will be returned.
// These functions are useful for "poor-mans-VRF".
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(bytes memory signature) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let l := mload(signature)
for {} 1 {} {
mstore(0x00, mload(add(signature, 0x20))) // `r`.
let s := mload(add(signature, 0x40))
let v := mload(add(signature, 0x41))
if eq(l, 64) {
v := add(shr(255, s), 27)
s := shr(1, shl(1, s))
}
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
break
}
// If the length is neither 64 nor 65, return a uniquely corrupted hash.
if iszero(lt(sub(l, 64), 2)) {
// `bytes4(keccak256("InvalidSignatureLength"))`.
result := xor(keccak256(add(signature, 0x20), l), 0xd62f1ab2)
}
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHashCalldata(bytes calldata signature)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
mstore(0x00, calldataload(signature.offset)) // `r`.
let s := calldataload(add(signature.offset, 0x20))
let v := calldataload(add(signature.offset, 0x21))
if eq(signature.length, 64) {
v := add(shr(255, s), 27)
s := shr(1, shl(1, s))
}
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
break
}
// If the length is neither 64 nor 65, return a uniquely corrupted hash.
if iszero(lt(sub(signature.length, 64), 2)) {
calldatacopy(mload(0x40), signature.offset, signature.length)
// `bytes4(keccak256("InvalidSignatureLength"))`.
result := xor(keccak256(mload(0x40), signature.length), 0xd62f1ab2)
}
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(bytes32 r, bytes32 vs) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, r) // `r`.
let v := add(shr(255, vs), 27)
let s := shr(1, shl(1, vs))
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(uint8 v, bytes32 r, bytes32 s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, r) // `r`.
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes.
function emptySignature() internal pure returns (bytes calldata signature) {
/// @solidity memory-safe-assembly
assembly {
signature.length := 0
}
}
}// 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))
}
}
}{
"viaIR": true,
"optimizer": {
"enabled": true,
"runs": 100000
},
"evmVersion": "paris",
"remappings": [
":@ensdomains/=lib/v4-core/node_modules/@ensdomains/",
":@openzeppelin/=lib/v4-core/lib/openzeppelin-contracts/",
":@uniswap/permit2/=lib/permit2/",
":@uniswap/universal-router/=lib/universal-router/",
":@uniswap/v2-core/=lib/universal-router/node_modules/@uniswap/v2-core/",
":@uniswap/v3-core/=lib/universal-router/node_modules/@uniswap/v3-core/",
":@uniswap/v3-periphery/=lib/universal-router/lib/v3-periphery/",
":@uniswap/v4-core/=lib/v4-core/",
":@uniswap/v4-periphery/=lib/v4-periphery/",
":ds-test/=lib/universal-router/lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-gas-snapshot/=lib/permit2/lib/forge-gas-snapshot/src/",
":forge-std/=lib/forge-std/src/",
":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
":hardhat/=lib/v4-core/node_modules/hardhat/",
":murky/=lib/murky/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":permit2/=lib/permit2/",
":solady/=lib/solady/src/",
":solmate/=lib/universal-router/lib/solmate/",
":universal-router/=lib/universal-router/",
":v3-periphery/=lib/universal-router/lib/v3-periphery/contracts/",
":v4-core/=lib/v4-core/src/",
":v4-periphery/=lib/v4-periphery/"
],
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"manager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"DeploymentFailed","type":"error"},{"inputs":[],"name":"InvalidDeploymentType","type":"error"},{"inputs":[],"name":"InvalidImplementation","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":false,"internalType":"address","name":"contractAddress","type":"address"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"ContractDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"NonceUsed","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"version","type":"uint256"},{"indexed":false,"internalType":"address","name":"proxyAddress","type":"address"},{"indexed":false,"internalType":"address","name":"implementation","type":"address"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"ProxyDeployed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum ContractFactory.ContractDeploymentType","name":"deployType","type":"uint8"},{"internalType":"bytes","name":"bytecode","type":"bytes"},{"internalType":"bytes","name":"constructorArgs","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"computeDeployAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum ContractFactory.ProxyDeploymentType","name":"deployType","type":"uint8"},{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"computeProxyAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"enum ContractFactory.ContractDeploymentType","name":"deployType","type":"uint8"},{"internalType":"bytes","name":"bytecode","type":"bytes"},{"internalType":"bytes","name":"constructorArgs","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes[]","name":"postDeployCalls","type":"bytes[]"}],"name":"deployContract","outputs":[{"internalType":"address","name":"deployed","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"enum ContractFactory.ContractDeploymentType","name":"deployType","type":"uint8"},{"internalType":"bytes","name":"bytecode","type":"bytes"},{"internalType":"bytes","name":"constructorArgs","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes[]","name":"postDeployCalls","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ContractFactory.ContractDeploymentRequest","name":"request","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"deployContractWithSignature","outputs":[{"internalType":"address","name":"deployed","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"enum ContractFactory.ProxyDeploymentType","name":"deployType","type":"uint8"},{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes[]","name":"postDeployCalls","type":"bytes[]"}],"name":"deployProxy","outputs":[{"internalType":"address","name":"deployed","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"enum ContractFactory.ProxyDeploymentType","name":"deployType","type":"uint8"},{"internalType":"address","name":"implementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes[]","name":"postDeployCalls","type":"bytes[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ContractFactory.ProxyDeploymentRequest","name":"request","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"deployProxyWithSignature","outputs":[{"internalType":"address","name":"deployed","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"},{"internalType":"uint256","name":"version","type":"uint256"}],"name":"getDeployment","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"latestVersion","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"nonceUsed","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":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
6080346100de57601f6128c038819003918201601f19168301916001600160401b038311848410176100e35780849260409485528339810103126100de57610052602061004b836100f9565b92016100f9565b6001600160a01b03909116638b78c6d81981905560007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3638b78c6d8600c526000526020600c206001815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a36040516127b2908161010e8239f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b03821682036100de5756fe6080604052600436101561001257600080fd5b60003560e01c80630a29517f146101775780631647795e14610172578063183a4f6e1461016d5780631c10893f146101685780631cd64df414610163578063256929621461015e5780632de94807146101595780634a4ee7b114610154578063514e62fc1461014f57806354d1f13d1461014a578063715018a6146101455780637bd1368b146101405780638bc106dd1461013b5780638da5cb5b14610136578063bef11b3114610131578063d5ec7faa1461012c578063e4d5944714610127578063e9e1075214610122578063f04e283e1461011d578063f2fde38b14610118578063fe513ef9146101135763fee81cf41461010e57600080fd5b610f82565b610ee1565b610e83565b610e11565b610dc7565b610c21565b610b91565b610afa565b610a7f565b6109ca565b610703565b6105c6565b610560565b6104fd565b6104b3565b610457565b6103ed565b610389565b610303565b6102cb565b61024d565b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576024356004358115610213575b600052600060205260406000209060005260205261020f73ffffffffffffffffffffffffffffffffffffffff604060002054166040519182918291909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0390f35b8091506000526001602052604060002054906101b3565b600080fd5b73ffffffffffffffffffffffffffffffffffffffff81160361022a57565b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576004356102888161022f565b73ffffffffffffffffffffffffffffffffffffffff60243591166000526002602052604060002090600052602052602060ff604060002054166040519015158152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5761030160043533611ddc565b005b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576004356103398161022f565b602435906103456115ed565b638b78c6d8600c526000526020600c2090815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3005b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760206103e36004356103c98161022f565b602435918291638b78c6d8600c526000526020600c205490565b1614604051908152f35b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5763389a75e1600c52336000526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a2005b3461022a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760206104ab6004356104978161022f565b638b78c6d8600c526000526020600c205490565b604051908152f35b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576103016004356104ec8161022f565b602435906104f86115ed565b611ddc565b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57602060043561053a8161022f565b61055560243591638b78c6d8600c526000526020600c205490565b161515604051908152f35b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5763389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2005b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576105f86115ed565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a360007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392755005b9181601f8401121561022a5782359167ffffffffffffffff831161022a576020838186019501011161022a57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261022a5760043567ffffffffffffffff811161022a576004016101008184031261022a57916024359067ffffffffffffffff821161022a576106ff91600401610666565b9091565b3461022a5761071136610694565b60e08301354211610965576107269183611ea2565b906107518273ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b9061077561076e60c0830135809490600052602052604060002090565b5460ff1690565b61093b5761078961078584610fd7565b1590565b806108e4575b6108ba577f2af71f10069c28afc67c3752e87e0e4616a97948d33c8f404a856c0c334b3e0182846108276107fc610893966107ed61020f9973ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b90600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff9290921682526020820192909252a1803561085d60208301611035565b9161086a60408201611042565b610877606083018361104c565b9161088b60808501359460a081019061109d565b9690956116e4565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b7f8baa579f0000000000000000000000000000000000000000000000000000000060005260046000fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff8416141561078f565b7f756688fe0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f0819bdcd0000000000000000000000000000000000000000000000000000000060005260046000fd5b6003111561022a57565b9181601f8401121561022a5782359167ffffffffffffffff831161022a576020808501948460051b01011161022a57565b3461022a5760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435602435610a088161098f565b60443567ffffffffffffffff811161022a57610a28903690600401610666565b91909260643567ffffffffffffffff811161022a57610a4b903690600401610666565b6084359160a4359567ffffffffffffffff871161022a5761020f97610a77610893983690600401610999565b9790966110f1565b3461022a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275473ffffffffffffffffffffffffffffffffffffffff60405191168152f35b6006111561022a57565b3461022a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610b3581610af0565b60243590610b428261022f565b6044359067ffffffffffffffff821161022a57602092610b69610b73933690600401610666565b91606435936111f0565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b3461022a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610bcc8161098f565b60243567ffffffffffffffff811161022a57610bec903690600401610666565b90916044359167ffffffffffffffff831161022a57602093610c15610b73943690600401610666565b92909160643594611473565b3461022a57610c2f36610694565b60e0830135421161096557610c449183612153565b90610c6f8273ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b90610c8c61076e60c0830135809490600052602052604060002090565b61093b57610c9c61078584610fd7565b80610d70575b6108ba577f2af71f10069c28afc67c3752e87e0e4616a97948d33c8f404a856c0c334b3e018284610d006107fc610893966107ed61020f9973ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b6040805173ffffffffffffffffffffffffffffffffffffffff9290921682526020820192909252a18035610d36602083016115cb565b91610d44604082018261104c565b90610d52606084018461104c565b929091610d6860808601359560a081019061109d565b9790966119ef565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff84161415610ca2565b3461022a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760043560005260016020526020604060002054604051908152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610e478161022f565b610e4f6115ed565b63389a75e1600c52806000526020600c209081544211610e755760006103019255611625565b636f5e88186000526004601cfd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610eb98161022f565b610ec16115ed565b8060601b15610ed35761030190611625565b637448fbae6000526004601cfd5b3461022a5760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57602435600435610f1f82610af0565b60443591610f2c8361022f565b60643567ffffffffffffffff811161022a57610f4c903690600401610666565b60a4359391608435919067ffffffffffffffff861161022a5761020f96610f7a610893973690600401610999565b9690956115d5565b3461022a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610fbd8161022f565b63389a75e1600c52600052602080600c2054604051908152f35b610ff1600191638b78c6d8600c526000526020600c205490565b16151590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6006111561103057565b610ff7565b3561103f81610af0565b90565b3561103f8161022f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561022a570180359067ffffffffffffffff821161022a5760200191813603831361022a57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561022a570180359067ffffffffffffffff821161022a57602001918160051b3603831361022a57565b9061103f98979695949392916111056119d3565b6119ef565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761117a57604052565b61110a565b67ffffffffffffffff811161117a57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926111c58261117f565b916111d36040519384611139565b82948184528183011161022a578281602093846000960137010152565b9391939290926111ff81611026565b8061124e57505061103f925061124930926c5af43d3d93803e602a57fd5bf360215260145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c20906000602152565b6120cb565b61125a81949294611026565b60018103611279575061127361103f94309436916111b9565b90611d0b565b61128581949294611026565b6002810361130c57505061103f9250611249309290604051917fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076604052616009602052601e5268603d3d8160223d3973600a52605f602120916040526000606052565b61131881949294611026565b60038103611337575061133161103f94309436916111b9565b90611c57565b61134381949294611026565b6004810361140757505061103f925061124930929073ffffffffffffffffffffffffffffffffffffffff604051927fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f36060527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c6040527660195155f3363d3d373d3d363d602036600436635c60da602052167c60523d8160223d39730000000000000000000000000000000000000000176009526074600c20916040526000606052565b80611416600592959395611026565b036114315761142b61103f94309436916111b9565b90611b8d565b7f5c68875d0000000000000000000000000000000000000000000000000000000060005260046000fd5b6003111561103057565b908092918237016000815290565b939092936114808161145b565b600181036115aa575061103f9461157f9490936114c393611563938015611598576114ef92936114c3916114bd6040519687956020870191611465565b91611465565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611139565b6020815191012060405192839160208301953087917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000605594927fff00000000000000000000000000000000000000000000000000000000000000855260601b166001840152601583015260358201520190565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b506115a5925036916111b9565b6114ef565b92505050600291506115bb8161145b565b036114315761103f903090611d8b565b3561103f8161098f565b9061103f979695949392916115e86119d3565b6116e4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754330361161757565b6382b429006000526004601cfd5b73ffffffffffffffffffffffffffffffffffffffff16807fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a37fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392755565b90600182018092116116b557565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9396959694929094823b156119a95761171061170a866000526001602052604060002090565b546116a7565b9561171a81611026565b8061181957505050908161175e7feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661175684611813966126ec565b985b89611fd4565b6117ba8761177a876107ed886000526000602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b846117cf856000526001602052604060002090565b558660405195869586919373ffffffffffffffffffffffffffffffffffffffff608094819398979660a0860199865260208601521660408401521660608201520152565b0390a190565b61182281611026565b6001810361187157507feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b8561186561181397969561175e9536916111b9565b85612685565b98611758565b61187a81611026565b600281036118b957505050908161175e7feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b8461181396612609565b6118c281611026565b6003810361190b57507feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b8561190561181397969561175e9536916111b9565b85612571565b61191781939293611026565b6004810361195657505050908161175e7feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b84611813966124b8565b8061196660059296959496611026565b03611431577feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b846119a361175e946118139836916111b9565b856123f8565b7f68155f9a0000000000000000000000000000000000000000000000000000000060005260046000fd5b638b78c6d8600c523360005260016020600c205416156115ed57565b9495969793919092611a0e61170a876000526001602052604060002090565b968015611b7a57611a3192936114c3916114bd6040519687956020870191611465565b905b611a3c8161145b565b80611ae9575093611a7c61181392611a747fb9b3ce774ed64bac5843e4d220bb1266963d22ccb555eaac751476bb1fdd6a39976120a3565b975b88611fd4565b611a988661177a866107ed876000526000602052604060002090565b83611aad846000526001602052604060002090565b5585604051948594859094939273ffffffffffffffffffffffffffffffffffffffff906060936080840197845260208401521660408201520152565b611af28161145b565b60018103611b34575093611a7c61181392611b2e837fb9b3ce774ed64bac5843e4d220bb1266963d22ccb555eaac751476bb1fdd6a3998612051565b97611a76565b80611b4360029297939761145b565b0361143157611a7c61181392611b2e837fb9b3ce774ed64bac5843e4d220bb1266963d22ccb555eaac751476bb1fdd6a399861272d565b50611b87925036916111b9565b90611a33565b93929190936040519085519061ffad82113d3d3e60005b828110611c41575061103f9596506016916075917fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3606b8601527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c604b8601527660195155f3363d3d373d3d363d602036600436635c60da602b86015260148501528060381b696100523d8160233d3973018452019101206120cb565b80602080928a010151608b828701015201611ba4565b93929190936040519085519061ffc282113d3d3e60005b828110611cf5575061103f959650906060917fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f360408501527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e207660208501526160096016526014528060381b6961003d3d8160233d39730160005260165183520190206120cb565b80602080928a0101516060828701015201611c6e565b93929190936040519085519061ffd282113d3d3e60005b828110611d75575061103f959650600c916037916e5af43d82803e903d91602b57fd5bf3602386015260148501528060881b7361002d3d81600a3d39f3363d3d373d3d3d363d73018452019101206120cb565b80602080928a0101516043828701015201611d22565b6040519160005260ff600b536020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b2060145260405261d69460005260016034536017601e2090565b638b78c6d8600c526000526020600c2090815490811618809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3565b94919897969390989592956101208601997f9cd6e13852212116e23b1b7439c9d28a11dbbc7b355f5b0f3e71e5f5fec5a69d875260208701526006811015611030576101009673ffffffffffffffffffffffffffffffffffffffff916040880152166060860152608085015260a084015260c083015260e08201520152565b61103f9291611f8391803590611f24611ebd60208301611035565b6114c3611ecc60408501611042565b93611ee4611edd606083018361104c565b36916111b9565b60208151910120906080810135611f07611f0160a084018461109d565b90612219565b9060e060c084013593013593604051988997602089019b8c611e23565b5190206114c3611f78611f356122be565b9260405192839160208301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b5190209236916111b9565b90612350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90821015611fcf576106ff9160051b81019061104c565b611f89565b909160005b818110611fe65750505050565b600080611ff4838588611fb8565b908160405192839283378101838152039082875af13d15612049573d9061201a8261117f565b916120286040519384611139565b82523d6000602084013e5b156120415750600101611fd9565b602081519101fd5b606090612033565b6020815191016000f59073ffffffffffffffffffffffffffffffffffffffff82161561207957565b7f301164250000000000000000000000000000000000000000000000000000000060005260046000fd5b6020815191016000f09073ffffffffffffffffffffffffffffffffffffffff82161561207957565b91909160ff60005360355260601b6001526015526055600020906000603552565b949195929897969390986101208601997f75fa0565ef631e3bafea98a699d084a8c713c8a872b040d645f22c1114a08984875260208701526003871015611030576101009660408701526060860152608085015260a084015260c083015260e08201520152565b61103f9291611f8391803590611f2461216e602083016115cb565b6114c3612181611edd604086018661104c565b6020815191012093612199611edd606083018361104c565b602081519101209060808101356121b6611f0160a084018461109d565b9060e060c084013593013593604051988997602089019b8c6120ec565b67ffffffffffffffff811161117a5760051b60200190565b805160209091019060005b8181106122035750505090565b82518452602093840193909201916001016121f6565b612222826121d3565b916122306040519384611139565b8083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061225d826121d3565b0136602085013760005b81811061228c57505050604051612286816114c36020820180956121eb565b51902090565b61229a611edd828486611fb8565b60208151910120908451811015611fcf5760019160208260051b8701015201612267565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f24883a27c7cf596f4158af359c654398867831bf32ca431b4b77484420407ba860408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815261228660c082611139565b919091604051928051806040146123bc5760411461237b57505050505b638baa579f6000526004601cfd5b602091606082015160001a835260408201516060525b60005201516040526020600160806000825afa519160006060526040523d6123ba57505061236d565b565b506020917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040830151601b8160ff1c01855216606052612391565b9060756016916040519381518092816020608b8901920160045afa507fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3606b8601527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c604b8601527660195155f3363d3d373d3d363d602036600436635c60da602b86015260148501528060381b6afe6100523d8160233d39730161ffad82118501520191016000f59081156124aa57565b63301164256000526004601cfd5b919073ffffffffffffffffffffffffffffffffffffffff604051937fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f36060527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c6040527660195155f3363d3d373d3d363d602036600436635c60da602052167c60523d8160223d39730000000000000000000000000000000000000000176009526074600c6000f59182156124aa576040526000606052565b906060906040519281518092816020868801920160045afa507fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f360408501527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e207660208501526160096016526014528060381b6afe61003d3d8160233d39730161ffc2821152601651835201906000f59081156124aa57565b9190604051927fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076604052616009602052601e5268603d3d8160223d3973600a52605f60216000f59182156124aa576040526000606052565b600b90604051908351809481602060438601920160045afa506e5af43d82803e903d91602b57fd5bf3602383015260148201528260881b74fe61002d3d81600a3d39f3363d3d373d3d3d363d7301815261ffd360378401931001016000f59081156124aa57565b6c5af43d3d93803e602a57fd5bf360215260145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c6000f59081156124aa576000602152565b91906f67363d3d37363d34f03d5260086018f36000526010806000f59182156124aa57600080918460145261d694825260016034536017601e209482602083519301915af1823b02156124aa5756fea2646970667358221220fe81e60c13ef87adde667a0a7072c940d9d7c1d5fb7753a30690cc7f42a6969064736f6c634300081e00330000000000000000000000001a472863cf21d5aa27f417df9140400324c48f220000000000000000000000009d4d20b7571f9552d730eca812e805e7d5fb64e5
Deployed Bytecode
0x6080604052600436101561001257600080fd5b60003560e01c80630a29517f146101775780631647795e14610172578063183a4f6e1461016d5780631c10893f146101685780631cd64df414610163578063256929621461015e5780632de94807146101595780634a4ee7b114610154578063514e62fc1461014f57806354d1f13d1461014a578063715018a6146101455780637bd1368b146101405780638bc106dd1461013b5780638da5cb5b14610136578063bef11b3114610131578063d5ec7faa1461012c578063e4d5944714610127578063e9e1075214610122578063f04e283e1461011d578063f2fde38b14610118578063fe513ef9146101135763fee81cf41461010e57600080fd5b610f82565b610ee1565b610e83565b610e11565b610dc7565b610c21565b610b91565b610afa565b610a7f565b6109ca565b610703565b6105c6565b610560565b6104fd565b6104b3565b610457565b6103ed565b610389565b610303565b6102cb565b61024d565b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576024356004358115610213575b600052600060205260406000209060005260205261020f73ffffffffffffffffffffffffffffffffffffffff604060002054166040519182918291909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0390f35b8091506000526001602052604060002054906101b3565b600080fd5b73ffffffffffffffffffffffffffffffffffffffff81160361022a57565b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576004356102888161022f565b73ffffffffffffffffffffffffffffffffffffffff60243591166000526002602052604060002090600052602052602060ff604060002054166040519015158152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5761030160043533611ddc565b005b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576004356103398161022f565b602435906103456115ed565b638b78c6d8600c526000526020600c2090815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3005b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760206103e36004356103c98161022f565b602435918291638b78c6d8600c526000526020600c205490565b1614604051908152f35b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5763389a75e1600c52336000526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a2005b3461022a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760206104ab6004356104978161022f565b638b78c6d8600c526000526020600c205490565b604051908152f35b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576103016004356104ec8161022f565b602435906104f86115ed565b611ddc565b3461022a5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57602060043561053a8161022f565b61055560243591638b78c6d8600c526000526020600c205490565b161515604051908152f35b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5763389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2005b60007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a576105f86115ed565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a360007fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392755005b9181601f8401121561022a5782359167ffffffffffffffff831161022a576020838186019501011161022a57565b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc83011261022a5760043567ffffffffffffffff811161022a576004016101008184031261022a57916024359067ffffffffffffffff821161022a576106ff91600401610666565b9091565b3461022a5761071136610694565b60e08301354211610965576107269183611ea2565b906107518273ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b9061077561076e60c0830135809490600052602052604060002090565b5460ff1690565b61093b5761078961078584610fd7565b1590565b806108e4575b6108ba577f2af71f10069c28afc67c3752e87e0e4616a97948d33c8f404a856c0c334b3e0182846108276107fc610893966107ed61020f9973ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b90600052602052604060002090565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff9290921682526020820192909252a1803561085d60208301611035565b9161086a60408201611042565b610877606083018361104c565b9161088b60808501359460a081019061109d565b9690956116e4565b60405173ffffffffffffffffffffffffffffffffffffffff90911681529081906020820190565b7f8baa579f0000000000000000000000000000000000000000000000000000000060005260046000fd5b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff8416141561078f565b7f756688fe0000000000000000000000000000000000000000000000000000000060005260046000fd5b7f0819bdcd0000000000000000000000000000000000000000000000000000000060005260046000fd5b6003111561022a57565b9181601f8401121561022a5782359167ffffffffffffffff831161022a576020808501948460051b01011161022a57565b3461022a5760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435602435610a088161098f565b60443567ffffffffffffffff811161022a57610a28903690600401610666565b91909260643567ffffffffffffffff811161022a57610a4b903690600401610666565b6084359160a4359567ffffffffffffffff871161022a5761020f97610a77610893983690600401610999565b9790966110f1565b3461022a5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760207fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275473ffffffffffffffffffffffffffffffffffffffff60405191168152f35b6006111561022a57565b3461022a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610b3581610af0565b60243590610b428261022f565b6044359067ffffffffffffffff821161022a57602092610b69610b73933690600401610666565b91606435936111f0565b73ffffffffffffffffffffffffffffffffffffffff60405191168152f35b3461022a5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610bcc8161098f565b60243567ffffffffffffffff811161022a57610bec903690600401610666565b90916044359167ffffffffffffffff831161022a57602093610c15610b73943690600401610666565b92909160643594611473565b3461022a57610c2f36610694565b60e0830135421161096557610c449183612153565b90610c6f8273ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b90610c8c61076e60c0830135809490600052602052604060002090565b61093b57610c9c61078584610fd7565b80610d70575b6108ba577f2af71f10069c28afc67c3752e87e0e4616a97948d33c8f404a856c0c334b3e018284610d006107fc610893966107ed61020f9973ffffffffffffffffffffffffffffffffffffffff166000526002602052604060002090565b6040805173ffffffffffffffffffffffffffffffffffffffff9290921682526020820192909252a18035610d36602083016115cb565b91610d44604082018261104c565b90610d52606084018461104c565b929091610d6860808601359560a081019061109d565b9790966119ef565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffff748739275473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff84161415610ca2565b3461022a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a5760043560005260016020526020604060002054604051908152f35b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610e478161022f565b610e4f6115ed565b63389a75e1600c52806000526020600c209081544211610e755760006103019255611625565b636f5e88186000526004601cfd5b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610eb98161022f565b610ec16115ed565b8060601b15610ed35761030190611625565b637448fbae6000526004601cfd5b3461022a5760c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57602435600435610f1f82610af0565b60443591610f2c8361022f565b60643567ffffffffffffffff811161022a57610f4c903690600401610666565b60a4359391608435919067ffffffffffffffff861161022a5761020f96610f7a610893973690600401610999565b9690956115d5565b3461022a5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261022a57600435610fbd8161022f565b63389a75e1600c52600052602080600c2054604051908152f35b610ff1600191638b78c6d8600c526000526020600c205490565b16151590565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6006111561103057565b610ff7565b3561103f81610af0565b90565b3561103f8161022f565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561022a570180359067ffffffffffffffff821161022a5760200191813603831361022a57565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18136030182121561022a570180359067ffffffffffffffff821161022a57602001918160051b3603831361022a57565b9061103f98979695949392916111056119d3565b6119ef565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761117a57604052565b61110a565b67ffffffffffffffff811161117a57601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b9291926111c58261117f565b916111d36040519384611139565b82948184528183011161022a578281602093846000960137010152565b9391939290926111ff81611026565b8061124e57505061103f925061124930926c5af43d3d93803e602a57fd5bf360215260145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c20906000602152565b6120cb565b61125a81949294611026565b60018103611279575061127361103f94309436916111b9565b90611d0b565b61128581949294611026565b6002810361130c57505061103f9250611249309290604051917fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076604052616009602052601e5268603d3d8160223d3973600a52605f602120916040526000606052565b61131881949294611026565b60038103611337575061133161103f94309436916111b9565b90611c57565b61134381949294611026565b6004810361140757505061103f925061124930929073ffffffffffffffffffffffffffffffffffffffff604051927fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f36060527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c6040527660195155f3363d3d373d3d363d602036600436635c60da602052167c60523d8160223d39730000000000000000000000000000000000000000176009526074600c20916040526000606052565b80611416600592959395611026565b036114315761142b61103f94309436916111b9565b90611b8d565b7f5c68875d0000000000000000000000000000000000000000000000000000000060005260046000fd5b6003111561103057565b908092918237016000815290565b939092936114808161145b565b600181036115aa575061103f9461157f9490936114c393611563938015611598576114ef92936114c3916114bd6040519687956020870191611465565b91611465565b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611139565b6020815191012060405192839160208301953087917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000605594927fff00000000000000000000000000000000000000000000000000000000000000855260601b166001840152601583015260358201520190565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b506115a5925036916111b9565b6114ef565b92505050600291506115bb8161145b565b036114315761103f903090611d8b565b3561103f8161098f565b9061103f979695949392916115e86119d3565b6116e4565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392754330361161757565b6382b429006000526004601cfd5b73ffffffffffffffffffffffffffffffffffffffff16807fffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a37fffffffffffffffffffffffffffffffffffffffffffffffffffffffff7487392755565b90600182018092116116b557565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9396959694929094823b156119a95761171061170a866000526001602052604060002090565b546116a7565b9561171a81611026565b8061181957505050908161175e7feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661175684611813966126ec565b985b89611fd4565b6117ba8761177a876107ed886000526000602052604060002090565b9073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b846117cf856000526001602052604060002090565b558660405195869586919373ffffffffffffffffffffffffffffffffffffffff608094819398979660a0860199865260208601521660408401521660608201520152565b0390a190565b61182281611026565b6001810361187157507feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b8561186561181397969561175e9536916111b9565b85612685565b98611758565b61187a81611026565b600281036118b957505050908161175e7feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b8461181396612609565b6118c281611026565b6003810361190b57507feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b8561190561181397969561175e9536916111b9565b85612571565b61191781939293611026565b6004810361195657505050908161175e7feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b84611813966124b8565b8061196660059296959496611026565b03611431577feea391f0f1d2de963bc4696b351fe62ec143a55a9ab92a1a490e818702e8b3309661186b846119a361175e946118139836916111b9565b856123f8565b7f68155f9a0000000000000000000000000000000000000000000000000000000060005260046000fd5b638b78c6d8600c523360005260016020600c205416156115ed57565b9495969793919092611a0e61170a876000526001602052604060002090565b968015611b7a57611a3192936114c3916114bd6040519687956020870191611465565b905b611a3c8161145b565b80611ae9575093611a7c61181392611a747fb9b3ce774ed64bac5843e4d220bb1266963d22ccb555eaac751476bb1fdd6a39976120a3565b975b88611fd4565b611a988661177a866107ed876000526000602052604060002090565b83611aad846000526001602052604060002090565b5585604051948594859094939273ffffffffffffffffffffffffffffffffffffffff906060936080840197845260208401521660408201520152565b611af28161145b565b60018103611b34575093611a7c61181392611b2e837fb9b3ce774ed64bac5843e4d220bb1266963d22ccb555eaac751476bb1fdd6a3998612051565b97611a76565b80611b4360029297939761145b565b0361143157611a7c61181392611b2e837fb9b3ce774ed64bac5843e4d220bb1266963d22ccb555eaac751476bb1fdd6a399861272d565b50611b87925036916111b9565b90611a33565b93929190936040519085519061ffad82113d3d3e60005b828110611c41575061103f9596506016916075917fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3606b8601527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c604b8601527660195155f3363d3d373d3d363d602036600436635c60da602b86015260148501528060381b696100523d8160233d3973018452019101206120cb565b80602080928a010151608b828701015201611ba4565b93929190936040519085519061ffc282113d3d3e60005b828110611cf5575061103f959650906060917fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f360408501527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e207660208501526160096016526014528060381b6961003d3d8160233d39730160005260165183520190206120cb565b80602080928a0101516060828701015201611c6e565b93929190936040519085519061ffd282113d3d3e60005b828110611d75575061103f959650600c916037916e5af43d82803e903d91602b57fd5bf3602386015260148501528060881b7361002d3d81600a3d39f3363d3d373d3d3d363d73018452019101206120cb565b80602080928a0101516043828701015201611d22565b6040519160005260ff600b536020527f21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f6040526055600b2060145260405261d69460005260016034536017601e2090565b638b78c6d8600c526000526020600c2090815490811618809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26600080a3565b94919897969390989592956101208601997f9cd6e13852212116e23b1b7439c9d28a11dbbc7b355f5b0f3e71e5f5fec5a69d875260208701526006811015611030576101009673ffffffffffffffffffffffffffffffffffffffff916040880152166060860152608085015260a084015260c083015260e08201520152565b61103f9291611f8391803590611f24611ebd60208301611035565b6114c3611ecc60408501611042565b93611ee4611edd606083018361104c565b36916111b9565b60208151910120906080810135611f07611f0160a084018461109d565b90612219565b9060e060c084013593013593604051988997602089019b8c611e23565b5190206114c3611f78611f356122be565b9260405192839160208301958690916042927f19010000000000000000000000000000000000000000000000000000000000008352600283015260228201520190565b5190209236916111b9565b90612350565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b90821015611fcf576106ff9160051b81019061104c565b611f89565b909160005b818110611fe65750505050565b600080611ff4838588611fb8565b908160405192839283378101838152039082875af13d15612049573d9061201a8261117f565b916120286040519384611139565b82523d6000602084013e5b156120415750600101611fd9565b602081519101fd5b606090612033565b6020815191016000f59073ffffffffffffffffffffffffffffffffffffffff82161561207957565b7f301164250000000000000000000000000000000000000000000000000000000060005260046000fd5b6020815191016000f09073ffffffffffffffffffffffffffffffffffffffff82161561207957565b91909160ff60005360355260601b6001526015526055600020906000603552565b949195929897969390986101208601997f75fa0565ef631e3bafea98a699d084a8c713c8a872b040d645f22c1114a08984875260208701526003871015611030576101009660408701526060860152608085015260a084015260c083015260e08201520152565b61103f9291611f8391803590611f2461216e602083016115cb565b6114c3612181611edd604086018661104c565b6020815191012093612199611edd606083018361104c565b602081519101209060808101356121b6611f0160a084018461109d565b9060e060c084013593013593604051988997602089019b8c6120ec565b67ffffffffffffffff811161117a5760051b60200190565b805160209091019060005b8181106122035750505090565b82518452602093840193909201916001016121f6565b612222826121d3565b916122306040519384611139565b8083527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061225d826121d3565b0136602085013760005b81811061228c57505050604051612286816114c36020820180956121eb565b51902090565b61229a611edd828486611fb8565b60208151910120908451811015611fcf5760019160208260051b8701015201612267565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f24883a27c7cf596f4158af359c654398867831bf32ca431b4b77484420407ba860408201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260a0815261228660c082611139565b919091604051928051806040146123bc5760411461237b57505050505b638baa579f6000526004601cfd5b602091606082015160001a835260408201516060525b60005201516040526020600160806000825afa519160006060526040523d6123ba57505061236d565b565b506020917f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6040830151601b8160ff1c01855216606052612391565b9060756016916040519381518092816020608b8901920160045afa507fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f3606b8601527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c604b8601527660195155f3363d3d373d3d363d602036600436635c60da602b86015260148501528060381b6afe6100523d8160233d39730161ffad82118501520191016000f59081156124aa57565b63301164256000526004601cfd5b919073ffffffffffffffffffffffffffffffffffffffff604051937fb3582b35133d50545afa5036515af43d6000803e604d573d6000fd5b3d6000f36060527f1b60e01b36527fa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6c6040527660195155f3363d3d373d3d363d602036600436635c60da602052167c60523d8160223d39730000000000000000000000000000000000000000176009526074600c6000f59182156124aa576040526000606052565b906060906040519281518092816020868801920160045afa507fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f360408501527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e207660208501526160096016526014528060381b6afe61003d3d8160233d39730161ffc2821152601651835201906000f59081156124aa57565b9190604051927fcc3735a920a3ca505d382bbc545af43d6000803e6038573d6000fd5b3d6000f36060527f5155f3363d3d373d3d363d7f360894a13ba1a3210667c828492db98dca3e2076604052616009602052601e5268603d3d8160223d3973600a52605f60216000f59182156124aa576040526000606052565b600b90604051908351809481602060438601920160045afa506e5af43d82803e903d91602b57fd5bf3602383015260148201528260881b74fe61002d3d81600a3d39f3363d3d373d3d3d363d7301815261ffd360378401931001016000f59081156124aa57565b6c5af43d3d93803e602a57fd5bf360215260145273602c3d8160093d39f33d3d3d3d363d3d37363d736000526035600c6000f59081156124aa576000602152565b91906f67363d3d37363d34f03d5260086018f36000526010806000f59182156124aa57600080918460145261d694825260016034536017601e209482602083519301915af1823b02156124aa5756fea2646970667358221220fe81e60c13ef87adde667a0a7072c940d9d7c1d5fb7753a30690cc7f42a6969064736f6c634300081e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001a472863cf21d5aa27f417df9140400324c48f220000000000000000000000009d4d20b7571f9552d730eca812e805e7d5fb64e5
-----Decoded View---------------
Arg [0] : owner (address): 0x1A472863cF21D5Aa27F417dF9140400324C48f22
Arg [1] : manager (address): 0x9d4D20B7571F9552D730eCA812E805E7d5fb64E5
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000001a472863cf21d5aa27f417df9140400324c48f22
Arg [1] : 0000000000000000000000009d4d20b7571f9552d730eca812e805e7d5fb64e5
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
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.