false
true
0

Contract Address Details

0x87fC31413534733A09Df5Dc5Aa33b4dBa1f64b61

Contract Name
Random
Creator
0xaf2b21–3e4225 at 0xb2bb71–91e9ba
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
26784339
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
Random




Optimization enabled
false
Compiler version
v0.8.25+commit.b61c2a91




EVM Version




Verified at
2026-06-11T13:08:33.822507Z

Constructor Arguments


              

contracts/Random.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

// import {console} from "hardhat/console.sol";

import {SSTORE2} from "solady/src/utils/SSTORE2.sol";
import {LibPRNG} from "solady/src/utils/LibPRNG.sol";
import {LibBitmap} from "solady/src/utils/LibBitmap.sol";
import {SafeTransferLib} from "solady/src/utils/SafeTransferLib.sol";
import {EfficientHashLib} from "solady/src/utils/EfficientHashLib.sol";
import {LibMulticaller} from "multicaller/src/LibMulticaller.sol";
import {IRandom} from "./implementations/IRandom.sol";
import {PreimageLocation} from "./PreimageLocation.sol";
import {Errors, Cast, Reveal, Link, Ink, Heat, Start, Expired, Chop, Bleach, FailedToCall} from "./Constants.sol";
import {StorageSlot} from "./StorageSlot.sol";
import {SlotDerivation} from "./SlotDerivation.sol";
import {ConsumerReceiver} from "./implementations/ConsumerReceiver.sol";

contract Random is IRandom {
    // this error is used inside of sstore to so we surface it here so that it sticks in the abi
    using SSTORE2 for address;
    using SSTORE2 for bytes;

    using SafeTransferLib for address;

    using StorageSlot for bytes32;
    using StorageSlot for StorageSlot.Bytes32SlotType;
    using SlotDerivation for *;

    using LibPRNG for LibPRNG.PRNG;

    using EfficientHashLib for bytes32;
    using EfficientHashLib for bytes32[];

    using PreimageLocation for PreimageLocation.Info;
    using PreimageLocation for bytes32;

    using LibBitmap for LibBitmap.Bitmap;

    string private constant _NAMESPACE = "random";

    mapping(address account => bytes32 latest) internal _latest;
    mapping(address account => mapping(address token => uint256 amount)) internal _custodied;
    mapping(address provider => mapping(uint256 token => mapping(uint256 price => uint256 max))) internal _preimageCount;
    mapping(
        address provider
            => mapping(uint256 token => mapping(uint256 price => mapping(uint256 offset => address pointer)))
    ) internal _pointers;
    mapping(address provider => mapping(uint256 token => mapping(uint256 price => LibBitmap.Bitmap bitmap))) internal
        _accessFlags;
    mapping(
        address provider
            => mapping(uint256 token => mapping(uint256 price => mapping(uint256 index => bytes32 formerSecret)))
    ) internal _linkedSecret;
    mapping(
        address provider
            => mapping(uint256 token => mapping(uint256 price => mapping(uint256 index => bytes32 formerSecret)))
    ) internal _revealedSecret;
    mapping(bytes32 key => bool chopped) internal _chopped;
    mapping(address account => mapping(bytes32 txHash => bytes32 latest)) internal _latestInTx;

    /**
     * start the process to reveal the ink that was written (using invisible ink as a visual analogy)
     * @dev the reason why this method uses flags (256 per slot) is because this allows a
     * central entity to benefit from requesting randomness such as an eip3074 enabled multicaller
     * and benefit greatly from the gas savings of access the same slot up to 256 times
     * @dev notice that the index is derived from the preimage key by adding [95..16] and [15..1] together
     */
    function _ignite(PreimageLocation.Info memory info, bytes32 section) internal returns (bool) {
        unchecked {
            uint256 encodedToken = info.encodeToken();
            if (_consumed({info: info, encodedToken: encodedToken})) {
                return false;
            }
            _accessFlags[info.provider][encodedToken][info.price].set(info.offset + info.index);
            emit Heat({provider: info.provider, section: section, index: info.offset + info.index});
            return true;
        }
    }

    /**
     * check if the preimage has been consumed by randomness
     * @param info the location of a preimage
     * @param encodedToken the encoded token information (durationIsTimestamp[0,1),duration[56,95),token[96,255])
     */
    function _consumed(PreimageLocation.Info memory info, uint256 encodedToken) internal view returns (bool) {
        if (_pointerSize({info: info, encodedToken: encodedToken}) / THREE_TWO <= info.index) {
            revert Errors.Misconfigured();
        }
        // returning zero means that the secret has not been requested yet on chain
        return _accessFlags[info.provider][encodedToken][info.price].get(info.offset + info.index);
    }

    /**
     * gets the number of bytes held by the pointer - a contract generated from preimage bytes
     * @param info the preimage location
     * @dev the index is not used for this so it can be set to 0
     * @param encodedToken the encoded token information (durationIsTimestamp[0,1),duration[56,95),token[96,255])
     */
    function _pointerSize(PreimageLocation.Info memory info, uint256 encodedToken)
        internal
        view
        returns (uint256 size)
    {
        address pntr = _pointers[info.provider][encodedToken][info.price][info.offset];
        if (pntr == address(0)) {
            revert Errors.Misconfigured();
        }
        assembly {
            size := extcodesize(pntr)
        }
        size -= ONE;
    }

    /**
     * write the secret to storage and emit an event
     * @param info the location of the preimage that is being revealed
     * @param formerSecret the former secret - this value, when run through keccak256 must match the preimage
     * @return location the location hash of the preimage location info - this is used to create the randomness key
     * @return first whether or not this was the first time that _flick was run successfully for this preimage location
     * @dev this method will fail if an invalid info is passed and there is no pointer (storage to check against)
     * @dev this method will fail if the secret does not match the stored preimage
     */
    function _flick(PreimageLocation.Info calldata info, bytes32 formerSecret)
        internal
        returns (bytes32 location, bool first)
    {
        unchecked {
            // length check is skipped because if one goes out of bounds you either err
            // or you end up with zero bytes, which would be quite the feat to find the hash for
            // always read 32 bytes
            if (formerSecret.hash() != _toPreimage(info)) {
                revert Errors.SecretMismatch();
            }
            uint256 tkn = info.encodeToken();
            // only ever set once but do not penalize for lack of coordination
            location = info.location();
            (bytes32 linkedSecret,) = _secret(info, tkn);
            if (linkedSecret == bytes32(ZERO)) {
                _linkedSecret[info.provider][tkn][info.price][info.offset + info.index] = formerSecret;
                // gives provider access to staked tokens
                _custodied[info.provider][info.token] += info.price;
                emit Link({provider: info.provider, location: location, formerSecret: formerSecret});
                return (location, true);
            }
            return (location, false);
        }
    }

    function _toPreimage(PreimageLocation.Info calldata info) internal view returns (bytes32) {
        uint256 tkn = info.encodeToken();
        address pntr = _pointers[info.provider][tkn][info.price][info.offset];
        if (pntr == address(0)) {
            revert Errors.Misconfigured();
        }
        // length check is skipped because if one goes out of bounds you either err
        // or you end up with zero bytes, which would be quite the feat to find the hash for
        // always read 32 bytes
        return bytes32(pntr.read((info.index * THREE_TWO), ((info.index * THREE_TWO) + THREE_TWO)));
    }

    function reveal(PreimageLocation.Info calldata info, bytes32 formerSecret) external payable {
        if (_toPreimage(info) == keccak256(abi.encode(formerSecret))) {
            // this event is the same one used during cast
            // but it should not be used as a signal that the randomness has been cast
            // only the cast event should be used for that
            _revealedSecret[info.provider][info.encodeToken()][info.price][info.offset + info.index] = formerSecret;
            emit Reveal({provider: info.provider, location: info.location(), formerSecret: formerSecret});
        }
    }

    enum CastState {
        SCATTERED,
        SEED_SET,
        MISSING_SECRET
    }

    /**
     * accesses the stored secret
     * @param info the info to access the location
     * @param encodedToken encoded token info
     */
    function _secret(PreimageLocation.Info calldata info, uint256 encodedToken)
        internal
        view
        returns (bytes32 linkedSecret, bytes32 revealedSecret)
    {
        linkedSecret = _linkedSecret[info.provider][encodedToken][info.price][info.offset + info.index];
        if (linkedSecret == bytes32(ZERO)) {
            revealedSecret = _revealedSecret[info.provider][encodedToken][info.price][info.offset + info.index];
        } else {
            revealedSecret = linkedSecret;
        }
    }

    /**
     * distribute tokens to a recipient
     * @param recipient the recipient of the tokens
     * @param token the token to send
     * @param amount the number of tokens
     */
    function _distribute(address recipient, address token, uint256 amount) internal {
        if (amount == ZERO) return;
        if (token == address(0)) {
            recipient.safeTransferETH(amount);
        } else {
            token.safeTransfer(recipient, amount);
        }
    }

    /**
     * reverse previous charges toward the owner. owner can end up with up to 2x the amount they put in and
     * will have to handle distributing tokens according to their own policy
     * @param timeline the timeline of the randomness which holds the owner and whether a call should be triggered
     * @param key the randomness key
     * @param token the token being reversed
     * @param payout the amount of the token being reversed
     */
    function _reverseCharges(uint256 timeline, bytes32 key, address token, uint256 payout) internal returns (bool) {
        address owner = address(uint160(timeline >> NINE_SIX));
        _custodied[owner][token] += payout;
        if (_shouldCall(timeline)) {
            // allow owner to take his ball and go home
            // do not check if the account call was successful
            _call({
                to: owner,
                b: abi.encodeWithSelector(ConsumerReceiver.onReverse.selector, key, token, payout),
                key: key
            });
            return true;
        }
        return false;
    }

    /**
     * receive a number of tokens and attribute them to an account
     * @param account the account to attribute tokens to
     * @param token the tokens being received
     * @param amount the number of tokens being received
     */
    function _receiveTokens(address account, address token, uint256 amount) internal returns (uint256) {
        unchecked {
            if (token == address(0)) {
                if (amount > msg.value) {
                    revert Errors.MissingPayment();
                }
                amount = msg.value;
            } else {
                // because we do not check balanceof delta, we will
                // not correctly attribute tax/reflection tokens
                uint256 before = token.balanceOf(address(this));
                token.safeTransferFrom2(account, address(this), amount);
                amount = token.balanceOf(address(this)) - before;
            }
            return amount;
        }
    }

    /**
     * decrement a desired amount from the provided account's token balance
     * @param account the address to decrement against
     * @param token the token balance to decrement
     * @param desired the desired decrementation
     * @return delta may be less than the desired. note that the amount
     * actually decremented may be less than the desired input
     */
    function _decrementTokenAmount(address account, address token, uint256 desired) internal returns (uint256 delta) {
        unchecked {
            uint256 limit = _custodied[account][token];
            delta = desired > limit ? limit : desired;
            if (delta > ZERO) {
                _custodied[account][token] = limit - delta;
            }
        }
    }

    /**
     * get a account's token balance - the number of tokens that can be used
     * to perform certain actions such as inking or heating
     * @param account the account in question
     * @param token the token balance being queried
     */
    function balanceOf(address account, address token) external view returns (uint256) {
        return _custodied[account][token];
    }

    /**
     * access the timeline, owner, duration, contribution count and seed if it exists
     * the number of locations that recreates the final hash is equivalent the number of required seed contributions
     * @param key the randomness key
     */
    function randomness(bytes32 key) external view override returns (Randomness memory) {
        unchecked {
            return Randomness({
                contributed: uint256(uint8(_timeline[key])), // 8 bits
                callAtChange: _shouldCall(_timeline[key]), // 1 bit
                owner: address(uint160(_timeline[key] >> NINE_SIX)), // 160 bits
                start: uint256(uint48(_timeline[key] >> FOUR_EIGHT)), // 48 bits
                duration: uint256(uint256(uint48(_timeline[key])) >> (EIGHT + ONE)), // only 39 bits
                usesTimestamp: (_timeline[key] >> EIGHT) & ONE == ONE, // 1 bit
                timeline: _timeline[key],
                seed: _seed[key]
            });
        }
    }

    /**
     * get the latest key generated by a provided address. restrict to same transaction if desired
     * @param owner the address that requested randomness
     * @param onlySameTx whether or not to only consider randomness that has been requested within this transaction
     * utilizes transient storage and provides certain guarantees regarding the relationship between randomness
     * and the its utility to outsiders depending on how the transaction was executed
     */
    function latest(address owner, bool onlySameTx, bool useTSTORE) external view override returns (bytes32 key) {
        key = useTSTORE
            ? _NAMESPACE.erc7201Slot().deriveMapping(owner).asBytes32().tload()
            : _latestInTx[owner][_txHash()];
        if (key == bytes32(ZERO)) {
            if (onlySameTx) {
                revert Errors.UnableToService();
            }
            key = _latest[owner];
        }
    }

    /**
     * check if a preimage at the provided location has been consumed / accessed for randomness
     * @param info preimage location info to locate the preimage
     * @return consumed a boolean to indicate that the location has or has not been consumed
     */
    function consumed(PreimageLocation.Info calldata info) external view override returns (bool) {
        return _consumed({info: info, encodedToken: info.encodeToken()});
    }

    /**
     * check for a minimum number of unconsumed preimages. provide a duration in
     * seconds or blocks to consider the randomness set to be valid
     * @param required the minimum number of locations required to be a valid (desired) set
     * @param settings the settings required to setup the randomness campaign
     * @notice if the duration in the settings is lower than any location or the
     * duration is timestamp does not match, then the contract will err
     * @param potentialLocations the locations to check for unconsumed preimages
     * @dev note that the contract stores the latest key for each owner in transient storage
     * this allows for many other chained games to use the same randomness seeds and have guarantees
     * that no secrets have been exposed before the initiating transaction has been mined
     */
    function heat(
        uint256 required,
        PreimageLocation.Info calldata settings,
        PreimageLocation.Info[] calldata potentialLocations,
        bool useTSTORE
    ) external payable override returns (bytes32) {
        unchecked {
            bytes32[] memory locations = new bytes32[](required);
            address account = LibMulticaller.senderOrSigner();
            {
                if (msg.value > ZERO) {
                    _custodied[account][address(0)] += msg.value;
                }
                if (settings.provider == address(0)) {
                    revert Errors.UnableToService();
                }
                if (required == ZERO || required > TWO_FIVE_FIVE || required > potentialLocations.length) {
                    // only 255 len or fewer allowed
                    revert Errors.UnableToService();
                }
                if ((uint256(uint40(settings.duration << ONE)) >> ONE) != settings.duration) {
                    revert Errors.Misconfigured();
                }
                uint256 len = potentialLocations.length;
                uint256 i;
                uint256 contributing;
                uint256 amount;
                bytes32 section;
                address token = potentialLocations[ZERO].token;
                PreimageLocation.Info calldata target;
                do {
                    target = potentialLocations[i];
                    // non zero means that the value exists
                    if (token != target.token) {
                        revert Errors.Misconfigured();
                    }
                    if (target.durationIsTimestamp != settings.durationIsTimestamp) {
                        revert Errors.Misconfigured();
                    }
                    // target.minDuration > duration
                    if (target.duration > settings.duration) {
                        revert Errors.Misconfigured();
                    }
                    section = target.section();
                    if (_ignite({info: target, section: section})) {
                        locations[contributing] = section.hash(bytes32(target.index));
                        amount += target.price;
                        ++contributing;
                        if (required == contributing) {
                            break;
                        }
                    }
                    ++i;
                } while (i < len);

                if (contributing < required) {
                    // let other contracts revert if they must
                    revert Errors.UnableToService();
                }
                if (amount > ZERO && amount > _decrementTokenAmount({account: account, token: token, desired: amount}))
                {
                    revert Errors.MissingPayment();
                }
            }
            {
                bytes32 key = locations.hash();
                // front load the cost of requesting randomness
                // put it on the shoulders of the consumer
                // this can probably be optimized
                _timeline[key] = _timelineFromInputs({
                    owner: settings.provider,
                    callAtChange: settings.callAtChange,
                    // we already checked expiry offset above is constrained to 38 bits
                    expiryOffset: (settings.duration << ONE) | (settings.durationIsTimestamp ? ONE : ZERO),
                    start: settings.durationIsTimestamp ? block.timestamp : block.number
                });
                _storeLatest({provider: settings.provider, key: key, useTSTORE: useTSTORE});
                emit Start({owner: settings.provider, key: key});
                return key;
            }
        }
    }

    function _storeLatest(address provider, bool useTSTORE, bytes32 key) internal {
        // this mode is insufficient for randomness due to block builders
        // being able to name their own transaction order
        if (useTSTORE) {
            _NAMESPACE.erc7201Slot().deriveMapping(provider).asBytes32().tstore(key);
        } else {
            _latestInTx[provider][_txHash()] = key;
        }
        _latest[provider] = key;
    }

    function _txHash() internal view returns (bytes32) {
        return keccak256(
            abi.encodePacked(
                block.coinbase,
                block.basefee,
                block.chainid,
                block.timestamp,
                block.number,
                blockhash(block.number),
                tx.origin,
                tx.gasprice
            )
        );
    }

    /**
     * encodes a timeline that will only change the last 8 bits as secrets are revealed
     * @param owner the owner of the randomness - the address that will be refunded if not all secrets are provided in a timely manner
     * @param expiryOffset the expiration offset from the time that the randomness was first requested
     * @param start the start time or block number
     * @return timeline an encoded number with relevant owner, and timing data
     */
    function _timelineFromInputs(address owner, bool callAtChange, uint256 expiryOffset, uint256 start)
        internal
        pure
        returns (uint256)
    {
        return (uint256(uint160(owner)) << NINE_SIX) | (uint256((uint48(start))) << FOUR_EIGHT)
            | (uint256(uint40(expiryOffset << TWO)) << (EIGHT - ONE)) | (uint256(callAtChange ? ONE : ZERO) << EIGHT); // last 8 bits left blank for counting as secrets are revealed
    }

    /**
     * retrieve the pointer or address that holds the series of preimages for a tranche of secrets
     * @param info access the pointer as defined by the preimage location
     * @return pointer the address that holds preimages
     */
    function pointer(PreimageLocation.Info calldata info) external view override returns (address) {
        return _pointers[info.provider][info.encodeToken()][info.price][info.offset];
    }

    /**
     * advertise immutable randomness preimages for future revelation. imagine painting a die with invisible ink
     * @param data the concatenated, immutable preimages to write on chain
     * @dev if data length is > (24576-32), then this method will fail
     * @dev if data is not evenly divisible by 32, then this method will fail
     * @dev it is best to call this infrequently but to do so with as
     * much calldata as possible to increase gas savings for randomness providers
     */
    function ink(PreimageLocation.Info memory info, bytes calldata data) external payable {
        unchecked {
            uint256 count = data.length / THREE_TWO;
            if (data.length == ZERO || data.length % THREE_TWO != ZERO) {
                revert Errors.Misconfigured();
            }
            // access control regulated by the sender/signer
            address account = LibMulticaller.senderOrSigner();
            if (msg.value > ZERO) {
                _custodied[account][address(0)] += msg.value;
            }
            uint256 limit = _custodied[account][info.token];
            uint256 toStake = count * info.price;
            if (limit < toStake) {
                revert Errors.MissingPayment();
            }
            // at this point, the only address that can unlock this value
            // is one that has access to the secrets or pays for randomness and does not get it in a timely manner
            _custodied[account][info.token] -= toStake;
            // owner of the newly created randomness set by calldata
            address owner = info.provider;
            if (owner == address(0)) {
                revert Errors.UnableToService();
            }
            uint256 tkn = info.encodeToken();
            uint256 start = _preimageCount[owner][tkn][info.price];
            address pntr = data.write(); // deploy a contract with immutable preimages written into it
            _pointers[owner][tkn][info.price][start] = pntr;
            _preimageCount[owner][tkn][info.price] = start + count;
            info.provider = owner;
            info.offset = start;
            emit Ink({
                sender: account,
                provider: owner,
                section: info.section(),
                offset: (start << ONE_TWO_EIGHT) | (start + count),
                pointer: pntr
            });
        }
    }

    /**
     * refund an owner of randomness for any secrets that are not written on chain.
     * the amount refunded is equal to the amount of tokens for each preimage that was not revealed.
     * @dev this method will fail if the timeline has not yet expired. because the duration must be >= to the
     * location defined by each provider, implicit consent and declaration has been provided by each provider
     * that they will have their randomness on chain by the time this method can be executed
     * @param key the key of the randomness that did not have all of its secrets revealed
     * @param info the set of locations of the randomness that was requested
     */
    function chop(bytes32 key, PreimageLocation.Info[] calldata info) external payable {
        unchecked {
            if (msg.value > ZERO) {
                _custodied[LibMulticaller.senderOrSigner()][address(0)] += msg.value;
            }
            if (_seed[key] != bytes32(ZERO)) {
                // don't penalize, because a provider could slip in before
                return;
            }
            uint256 timeline = _timeline[key];
            if (!_expired({timeline: timeline})) {
                revert Errors.UnableToService();
            }
            if (_chopped[key]) {
                revert Errors.UnableToService();
            }
            uint256 remaining;
            uint256 original;
            uint256 i;
            uint256 len = info.length;
            bytes32[] memory locations = new bytes32[](len);
            bytes32 revealedSecret;
            do {
                (, revealedSecret) = _secret({info: info[i], encodedToken: info[i].encodeToken()});
                if (revealedSecret == bytes32(ZERO)) {
                    // take the provider's stake
                    remaining += info[i].price;
                }
                original += info[i].price;
                locations[i] = info[i].location();
                ++i;
            } while (i < len);
            if (locations.hash() != key) {
                revert Errors.NotInCohort();
            }
            // for any secrets that do not reach the chain, the payment
            // AND the staked amount is released to the owner
            _chopped[key] = true;
            if (_reverseCharges({timeline: timeline, key: key, token: info[ZERO].token, payout: remaining + original}))
            {
                _call({
                    to: address(uint160(timeline >> NINE_SIX)),
                    b: abi.encodeWithSelector(ConsumerReceiver.onChop.selector, key),
                    key: key
                });
            }
            emit Chop({key: key});
        }
    }

    function _call(address to, bytes memory b, bytes32 key) internal {
        (bool success,) = to.call(b);
        if (!success) {
            emit FailedToCall({to: to, key: key});
        }
    }

    /**
     * write a randomness request's secrets into storage
     * @param key the randomness key. provided info param must be hashed to recreate this key
     * @param info the raw location info of preimages
     * @param revealed the list of secrets that must match the written preimages
     */
    function cast(bytes32 key, PreimageLocation.Info[] calldata info, bytes32[] memory revealed)
        external
        payable
        returns (CastState)
    {
        unchecked {
            if (msg.value > ZERO) {
                _custodied[LibMulticaller.senderOrSigner()][address(0)] += msg.value;
            }
            bytes32 seed = _seed[key];
            if (seed != bytes32(ZERO)) {
                return CastState.SEED_SET;
            }
            if (_chopped[key]) {
                revert Errors.UnableToService();
            }
            uint256 len = info.length;
            uint256 i;
            uint256 total;
            uint256 timeline = _timeline[key];
            {
                bytes32[] memory locations = new bytes32[](len);
                uint256 firstFlicks;
                bool first;
                bool missing;
                bytes32 linkedSecret;
                do {
                    if (revealed[i] != bytes32(ZERO)) {
                        (locations[i], first) = _flick({info: info[i], formerSecret: revealed[i]});
                        if (first) {
                            ++firstFlicks;
                        }
                    } else {
                        (revealed[i], linkedSecret) = _secret({info: info[i], encodedToken: info[i].encodeToken()});
                        if (revealed[i] == bytes32(ZERO)) {
                            if (linkedSecret == bytes32(ZERO)) {
                                missing = true;
                                locations[i] = info[i].location();
                            } else {
                                (locations[i], first) = _flick({info: info[i], formerSecret: linkedSecret});
                                revealed[i] = linkedSecret;
                                if (first) {
                                    ++firstFlicks;
                                }
                            }
                        } else {
                            locations[i] = info[i].location();
                        }
                    }
                    total += info[i].price;
                    ++i;
                } while (i < len);
                if (key != locations.hash()) {
                    revert Errors.NotInCohort();
                }
                // this allows users to submit partial secret sets and unlock their staked tokens
                // without risking omission attacks from late or downed actors
                timeline += firstFlicks;
                _timeline[key] = timeline;
                if (missing) {
                    return CastState.MISSING_SECRET;
                }
                // mark as generated
                seed = revealed.hash();
                _seed[key] = seed;
                emit Cast({key: key, seed: seed});
            }
            {
                // until the seed is properly formed, no one validator
                // knows which one of them is going to get the bonus
                // only the last validator to reveal their secret has an edge in that they can choose to
                // omit their secret, they will however, forfeit their staked tokens to whoever calls chop
                PreimageLocation.Info calldata item = info[_random({key: seed, upper: len})];
                if (_expired({timeline: _timeline[key]})) {
                    // if secrets are submitted late, then the owner gets half of their payment back
                    uint256 payout = total / 2;
                    total -= payout;
                    _reverseCharges({timeline: timeline, key: key, token: item.token, payout: payout});
                    // can be used as reputation
                    emit Expired({key: key});
                }
                _custodied[item.provider][item.token] += total;
            }
            if (_shouldCall(timeline)) {
                _call({
                    to: address(uint160(timeline >> NINE_SIX)),
                    b: abi.encodeWithSelector(ConsumerReceiver.onCast.selector, key, seed),
                    key: key
                });
            }
            return CastState.SCATTERED;
        }
    }

    /**
     * check a timeline's boolean flags in order to determine if a method should be called for it
     * @param timeline provides the context to check
     */
    function _shouldCall(uint256 timeline) internal pure returns (bool) {
        return (timeline << 247) >> TWO_FIVE_FIVE == ONE;
    }

    /**
     * retrieve a random number between 0 and the upper limit (exclusive)
     * @param key the randomness key
     * @param upper the upper limit of the uniform range
     */
    function _random(bytes32 key, uint256 upper) internal view returns (uint256) {
        return LibPRNG.PRNG({state: uint256(_seed[key])}).uniform(upper);
    }

    /**
     * hand off tokens between an address (caller) or optional recipient and this contract
     * @param recipient the recipient of tokens - either the account in this contract or an address outside of this contract
     * @param token the token address to transfer - use zero address for native tokens
     * @param amount a number of tokens to transfer
     */
    function handoff(address recipient, address token, int256 amount) external payable {
        unchecked {
            address account = LibMulticaller.senderOrSigner();
            recipient = recipient == address(0) ? account : recipient;
            if (amount < 0) {
                // move take tokens from signer to recipient custodied by signer
                _custodied[recipient][token] += _receiveTokens(account, token, uint256(-amount));
            } else {
                // move tokens from signer to recipient custodied by contract
                _distribute(recipient, token, _decrementTokenAmount(account, token, uint256(amount)));
            }
        }
    }

    /**
     * when a provider no longer has access to appropriate data, he should
     * invalidate the data that he has written so that he does not confuse front ends
     * @param info the unhashed section to bleach
     * @dev calling this method means that all preimages will be invalidated. it will be costly
     */
    function bleach(PreimageLocation.Info memory info) external payable {
        unchecked {
            address provider = LibMulticaller.senderOrSigner();
            if (msg.value > ZERO) {
                _custodied[provider][address(0)] += msg.value;
            }
            if (provider != info.provider) {
                revert Errors.SignerMismatch();
            }
            uint256 encodedToken = info.encodeToken();
            uint256 size = _pointerSize({info: info, encodedToken: encodedToken}) / THREE_TWO;
            bytes32 section = info.section();
            // consumes a whole pointer
            uint256 amount;
            uint256 start = info.offset;
            uint256 end = start + size; // exclusive end
            uint256 mask;
            uint256 len;
            uint256 f;
            uint256 i;
            LibBitmap.Bitmap storage bitmap = _accessFlags[info.provider][encodedToken][info.price];
            uint256 flags;
            uint256 targetedFlags;
            uint256 max = type(uint256).max;
            do {
                if (len == ZERO) {
                    len = TWO_FIVE_SIX - (start % TWO_FIVE_SIX);
                }
                if (start + len > end) {
                    len = end - start;
                }
                mask = (max >> (TWO_FIVE_SIX - len)); // at root (all f's to the right)
                flags = bitmap.map[start / TWO_FIVE_SIX];
                targetedFlags = ((flags << (TWO_FIVE_SIX - (start + len))) >> (TWO_FIVE_SIX - len)); // at root (all bits to the right)
                if (targetedFlags < mask) {
                    bitmap.setBatch(start, len);
                    i = start % TWO_FIVE_SIX;
                    f = i + len;
                    do {
                        if (((flags >> i) & ONE) == ZERO) {
                            amount += info.price;
                        }
                        ++i;
                    } while (i < f);
                }
                start += len;
                len = TWO_FIVE_SIX;
            } while (start < end);
            if (amount > ZERO) {
                emit Bleach({provider: provider, section: section});
                // assume that amount is > 0 otherwise there is not economic reason to run this fn
                // therefore writing the sstore is always going to have a non zero delta
                _custodied[provider][info.token] += amount;
            }
        }
    }
}
        

