// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)pragmasolidity ^0.8.20;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
function_contextSuffixLength() internalviewvirtualreturns (uint256) {
return0;
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)pragmasolidity ^0.8.20;import {Context} from"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/errorOwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/errorOwnableInvalidOwner(address owner);
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/constructor(address initialOwner) {
if (initialOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
if (newOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 7 of 7: SSTORE2.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;/// @notice Read and write to persistent storage at a fraction of the cost./// @author Solady (https://github.com/vectorized/solmady/blob/main/src/utils/SSTORE2.sol)/// @author Saw-mon-and-Natalie (https://github.com/Saw-mon-and-Natalie)/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)librarySSTORE2{
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*//* CUSTOM ERRORS *//*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/errorDeploymentFailed();
errorInvalidPointer();
errorReadOutOfBounds();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*//* WRITE LOGIC *//*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/functionwrite(bytesmemory data) internalreturns (address pointer) {
// Note: The assembly block below does not expand the memory.assembly {
let originalDataLength :=mload(data)
// Add 1 to data size since we are prefixing it with a STOP opcode.let dataSize :=add(originalDataLength, 1)
/**
* ------------------------------------------------------------------------------+
* Opcode | Mnemonic | Stack | Memory |
* ------------------------------------------------------------------------------|
* 61 codeSize | PUSH2 codeSize | codeSize | |
* 80 | DUP1 | codeSize codeSize | |
* 60 0xa | PUSH1 0xa | 0xa codeSize codeSize | |
* 3D | RETURNDATASIZE | 0 0xa codeSize codeSize | |
* 39 | CODECOPY | codeSize | [0..codeSize): code |
* 3D | RETURNDATASZIE | 0 codeSize | [0..codeSize): code |
* F3 | RETURN | | [0..codeSize): code |
* 00 | STOP | | |
* ------------------------------------------------------------------------------+
* @dev Prefix the bytecode with a STOP opcode to ensure it cannot be called.
* Also PUSH2 is used since max contract size cap is 24,576 bytes which is less than 2 ** 16.
*/mstore(
data,
or(
0x61000080600a3d393df300,
// Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2.shl(0x40, dataSize)
)
)
// Deploy a new contract with the generated creation code.
pointer :=create(0, add(data, 0x15), add(dataSize, 0xa))
// If `pointer` is zero, revert.ifiszero(pointer) {
// Store the function selector of `DeploymentFailed()`.mstore(0x00, 0x30116425)
// Revert with (offset, size).revert(0x1c, 0x04)
}
// Restore original length of the variable size `data`.mstore(data, originalDataLength)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*//* READ LOGIC *//*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/functionread(address pointer) internalviewreturns (bytesmemory data) {
assembly {
let pointerCodesize :=extcodesize(pointer)
ifiszero(pointerCodesize) {
// Store the function selector of `InvalidPointer()`.mstore(0x00, 0x11052bb4)
// Revert with (offset, size).revert(0x1c, 0x04)
}
// Offset all indices by 1 to skip the STOP opcode.let size :=sub(pointerCodesize, 1)
// Get the pointer to the free memory and allocate// enough 32-byte words for the data and the length of the data,// then copy the code to the allocated memory.// Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
data :=mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
extcodecopy(pointer, add(data, 0x20), 1, size)
}
}
functionread(address pointer, uint256 start) internalviewreturns (bytesmemory data) {
assembly {
let pointerCodesize :=extcodesize(pointer)
ifiszero(pointerCodesize) {
// Store the function selector of `InvalidPointer()`.mstore(0x00, 0x11052bb4)
// Revert with (offset, size).revert(0x1c, 0x04)
}
// If `!(pointer.code.size > start)`, reverts.// This also handles the case where `start + 1` overflows.ifiszero(gt(pointerCodesize, start)) {
// Store the function selector of `ReadOutOfBounds()`.mstore(0x00, 0x84eb0dd1)
// Revert with (offset, size).revert(0x1c, 0x04)
}
let size :=sub(pointerCodesize, add(start, 1))
// Get the pointer to the free memory and allocate// enough 32-byte words for the data and the length of the data,// then copy the code to the allocated memory.// Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
data :=mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
extcodecopy(pointer, add(data, 0x20), add(start, 1), size)
}
}
functionread(address pointer,
uint256 start,
uint256 end
) internalviewreturns (bytesmemory data) {
assembly {
let pointerCodesize :=extcodesize(pointer)
ifiszero(pointerCodesize) {
// Store the function selector of `InvalidPointer()`.mstore(0x00, 0x11052bb4)
// Revert with (offset, size).revert(0x1c, 0x04)
}
// If `!(pointer.code.size > end) || (start > end)`, revert.// This also handles the cases where `end + 1` or `start + 1` overflow.ifiszero(
and(
gt(pointerCodesize, end), // Within bounds.iszero(gt(start, end)) // Valid range.
)
) {
// Store the function selector of `ReadOutOfBounds()`.mstore(0x00, 0x84eb0dd1)
// Revert with (offset, size).revert(0x1c, 0x04)
}
let size :=sub(end, start)
// Get the pointer to the free memory and allocate// enough 32-byte words for the data and the length of the data,// then copy the code to the allocated memory.// Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
data :=mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
extcodecopy(pointer, add(data, 0x20), add(start, 1), size)
}
}
}