solady/src/utils/LibBitmap.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import {LibBit} from "./LibBit.sol";

/// @notice Library for storage of packed unsigned booleans.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/LibBitmap.sol)
/// @author Modified from Solidity-Bits (https://github.com/estarriolvetch/solidity-bits/blob/main/contracts/BitMaps.sol)
library LibBitmap {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The constant returned when a bitmap scan does not find a result.
    uint256 internal constant NOT_FOUND = type(uint256).max;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A bitmap in storage.
    struct Bitmap {
        mapping(uint256 => uint256) map;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         OPERATIONS                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the boolean value of the bit at `index` in `bitmap`.
    function get(Bitmap storage bitmap, uint256 index) internal view returns (bool isSet) {
        // It is better to set `isSet` to either 0 or 1, than zero vs non-zero.
        // Both cost the same amount of gas, but the former allows the returned value
        // to be reused without cleaning the upper bits.
        uint256 b = (bitmap.map[index >> 8] >> (index & 0xff)) & 1;
        /// @solidity memory-safe-assembly
        assembly {
            isSet := b
        }
    }

    /// @dev Updates the bit at `index` in `bitmap` to true.
    function set(Bitmap storage bitmap, uint256 index) internal {
        bitmap.map[index >> 8] |= (1 << (index & 0xff));
    }

    /// @dev Updates the bit at `index` in `bitmap` to false.
    function unset(Bitmap storage bitmap, uint256 index) internal {
        bitmap.map[index >> 8] &= ~(1 << (index & 0xff));
    }

    /// @dev Flips the bit at `index` in `bitmap`.
    /// Returns the boolean result of the flipped bit.
    function toggle(Bitmap storage bitmap, uint256 index) internal returns (bool newIsSet) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, index))
            let storageSlot := keccak256(0x00, 0x40)
            let shift := and(index, 0xff)
            let storageValue := xor(sload(storageSlot), shl(shift, 1))
            // It makes sense to return the `newIsSet`,
            // as it allow us to skip an additional warm `sload`,
            // and it costs minimal gas (about 15),
            // which may be optimized away if the returned value is unused.
            newIsSet := and(1, shr(shift, storageValue))
            sstore(storageSlot, storageValue)
        }
    }

    /// @dev Updates the bit at `index` in `bitmap` to `shouldSet`.
    function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, index))
            let storageSlot := keccak256(0x00, 0x40)
            let storageValue := sload(storageSlot)
            let shift := and(index, 0xff)
            sstore(
                storageSlot,
                // Unsets the bit at `shift` via `and`, then sets its new value via `or`.
                or(and(storageValue, not(shl(shift, 1))), shl(shift, iszero(iszero(shouldSet))))
            )
        }
    }

    /// @dev Consecutively sets `amount` of bits starting from the bit at `start`.
    function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let shift := and(start, 0xff)
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, start))
            if iszero(lt(add(shift, amount), 257)) {
                let storageSlot := keccak256(0x00, 0x40)
                sstore(storageSlot, or(sload(storageSlot), shl(shift, max)))
                let bucket := add(mload(0x00), 1)
                let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
                amount := and(add(amount, shift), 0xff)
                shift := 0
                for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
                    mstore(0x00, bucket)
                    sstore(keccak256(0x00, 0x40), max)
                }
                mstore(0x00, bucket)
            }
            let storageSlot := keccak256(0x00, 0x40)
            sstore(storageSlot, or(sload(storageSlot), shl(shift, shr(sub(256, amount), max))))
        }
    }

    /// @dev Consecutively unsets `amount` of bits starting from the bit at `start`.
    function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let shift := and(start, 0xff)
            mstore(0x20, bitmap.slot)
            mstore(0x00, shr(8, start))
            if iszero(lt(add(shift, amount), 257)) {
                let storageSlot := keccak256(0x00, 0x40)
                sstore(storageSlot, and(sload(storageSlot), not(shl(shift, not(0)))))
                let bucket := add(mload(0x00), 1)
                let bucketEnd := add(mload(0x00), shr(8, add(amount, shift)))
                amount := and(add(amount, shift), 0xff)
                shift := 0
                for {} iszero(eq(bucket, bucketEnd)) { bucket := add(bucket, 1) } {
                    mstore(0x00, bucket)
                    sstore(keccak256(0x00, 0x40), 0)
                }
                mstore(0x00, bucket)
            }
            let storageSlot := keccak256(0x00, 0x40)
            sstore(
                storageSlot, and(sload(storageSlot), not(shl(shift, shr(sub(256, amount), not(0)))))
            )
        }
    }

    /// @dev Returns number of set bits within a range by
    /// scanning `amount` of bits starting from the bit at `start`.
    function popCount(Bitmap storage bitmap, uint256 start, uint256 amount)
        internal
        view
        returns (uint256 count)
    {
        unchecked {
            uint256 bucket = start >> 8;
            uint256 shift = start & 0xff;
            if (!(amount + shift < 257)) {
                count = LibBit.popCount(bitmap.map[bucket] >> shift);
                uint256 bucketEnd = bucket + ((amount + shift) >> 8);
                amount = (amount + shift) & 0xff;
                shift = 0;
                for (++bucket; bucket != bucketEnd; ++bucket) {
                    count += LibBit.popCount(bitmap.map[bucket]);
                }
            }
            count += LibBit.popCount((bitmap.map[bucket] >> shift) << (256 - amount));
        }
    }

    /// @dev Returns the index of the most significant set bit in `[0..upTo]`.
    /// If no set bit is found, returns `NOT_FOUND`.
    function findLastSet(Bitmap storage bitmap, uint256 upTo)
        internal
        view
        returns (uint256 setBitIndex)
    {
        setBitIndex = NOT_FOUND;
        uint256 bucket = upTo >> 8;
        uint256 bits;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, bucket)
            mstore(0x20, bitmap.slot)
            let offset := and(0xff, not(upTo)) // `256 - (255 & upTo) - 1`.
            bits := shr(offset, shl(offset, sload(keccak256(0x00, 0x40))))
            if iszero(or(bits, iszero(bucket))) {
                for {} 1 {} {
                    bucket := add(bucket, setBitIndex) // `sub(bucket, 1)`.
                    mstore(0x00, bucket)
                    bits := sload(keccak256(0x00, 0x40))
                    if or(bits, iszero(bucket)) { break }
                }
            }
        }
        if (bits != 0) {
            setBitIndex = (bucket << 8) | LibBit.fls(bits);
            /// @solidity memory-safe-assembly
            assembly {
                setBitIndex := or(setBitIndex, sub(0, gt(setBitIndex, upTo)))
            }
        }
    }

    /// @dev Returns the index of the least significant unset bit in `[begin..upTo]`.
    /// If no unset bit is found, returns `NOT_FOUND`.
    function findFirstUnset(Bitmap storage bitmap, uint256 begin, uint256 upTo)
        internal
        view
        returns (uint256 unsetBitIndex)
    {
        unsetBitIndex = NOT_FOUND;
        uint256 bucket = begin >> 8;
        uint256 negBits;
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, bucket)
            mstore(0x20, bitmap.slot)
            let offset := and(0xff, begin)
            negBits := shl(offset, shr(offset, not(sload(keccak256(0x00, 0x40)))))
            if iszero(negBits) {
                let lastBucket := shr(8, upTo)
                for {} 1 {} {
                    bucket := add(bucket, 1)
                    mstore(0x00, bucket)
                    negBits := not(sload(keccak256(0x00, 0x40)))
                    if or(negBits, gt(bucket, lastBucket)) { break }
                }
                if gt(bucket, lastBucket) {
                    negBits := shl(and(0xff, not(upTo)), shr(and(0xff, not(upTo)), negBits))
                }
            }
        }
        if (negBits != 0) {
            uint256 r = (bucket << 8) | LibBit.ffs(negBits);
            /// @solidity memory-safe-assembly
            assembly {
                unsetBitIndex := or(r, sub(0, or(gt(r, upTo), lt(r, begin))))
            }
        }
    }
}
          

contracts/implementations/IRandom.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {PreimageLocation} from "../PreimageLocation.sol";

abstract contract IRandom {
    uint256 internal constant ZERO = 0;
    uint256 internal constant ONE = 1;
    uint256 internal constant TWO = 2;
    uint256 internal constant EIGHT = 8;
    uint256 internal constant ONE_SIX = 16;
    uint256 internal constant THREE_TWO = 32;
    uint256 internal constant FOUR_EIGHT = 48;
    uint256 internal constant NINE_SIX = 96;
    uint256 internal constant ONE_TWO_EIGHT = 128;
    uint256 internal constant ONE_SIX_ZERO = 160;
    uint256 internal constant TWO_ZERO_EIGHT = 208;
    uint256 internal constant TWO_ZERO_NINE = ONE + TWO_ZERO_EIGHT;
    uint256 internal constant TWO_FOUR_EIGHT = 248;
    uint256 internal constant TWO_FIVE_FIVE = 255;
    uint256 internal constant TWO_FIVE_SIX = 256;

    mapping(bytes32 key => uint256 timeline) internal _timeline;
    mapping(bytes32 key => bytes32 seed) internal _seed;

    struct Randomness {
        address owner;
        bool callAtChange;
        bool usesTimestamp;
        uint256 duration;
        uint256 start;
        uint256 timeline;
        uint256 contributed;
        bytes32 seed;
    }

    function heat(
        uint256 required,
        PreimageLocation.Info calldata settings,
        PreimageLocation.Info[] calldata info,
        bool useTSTORE
    ) external payable virtual returns (bytes32);

    function pointer(PreimageLocation.Info calldata info) external view virtual returns (address);

    function consumed(PreimageLocation.Info calldata info) external view virtual returns (bool);

    function randomness(bytes32 key) external view virtual returns (Randomness memory);

    function latest(address account, bool onlySameTx, bool useTSTORE) external view virtual returns (bytes32);

    function expired(uint256 timeline) external view virtual returns (bool) {
        return _expired(timeline);
    }

    function _expired(uint256 timeline) internal view virtual returns (bool) {
        unchecked {
            // end
            return
                (
                    (timeline << (TWO_FIVE_FIVE - (EIGHT + ONE))) >>
                        TWO_FIVE_FIVE ==
                        ZERO
                        ? block.number
                        : block.timestamp
                ) -
                    // start
                    (uint256(uint48(timeline >> FOUR_EIGHT))) >
                // expiration delta
                (uint256(uint40(timeline) >> (EIGHT + TWO)));
        }
    }
}
          

contracts/SlotDerivation.sol

// SPDX-License-Identifier: MIT
// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.

pragma solidity ^0.8.24;

/**
 * @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
 * corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
 * the solidity language / compiler.
 *
 * See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
 *
 * Example usage:
 * ```solidity
 * contract Example {
 *     // Add the library methods
 *     using StorageSlot for bytes32;
 *     using SlotDerivation for bytes32;
 *
 *     // Declare a namespace
 *     string private constant _NAMESPACE = "<namespace>" // eg. OpenZeppelin.Slot
 *
 *     function setValueInNamespace(uint256 key, address newValue) internal {
 *         _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
 *     }
 *
 *     function getValueInNamespace(uint256 key) internal view returns (address) {
 *         return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {StorageSlot}.
 *
 * NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
 * upgrade safety will ignore the slots accessed through this library.
 */
library SlotDerivation {
    /**
     * @dev Derive an ERC-7201 slot from a string (namespace).
     */
    function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
            slot := and(keccak256(0x00, 0x20), not(0xff))
        }
    }

    // /**
    //  * @dev Add an offset to a slot to get the n-th element of a structure or an array.
    //  */
    // function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
    //     unchecked {
    //         return bytes32(uint256(slot) + pos);
    //     }
    // }

    // /**
    //  * @dev Derive the location of the first element in an array from the slot where the length is stored.
    //  */
    // function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         mstore(0x00, slot)
    //         result := keccak256(0x00, 0x20)
    //     }
    // }

    /**
     * @dev Derive the location of a mapping element from the key.
     */
    function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, key)
            mstore(0x20, slot)
            result := keccak256(0x00, 0x40)
        }
    }

    // /**
    //  * @dev Derive the location of a mapping element from the key.
    //  */
    // function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         mstore(0x00, key)
    //         mstore(0x20, slot)
    //         result := keccak256(0x00, 0x40)
    //     }
    // }

    // /**
    //  * @dev Derive the location of a mapping element from the key.
    //  */
    // function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         mstore(0x00, key)
    //         mstore(0x20, slot)
    //         result := keccak256(0x00, 0x40)
    //     }
    // }

    // /**
    //  * @dev Derive the location of a mapping element from the key.
    //  */
    // function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         mstore(0x00, key)
    //         mstore(0x20, slot)
    //         result := keccak256(0x00, 0x40)
    //     }
    // }

    // /**
    //  * @dev Derive the location of a mapping element from the key.
    //  */
    // function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         mstore(0x00, key)
    //         mstore(0x20, slot)
    //         result := keccak256(0x00, 0x40)
    //     }
    // }

    // /**
    //  * @dev Derive the location of a mapping element from the key.
    //  */
    // function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         let length := mload(key)
    //         let begin := add(key, 0x20)
    //         let end := add(begin, length)
    //         let cache := mload(end)
    //         mstore(end, slot)
    //         result := keccak256(begin, add(length, 0x20))
    //         mstore(end, cache)
    //     }
    // }

    // /**
    //  * @dev Derive the location of a mapping element from the key.
    //  */
    // function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {
    //     /// @solidity memory-safe-assembly
    //     assembly {
    //         let length := mload(key)
    //         let begin := add(key, 0x20)
    //         let end := add(begin, length)
    //         let cache := mload(end)
    //         mstore(end, slot)
    //         result := keccak256(begin, add(length, 0x20))
    //         mstore(end, cache)
    //     }
    // }
}
          

contracts/StorageSlot.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.24;

library StorageSlot {
    struct Bytes32Slot {
        bytes32 value;
    }
    /**
     * @dev UDVT that represent a slot holding a bytes32.
     */

    type Bytes32SlotType is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Bytes32SlotType.
     */
    function asBytes32(bytes32 slot) internal pure returns (Bytes32SlotType) {
        return Bytes32SlotType.wrap(slot);
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */

    function tload(Bytes32SlotType slot) internal view returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Bytes32SlotType slot, bytes32 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            tstore(slot, value)
        }
    }
}
          

solady/src/utils/LibBit.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for bit twiddling and boolean operations.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibBit.sol)
/// @author Inspired by (https://graphics.stanford.edu/~seander/bithacks.html)
library LibBit {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  BIT TWIDDLING OPERATIONS                  */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Find last set.
    /// Returns the index of the most significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    function fls(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := or(shl(8, iszero(x)), shl(7, lt(0xffffffffffffffffffffffffffffffff, x)))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := or(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0x0706060506020504060203020504030106050205030304010505030400000000))
        }
    }

    /// @dev Count leading zeros.
    /// Returns the number of zeros preceding the most significant one bit.
    /// If `x` is zero, returns 256.
    function clz(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            r := shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
            r := or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
            r := or(r, shl(5, lt(0xffffffff, shr(r, x))))
            r := or(r, shl(4, lt(0xffff, shr(r, x))))
            r := or(r, shl(3, lt(0xff, shr(r, x))))
            // forgefmt: disable-next-item
            r := add(xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
                0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff)), iszero(x))
        }
    }

    /// @dev Find first set.
    /// Returns the index of the least significant bit of `x`,
    /// counting from the least significant bit position.
    /// If `x` is zero, returns 256.
    /// Equivalent to `ctz` (count trailing zeros), which gives
    /// the number of zeros following the least significant one bit.
    function ffs(uint256 x) internal pure returns (uint256 r) {
        /// @solidity memory-safe-assembly
        assembly {
            // Isolate the least significant bit.
            x := and(x, add(not(x), 1))
            // For the upper 3 bits of the result, use a De Bruijn-like lookup.
            // Credit to adhusson: https://blog.adhusson.com/cheap-find-first-set-evm/
            // forgefmt: disable-next-item
            r := shl(5, shr(252, shl(shl(2, shr(250, mul(x,
                0xb6db6db6ddddddddd34d34d349249249210842108c6318c639ce739cffffffff))),
                0x8040405543005266443200005020610674053026020000107506200176117077)))
            // For the lower 5 bits of the result, use a De Bruijn lookup.
            // forgefmt: disable-next-item
            r := or(r, byte(and(div(0xd76453e0, shr(r, x)), 0x1f),
                0x001f0d1e100c1d070f090b19131c1706010e11080a1a141802121b1503160405))
        }
    }

    /// @dev Returns the number of set bits in `x`.
    function popCount(uint256 x) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            let max := not(0)
            let isMax := eq(x, max)
            x := sub(x, and(shr(1, x), div(max, 3)))
            x := add(and(x, div(max, 5)), and(shr(2, x), div(max, 5)))
            x := and(add(x, shr(4, x)), div(max, 17))
            c := or(shl(8, isMax), shr(248, mul(x, div(max, 255))))
        }
    }

    /// @dev Returns the number of zero bytes in `x`.
    /// To get the number of non-zero bytes, simply do `32 - countZeroBytes(x)`.
    function countZeroBytes(uint256 x) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f
            c := byte(0, mul(shr(7, not(m)), shr(7, not(or(or(add(and(x, m), m), x), m)))))
        }
    }

    /// @dev Returns the number of zero bytes in `s`.
    /// To get the number of non-zero bytes, simply do `s.length - countZeroBytes(s)`.
    function countZeroBytes(bytes memory s) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            function czb(x_) -> _c {
                let _m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f
                _c := shr(7, not(or(or(add(and(x_, _m), _m), x_), _m)))
                _c := byte(0, mul(shr(7, not(_m)), _c))
            }
            let n := mload(s)
            let l := shl(5, shr(5, n))
            s := add(s, 0x20)
            for { let i } xor(i, l) { i := add(i, 0x20) } { c := add(czb(mload(add(s, i))), c) }
            if lt(l, n) { c := add(czb(or(shr(shl(3, sub(n, l)), not(0)), mload(add(s, l)))), c) }
        }
    }

    /// @dev Returns the number of zero bytes in `s`.
    /// To get the number of non-zero bytes, simply do `s.length - countZeroBytes(s)`.
    function countZeroBytesCalldata(bytes calldata s) internal pure returns (uint256 c) {
        /// @solidity memory-safe-assembly
        assembly {
            function czb(x_) -> _c {
                let _m := 0x7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f7f
                _c := shr(7, not(or(or(add(and(x_, _m), _m), x_), _m)))
                _c := byte(0, mul(shr(7, not(_m)), _c))
            }
            let l := shl(5, shr(5, s.length))
            for { let i } xor(i, l) { i := add(i, 0x20) } {
                c := add(czb(calldataload(add(s.offset, i))), c)
            }
            if lt(l, s.length) {
                let m := shr(shl(3, sub(s.length, l)), not(0))
                c := add(czb(or(m, calldataload(add(s.offset, l)))), c)
            }
        }
    }

    /// @dev Returns whether `x` is a power of 2.
    function isPo2(uint256 x) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Equivalent to `x && !(x & (x - 1))`.
            result := iszero(add(and(x, sub(x, 1)), iszero(x)))
        }
    }

    /// @dev Returns `x` reversed at the bit level.
    function reverseBits(uint256 x) internal pure returns (uint256 r) {
        uint256 m0 = 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f;
        uint256 m1 = m0 ^ (m0 << 2);
        uint256 m2 = m1 ^ (m1 << 1);
        r = reverseBytes(x);
        r = (m2 & (r >> 1)) | ((m2 & r) << 1);
        r = (m1 & (r >> 2)) | ((m1 & r) << 2);
        r = (m0 & (r >> 4)) | ((m0 & r) << 4);
    }

    /// @dev Returns `x` reversed at the byte level.
    function reverseBytes(uint256 x) internal pure returns (uint256 r) {
        unchecked {
            // Computing masks on-the-fly reduces bytecode size by about 200 bytes.
            uint256 m0 = 0x100000000000000000000000000000001 * (~toUint(x == uint256(0)) >> 192);
            uint256 m1 = m0 ^ (m0 << 32);
            uint256 m2 = m1 ^ (m1 << 16);
            uint256 m3 = m2 ^ (m2 << 8);
            r = (m3 & (x >> 8)) | ((m3 & x) << 8);
            r = (m2 & (r >> 16)) | ((m2 & r) << 16);
            r = (m1 & (r >> 32)) | ((m1 & r) << 32);
            r = (m0 & (r >> 64)) | ((m0 & r) << 64);
            r = (r >> 128) | (r << 128);
        }
    }

    /// @dev Returns the common prefix of `x` and `y` at the bit level.
    function commonBitPrefix(uint256 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            uint256 s = 256 - clz(x ^ y);
            return (x >> s) << s;
        }
    }

    /// @dev Returns the common prefix of `x` and `y` at the nibble level.
    function commonNibblePrefix(uint256 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            uint256 s = (64 - (clz(x ^ y) >> 2)) << 2;
            return (x >> s) << s;
        }
    }

    /// @dev Returns the common prefix of `x` and `y` at the byte level.
    function commonBytePrefix(uint256 x, uint256 y) internal pure returns (uint256) {
        unchecked {
            uint256 s = (32 - (clz(x ^ y) >> 3)) << 3;
            return (x >> s) << s;
        }
    }

    /// @dev hex"ABCD" -> hex"0A0B0C0D".
    function toNibbles(bytes memory s) internal pure returns (bytes memory result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(0x40)
            let n := mload(s)
            mstore(result, add(n, n)) // Store the new length.
            s := add(s, 0x20)
            let o := add(result, 0x20)
            // forgefmt: disable-next-item
            for { let i := 0 } lt(i, n) { i := add(i, 0x10) } {
                let x := shr(128, mload(add(s, i)))
                x := and(0x0000000000000000ffffffffffffffff0000000000000000ffffffffffffffff, or(shl(64, x), x))
                x := and(0x00000000ffffffff00000000ffffffff00000000ffffffff00000000ffffffff, or(shl(32, x), x))
                x := and(0x0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff0000ffff, or(shl(16, x), x))
                x := and(0x00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff00ff, or(shl(8, x), x))
                mstore(add(o, add(i, i)),
                    and(0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f, or(shl(4, x), x)))
            }
            mstore(add(o, add(s, s)), 0) // Zeroize slot after result.
            mstore(0x40, add(0x40, add(o, add(s, s)))) // Allocate memory.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     BOOLEAN OPERATIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // A Solidity bool on the stack or memory is represented as a 256-bit word.
    // Non-zero values are true, zero is false.
    // A clean bool is either 0 (false) or 1 (true) under the hood.
    // Usually, if not always, the bool result of a regular Solidity expression,
    // or the argument of a public/external function will be a clean bool.
    // You can usually use the raw variants for more performance.
    // If uncertain, test (best with exact compiler settings).
    // Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s).

    /// @dev Returns `x & y`. Inputs must be clean.
    function rawAnd(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(x, y)
        }
    }

    /// @dev Returns `x & y`.
    function and(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := and(iszero(iszero(x)), iszero(iszero(y)))
        }
    }

    /// @dev Returns `w & x & y`.
    function and(bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(or(iszero(w), or(iszero(x), iszero(y))))
        }
    }

    /// @dev Returns `v & w & x & y`.
    function and(bool v, bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(or(or(iszero(v), iszero(w)), or(iszero(x), iszero(y))))
        }
    }

    /// @dev Returns `x | y`. Inputs must be clean.
    function rawOr(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := or(x, y)
        }
    }

    /// @dev Returns `x | y`.
    function or(bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(or(x, y)))
        }
    }

    /// @dev Returns `w | x | y`.
    function or(bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(or(w, or(x, y))))
        }
    }

    /// @dev Returns `v | w | x | y`.
    function or(bool v, bool w, bool x, bool y) internal pure returns (bool z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(or(v, or(w, or(x, y)))))
        }
    }

    /// @dev Returns 1 if `b` is true, else 0. Input must be clean.
    function rawToUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := b
        }
    }

    /// @dev Returns 1 if `b` is true, else 0.
    function toUint(bool b) internal pure returns (uint256 z) {
        /// @solidity memory-safe-assembly
        assembly {
            z := iszero(iszero(b))
        }
    }
}
          

contracts/implementations/ConsumerReceiver.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

abstract contract ConsumerReceiver {
    function onReverse(
        bytes32 /*key*/,
        address /*token*/,
        uint256 /*amount*/
    ) external virtual;

    function onCast(bytes32 /*key*/, bytes32 /*seed*/) external virtual;

    function onChop(bytes32 /*key*/) external virtual;
}
          

contracts/PreimageLocation.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

import {EfficientHashLib} from "solady/src/utils/EfficientHashLib.sol";

library PreimageLocation {
    struct Info {
        address provider;
        bool callAtChange;
        bool durationIsTimestamp;
        uint256 duration;
        address token;
        uint256 price;
        uint256 offset;
        uint256 index;
    }

    using PreimageLocation for Info;
    using PreimageLocation for bytes32;
    using EfficientHashLib for bytes32;

    /**
     * derive a unique location hash that is hash(section + index)
     * @param info location info to help derive hashes
     */
    function location(Info memory info) internal pure returns (bytes32) {
        return info.section().location(info.index);
    }

    function location(
        bytes32 sec,
        uint256 index
    ) internal pure returns (bytes32) {
        return sec.hash(bytes32(index));
    }

    function section(Info memory info) internal pure returns (bytes32) {
        unchecked {
            return
                EfficientHashLib.hash(
                    bytes32(uint256(uint160(info.provider))),
                    bytes32(info.encodeToken()),
                    bytes32(info.price),
                    bytes32(info.offset)
                );
        }
    }

    function encodeToken(Info memory info) internal pure returns (uint256) {
        return
            (uint256(info.durationIsTimestamp ? 1 : 0) << 255) |
            (uint256(info.callAtChange ? 1 : 0) << 254) |
            (uint256((uint40(info.duration) << 1) >> 1) << 160) |
            uint256(uint160(info.token));
    }
}
          

solady/src/utils/LibPRNG.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for generating pseudorandom numbers.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibPRNG.sol)
/// @author LazyShuffler based on NextShuffler by aschlosberg (divergencearran)
/// (https://github.com/divergencetech/ethier/blob/main/contracts/random/NextShuffler.sol)
library LibPRNG {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The initial length must be greater than zero and less than `2**32 - 1`.
    error InvalidInitialLazyShufflerLength();

    /// @dev The new length must not be less than the current length.
    error InvalidNewLazyShufflerLength();

    /// @dev The lazy shuffler has not been initialized.
    error LazyShufflerNotInitialized();

    /// @dev Cannot double initialize the lazy shuffler.
    error LazyShufflerAlreadyInitialized();

    /// @dev The lazy shuffle has finished.
    error LazyShuffleFinished();

    /// @dev The queried index is out of bounds.
    error LazyShufflerGetOutOfBounds();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The scalar of ETH and most ERC20s.
    uint256 internal constant WAD = 1e18;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STRUCTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev A pseudorandom number state in memory.
    struct PRNG {
        uint256 state;
    }

    /// @dev A lazy Fisher-Yates shuffler for a range `[0..n)` in storage.
    struct LazyShuffler {
        // Bits Layout:
        // - [0..31]    `numShuffled`
        // - [32..223]  `permutationSlot`
        // - [224..255] `length`
        uint256 _state;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         OPERATIONS                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Seeds the `prng` with `state`.
    function seed(PRNG memory prng, uint256 state) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(prng, state)
        }
    }

    /// @dev Returns the next pseudorandom uint256.
    /// All bits of the returned uint256 pass the NIST Statistical Test Suite.
    function next(PRNG memory prng) internal pure returns (uint256 result) {
        // We simply use `keccak256` for a great balance between
        // runtime gas costs, bytecode size, and statistical properties.
        //
        // A high-quality LCG with a 32-byte state
        // is only about 30% more gas efficient during runtime,
        // but requires a 32-byte multiplier, which can cause bytecode bloat
        // when this function is inlined.
        //
        // Using this method is about 2x more efficient than
        // `nextRandomness = uint256(keccak256(abi.encode(randomness)))`.
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(prng, 0x20)
            mstore(prng, result)
        }
    }

    /// @dev Returns a pseudorandom uint256, uniformly distributed
    /// between 0 (inclusive) and `upper` (exclusive).
    /// If your modulus is big, this method is recommended
    /// for uniform sampling to avoid modulo bias.
    /// For uniform sampling across all uint256 values,
    /// or for small enough moduli such that the bias is negligible,
    /// use {next} instead.
    function uniform(PRNG memory prng, uint256 upper) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            for {} 1 {} {
                result := keccak256(prng, 0x20)
                mstore(prng, result)
                if iszero(lt(result, mod(sub(0, upper), upper))) { break }
            }
            result := mod(result, upper)
        }
    }

    /// @dev Returns a sample from the standard normal distribution denominated in `WAD`.
    function standardNormalWad(PRNG memory prng) internal pure returns (int256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Technically, this is the Irwin-Hall distribution with 20 samples.
            // The chance of drawing a sample outside 10 σ from the standard normal distribution
            // is ≈ 0.000000000000000000000015, which is insignificant for most practical purposes.
            // Passes the Kolmogorov-Smirnov test for 200k samples. Uses about 322 gas.
            result := keccak256(prng, 0x20)
            mstore(prng, result)
            let n := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43 // Prime.
            let a := 0x100000000000000000000000000000051 // Prime and a primitive root of `n`.
            let m := 0x1fffffffffffffff1fffffffffffffff1fffffffffffffff1fffffffffffffff
            let s := 0x1000000000000000100000000000000010000000000000001
            let r1 := mulmod(result, a, n)
            let r2 := mulmod(r1, a, n)
            let r3 := mulmod(r2, a, n)
            // forgefmt: disable-next-item
            result := sub(sar(96, mul(26614938895861601847173011183,
                add(add(shr(192, mul(s, add(and(m, result), and(m, r1)))),
                shr(192, mul(s, add(and(m, r2), and(m, r3))))),
                shr(192, mul(s, and(m, mulmod(r3, a, n))))))), 7745966692414833770)
        }
    }

    /// @dev Returns a sample from the unit exponential distribution denominated in `WAD`.
    function exponentialWad(PRNG memory prng) internal pure returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            // Passes the Kolmogorov-Smirnov test for 200k samples.
            // Gas usage varies, starting from about 172+ gas.
            let r := keccak256(prng, 0x20)
            mstore(prng, r)
            let p := shl(129, r)
            let w := shl(1, r)
            if iszero(gt(w, p)) {
                let n := 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43 // Prime.
                let a := 0x100000000000000000000000000000051 // Prime and a primitive root of `n`.
                for {} 1 {} {
                    r := mulmod(r, a, n)
                    if iszero(lt(shl(129, r), w)) {
                        r := mulmod(r, a, n)
                        result := add(1000000000000000000, result)
                        w := shl(1, r)
                        p := shl(129, r)
                        if iszero(lt(w, p)) { break }
                        continue
                    }
                    w := shl(1, r)
                    if iszero(lt(w, shl(129, r))) { break }
                }
            }
            result := add(div(p, shl(129, 170141183460469231732)), result)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*             MEMORY ARRAY SHUFFLING OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Shuffles the array in-place with Fisher-Yates shuffle.
    function shuffle(PRNG memory prng, uint256[] memory a) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(a)
            let w := not(0)
            let mask := shr(128, w)
            if n {
                for { a := add(a, 0x20) } 1 {} {
                    // We can just directly use `keccak256`, cuz
                    // the other approaches don't save much.
                    let r := keccak256(prng, 0x20)
                    mstore(prng, r)

                    // Note that there will be a very tiny modulo bias
                    // if the length of the array is not a power of 2.
                    // For all practical purposes, it is negligible
                    // and will not be a fairness or security concern.
                    {
                        let j := add(a, shl(5, mod(shr(128, r), n)))
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let i := add(a, shl(5, n))
                        let t := mload(i)
                        mstore(i, mload(j))
                        mstore(j, t)
                    }

                    {
                        let j := add(a, shl(5, mod(and(r, mask), n)))
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let i := add(a, shl(5, n))
                        let t := mload(i)
                        mstore(i, mload(j))
                        mstore(j, t)
                    }
                }
            }
        }
    }

    /// @dev Shuffles the array in-place with Fisher-Yates shuffle.
    function shuffle(PRNG memory prng, int256[] memory a) internal pure {
        shuffle(prng, _toUints(a));
    }

    /// @dev Shuffles the array in-place with Fisher-Yates shuffle.
    function shuffle(PRNG memory prng, address[] memory a) internal pure {
        shuffle(prng, _toUints(a));
    }

    /// @dev Partially shuffles the array in-place with Fisher-Yates shuffle.
    /// The first `k` elements will be uniformly sampled without replacement.
    function shuffle(PRNG memory prng, uint256[] memory a, uint256 k) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(a)
            k := xor(k, mul(xor(k, n), lt(n, k))) // `min(n, k)`.
            if k {
                let mask := shr(128, not(0))
                let b := 0
                for { a := add(a, 0x20) } 1 {} {
                    // We can just directly use `keccak256`, cuz
                    // the other approaches don't save much.
                    let r := keccak256(prng, 0x20)
                    mstore(prng, r)

                    // Note that there will be a very tiny modulo bias
                    // if the length of the array is not a power of 2.
                    // For all practical purposes, it is negligible
                    // and will not be a fairness or security concern.
                    {
                        let j := add(a, shl(5, add(b, mod(shr(128, r), sub(n, b)))))
                        let i := add(a, shl(5, b))
                        let t := mload(i)
                        mstore(i, mload(j))
                        mstore(j, t)
                        b := add(b, 1)
                        if eq(b, k) { break }
                    }

                    {
                        let j := add(a, shl(5, add(b, mod(and(r, mask), sub(n, b)))))
                        let i := add(a, shl(5, b))
                        let t := mload(i)
                        mstore(i, mload(j))
                        mstore(j, t)
                        b := add(b, 1)
                        if eq(b, k) { break }
                    }
                }
            }
        }
    }

    /// @dev Partially shuffles the array in-place with Fisher-Yates shuffle.
    /// The first `k` elements will be uniformly sampled without replacement.
    function shuffle(PRNG memory prng, int256[] memory a, uint256 k) internal pure {
        shuffle(prng, _toUints(a), k);
    }

    /// @dev Partially shuffles the array in-place with Fisher-Yates shuffle.
    /// The first `k` elements will be uniformly sampled without replacement.
    function shuffle(PRNG memory prng, address[] memory a, uint256 k) internal pure {
        shuffle(prng, _toUints(a), k);
    }

    /// @dev Shuffles the bytes in-place with Fisher-Yates shuffle.
    function shuffle(PRNG memory prng, bytes memory a) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(a)
            let w := not(0)
            let mask := shr(128, w)
            if n {
                let b := add(a, 0x01)
                for { a := add(a, 0x20) } 1 {} {
                    // We can just directly use `keccak256`, cuz
                    // the other approaches don't save much.
                    let r := keccak256(prng, 0x20)
                    mstore(prng, r)

                    // Note that there will be a very tiny modulo bias
                    // if the length of the array is not a power of 2.
                    // For all practical purposes, it is negligible
                    // and will not be a fairness or security concern.
                    {
                        let o := mod(shr(128, r), n)
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let t := mload(add(b, n))
                        mstore8(add(a, n), mload(add(b, o)))
                        mstore8(add(a, o), t)
                    }

                    {
                        let o := mod(and(r, mask), n)
                        n := add(n, w) // `sub(n, 1)`.
                        if iszero(n) { break }

                        let t := mload(add(b, n))
                        mstore8(add(a, n), mload(add(b, o)))
                        mstore8(add(a, o), t)
                    }
                }
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*       STORAGE-BASED RANGE LAZY SHUFFLING OPERATIONS        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Initializes the state for lazy-shuffling the range `[0..n)`.
    /// Reverts if `n == 0 || n >= 2**32 - 1`.
    /// Reverts if `$` has already been initialized.
    /// If you need to reduce the length after initialization, just use a fresh new `$`.
    function initialize(LazyShuffler storage $, uint256 n) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(lt(sub(n, 1), 0xfffffffe)) {
                mstore(0x00, 0x83b53941) // `InvalidInitialLazyShufflerLength()`.
                revert(0x1c, 0x04)
            }
            if sload($.slot) {
                mstore(0x00, 0x0c9f11f2) // `LazyShufflerAlreadyInitialized()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, $.slot)
            sstore($.slot, or(shl(224, n), shl(32, shr(64, keccak256(0x00, 0x20)))))
        }
    }

    /// @dev Increases the length of `$`.
    /// Reverts if `$` has not been initialized.
    function grow(LazyShuffler storage $, uint256 n) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let state := sload($.slot) // The packed value at `$`.
            // If the new length is smaller than the old length, revert.
            if lt(n, shr(224, state)) {
                mstore(0x00, 0xbed37c6e) // `InvalidNewLazyShufflerLength()`.
                revert(0x1c, 0x04)
            }
            if iszero(state) {
                mstore(0x00, 0x1ead2566) // `LazyShufflerNotInitialized()`.
                revert(0x1c, 0x04)
            }
            sstore($.slot, or(shl(224, n), shr(32, shl(32, state))))
        }
    }

    /// @dev Restarts the shuffler by setting `numShuffled` to zero,
    /// such that all elements can be drawn again.
    /// Restarting does NOT clear the internal permutation, nor changes the length.
    /// Even with the same sequence of randomness, reshuffling can yield different results.
    function restart(LazyShuffler storage $) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let state := sload($.slot)
            if iszero(state) {
                mstore(0x00, 0x1ead2566) // `LazyShufflerNotInitialized()`.
                revert(0x1c, 0x04)
            }
            sstore($.slot, shl(32, shr(32, state)))
        }
    }

    /// @dev Returns the number of elements that have been shuffled.
    function numShuffled(LazyShuffler storage $) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(0xffffffff, sload($.slot))
        }
    }

    /// @dev Returns the length of `$`.
    /// Returns zero if `$` is not initialized, else a non-zero value less than `2**32 - 1`.
    function length(LazyShuffler storage $) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := shr(224, sload($.slot))
        }
    }

    /// @dev Returns if `$` has been initialized.
    function initialized(LazyShuffler storage $) internal view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := iszero(iszero(sload($.slot)))
        }
    }

    /// @dev Returns if there are any more elements left to shuffle.
    /// Reverts if `$` is not initialized.
    function finished(LazyShuffler storage $) internal view returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            let state := sload($.slot) // The packed value at `$`.
            if iszero(state) {
                mstore(0x00, 0x1ead2566) // `LazyShufflerNotInitialized()`.
                revert(0x1c, 0x04)
            }
            result := eq(shr(224, state), and(0xffffffff, state))
        }
    }

    /// @dev Returns the current value stored at `index`, accounting for all historical shuffling.
    /// Reverts if `index` is greater than or equal to the `length` of `$`.
    function get(LazyShuffler storage $, uint256 index) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let state := sload($.slot) // The packed value at `$`.
            let n := shr(224, state) // Length of `$`.
            if iszero(lt(index, n)) {
                mstore(0x00, 0x61367cc4) // `LazyShufflerGetOutOfBounds()`.
                revert(0x1c, 0x04)
            }
            let u32 := gt(n, 0xfffe)
            let s := add(shr(sub(4, u32), index), shr(64, shl(32, state))) // Bucket slot.
            let o := shl(add(4, u32), and(index, shr(u32, 15))) // Bucket slot offset (bits).
            let m := sub(shl(shl(u32, 16), 1), 1) // Value mask.
            result := and(m, shr(o, sload(s)))
            result := xor(index, mul(xor(index, sub(result, 1)), iszero(iszero(result))))
        }
    }

    /// @dev Does a single Fisher-Yates shuffle step, increments the `numShuffled` in `$`,
    /// and returns the next value in the shuffled range.
    /// `randomness` can be taken from a good-enough source, or a higher quality source like VRF.
    /// Reverts if there are no more values to shuffle, which includes the case if `$` is not initialized.
    function next(LazyShuffler storage $, uint256 randomness) internal returns (uint256 chosen) {
        /// @solidity memory-safe-assembly
        assembly {
            function _get(u32_, state_, i_) -> _value {
                let s_ := add(shr(sub(4, u32_), i_), shr(64, shl(32, state_))) // Bucket slot.
                let o_ := shl(add(4, u32_), and(i_, shr(u32_, 15))) // Bucket slot offset (bits).
                let m_ := sub(shl(shl(u32_, 16), 1), 1) // Value mask.
                _value := and(m_, shr(o_, sload(s_)))
                _value := xor(i_, mul(xor(i_, sub(_value, 1)), iszero(iszero(_value))))
            }
            function _set(u32_, state_, i_, value_) {
                let s_ := add(shr(sub(4, u32_), i_), shr(64, shl(32, state_))) // Bucket slot.
                let o_ := shl(add(4, u32_), and(i_, shr(u32_, 15))) // Bucket slot offset (bits).
                let m_ := sub(shl(shl(u32_, 16), 1), 1) // Value mask.
                let v_ := sload(s_) // Bucket slot value.
                value_ := mul(iszero(eq(i_, value_)), add(value_, 1))
                sstore(s_, xor(v_, shl(o_, and(m_, xor(shr(o_, v_), value_)))))
            }
            let state := sload($.slot) // The packed value at `$`.
            let shuffled := and(0xffffffff, state) // Number of elements shuffled.
            let n := shr(224, state) // Length of `$`.
            let remainder := sub(n, shuffled) // Number of elements left to shuffle.
            if iszero(remainder) {
                mstore(0x00, 0x51065f79) // `LazyShuffleFinished()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, randomness) // (Re)hash the randomness so that we don't
            mstore(0x20, shuffled) // need to expect guarantees on its distribution.
            let index := add(mod(keccak256(0x00, 0x40), remainder), shuffled)
            chosen := _get(gt(n, 0xfffe), state, index)
            _set(gt(n, 0xfffe), state, index, _get(gt(n, 0xfffe), state, shuffled))
            _set(gt(n, 0xfffe), state, shuffled, chosen)
            sstore($.slot, add(1, state)) // Increment the `numShuffled` by 1, and store it.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      PRIVATE HELPERS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Reinterpret cast to an uint256 array.
    function _toUints(int256[] memory a) private pure returns (uint256[] memory casted) {
        /// @solidity memory-safe-assembly
        assembly {
            casted := a
        }
    }

    /// @dev Reinterpret cast to an uint256 array.
    function _toUints(address[] memory a) private pure returns (uint256[] memory casted) {
        /// @solidity memory-safe-assembly
        assembly {
            // As any address written to memory will have the upper 96 bits
            // of the word zeroized (as per Solidity spec), we can directly
            // compare these addresses as if they are whole uint256 words.
            casted := a
        }
    }
}
          

multicaller/src/LibMulticaller.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * @title LibMulticaller
 * @author vectorized.eth
 * @notice Library to read the `msg.sender` of the multicaller with sender contract.
 *
 * @dev Note:
 * The functions in this library do NOT guard against reentrancy.
 * A single transaction can recurse through different Multicallers
 * (e.g. `MulticallerWithSender -> contract -> MulticallerWithSigner -> contract`).
 *
 * Think of these functions like `msg.sender`.
 *
 * If your contract `C` can handle reentrancy safely with plain old `msg.sender`
 * for any `A -> C -> B -> C`, you should be fine substituting `msg.sender` with these functions.
 */
library LibMulticaller {
    /**
     * @dev The address of the multicaller contract.
     */
    address internal constant MULTICALLER = 0x0000000000002Bdbf1Bf3279983603Ec279CC6dF;

    /**
     * @dev The address of the multicaller with sender contract.
     */
    address internal constant MULTICALLER_WITH_SENDER = 0x00000000002Fd5Aeb385D324B580FCa7c83823A0;

    /**
     * @dev The address of the multicaller with signer contract.
     */
    address internal constant MULTICALLER_WITH_SIGNER = 0x000000000000D9ECebf3C23529de49815Dac1c4c;

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`.
     */
    function multicallerSender() internal view returns (address result) {
        return at(MULTICALLER_WITH_SENDER);
    }

    /**
     * @dev Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`.
     */
    function multicallerSigner() internal view returns (address result) {
        return at(MULTICALLER_WITH_SIGNER);
    }

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
     *      Otherwise, returns `msg.sender`.
     */
    function sender() internal view returns (address result) {
        return resolve(MULTICALLER_WITH_SENDER);
    }

    /**
     * @dev Returns the caller of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`.
     *      Otherwise, returns `msg.sender`.
     */
    function signer() internal view returns (address) {
        return resolve(MULTICALLER_WITH_SIGNER);
    }

    /**
     * @dev Returns the caller or signer at `a`.
     * @param a The multicaller with sender / signer.
     */
    function at(address a) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x00)
            if iszero(staticcall(gas(), a, codesize(), 0x00, 0x00, 0x20)) {
                revert(codesize(), codesize()) // For better gas estimation.
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller or signer at `a`, if the caller is `a`.
     * @param a The multicaller with sender / signer.
     */
    function resolve(address a) internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            if eq(caller(), a) {
                if iszero(staticcall(gas(), a, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }

    /**
     * @dev Returns the caller of `aggregateWithSender` on `MULTICALLER_WITH_SENDER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SENDER`.
     *      Returns the signer of `aggregateWithSigner` on `MULTICALLER_WITH_SIGNER`,
     *      if the current context's `msg.sender` is `MULTICALLER_WITH_SIGNER`.
     *      Otherwise, returns `msg.sender`.
     */
    function senderOrSigner() internal view returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, caller())
            let withSender := MULTICALLER_WITH_SENDER
            if eq(caller(), withSender) {
                if iszero(staticcall(gas(), withSender, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            let withSigner := MULTICALLER_WITH_SIGNER
            if eq(caller(), withSigner) {
                if iszero(staticcall(gas(), withSigner, codesize(), 0x00, 0x00, 0x20)) {
                    revert(codesize(), codesize()) // For better gas estimation.
                }
            }
            result := mload(0x00)
        }
    }
}
          

solady/src/utils/EfficientHashLib.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Library for efficiently performing keccak256 hashes.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/EfficientHashLib.sol)
/// @dev To avoid stack-too-deep, you can use:
/// ```
/// bytes32[] memory buffer = EfficientHashLib.malloc(10);
/// EfficientHashLib.set(buffer, 0, value0);
/// ..
/// EfficientHashLib.set(buffer, 9, value9);
/// bytes32 finalHash = EfficientHashLib.hash(buffer);
/// ```
library EfficientHashLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               MALLOC-LESS HASHING OPERATIONS               */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `keccak256(abi.encode(v0))`.
    function hash(bytes32 v0) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            result := keccak256(0x00, 0x20)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0))`.
    function hash(uint256 v0) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            result := keccak256(0x00, 0x20)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1))`.
    function hash(bytes32 v0, bytes32 v1) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            mstore(0x20, v1)
            result := keccak256(0x00, 0x40)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1))`.
    function hash(uint256 v0, uint256 v1) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, v0)
            mstore(0x20, v1)
            result := keccak256(0x00, 0x40)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            result := keccak256(m, 0x60)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2))`.
    function hash(uint256 v0, uint256 v1, uint256 v2) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            result := keccak256(m, 0x60)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            result := keccak256(m, 0x80)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, v1, v2, v3))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            result := keccak256(m, 0x80)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            result := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v4))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            result := keccak256(m, 0xa0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
    function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4, bytes32 v5)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            result := keccak256(m, 0xc0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v5))`.
    function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4, uint256 v5)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            result := keccak256(m, 0xc0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            result := keccak256(m, 0xe0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v6))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            result := keccak256(m, 0xe0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            result := keccak256(m, 0x100)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v7))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            result := keccak256(m, 0x100)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            result := keccak256(m, 0x120)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v8))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            result := keccak256(m, 0x120)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            result := keccak256(m, 0x140)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v9))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            result := keccak256(m, 0x140)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            result := keccak256(m, 0x160)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v10))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            result := keccak256(m, 0x160)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            result := keccak256(m, 0x180)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v11))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            result := keccak256(m, 0x180)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11,
        bytes32 v12
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            result := keccak256(m, 0x1a0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v12))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11,
        uint256 v12
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            result := keccak256(m, 0x1a0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
    function hash(
        bytes32 v0,
        bytes32 v1,
        bytes32 v2,
        bytes32 v3,
        bytes32 v4,
        bytes32 v5,
        bytes32 v6,
        bytes32 v7,
        bytes32 v8,
        bytes32 v9,
        bytes32 v10,
        bytes32 v11,
        bytes32 v12,
        bytes32 v13
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            mstore(add(m, 0x1a0), v13)
            result := keccak256(m, 0x1c0)
        }
    }

    /// @dev Returns `keccak256(abi.encode(v0, .., v13))`.
    function hash(
        uint256 v0,
        uint256 v1,
        uint256 v2,
        uint256 v3,
        uint256 v4,
        uint256 v5,
        uint256 v6,
        uint256 v7,
        uint256 v8,
        uint256 v9,
        uint256 v10,
        uint256 v11,
        uint256 v12,
        uint256 v13
    ) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, v0)
            mstore(add(m, 0x20), v1)
            mstore(add(m, 0x40), v2)
            mstore(add(m, 0x60), v3)
            mstore(add(m, 0x80), v4)
            mstore(add(m, 0xa0), v5)
            mstore(add(m, 0xc0), v6)
            mstore(add(m, 0xe0), v7)
            mstore(add(m, 0x100), v8)
            mstore(add(m, 0x120), v9)
            mstore(add(m, 0x140), v10)
            mstore(add(m, 0x160), v11)
            mstore(add(m, 0x180), v12)
            mstore(add(m, 0x1a0), v13)
            result := keccak256(m, 0x1c0)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*             BYTES32 BUFFER HASHING OPERATIONS              */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `keccak256(abi.encode(buffer[0], .., buffer[buffer.length - 1]))`.
    function hash(bytes32[] memory buffer) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(add(buffer, 0x20), shl(5, mload(buffer)))
        }
    }

    /// @dev Sets `buffer[i]` to `value`, without a bounds check.
    /// Returns the `buffer` for function chaining.
    function set(bytes32[] memory buffer, uint256 i, bytes32 value)
        internal
        pure
        returns (bytes32[] memory)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(add(buffer, shl(5, add(1, i))), value)
        }
        return buffer;
    }

    /// @dev Sets `buffer[i]` to `value`, without a bounds check.
    /// Returns the `buffer` for function chaining.
    function set(bytes32[] memory buffer, uint256 i, uint256 value)
        internal
        pure
        returns (bytes32[] memory)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(add(buffer, shl(5, add(1, i))), value)
        }
        return buffer;
    }

    /// @dev Returns `new bytes32[](n)`, without zeroing out the memory.
    function malloc(uint256 n) internal pure returns (bytes32[] memory buffer) {
        /// @solidity memory-safe-assembly
        assembly {
            buffer := mload(0x40)
            mstore(buffer, n)
            mstore(0x40, add(shl(5, add(1, n)), buffer))
        }
    }

    /// @dev Frees memory that has been allocated for `buffer`.
    /// No-op if `buffer.length` is zero, or if new memory has been allocated after `buffer`.
    function free(bytes32[] memory buffer) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(buffer)
            mstore(shl(6, lt(iszero(n), eq(add(shl(5, add(1, n)), buffer), mload(0x40)))), buffer)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      EQUALITY CHECKS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `a == abi.decode(b, (bytes32))`.
    function eq(bytes32 a, bytes memory b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(0x20, mload(b)), eq(a, mload(add(b, 0x20))))
        }
    }

    /// @dev Returns `abi.decode(a, (bytes32)) == a`.
    function eq(bytes memory a, bytes32 b) internal pure returns (bool result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := and(eq(0x20, mload(a)), eq(b, mload(add(a, 0x20))))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*               BYTE SLICE HASHING OPERATIONS                */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function hash(bytes memory b, uint256 start, uint256 end)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            end := xor(end, mul(xor(end, n), lt(n, end)))
            start := xor(start, mul(xor(start, n), lt(n, start)))
            result := keccak256(add(add(b, 0x20), start), mul(gt(end, start), sub(end, start)))
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
    function hash(bytes memory b, uint256 start) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            start := xor(start, mul(xor(start, n), lt(n, start)))
            result := keccak256(add(add(b, 0x20), start), mul(gt(n, start), sub(n, start)))
        }
    }

    /// @dev Returns the keccak256 of the bytes.
    function hash(bytes memory b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := keccak256(add(b, 0x20), mload(b))
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function hashCalldata(bytes calldata b, uint256 start, uint256 end)
        internal
        pure
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(end, start), sub(end, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := keccak256(mload(0x40), n)
        }
    }

    /// @dev Returns the keccak256 of the slice from `start` to the end of the bytes.
    function hashCalldata(bytes calldata b, uint256 start) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(b.length, start), sub(b.length, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := keccak256(mload(0x40), n)
        }
    }

    /// @dev Returns the keccak256 of the bytes.
    function hashCalldata(bytes calldata b) internal pure returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            calldatacopy(mload(0x40), b.offset, b.length)
            result := keccak256(mload(0x40), b.length)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      SHA2-256 HELPERS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns `sha256(abi.encode(b))`. Yes, it's more efficient.
    function sha2(bytes32 b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, b)
            result := mload(staticcall(gas(), 2, 0x00, 0x20, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function sha2(bytes memory b, uint256 start, uint256 end)
        internal
        view
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            end := xor(end, mul(xor(end, n), lt(n, end)))
            start := xor(start, mul(xor(start, n), lt(n, start)))
            // forgefmt: disable-next-item
            result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
                mul(gt(end, start), sub(end, start)), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
    function sha2(bytes memory b, uint256 start) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(b)
            start := xor(start, mul(xor(start, n), lt(n, start)))
            // forgefmt: disable-next-item
            result := mload(staticcall(gas(), 2, add(add(b, 0x20), start),
                mul(gt(n, start), sub(n, start)), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the bytes.
    function sha2(bytes memory b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := mload(staticcall(gas(), 2, add(b, 0x20), mload(b), 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to `end` (exclusive).
    /// `start` and `end` are byte offsets.
    function sha2Calldata(bytes calldata b, uint256 start, uint256 end)
        internal
        view
        returns (bytes32 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            end := xor(end, mul(xor(end, b.length), lt(b.length, end)))
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(end, start), sub(end, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the slice from `start` to the end of the bytes.
    function sha2Calldata(bytes calldata b, uint256 start) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            start := xor(start, mul(xor(start, b.length), lt(b.length, start)))
            let n := mul(gt(b.length, start), sub(b.length, start))
            calldatacopy(mload(0x40), add(b.offset, start), n)
            result := mload(staticcall(gas(), 2, mload(0x40), n, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }

    /// @dev Returns the sha256 of the bytes.
    function sha2Calldata(bytes calldata b) internal view returns (bytes32 result) {
        /// @solidity memory-safe-assembly
        assembly {
            calldatacopy(mload(0x40), b.offset, b.length)
            result := mload(staticcall(gas(), 2, mload(0x40), b.length, 0x01, 0x20))
            if iszero(returndatasize()) { invalid() }
        }
    }
}
          

contracts/Constants.sol

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

event Ok(address indexed provider, bytes32 section);

event Bleach(address indexed provider, bytes32 section);

event Reprice(address indexed provider, uint256 pricePer);

event Ink(address sender, address indexed provider, bytes32 section, uint256 offset, address pointer);

event Heat(address indexed provider, bytes32 section, uint256 index);

event Start(address indexed owner, bytes32 key); // no need to index because all keys should be unique

event Link(address indexed provider, bytes32 location, bytes32 formerSecret);

event Reveal(address indexed provider, bytes32 location, bytes32 formerSecret);

event Expired(bytes32 key);

event Cast(bytes32 key, bytes32 seed);

event Chop(bytes32 key);

event FailedToCall(address to, bytes32 key);

abstract contract Errors {
    error DeploymentFailed();
    error Misconfigured();
    error UnableToService();
    error MissingPayment();
    error SecretMismatch();
    error ZeroSecret();
    error NotInCohort();
    error SignerMismatch();
}
          

solady/src/utils/SafeTransferLib.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /// @dev The ERC20 `totalSupply` query has failed.
    error TotalSupplyQueryFailed();

    /// @dev The Permit2 operation has failed.
    error Permit2Failed();

    /// @dev The Permit2 amount must be less than `2**160 - 1`.
    error Permit2AmountOverflow();

    /// @dev The Permit2 approve operation has failed.
    error Permit2ApproveFailed();

    /// @dev The Permit2 lockdown operation has failed.
    error Permit2LockdownFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /// @dev The unique EIP-712 domain separator for the DAI token contract.
    bytes32 internal constant DAI_DOMAIN_SEPARATOR =
        0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;

    /// @dev The address for the WETH9 contract on Ethereum mainnet.
    address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    /// @dev The canonical Permit2 address.
    /// [Github](https://github.com/Uniswap/permit2)
    /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)
    address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

    /// @dev The canonical address of the `SELFDESTRUCT` ETH mover.
    /// See: https://gist.github.com/Vectorized/1cb8ad4cf393b1378e08f23f79bd99fa
    /// [Etherscan](https://etherscan.io/address/0x00000000000073c48c8055bD43D1A53799176f0D)
    address internal constant ETH_MOVER = 0x00000000000073c48c8055bD43D1A53799176f0D;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Force transfers ETH to `to`, without triggering the fallback (if any).
    /// This method attempts to use a separate contract to send via `SELFDESTRUCT`,
    /// and upon failure, deploys a minimal vault to accrue the ETH.
    function safeMoveETH(address to, uint256 amount) internal returns (address vault) {
        /// @solidity memory-safe-assembly
        assembly {
            to := shr(96, shl(96, to)) // Clean upper 96 bits.
            for { let mover := ETH_MOVER } iszero(eq(to, address())) {} {
                let selfBalanceBefore := selfbalance()
                if or(lt(selfBalanceBefore, amount), eq(to, mover)) {
                    mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                    revert(0x1c, 0x04)
                }
                if extcodesize(mover) {
                    let balanceBefore := balance(to) // Check via delta, in case `SELFDESTRUCT` is bricked.
                    mstore(0x00, to)
                    pop(call(gas(), mover, amount, 0x00, 0x20, codesize(), 0x00))
                    // If `address(to).balance >= amount + balanceBefore`, skip vault workflow.
                    if iszero(lt(balance(to), add(amount, balanceBefore))) { break }
                    // Just in case `SELFDESTRUCT` is changed to not revert and do nothing.
                    if lt(selfBalanceBefore, selfbalance()) { invalid() }
                }
                let m := mload(0x40)
                // If the mover is missing or bricked, deploy a minimal vault
                // that withdraws all ETH to `to` when being called only by `to`.
                // forgefmt: disable-next-item
                mstore(add(m, 0x20), 0x33146025575b600160005260206000f35b3d3d3d3d47335af1601a5760003dfd)
                mstore(m, or(to, shl(160, 0x6035600b3d3960353df3fe73)))
                // Compute and store the bytecode hash.
                mstore8(0x00, 0xff) // Write the prefix.
                mstore(0x35, keccak256(m, 0x40))
                mstore(0x01, shl(96, address())) // Deployer.
                mstore(0x15, 0) // Salt.
                vault := keccak256(0x00, 0x55)
                pop(call(gas(), vault, amount, codesize(), 0x00, codesize(), 0x00))
                // The vault returns a single word on success. Failure reverts with empty data.
                if iszero(returndatasize()) {
                    if iszero(create2(0, m, 0x40, 0)) { revert(codesize(), codesize()) } // For gas estimation.
                }
                mstore(0x40, m) // Restore the free memory pointer.
                break
            }
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function trySafeTransferFrom(address token, address from, address to, uint256 amount)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                success := lt(or(iszero(extcodesize(token)), returndatasize()), success)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x34, 0) // Store 0 for the `amount`.
                    mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                    pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
                    mstore(0x34, amount) // Store back the original `amount`.
                    // Retry the approval, reverting upon failure.
                    success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    if iszero(and(eq(mload(0x00), 1), success)) {
                        // Check the `extcodesize` again just in case the token selfdestructs lol.
                        if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                            mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                            revert(0x1c, 0x04)
                        }
                    }
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul( // The arguments of `mul` are evaluated from right to left.
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }

    /// @dev Performs a `token.balanceOf(account)` check.
    /// `implemented` denotes whether the `token` does not implement `balanceOf`.
    /// `amount` is zero if the `token` does not implement `balanceOf`.
    function checkBalanceOf(address token, address account)
        internal
        view
        returns (bool implemented, uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            implemented :=
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                )
            amount := mul(mload(0x20), implemented)
        }
    }

    /// @dev Returns the total supply of the `token`.
    /// Reverts if the token does not exist or does not implement `totalSupply()`.
    function totalSupply(address token) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x18160ddd) // `totalSupply()`.
            if iszero(
                and(gt(returndatasize(), 0x1f), staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20))
            ) {
                mstore(0x00, 0x54cd9435) // `TotalSupplyQueryFailed()`.
                revert(0x1c, 0x04)
            }
            result := mload(0x00)
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// If the initial attempt fails, try to use Permit2 to transfer the token.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {
        if (!trySafeTransferFrom(token, from, to, amount)) {
            permit2TransferFrom(token, from, to, amount);
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.
    /// Reverts upon failure.
    function permit2TransferFrom(address token, address from, address to, uint256 amount)
        internal
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(add(m, 0x74), shr(96, shl(96, token)))
            mstore(add(m, 0x54), amount)
            mstore(add(m, 0x34), to)
            mstore(add(m, 0x20), shl(96, from))
            // `transferFrom(address,address,uint160,address)`.
            mstore(m, 0x36c78516000000000000000000000000)
            let p := PERMIT2
            let exists := eq(chainid(), 1)
            if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }
            if iszero(
                and(
                    call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00),
                    lt(iszero(extcodesize(token)), exists) // Token has code and Permit2 exists.
                )
            ) {
                mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.
                revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)
            }
        }
    }

    /// @dev Permit a user to spend a given amount of
    /// another user's tokens via native EIP-2612 permit if possible, falling
    /// back to Permit2 if native permit fails or is not implemented on the token.
    function permit2(
        address token,
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        bool success;
        /// @solidity memory-safe-assembly
        assembly {
            for {} shl(96, xor(token, WETH9)) {} {
                mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.
                        // Gas stipend to limit gas burn for tokens that don't refund gas when
                        // an non-existing function is called. 5K should be enough for a SLOAD.
                        staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)
                    )
                ) { break }
                // After here, we can be sure that token is a contract.
                let m := mload(0x40)
                mstore(add(m, 0x34), spender)
                mstore(add(m, 0x20), shl(96, owner))
                mstore(add(m, 0x74), deadline)
                if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {
                    mstore(0x14, owner)
                    mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.
                    mstore(
                        add(m, 0x94),
                        lt(iszero(amount), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))
                    )
                    mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.
                    // `nonces` is already at `add(m, 0x54)`.
                    // `amount != 0` is already stored at `add(m, 0x94)`.
                    mstore(add(m, 0xb4), and(0xff, v))
                    mstore(add(m, 0xd4), r)
                    mstore(add(m, 0xf4), s)
                    success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)
                    break
                }
                mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.
                mstore(add(m, 0x54), amount)
                mstore(add(m, 0x94), and(0xff, v))
                mstore(add(m, 0xb4), r)
                mstore(add(m, 0xd4), s)
                success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)
                break
            }
        }
        if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);
    }

    /// @dev Simple permit on the Permit2 contract.
    function simplePermit2(
        address token,
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, 0x927da105) // `allowance(address,address,address)`.
            {
                let addressMask := shr(96, not(0))
                mstore(add(m, 0x20), and(addressMask, owner))
                mstore(add(m, 0x40), and(addressMask, token))
                mstore(add(m, 0x60), and(addressMask, spender))
                mstore(add(m, 0xc0), and(addressMask, spender))
            }
            let p := mul(PERMIT2, iszero(shr(160, amount)))
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.
                    staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)
                )
            ) {
                mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.
                revert(add(0x18, shl(2, iszero(p))), 0x04)
            }
            mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).
            // `owner` is already `add(m, 0x20)`.
            // `token` is already at `add(m, 0x40)`.
            mstore(add(m, 0x60), amount)
            mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.
            // `nonce` is already at `add(m, 0xa0)`.
            // `spender` is already at `add(m, 0xc0)`.
            mstore(add(m, 0xe0), deadline)
            mstore(add(m, 0x100), 0x100) // `signature` offset.
            mstore(add(m, 0x120), 0x41) // `signature` length.
            mstore(add(m, 0x140), r)
            mstore(add(m, 0x160), s)
            mstore(add(m, 0x180), shl(248, v))
            if iszero( // Revert if token does not have code, or if the call fails.
            mul(extcodesize(token), call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00))) {
                mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Approves `spender` to spend `amount` of `token` for `address(this)`.
    function permit2Approve(address token, address spender, uint160 amount, uint48 expiration)
        internal
    {
        /// @solidity memory-safe-assembly
        assembly {
            let addressMask := shr(96, not(0))
            let m := mload(0x40)
            mstore(m, 0x87517c45) // `approve(address,address,uint160,uint48)`.
            mstore(add(m, 0x20), and(addressMask, token))
            mstore(add(m, 0x40), and(addressMask, spender))
            mstore(add(m, 0x60), and(addressMask, amount))
            mstore(add(m, 0x80), and(0xffffffffffff, expiration))
            if iszero(call(gas(), PERMIT2, 0, add(m, 0x1c), 0xa0, codesize(), 0x00)) {
                mstore(0x00, 0x324f14ae) // `Permit2ApproveFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Revokes an approval for `token` and `spender` for `address(this)`.
    function permit2Lockdown(address token, address spender) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, 0xcc53287f) // `Permit2.lockdown`.
            mstore(add(m, 0x20), 0x20) // Offset of the `approvals`.
            mstore(add(m, 0x40), 1) // `approvals.length`.
            mstore(add(m, 0x60), shr(96, shl(96, token)))
            mstore(add(m, 0x80), shr(96, shl(96, spender)))
            if iszero(call(gas(), PERMIT2, 0, add(m, 0x1c), 0xa0, codesize(), 0x00)) {
                mstore(0x00, 0x96b3de23) // `Permit2LockdownFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }
}
          

solady/src/utils/SSTORE2.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Read and write to persistent storage at a fraction of the cost.
/// @author Solady (https://github.com/vectorized/solady/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)
/// @author Modified from SSTORE3 (https://github.com/Philogy/sstore3)
library SSTORE2 {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The proxy initialization code.
    uint256 private constant _CREATE3_PROXY_INITCODE = 0x67363d3d37363d34f03d5260086018f3;

    /// @dev Hash of the `_CREATE3_PROXY_INITCODE`.
    /// Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`.
    bytes32 internal constant CREATE3_PROXY_INITCODE_HASH =
        0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                        CUSTOM ERRORS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Unable to deploy the storage contract.
    error DeploymentFailed();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         WRITE LOGIC                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Writes `data` into the bytecode of a storage contract and returns its address.
    function write(bytes memory data) internal returns (address pointer) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(data) // Let `l` be `n + 1`. +1 as we prefix a STOP opcode.
            /**
             * ---------------------------------------------------+
             * Opcode | Mnemonic       | Stack     | Memory       |
             * ---------------------------------------------------|
             * 61 l   | PUSH2 l        | l         |              |
             * 80     | DUP1           | l l       |              |
             * 60 0xa | PUSH1 0xa      | 0xa l l   |              |
             * 3D     | RETURNDATASIZE | 0 0xa l l |              |
             * 39     | CODECOPY       | l         | [0..l): code |
             * 3D     | RETURNDATASIZE | 0 l       | [0..l): code |
             * F3     | RETURN         |           | [0..l): 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.
             */
            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.
            mstore(add(data, gt(n, 0xfffe)), add(0xfe61000180600a3d393df300, shl(0x40, n)))
            // Deploy a new contract with the generated creation code.
            pointer := create(0, add(data, 0x15), add(n, 0xb))
            if iszero(pointer) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(data, n) // Restore the length of `data`.
        }
    }

    /// @dev Writes `data` into the bytecode of a storage contract with `salt`
    /// and returns its normal CREATE2 deterministic address.
    function writeCounterfactual(bytes memory data, bytes32 salt)
        internal
        returns (address pointer)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(data)
            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.
            mstore(add(data, gt(n, 0xfffe)), add(0xfe61000180600a3d393df300, shl(0x40, n)))
            // Deploy a new contract with the generated creation code.
            pointer := create2(0, add(data, 0x15), add(n, 0xb), salt)
            if iszero(pointer) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(data, n) // Restore the length of `data`.
        }
    }

    /// @dev Writes `data` into the bytecode of a storage contract and returns its address.
    /// This uses the so-called "CREATE3" workflow,
    /// which means that `pointer` is agnostic to `data, and only depends on `salt`.
    function writeDeterministic(bytes memory data, bytes32 salt)
        internal
        returns (address pointer)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(data)
            mstore(0x00, _CREATE3_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).
            pointer := keccak256(0x1e, 0x17)

            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.
            mstore(add(data, gt(n, 0xfffe)), add(0xfe61000180600a3d393df300, shl(0x40, n)))
            if iszero(
                mul( // The arguments of `mul` are evaluated last to first.
                    extcodesize(pointer),
                    call(gas(), proxy, 0, add(data, 0x15), add(n, 0xb), codesize(), 0x00)
                )
            ) {
                mstore(0x00, 0x30116425) // `DeploymentFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(data, n) // Restore the length of `data`.
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                    ADDRESS CALCULATIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the initialization code hash of the storage contract for `data`.
    /// Used for mining vanity addresses with create2crunch.
    function initCodeHash(bytes memory data) internal pure returns (bytes32 hash) {
        /// @solidity memory-safe-assembly
        assembly {
            let n := mload(data)
            // Do a out-of-gas revert if `n + 1` is more than 2 bytes.
            returndatacopy(returndatasize(), returndatasize(), gt(n, 0xfffe))
            mstore(data, add(0x61000180600a3d393df300, shl(0x40, n)))
            hash := keccak256(add(data, 0x15), add(n, 0xb))
            mstore(data, n) // Restore the length of `data`.
        }
    }

    /// @dev Equivalent to `predictCounterfactualAddress(data, salt, address(this))`
    function predictCounterfactualAddress(bytes memory data, bytes32 salt)
        internal
        view
        returns (address pointer)
    {
        pointer = predictCounterfactualAddress(data, salt, address(this));
    }

    /// @dev Returns the CREATE2 address of the storage contract for `data`
    /// deployed with `salt` by `deployer`.
    /// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
    function predictCounterfactualAddress(bytes memory data, bytes32 salt, address deployer)
        internal
        pure
        returns (address predicted)
    {
        bytes32 hash = initCodeHash(data);
        /// @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)
            // Restore the part of the free memory pointer that has been overwritten.
            mstore(0x35, 0)
        }
    }

    /// @dev Equivalent to `predictDeterministicAddress(salt, address(this))`.
    function predictDeterministicAddress(bytes32 salt) internal view returns (address pointer) {
        pointer = predictDeterministicAddress(salt, address(this));
    }

    /// @dev Returns the "CREATE3" deterministic address for `salt` with `deployer`.
    function predictDeterministicAddress(bytes32 salt, address deployer)
        internal
        pure
        returns (address pointer)
    {
        /// @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, CREATE3_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).
            pointer := keccak256(0x1e, 0x17)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         READ LOGIC                         */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Equivalent to `read(pointer, 0, 2 ** 256 - 1)`.
    function read(address pointer) internal view returns (bytes memory data) {
        /// @solidity memory-safe-assembly
        assembly {
            data := mload(0x40)
            let n := and(0xffffffffff, sub(extcodesize(pointer), 0x01))
            extcodecopy(pointer, add(data, 0x1f), 0x00, add(n, 0x21))
            mstore(data, n) // Store the length.
            mstore(0x40, add(n, add(data, 0x40))) // Allocate memory.
        }
    }

    /// @dev Equivalent to `read(pointer, start, 2 ** 256 - 1)`.
    function read(address pointer, uint256 start) internal view returns (bytes memory data) {
        /// @solidity memory-safe-assembly
        assembly {
            data := mload(0x40)
            let n := and(0xffffffffff, sub(extcodesize(pointer), 0x01))
            let l := sub(n, and(0xffffff, mul(lt(start, n), start)))
            extcodecopy(pointer, add(data, 0x1f), start, add(l, 0x21))
            mstore(data, mul(sub(n, start), lt(start, n))) // Store the length.
            mstore(0x40, add(data, add(0x40, mload(data)))) // Allocate memory.
        }
    }

    /// @dev Returns a slice of the data on `pointer` from `start` to `end`.
    /// `start` and `end` will be clamped to the range `[0, args.length]`.
    /// The `pointer` MUST be deployed via the SSTORE2 write functions.
    /// Otherwise, the behavior is undefined.
    /// Out-of-gas reverts if `pointer` does not have any code.
    function read(address pointer, uint256 start, uint256 end)
        internal
        view
        returns (bytes memory data)
    {
        /// @solidity memory-safe-assembly
        assembly {
            data := mload(0x40)
            if iszero(lt(end, 0xffff)) { end := 0xffff }
            let d := mul(sub(end, start), lt(start, end))
            extcodecopy(pointer, add(data, 0x1f), start, add(d, 0x01))
            if iszero(and(0xff, mload(add(data, d)))) {
                let n := sub(extcodesize(pointer), 0x01)
                returndatacopy(returndatasize(), returndatasize(), shr(40, n))
                d := mul(gt(n, start), sub(d, mul(gt(end, n), sub(end, n))))
            }
            mstore(data, d) // Store the length.
            mstore(add(add(data, 0x20), d), 0) // Zeroize the slot after the bytes.
            mstore(0x40, add(add(data, 0x40), d)) // Allocate memory.
        }
    }
}
          

Compiler Settings

{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":1000,"enabled":true},"libraries":{},"evmVersion":"cancun"}
              

Contract ABI

[{"type":"error","name":"Misconfigured","inputs":[]},{"type":"error","name":"MissingPayment","inputs":[]},{"type":"error","name":"NotInCohort","inputs":[]},{"type":"error","name":"SecretMismatch","inputs":[]},{"type":"error","name":"SignerMismatch","inputs":[]},{"type":"error","name":"UnableToService","inputs":[]},{"type":"event","name":"Bleach","inputs":[{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"bytes32","name":"section","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Cast","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"seed","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Chop","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Expired","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"FailedToCall","inputs":[{"type":"address","name":"to","internalType":"address","indexed":false},{"type":"bytes32","name":"key","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Heat","inputs":[{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"bytes32","name":"section","internalType":"bytes32","indexed":false},{"type":"uint256","name":"index","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Ink","inputs":[{"type":"address","name":"sender","internalType":"address","indexed":false},{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"bytes32","name":"section","internalType":"bytes32","indexed":false},{"type":"uint256","name":"offset","internalType":"uint256","indexed":false},{"type":"address","name":"pointer","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Link","inputs":[{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"bytes32","name":"location","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"formerSecret","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Reveal","inputs":[{"type":"address","name":"provider","internalType":"address","indexed":true},{"type":"bytes32","name":"location","internalType":"bytes32","indexed":false},{"type":"bytes32","name":"formerSecret","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"event","name":"Start","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"bytes32","name":"key","internalType":"bytes32","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"},{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"bleach","inputs":[{"type":"tuple","name":"info","internalType":"struct PreimageLocation.Info","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"uint8","name":"","internalType":"enum Random.CastState"}],"name":"cast","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32"},{"type":"tuple[]","name":"info","internalType":"struct PreimageLocation.Info[]","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"bytes32[]","name":"revealed","internalType":"bytes32[]"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"chop","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32"},{"type":"tuple[]","name":"info","internalType":"struct PreimageLocation.Info[]","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"consumed","inputs":[{"type":"tuple","name":"info","internalType":"struct PreimageLocation.Info","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"expired","inputs":[{"type":"uint256","name":"timeline","internalType":"uint256"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"handoff","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"address","name":"token","internalType":"address"},{"type":"int256","name":"amount","internalType":"int256"}]},{"type":"function","stateMutability":"payable","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"heat","inputs":[{"type":"uint256","name":"required","internalType":"uint256"},{"type":"tuple","name":"settings","internalType":"struct PreimageLocation.Info","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"tuple[]","name":"potentialLocations","internalType":"struct PreimageLocation.Info[]","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"bool","name":"useTSTORE","internalType":"bool"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"ink","inputs":[{"type":"tuple","name":"info","internalType":"struct PreimageLocation.Info","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"key","internalType":"bytes32"}],"name":"latest","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"bool","name":"onlySameTx","internalType":"bool"},{"type":"bool","name":"useTSTORE","internalType":"bool"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"pointer","inputs":[{"type":"tuple","name":"info","internalType":"struct PreimageLocation.Info","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct IRandom.Randomness","components":[{"type":"address","name":"owner","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"usesTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"uint256","name":"start","internalType":"uint256"},{"type":"uint256","name":"timeline","internalType":"uint256"},{"type":"uint256","name":"contributed","internalType":"uint256"},{"type":"bytes32","name":"seed","internalType":"bytes32"}]}],"name":"randomness","inputs":[{"type":"bytes32","name":"key","internalType":"bytes32"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"reveal","inputs":[{"type":"tuple","name":"info","internalType":"struct PreimageLocation.Info","components":[{"type":"address","name":"provider","internalType":"address"},{"type":"bool","name":"callAtChange","internalType":"bool"},{"type":"bool","name":"durationIsTimestamp","internalType":"bool"},{"type":"uint256","name":"duration","internalType":"uint256"},{"type":"address","name":"token","internalType":"address"},{"type":"uint256","name":"price","internalType":"uint256"},{"type":"uint256","name":"offset","internalType":"uint256"},{"type":"uint256","name":"index","internalType":"uint256"}]},{"type":"bytes32","name":"formerSecret","internalType":"bytes32"}]}]
              

Contract Creation Code

0x6080806040523460155761236c908161001a8239f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c806302a381bf14610f9e5780630cf9dff714610e9b5780632f93018814610c3d57806338ee1b8e14610c0c5780636da844ea146109765780637e4a22cc1461072f5780637f5299bb1461036a578063a8d3600c14610292578063b90b4a87146101c5578063ba065e1f1461019d578063ce8c091514610163578063eca4ba70146100fa5763f7888aec146100a8575f80fd5b346100f65760403660031901126100f6576100c161114a565b6100c9611160565b906001600160a01b038091165f52600360205260405f2091165f52602052602060405f2054604051908152f35b5f80fd5b346100f6576101003660031901126100f65760206001600160a01b038061011f611372565b165f526005825260405f2061013b61013636611206565b611beb565b5f52825260405f2060a4355f52825260405f2060c4355f52825260405f205416604051908152f35b60403660031901126100f65760243567ffffffffffffffff81116100f65761019261019b91369060040161130d565b90600435611836565b005b346100f65760203660031901126100f65760206101bb6004356121a4565b6040519015158152f35b60603660031901126100f65767ffffffffffffffff6024358181116100f6576101f290369060040161130d565b6044929192359182116100f657366023830112156100f6578160040135926102198461133e565b9261022760405194856111d7565b8484526020946024602086019160051b830101913683116100f657602401905b8282106102835761025c86868660043561145d565b604051600382101561026f576020918152f35b634e487b7160e01b5f52602160045260245ffd5b81358152908601908601610247565b346100f65760603660031901126100f6576102ab61114a565b60243580151581036100f65760443580151581036100f6571561033d576102ea6102d3611424565b80516020918201205f19015f9081522060ff191690565b825f5260205260405f205c905b8115610309575b602082604051908152f35b905061032c576001600160a01b03165f526002602052602060405f2054826102fe565b600460405163d3e0741d60e01b8152fd5b6001600160a01b0382165f52600a60205260405f2061035a611e73565b5f5260205260405f2054906102f7565b6101603660031901126100f6576101003660231901126100f6576101243567ffffffffffffffff81116100f6576103a590369060040161130d565b61014435151561014435036100f6576103bf6004356113bf565b916103c8611a8c565b9034610705575b6001600160a01b036103df611388565b161561032c576004351580156106f9575b80156106ee575b61032c57608435647fffffffff8116036106b7575f925f905f9080156106da5761042560808597950161139e565b9360015b156106c8575b5f9061043c81848a6113f1565b6001600160a01b036104506080830161139e565b166001600160a01b038816036106b75760408101358015158091036100f657610477611401565b1515036106b7576084356060820135116106b75761049d610498368361128c565b611ca0565b6104b0816104ab368561128c565b611dc2565b6104c0575b505060010190610429565b60019296959160a0915f5260e08101356020528b6104e28860405f2092611410565b5201350193019384600435146104f95789806104b5565b505050919293505b6004351161032c5780151591826106a2575b5050905061067857805160051b60208092012061052e611388565b60443580151581036100f657610542611401565b15610671576001915b610553611401565b1561066a5742915b15610650576bffffffffffff000000000000657fffffffff8060015b865f525f885260081b9460843560011b1760091b169260301b16906bffffffffffffffffffffffff199060601b1617171760405f20556001600160a01b036105bd611388565b610144351561062c576105d16102d3611424565b815f5284528260405f205d5b165f52600282528060405f20556001600160a01b036105fa611388565b167f7a1cb491da9915d087844d867ad00ac476b12041d231adb7a04be595db91e44b83604051848152a2604051908152f35b8181165f52600a845260405f20610641611e73565b5f5284528260405f20556105dd565b6bffffffffffff000000000000657fffffffff805f610577565b439161055b565b5f9161054b565b60046040517f62128b04000000000000000000000000000000000000000000000000000000008152fd5b6106ae92508193611aef565b10808380610513565b60046040516321f9f13f60e11b8152fd5b81811061042f57505091929350610501565b634e487b7160e01b5f52603260045260245ffd5b5082600435116103f7565b5060ff600435116103f0565b6001600160a01b0382165f52600360205260405f205f805260205260405f203481540190556103cf565b366003190161012081126100f657610100136100f657610104356040516107558161118a565b600435906001600160a01b03808316928381036100f65782526024359384151585036100f6576020948584015260443580151581036100f6576040840152606435606084015260843582811681036100f657608084015260a435938460a085015260c435908160c08601526107d260e435958660e0820152611beb565b905f526005875260405f20905f52865260405f20855f52865260405f20815f5286528260405f20541680156106b7578460051b908582048814861517156109625787820191828111610962576040519261ffff8082101561095a575b5080821082820302926001840183601f8701833c8385015160ff1615610933575b50505080825281015f888201526040810190816040528883519301519289811061091f575b5060600190848252888152610888816111bb565b5190201461089257005b6108ee6040947fa8080584ebb92497a93bf0923d88f7a218d6b2b12e73938ec37157d8df9c561e96856108c3611372565b165f5260088952865f206108d961013636611206565b5f528952865f20905f528852855f20926113b2565b5f52855280835f20556108ff611372565b9061091161090c36611206565b611da7565b9584519687528601521692a2005b5f19908a0360031b1b909216916060610874565b90600193913b5f1981019485918260281c3d3d3e830301911102900391110288808061084f565b90508a61082e565b634e487b7160e01b5f52601160045260245ffd5b6101003660031901126100f65761098c36611206565b610994611a8c565b9034610be2575b6001600160a01b038151166001600160a01b03831603610bb857906109bf82611beb565b6109c98184611d52565b60051c926109d681611ca0565b5f9060c0830151958601905f946001600160a01b038551165f52600660205260405f20905f5260205260405f2060a08501515f5260205260405f209460015b15610b42575b5f978115610b33575b8382820111610b29575b81610100038160081c5f528760205260405f208054915f19811c9083868601610100031b901c10610a67575b5050019661010090610a15565b93989194839698919a9360ff8716908189810197610101891015610ae3575b5060405f20915f1990610100031c901b81541790559960015b15610aca575b5f9a60018d821c1615610abc575b6001019a610a9f565b60a08a0151909a0199610ab3565b858b10610aa55794509491985096949198508980610a5a565b5f19821b8f179055890160ff811691505f90600160088b811c91820192901c015b808203610b1457505f528e610a86565b90806001915f525f1960405f20550190610b04565b8084039150610a2e565b60ff8116610100039150610a24565b828810610a1b578385838983610b5457005b6001600160a01b03916040519081527fbd86c8c76936132dbc24244b04f4607b8bc2b75dd1cb36379bbedeee254b9260602084841692a2165f5260036020526001600160a01b03608060405f20920151165f5260205260405f209081540190555f80f35b60046040517f10c74b03000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b0382165f52600360205260405f205f805260205260405f2034815401905561099b565b346100f6576101003660031901126100f65760206101bb610c2f61013636611206565b610c3836611206565b611cdd565b6101203660031901126100f657610c5336611206565b610104359067ffffffffffffffff8083116100f657366023840112156100f65782600401359081116100f65736602482850101116100f6578060051c9181158015610e8f575b6106b757610ca5611a8c565b9234610e65575b6001600160a01b0380941691825f526020936003855260405f20946080830195878751165f52815260405f205460a08401968751860280921061067857865f52600383528860405f209151165f52825260405f209081540390558683511697881561032c57610d1a84611beb565b93895f526004835260405f20855f52835260405f2088515f5283525f83604082205495806024610d4982611356565b96610d5760405198896111d7565b8288520183870137840101528151978860401b6bfe61000180600a3d393df3000161fffe8a11840152600b8901601584015ff0968715610e58577f0a0b08ec1802460e3e5a597cf64a8b64b588d0b0938df0adf5fc125781558d659a60809a610e3e95528c5f526005865260405f20885f52865260405f2083515f52865260405f20875f52865260405f20981697887fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790558501958b5f526004855260405f20905f52845260405f2090515f5283528460405f20558981528360c0820152611ca0565b90604051958652850152841b1760408301526060820152a2005b63301164255f526004601cfd5b6001600160a01b0384165f52600360205260405f205f805260205260405f20348154019055610cac565b50601f82161515610c99565b346100f6576020806003193601126100f657610100905f60e0604051610ec08161118a565b82815282848201528260408201528260608201528260808201528260a08201528260c082015201526004355f525f815260405f20546001808260081c1614908060601c926001815260405f20549260405191610f1b8361118a565b85835280830191808352604084019081526060840191647fffffffff8660091c168352608085019365ffffffffffff8760301c16855260e060a087019688885260ff60c0820199168952019788526040519889525115159088015251151560408701525160608601525160808501525160a08401525160c08301525160e0820152f35b60603660031901126100f657610fb261114a565b610fba611160565b60443591610fc6611a8c565b6001600160a01b0391808316611144575080935b5f81121561112d575f03908284169384155f1461101c57505034106106785734925b165f52600360205260405f20905f5260205260405f209081540190555f80f35b90916110283083612308565b9260405190826060523060405260601b80602c526f23b872dd000000000000000000000000600c5260205f6064601c82885af18060015f51141615611122575b5f606052826040521561108b575b505050611084903090612308565b0392610ffc565b86607483015282605483015230603483015260208201526f36c785160000000000000000000000008152600146148015611109575b5f90843b15109160846010389201836e22d473030f116ddee9f6b43ac78ba35af116156110ee578080611076565b600490677939f4248757f0fd5f5260a01c151560021b601801fd5b506e22d473030f116ddee9f6b43ac78ba33b15156110c0565b3d853b151710611068565b8361019b9594935061113e92611aef565b91611b59565b93610fda565b600435906001600160a01b03821682036100f657565b602435906001600160a01b03821682036100f657565b35906001600160a01b03821682036100f657565b610100810190811067ffffffffffffffff8211176111a757604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176111a757604052565b90601f8019910116810190811067ffffffffffffffff8211176111a757604052565b359081151582036100f657565b6101009060031901126100f657604051906112208261118a565b816001600160a01b0360043581811681036100f657825260243580151581036100f657602083015260443580151581036100f6576040830152606435606083015260843590811681036100f657608082015260a43560a082015260c43560c082015260e060e435910152565b9190826101009103126100f6576040516112a58161118a565b60e08082946112b381611176565b84526112c1602082016111f9565b60208501526112d2604082016111f9565b6040850152606081013560608501526112ed60808201611176565b608085015260a081013560a085015260c081013560c08501520135910152565b9181601f840112156100f65782359167ffffffffffffffff83116100f6576020808501948460081b0101116100f657565b67ffffffffffffffff81116111a75760051b60200190565b67ffffffffffffffff81116111a757601f01601f191660200190565b6004356001600160a01b03811681036100f65790565b6024356001600160a01b03811681036100f65790565b356001600160a01b03811681036100f65790565b9190820180921161096257565b906113c98261133e565b6113d660405191826111d7565b82815280926113e7601f199161133e565b0190602036910137565b91908110156106da5760081b0190565b60643580151581036100f65790565b80518210156106da5760209160051b010190565b60405190611431826111bb565b600682527f72616e646f6d00000000000000000000000000000000000000000000000000006020830152565b9391909334611805575b805f52602060018152604094855f20546117f9576009825260ff865f2054166117e9575f9695945f95845f525f8452805f2054946114a4876113bf565b945f965f9b60015b156115f7575b908b9c918b8b5f9e8b8b6114c68582611410565b511561152b57906114f96114f186936114ea856114e4818a8a6113f1565b92611410565b5190611f76565b939092611410565b52611520575b6001939260a09261150f926113f1565b0135019b019b9c9b9a90919c6114ac565b6001909c019b6114ff565b6115708561155e6115408288889d979d6113f1565b611558610136611551858b8b6113f1565b369061128c565b90611ed4565b939061156a8383611410565b52611410565b516115d3578c816115ac575050506001939260a09261150f9286986115a6846114e461090c366115a18489896113f1565b61128c565b526113f1565b856114f99181949a61156a6115cb866115c6868c8c6113f1565b611f76565b979092611410565b50959260a09261150f92600196956115a6846114e461090c366115a18489896113f1565b898b106114b257949b9792995090979492999588815160051b91012089036117d9570194875f525f875285895f20556117cc5785815160051b910120916001865282885f20557f46adc4912184d61bbcd0939b961e9388a3fa9122b827b48b36fdf552759f3e7d8880518981528589820152a1825f5260018652875f2054938851918783019567ffffffffffffffff96848110888211176111a7578b5283525b87832080845281805f03068110156116af5750611697565b6116bd9350819006916113f1565b865f525f86526116cf885f20546121a4565b611780575b6001600160a01b03806116e68361139e565b165f52600387526116fc60808a5f20930161139e565b165f528552865f209081540190556001808460081c1614611722575b5050505050505f90565b7f1f27220b000000000000000000000000000000000000000000000000000000008651948501528460248501526044840152604483526080830190838210908211176111a757611775945260601c612288565b5f8080808080611718565b61179e8260011c809303926117976080840161139e565b89886121d6565b507f3077f64f92ad91c6479071531304fa3c1e0bb9b63e130c746f3a564292f0ddc6868951898152a16116d4565b5050505050505050600290565b60048a51635c49863b60e11b8152fd5b6004865163d3e0741d60e01b8152fd5b50505050915050600190565b6001600160a01b03611815611a8c565b165f52600360205260405f205f805260205260405f20348154019055611467565b34611a5b575b805f5260019260209260018452604091825f2054611a53575f8552825f205495611865876121a4565b15611a4357845f526009865260ff845f205416611a43575f91855f925f61188b846113bf565b916001815b611998575b50505088815160051b9101200361198857855f5260098752845f20600160ff19825416179055156106da576118cf60806118d9940161139e565b91019084876121d6565b611908575b7fa1470b3e580ca86a806ba4cff90a8a7327f837f862b313e7c406aa942d62997e935051908152a1565b8051937f68ac31150000000000000000000000000000000000000000000000000000000084860152826024860152602485526060850185811067ffffffffffffffff8211176111a7577fa1470b3e580ca86a806ba4cff90a8a7327f837f862b313e7c406aa942d62997e95611983928592855260601c612288565b6118de565b60048551635c49863b60e11b8152fd5b9092935094909415611a2b575b5f906119c76119b587878b6113f1565b611558610136366115a18b8b8f6113f1565b905015611a0c575b9082809260a06119e089898d6113f1565b013501966119f661090c366115a1848b8f6113f1565b611a008288611410565b520191908a9493611890565b959082809260a0611a1e89898d6113f1565b01350197919250506119cf565b8884861015611a3a57506119a5565b92918195611895565b6004845163d3e0741d60e01b8152fd5b505050505050565b6001600160a01b03611a6b611a8c565b165f52600360205260405f205f805260205260405f2034815401905561183c565b335f526e2fd5aeb385d324b580fca7c83823a0803314611adc575b506dd9ecebf3c23529de49815dac1c4c803314611ac5575b505f5190565b5f80806020935afa15611ad8575f611abf565b3838fd5b5f80806020935afa15611ad8575f611aa7565b92916001600160a01b0380941693845f52600360205260405f20921691825f5260205260405f2054908181115f14611b53575080915b829483611b33575b50505050565b5f52600360205260405f20905f526020520360405f20555f808080611b2d565b91611b25565b91908115611be6576001600160a01b038116611b8d5750905f80809338935af115611b8057565b63b12d13eb5f526004601cfd5b916014526034526fa9059cbb0000000000000000000000005f5260205f6044601082855af1908160015f51141615611bc8575b50505f603452565b3b153d171015611bd9575f80611bc0565b6390b8ec185f526004601cfd5b505050565b604081015115611c90576001600160a01b03608060015b602084015115611c89576001905b7f80000000000000000000000000000000000000000000000000000000000000007fc000000000000000000000000000000000000000000000000000000000000000787fffffffff0000000000000000000000000000000000000000606088015160a01b169360fe1b169160ff1b161717920151161790565b5f90611c10565b6001600160a01b0360805f611c02565b6080906001600160a01b0381511690611cb881611beb565b9060c060a0820151910151916040519384526020840152604083015260608201522090565b611ce78282611d52565b60051c9160e0820192835110156106b757600192611d3a916001600160a01b038451165f52600660205260405f20905f5260205260405f2060a08401515f5260205260c060405f209301519051906113b2565b908160081c5f5260205260ff60405f205491161c1690565b6001600160a01b0391828251165f52600560205260405f20905f5260205260405f2060a08201515f5260205260c060405f209101515f5260205260405f20541680156106b7573b5f1981019081116109625790565b60e0611db282611ca0565b910151905f5260205260405f2090565b90611dcc82611beb565b611dd68184611cdd565b611e6c577fed034d9d62bb699c05145f178d69dcac2bbbe1b6ab1bb196ac35b5d0bd00e2d0916001600160a01b03808551165f526006602052604092835f20905f52602052825f2060a08601515f52602052825f209060c086019586519260e0820193845101908160081c5f52602052600160ff875f2092161b81541790555116945190510182519182526020820152a2600190565b5050505f90565b60405160208101904160601b8252486034820152466054820152426074820152436094820152434060b48201523260601b60d48201523a60e882015260e88152610120810181811067ffffffffffffffff8211176111a75760405251902090565b6001600160a01b03929183611ee88361139e565b165f52602060078152604092835f20835f528252835f2060a082013590815f528352845f209060c08301359460e084013592611f2484886113b2565b5f528552865f20549889155f14611f6a57611f41611f619561139e565b165f5260088552865f20905f528452855f20905f528352845f20936113b2565b5f52525f205490565b50505050505050508190565b90805f526020805f2090611f8d610136368661128c565b906001600160a01b0380611fa08761139e565b165f5260058252604092835f20905f528252825f2060a087013590815f528352835f209660c081013597885f52845282855f20541680156121945760e0820135968760051b88810487148915171561096257868101928382116109625788918483519561ffff8091101561218c575b5080821082820302926001840183601f8901833c8387015160ff1615612165575b50505080845283015f88820152019182885286815191015190878110612155575b500361212d5750612065610136368361128c565b9161207361090c368461128c565b9861207e8484611ed4565b501561209257505050505050505050905f90565b7f09826593bca8be99c4b448ea9fbf37d84e796f2ff2eb957e13e5dfe5f2a99afb9761211b94866120c28661139e565b165f5260078852885f20905f528752875f20835f528752875f2091015f52855287865f2055836120f18361139e565b165f5260038552855f20846121086080850161139e565b165f528552855f2090815401905561139e565b1693825191868352820152a290600190565b807f162c5b650000000000000000000000000000000000000000000000000000000060049252fd5b5f1990880360031b1b165f612051565b90600193913b5f1981019485918260281c3d3d3e83030191110290039111025f8080612030565b90505f61200f565b600486516321f9f13f60e11b8152fd5b60018160091c16155f146121d057435b65ffffffffffff633fffffff83600a1c169260301c1690031190565b426121b4565b929190916001808560601c95865f5260036020526001600160a01b0360405f20951694855f5260205260405f2061220e8582546113b2565b905560081c161461222157505050505f90565b604051917f0e4ee5e1000000000000000000000000000000000000000000000000000000006020840152836024840152604483015260648201526064815260a081019281841067ffffffffffffffff8511176111a75761228393604052612288565b600190565b91905f809160208151910182865af13d15612303573d6122a781611356565b906122b560405192836111d7565b81525f60203d92013e5b156122c8575050565b7f202ffa0caf210a1fc7ab8dc523280304749f65bbccedb81fd502a8fd51a6c77d916040916001600160a01b038351921682526020820152a1565b6122bf565b602460106020939284936014526f70a082310000000000000000000000005f525afa601f3d1116602051029056fea2646970667358221220904b80c047e07634a01281342f943d2da8fec0753ed0c87ffa7e7b2980a6279f64736f6c63430008190033

Deployed ByteCode

0x60806040526004361015610011575f80fd5b5f3560e01c806302a381bf14610f9e5780630cf9dff714610e9b5780632f93018814610c3d57806338ee1b8e14610c0c5780636da844ea146109765780637e4a22cc1461072f5780637f5299bb1461036a578063a8d3600c14610292578063b90b4a87146101c5578063ba065e1f1461019d578063ce8c091514610163578063eca4ba70146100fa5763f7888aec146100a8575f80fd5b346100f65760403660031901126100f6576100c161114a565b6100c9611160565b906001600160a01b038091165f52600360205260405f2091165f52602052602060405f2054604051908152f35b5f80fd5b346100f6576101003660031901126100f65760206001600160a01b038061011f611372565b165f526005825260405f2061013b61013636611206565b611beb565b5f52825260405f2060a4355f52825260405f2060c4355f52825260405f205416604051908152f35b60403660031901126100f65760243567ffffffffffffffff81116100f65761019261019b91369060040161130d565b90600435611836565b005b346100f65760203660031901126100f65760206101bb6004356121a4565b6040519015158152f35b60603660031901126100f65767ffffffffffffffff6024358181116100f6576101f290369060040161130d565b6044929192359182116100f657366023830112156100f6578160040135926102198461133e565b9261022760405194856111d7565b8484526020946024602086019160051b830101913683116100f657602401905b8282106102835761025c86868660043561145d565b604051600382101561026f576020918152f35b634e487b7160e01b5f52602160045260245ffd5b81358152908601908601610247565b346100f65760603660031901126100f6576102ab61114a565b60243580151581036100f65760443580151581036100f6571561033d576102ea6102d3611424565b80516020918201205f19015f9081522060ff191690565b825f5260205260405f205c905b8115610309575b602082604051908152f35b905061032c576001600160a01b03165f526002602052602060405f2054826102fe565b600460405163d3e0741d60e01b8152fd5b6001600160a01b0382165f52600a60205260405f2061035a611e73565b5f5260205260405f2054906102f7565b6101603660031901126100f6576101003660231901126100f6576101243567ffffffffffffffff81116100f6576103a590369060040161130d565b61014435151561014435036100f6576103bf6004356113bf565b916103c8611a8c565b9034610705575b6001600160a01b036103df611388565b161561032c576004351580156106f9575b80156106ee575b61032c57608435647fffffffff8116036106b7575f925f905f9080156106da5761042560808597950161139e565b9360015b156106c8575b5f9061043c81848a6113f1565b6001600160a01b036104506080830161139e565b166001600160a01b038816036106b75760408101358015158091036100f657610477611401565b1515036106b7576084356060820135116106b75761049d610498368361128c565b611ca0565b6104b0816104ab368561128c565b611dc2565b6104c0575b505060010190610429565b60019296959160a0915f5260e08101356020528b6104e28860405f2092611410565b5201350193019384600435146104f95789806104b5565b505050919293505b6004351161032c5780151591826106a2575b5050905061067857805160051b60208092012061052e611388565b60443580151581036100f657610542611401565b15610671576001915b610553611401565b1561066a5742915b15610650576bffffffffffff000000000000657fffffffff8060015b865f525f885260081b9460843560011b1760091b169260301b16906bffffffffffffffffffffffff199060601b1617171760405f20556001600160a01b036105bd611388565b610144351561062c576105d16102d3611424565b815f5284528260405f205d5b165f52600282528060405f20556001600160a01b036105fa611388565b167f7a1cb491da9915d087844d867ad00ac476b12041d231adb7a04be595db91e44b83604051848152a2604051908152f35b8181165f52600a845260405f20610641611e73565b5f5284528260405f20556105dd565b6bffffffffffff000000000000657fffffffff805f610577565b439161055b565b5f9161054b565b60046040517f62128b04000000000000000000000000000000000000000000000000000000008152fd5b6106ae92508193611aef565b10808380610513565b60046040516321f9f13f60e11b8152fd5b81811061042f57505091929350610501565b634e487b7160e01b5f52603260045260245ffd5b5082600435116103f7565b5060ff600435116103f0565b6001600160a01b0382165f52600360205260405f205f805260205260405f203481540190556103cf565b366003190161012081126100f657610100136100f657610104356040516107558161118a565b600435906001600160a01b03808316928381036100f65782526024359384151585036100f6576020948584015260443580151581036100f6576040840152606435606084015260843582811681036100f657608084015260a435938460a085015260c435908160c08601526107d260e435958660e0820152611beb565b905f526005875260405f20905f52865260405f20855f52865260405f20815f5286528260405f20541680156106b7578460051b908582048814861517156109625787820191828111610962576040519261ffff8082101561095a575b5080821082820302926001840183601f8701833c8385015160ff1615610933575b50505080825281015f888201526040810190816040528883519301519289811061091f575b5060600190848252888152610888816111bb565b5190201461089257005b6108ee6040947fa8080584ebb92497a93bf0923d88f7a218d6b2b12e73938ec37157d8df9c561e96856108c3611372565b165f5260088952865f206108d961013636611206565b5f528952865f20905f528852855f20926113b2565b5f52855280835f20556108ff611372565b9061091161090c36611206565b611da7565b9584519687528601521692a2005b5f19908a0360031b1b909216916060610874565b90600193913b5f1981019485918260281c3d3d3e830301911102900391110288808061084f565b90508a61082e565b634e487b7160e01b5f52601160045260245ffd5b6101003660031901126100f65761098c36611206565b610994611a8c565b9034610be2575b6001600160a01b038151166001600160a01b03831603610bb857906109bf82611beb565b6109c98184611d52565b60051c926109d681611ca0565b5f9060c0830151958601905f946001600160a01b038551165f52600660205260405f20905f5260205260405f2060a08501515f5260205260405f209460015b15610b42575b5f978115610b33575b8382820111610b29575b81610100038160081c5f528760205260405f208054915f19811c9083868601610100031b901c10610a67575b5050019661010090610a15565b93989194839698919a9360ff8716908189810197610101891015610ae3575b5060405f20915f1990610100031c901b81541790559960015b15610aca575b5f9a60018d821c1615610abc575b6001019a610a9f565b60a08a0151909a0199610ab3565b858b10610aa55794509491985096949198508980610a5a565b5f19821b8f179055890160ff811691505f90600160088b811c91820192901c015b808203610b1457505f528e610a86565b90806001915f525f1960405f20550190610b04565b8084039150610a2e565b60ff8116610100039150610a24565b828810610a1b578385838983610b5457005b6001600160a01b03916040519081527fbd86c8c76936132dbc24244b04f4607b8bc2b75dd1cb36379bbedeee254b9260602084841692a2165f5260036020526001600160a01b03608060405f20920151165f5260205260405f209081540190555f80f35b60046040517f10c74b03000000000000000000000000000000000000000000000000000000008152fd5b6001600160a01b0382165f52600360205260405f205f805260205260405f2034815401905561099b565b346100f6576101003660031901126100f65760206101bb610c2f61013636611206565b610c3836611206565b611cdd565b6101203660031901126100f657610c5336611206565b610104359067ffffffffffffffff8083116100f657366023840112156100f65782600401359081116100f65736602482850101116100f6578060051c9181158015610e8f575b6106b757610ca5611a8c565b9234610e65575b6001600160a01b0380941691825f526020936003855260405f20946080830195878751165f52815260405f205460a08401968751860280921061067857865f52600383528860405f209151165f52825260405f209081540390558683511697881561032c57610d1a84611beb565b93895f526004835260405f20855f52835260405f2088515f5283525f83604082205495806024610d4982611356565b96610d5760405198896111d7565b8288520183870137840101528151978860401b6bfe61000180600a3d393df3000161fffe8a11840152600b8901601584015ff0968715610e58577f0a0b08ec1802460e3e5a597cf64a8b64b588d0b0938df0adf5fc125781558d659a60809a610e3e95528c5f526005865260405f20885f52865260405f2083515f52865260405f20875f52865260405f20981697887fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790558501958b5f526004855260405f20905f52845260405f2090515f5283528460405f20558981528360c0820152611ca0565b90604051958652850152841b1760408301526060820152a2005b63301164255f526004601cfd5b6001600160a01b0384165f52600360205260405f205f805260205260405f20348154019055610cac565b50601f82161515610c99565b346100f6576020806003193601126100f657610100905f60e0604051610ec08161118a565b82815282848201528260408201528260608201528260808201528260a08201528260c082015201526004355f525f815260405f20546001808260081c1614908060601c926001815260405f20549260405191610f1b8361118a565b85835280830191808352604084019081526060840191647fffffffff8660091c168352608085019365ffffffffffff8760301c16855260e060a087019688885260ff60c0820199168952019788526040519889525115159088015251151560408701525160608601525160808501525160a08401525160c08301525160e0820152f35b60603660031901126100f657610fb261114a565b610fba611160565b60443591610fc6611a8c565b6001600160a01b0391808316611144575080935b5f81121561112d575f03908284169384155f1461101c57505034106106785734925b165f52600360205260405f20905f5260205260405f209081540190555f80f35b90916110283083612308565b9260405190826060523060405260601b80602c526f23b872dd000000000000000000000000600c5260205f6064601c82885af18060015f51141615611122575b5f606052826040521561108b575b505050611084903090612308565b0392610ffc565b86607483015282605483015230603483015260208201526f36c785160000000000000000000000008152600146148015611109575b5f90843b15109160846010389201836e22d473030f116ddee9f6b43ac78ba35af116156110ee578080611076565b600490677939f4248757f0fd5f5260a01c151560021b601801fd5b506e22d473030f116ddee9f6b43ac78ba33b15156110c0565b3d853b151710611068565b8361019b9594935061113e92611aef565b91611b59565b93610fda565b600435906001600160a01b03821682036100f657565b602435906001600160a01b03821682036100f657565b35906001600160a01b03821682036100f657565b610100810190811067ffffffffffffffff8211176111a757604052565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176111a757604052565b90601f8019910116810190811067ffffffffffffffff8211176111a757604052565b359081151582036100f657565b6101009060031901126100f657604051906112208261118a565b816001600160a01b0360043581811681036100f657825260243580151581036100f657602083015260443580151581036100f6576040830152606435606083015260843590811681036100f657608082015260a43560a082015260c43560c082015260e060e435910152565b9190826101009103126100f6576040516112a58161118a565b60e08082946112b381611176565b84526112c1602082016111f9565b60208501526112d2604082016111f9565b6040850152606081013560608501526112ed60808201611176565b608085015260a081013560a085015260c081013560c08501520135910152565b9181601f840112156100f65782359167ffffffffffffffff83116100f6576020808501948460081b0101116100f657565b67ffffffffffffffff81116111a75760051b60200190565b67ffffffffffffffff81116111a757601f01601f191660200190565b6004356001600160a01b03811681036100f65790565b6024356001600160a01b03811681036100f65790565b356001600160a01b03811681036100f65790565b9190820180921161096257565b906113c98261133e565b6113d660405191826111d7565b82815280926113e7601f199161133e565b0190602036910137565b91908110156106da5760081b0190565b60643580151581036100f65790565b80518210156106da5760209160051b010190565b60405190611431826111bb565b600682527f72616e646f6d00000000000000000000000000000000000000000000000000006020830152565b9391909334611805575b805f52602060018152604094855f20546117f9576009825260ff865f2054166117e9575f9695945f95845f525f8452805f2054946114a4876113bf565b945f965f9b60015b156115f7575b908b9c918b8b5f9e8b8b6114c68582611410565b511561152b57906114f96114f186936114ea856114e4818a8a6113f1565b92611410565b5190611f76565b939092611410565b52611520575b6001939260a09261150f926113f1565b0135019b019b9c9b9a90919c6114ac565b6001909c019b6114ff565b6115708561155e6115408288889d979d6113f1565b611558610136611551858b8b6113f1565b369061128c565b90611ed4565b939061156a8383611410565b52611410565b516115d3578c816115ac575050506001939260a09261150f9286986115a6846114e461090c366115a18489896113f1565b61128c565b526113f1565b856114f99181949a61156a6115cb866115c6868c8c6113f1565b611f76565b979092611410565b50959260a09261150f92600196956115a6846114e461090c366115a18489896113f1565b898b106114b257949b9792995090979492999588815160051b91012089036117d9570194875f525f875285895f20556117cc5785815160051b910120916001865282885f20557f46adc4912184d61bbcd0939b961e9388a3fa9122b827b48b36fdf552759f3e7d8880518981528589820152a1825f5260018652875f2054938851918783019567ffffffffffffffff96848110888211176111a7578b5283525b87832080845281805f03068110156116af5750611697565b6116bd9350819006916113f1565b865f525f86526116cf885f20546121a4565b611780575b6001600160a01b03806116e68361139e565b165f52600387526116fc60808a5f20930161139e565b165f528552865f209081540190556001808460081c1614611722575b5050505050505f90565b7f1f27220b000000000000000000000000000000000000000000000000000000008651948501528460248501526044840152604483526080830190838210908211176111a757611775945260601c612288565b5f8080808080611718565b61179e8260011c809303926117976080840161139e565b89886121d6565b507f3077f64f92ad91c6479071531304fa3c1e0bb9b63e130c746f3a564292f0ddc6868951898152a16116d4565b5050505050505050600290565b60048a51635c49863b60e11b8152fd5b6004865163d3e0741d60e01b8152fd5b50505050915050600190565b6001600160a01b03611815611a8c565b165f52600360205260405f205f805260205260405f20348154019055611467565b34611a5b575b805f5260019260209260018452604091825f2054611a53575f8552825f205495611865876121a4565b15611a4357845f526009865260ff845f205416611a43575f91855f925f61188b846113bf565b916001815b611998575b50505088815160051b9101200361198857855f5260098752845f20600160ff19825416179055156106da576118cf60806118d9940161139e565b91019084876121d6565b611908575b7fa1470b3e580ca86a806ba4cff90a8a7327f837f862b313e7c406aa942d62997e935051908152a1565b8051937f68ac31150000000000000000000000000000000000000000000000000000000084860152826024860152602485526060850185811067ffffffffffffffff8211176111a7577fa1470b3e580ca86a806ba4cff90a8a7327f837f862b313e7c406aa942d62997e95611983928592855260601c612288565b6118de565b60048551635c49863b60e11b8152fd5b9092935094909415611a2b575b5f906119c76119b587878b6113f1565b611558610136366115a18b8b8f6113f1565b905015611a0c575b9082809260a06119e089898d6113f1565b013501966119f661090c366115a1848b8f6113f1565b611a008288611410565b520191908a9493611890565b959082809260a0611a1e89898d6113f1565b01350197919250506119cf565b8884861015611a3a57506119a5565b92918195611895565b6004845163d3e0741d60e01b8152fd5b505050505050565b6001600160a01b03611a6b611a8c565b165f52600360205260405f205f805260205260405f2034815401905561183c565b335f526e2fd5aeb385d324b580fca7c83823a0803314611adc575b506dd9ecebf3c23529de49815dac1c4c803314611ac5575b505f5190565b5f80806020935afa15611ad8575f611abf565b3838fd5b5f80806020935afa15611ad8575f611aa7565b92916001600160a01b0380941693845f52600360205260405f20921691825f5260205260405f2054908181115f14611b53575080915b829483611b33575b50505050565b5f52600360205260405f20905f526020520360405f20555f808080611b2d565b91611b25565b91908115611be6576001600160a01b038116611b8d5750905f80809338935af115611b8057565b63b12d13eb5f526004601cfd5b916014526034526fa9059cbb0000000000000000000000005f5260205f6044601082855af1908160015f51141615611bc8575b50505f603452565b3b153d171015611bd9575f80611bc0565b6390b8ec185f526004601cfd5b505050565b604081015115611c90576001600160a01b03608060015b602084015115611c89576001905b7f80000000000000000000000000000000000000000000000000000000000000007fc000000000000000000000000000000000000000000000000000000000000000787fffffffff0000000000000000000000000000000000000000606088015160a01b169360fe1b169160ff1b161717920151161790565b5f90611c10565b6001600160a01b0360805f611c02565b6080906001600160a01b0381511690611cb881611beb565b9060c060a0820151910151916040519384526020840152604083015260608201522090565b611ce78282611d52565b60051c9160e0820192835110156106b757600192611d3a916001600160a01b038451165f52600660205260405f20905f5260205260405f2060a08401515f5260205260c060405f209301519051906113b2565b908160081c5f5260205260ff60405f205491161c1690565b6001600160a01b0391828251165f52600560205260405f20905f5260205260405f2060a08201515f5260205260c060405f209101515f5260205260405f20541680156106b7573b5f1981019081116109625790565b60e0611db282611ca0565b910151905f5260205260405f2090565b90611dcc82611beb565b611dd68184611cdd565b611e6c577fed034d9d62bb699c05145f178d69dcac2bbbe1b6ab1bb196ac35b5d0bd00e2d0916001600160a01b03808551165f526006602052604092835f20905f52602052825f2060a08601515f52602052825f209060c086019586519260e0820193845101908160081c5f52602052600160ff875f2092161b81541790555116945190510182519182526020820152a2600190565b5050505f90565b60405160208101904160601b8252486034820152466054820152426074820152436094820152434060b48201523260601b60d48201523a60e882015260e88152610120810181811067ffffffffffffffff8211176111a75760405251902090565b6001600160a01b03929183611ee88361139e565b165f52602060078152604092835f20835f528252835f2060a082013590815f528352845f209060c08301359460e084013592611f2484886113b2565b5f528552865f20549889155f14611f6a57611f41611f619561139e565b165f5260088552865f20905f528452855f20905f528352845f20936113b2565b5f52525f205490565b50505050505050508190565b90805f526020805f2090611f8d610136368661128c565b906001600160a01b0380611fa08761139e565b165f5260058252604092835f20905f528252825f2060a087013590815f528352835f209660c081013597885f52845282855f20541680156121945760e0820135968760051b88810487148915171561096257868101928382116109625788918483519561ffff8091101561218c575b5080821082820302926001840183601f8901833c8387015160ff1615612165575b50505080845283015f88820152019182885286815191015190878110612155575b500361212d5750612065610136368361128c565b9161207361090c368461128c565b9861207e8484611ed4565b501561209257505050505050505050905f90565b7f09826593bca8be99c4b448ea9fbf37d84e796f2ff2eb957e13e5dfe5f2a99afb9761211b94866120c28661139e565b165f5260078852885f20905f528752875f20835f528752875f2091015f52855287865f2055836120f18361139e565b165f5260038552855f20846121086080850161139e565b165f528552855f2090815401905561139e565b1693825191868352820152a290600190565b807f162c5b650000000000000000000000000000000000000000000000000000000060049252fd5b5f1990880360031b1b165f612051565b90600193913b5f1981019485918260281c3d3d3e83030191110290039111025f8080612030565b90505f61200f565b600486516321f9f13f60e11b8152fd5b60018160091c16155f146121d057435b65ffffffffffff633fffffff83600a1c169260301c1690031190565b426121b4565b929190916001808560601c95865f5260036020526001600160a01b0360405f20951694855f5260205260405f2061220e8582546113b2565b905560081c161461222157505050505f90565b604051917f0e4ee5e1000000000000000000000000000000000000000000000000000000006020840152836024840152604483015260648201526064815260a081019281841067ffffffffffffffff8511176111a75761228393604052612288565b600190565b91905f809160208151910182865af13d15612303573d6122a781611356565b906122b560405192836111d7565b81525f60203d92013e5b156122c8575050565b7f202ffa0caf210a1fc7ab8dc523280304749f65bbccedb81fd502a8fd51a6c77d916040916001600160a01b038351921682526020820152a1565b6122bf565b602460106020939284936014526f70a082310000000000000000000000005f525afa601f3d1116602051029056fea2646970667358221220904b80c047e07634a01281342f943d2da8fec0753ed0c87ffa7e7b2980a6279f64736f6c63430008190033