ETH Price: $2,524.30 (+1.16%)

Transaction Decoder

Block:
17685381 at Jul-13-2023 03:11:35 PM +UTC
Transaction Fee:
0.00091842783190808 ETH $2.32
Gas Used:
44,720 Gas / 20.537294989 Gwei

Emitted Events:

197 MultiAuction.BidMade( tokenId=52, bidder=[Sender] 0x19e95da754e77cb643534fd070b172da74a465ee, amount=440000000000000000, timestamp=1689261095 )

Account State Difference:

  Address   Before After State Difference Code
0x19E95Da7...a74A465Ee
0.986715803594059306 Eth
Nonce: 1491
0.545797375762151226 Eth
Nonce: 1492
0.44091842783190808
1.415480750433236665 Eth1.415525470433236665 Eth0.00004472
0x5Fae9D4B...883D17f7A 0.231812812450943867 Eth0.627812812450943867 Eth0.396
0xCaA9d6cD...6E9ff9fC2 59.59717499999999996 Eth59.64117499999999996 Eth0.044

Execution Trace

ETH 0.44 MultiAuction.bid( tokenId=52 )
  • ETH 0.396 0x5fae9d4b591f213b3ba75287f2cfac0883d17f7a.CALL( )
    // File: .deps/MultiAuction 6/libs/SafeTransferLib.sol
    
    
    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)
    ///
    /// @dev Note:
    /// - For ETH transfers, please use `forceSafeTransferETH` for gas griefing protection.
    /// - For ERC20s, this implementation won't check that a token has code,
    /// responsibility is delegated to the caller.
    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();
    
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                         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.
        /// Multiply by a small constant (e.g. 2), if needed.
        uint256 internal constant _GAS_STIPEND_NO_GRIEF = 100000;
    
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                       ETH OPERATIONS                       */
        /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
    
        /// @dev Sends `amount` (in wei) ETH to `to`.
        /// Reverts upon failure.
        ///
        /// Note: This implementation does NOT protect against gas griefing.
        /// Please use `forceSafeTransferETH` for gas griefing protection.
        function safeTransferETH(address to, uint256 amount) internal {
            /// @solidity memory-safe-assembly
            assembly {
                // Transfer the ETH and check if it succeeded or not.
                if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {
                    // Store the function selector of `ETHTransferFailed()`.
                    mstore(0x00, 0xb12d13eb)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
            }
        }
    
        /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
        /// The `gasStipend` can be set to a low enough value to prevent
        /// storage writes or gas griefing.
        ///
        /// If sending via the normal procedure fails, force sends the ETH by
        /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
        ///
        /// Reverts if the current contract has insufficient balance.
        function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
            /// @solidity memory-safe-assembly
            assembly {
                // If insufficient balance, revert.
                if lt(selfbalance(), amount) {
                    // Store the function selector of `ETHTransferFailed()`.
                    mstore(0x00, 0xb12d13eb)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
                // Transfer the ETH and check if it succeeded or not.
                if iszero(call(gasStipend, to, amount, 0, 0, 0, 0)) {
                    mstore(0x00, to) // Store the address in scratch space.
                    mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                    mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                    // We can directly use `SELFDESTRUCT` in the contract creation.
                    // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758
                    if iszero(create(amount, 0x0b, 0x16)) {
                        // To coerce gas estimation to provide enough gas for the `create` above.
                        if iszero(gt(gas(), 1000000)) { revert(0, 0) }
                    }
                }
            }
        }
    
        /// @dev Force sends `amount` (in wei) ETH to `to`, with a gas stipend
        /// equal to `_GAS_STIPEND_NO_GRIEF`. This gas stipend is a reasonable default
        /// for 99% of cases and can be overridden with the three-argument version of this
        /// function if necessary.
        ///
        /// If sending via the normal procedure fails, force sends the ETH by
        /// creating a temporary contract which uses `SELFDESTRUCT` to force send the ETH.
        ///
        /// Reverts if the current contract has insufficient balance.
        function forceSafeTransferETH(address to, uint256 amount) internal {
            // Manually inlined because the compiler doesn't inline functions with branches.
            /// @solidity memory-safe-assembly
            assembly {
                // If insufficient balance, revert.
                if lt(selfbalance(), amount) {
                    // Store the function selector of `ETHTransferFailed()`.
                    mstore(0x00, 0xb12d13eb)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
                // Transfer the ETH and check if it succeeded or not.
                if iszero(call(_GAS_STIPEND_NO_GRIEF, to, amount, 0, 0, 0, 0)) {
                    mstore(0x00, to) // Store the address in scratch space.
                    mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                    mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                    // We can directly use `SELFDESTRUCT` in the contract creation.
                    // Compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758
                    if iszero(create(amount, 0x0b, 0x16)) {
                        // To coerce gas estimation to provide enough gas for the `create` above.
                        if iszero(gt(gas(), 1000000)) { revert(0, 0) }
                    }
                }
            }
        }
    
        /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
        /// The `gasStipend` can be set to a low enough value to prevent
        /// storage writes or gas griefing.
        ///
        /// Simply use `gasleft()` for `gasStipend` if you don't need a gas stipend.
        ///
        /// Note: Does NOT revert upon failure.
        /// Returns whether the transfer of ETH is successful instead.
        function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
            internal
            returns (bool success)
        {
            /// @solidity memory-safe-assembly
            assembly {
                // Transfer the ETH and check if it succeeded or not.
                success := call(gasStipend, to, amount, 0, 0, 0, 0)
            }
        }
    
        /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
        /*                      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.
                // Store the function selector of `transferFrom(address,address,uint256)`.
                mstore(0x0c, 0x23b872dd000000000000000000000000)
    
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        // Set success to whether the call reverted, if not we check it either
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
                        or(eq(mload(0x00), 1), iszero(returndatasize())),
                        call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                    )
                ) {
                    // Store the function selector of `TransferFromFailed()`.
                    mstore(0x00, 0x7939f424)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
    
                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.
                // Store the function selector of `balanceOf(address)`.
                mstore(0x0c, 0x70a08231000000000000000000000000)
                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)
                    )
                ) {
                    // Store the function selector of `TransferFromFailed()`.
                    mstore(0x00, 0x7939f424)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
    
                // Store the function selector of `transferFrom(address,address,uint256)`.
                mstore(0x00, 0x23b872dd)
                // The `amount` argument is already written to the memory word at 0x60.
                amount := mload(0x60)
    
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        // Set success to whether the call reverted, if not we check it either
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
                        or(eq(mload(0x00), 1), iszero(returndatasize())),
                        call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
                    )
                ) {
                    // Store the function selector of `TransferFromFailed()`.
                    mstore(0x00, 0x7939f424)
                    // Revert with (offset, size).
                    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.
                // Store the function selector of `transfer(address,uint256)`.
                mstore(0x00, 0xa9059cbb000000000000000000000000)
    
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        // Set success to whether the call reverted, if not we check it either
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
                        or(eq(mload(0x00), 1), iszero(returndatasize())),
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    // Store the function selector of `TransferFailed()`.
                    mstore(0x00, 0x90b8ec18)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
                // Restore the part of the free memory pointer that was overwritten.
                mstore(0x34, 0)
            }
        }
    
        /// @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.
                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)
                    )
                ) {
                    // Store the function selector of `TransferFailed()`.
                    mstore(0x00, 0x90b8ec18)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
    
                mstore(0x14, to) // Store the `to` argument.
                // The `amount` argument is already written to the memory word at 0x34.
                amount := mload(0x34)
                // Store the function selector of `transfer(address,uint256)`.
                mstore(0x00, 0xa9059cbb000000000000000000000000)
    
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        // Set success to whether the call reverted, if not we check it either
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
                        or(eq(mload(0x00), 1), iszero(returndatasize())),
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    // Store the function selector of `TransferFailed()`.
                    mstore(0x00, 0x90b8ec18)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
                // Restore the part of the free memory pointer that was overwritten.
                mstore(0x34, 0)
            }
        }
    
        /// @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.
                // Store the function selector of `approve(address,uint256)`.
                mstore(0x00, 0x095ea7b3000000000000000000000000)
    
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        // Set success to whether the call reverted, if not we check it either
                        // returned exactly 1 (can't just be non-zero data), or had no return data.
                        or(eq(mload(0x00), 1), iszero(returndatasize())),
                        call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    )
                ) {
                    // Store the function selector of `ApproveFailed()`.
                    mstore(0x00, 0x3e3f8f73)
                    // Revert with (offset, size).
                    revert(0x1c, 0x04)
                }
                // Restore the part of the free memory pointer that was overwritten.
                mstore(0x34, 0)
            }
        }
    
        /// @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.
                // Store the function selector of `balanceOf(address)`.
                mstore(0x00, 0x70a08231000000000000000000000000)
                amount :=
                    mul(
                        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)
                        )
                    )
            }
        }
    }
    // File: .deps/MultiAuction 6/libs/MerkleProofLib.sol
    
    
    pragma solidity >=0.8.0;
    
    /// @notice Gas optimized merkle proof verification library.
    /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/MerkleProofLib.sol)
    /// @author Modified from Solady (https://github.com/Vectorized/solady/blob/main/src/utils/MerkleProofLib.sol)
    library MerkleProofLib {
        function verify(
            bytes32[] calldata proof,
            bytes32 root,
            bytes32 leaf
        ) internal pure returns (bool isValid) {
            /// @solidity memory-safe-assembly
            assembly {
                if proof.length {
                    // Left shifting by 5 is like multiplying by 32.
                    let end := add(proof.offset, shl(5, proof.length))
    
                    // Initialize offset to the offset of the proof in calldata.
                    let offset := proof.offset
    
                    // Iterate over proof elements to compute root hash.
                    // prettier-ignore
                    for {} 1 {} {
                        // Slot where the leaf should be put in scratch space. If
                        // leaf > calldataload(offset): slot 32, otherwise: slot 0.
                        let leafSlot := shl(5, gt(leaf, calldataload(offset)))
    
                        // Store elements to hash contiguously in scratch space.
                        // The xor puts calldataload(offset) in whichever slot leaf
                        // is not occupying, so 0 if leafSlot is 32, and 32 otherwise.
                        mstore(leafSlot, leaf)
                        mstore(xor(leafSlot, 32), calldataload(offset))
    
                        // Reuse leaf to store the hash to reduce stack operations.
                        leaf := keccak256(0, 64) // Hash both slots of scratch space.
    
                        offset := add(offset, 32) // Shift 1 word per cycle.
    
                        // prettier-ignore
                        if iszero(lt(offset, end)) { break }
                    }
                }
    
                isValid := eq(leaf, root) // The proof is valid if the roots match.
            }
        }
    }
    // File: .deps/MultiAuction 6/interfaces/IDelegationRegistry.sol
    
    
    pragma solidity ^0.8.17;
    
    /**
     * @title An immutable registry contract to be deployed as a standalone primitive
     * @dev See EIP-5639, new project launches can read previous cold wallet -> hot wallet delegations
     * from here and integrate those permissions into their flow
     */
    interface IDelegationRegistry {
        /// @notice Delegation type
        enum DelegationType {
            NONE,
            ALL,
            CONTRACT,
            TOKEN
        }
    
        /// @notice Info about a single delegation, used for onchain enumeration
        struct DelegationInfo {
            DelegationType type_;
            address vault;
            address delegate;
            address contract_;
            uint256 tokenId;
        }
    
        /// @notice Info about a single contract-level delegation
        struct ContractDelegation {
            address contract_;
            address delegate;
        }
    
        /// @notice Info about a single token-level delegation
        struct TokenDelegation {
            address contract_;
            uint256 tokenId;
            address delegate;
        }
    
        /// @notice Emitted when a user delegates their entire wallet
        event DelegateForAll(address vault, address delegate, bool value);
    
        /// @notice Emitted when a user delegates a specific contract
        event DelegateForContract(address vault, address delegate, address contract_, bool value);
    
        /// @notice Emitted when a user delegates a specific token
        event DelegateForToken(address vault, address delegate, address contract_, uint256 tokenId, bool value);
    
        /// @notice Emitted when a user revokes all delegations
        event RevokeAllDelegates(address vault);
    
        /// @notice Emitted when a user revoes all delegations for a given delegate
        event RevokeDelegate(address vault, address delegate);
    
        /**
         * -----------  WRITE -----------
         */
    
        /**
         * @notice Allow the delegate to act on your behalf for all contracts
         * @param delegate The hotwallet to act on your behalf
         * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
         */
        function delegateForAll(address delegate, bool value) external;
    
        /**
         * @notice Allow the delegate to act on your behalf for a specific contract
         * @param delegate The hotwallet to act on your behalf
         * @param contract_ The address for the contract you're delegating
         * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
         */
        function delegateForContract(address delegate, address contract_, bool value) external;
    
        /**
         * @notice Allow the delegate to act on your behalf for a specific token
         * @param delegate The hotwallet to act on your behalf
         * @param contract_ The address for the contract you're delegating
         * @param tokenId The token id for the token you're delegating
         * @param value Whether to enable or disable delegation for this address, true for setting and false for revoking
         */
        function delegateForToken(address delegate, address contract_, uint256 tokenId, bool value) external;
    
        /**
         * @notice Revoke all delegates
         */
        function revokeAllDelegates() external;
    
        /**
         * @notice Revoke a specific delegate for all their permissions
         * @param delegate The hotwallet to revoke
         */
        function revokeDelegate(address delegate) external;
    
        /**
         * @notice Remove yourself as a delegate for a specific vault
         * @param vault The vault which delegated to the msg.sender, and should be removed
         */
        function revokeSelf(address vault) external;
    
        /**
         * -----------  READ -----------
         */
    
        /**
         * @notice Returns all active delegations a given delegate is able to claim on behalf of
         * @param delegate The delegate that you would like to retrieve delegations for
         * @return info Array of DelegationInfo structs
         */
        function getDelegationsByDelegate(address delegate) external view returns (DelegationInfo[] memory);
    
        /**
         * @notice Returns an array of wallet-level delegates for a given vault
         * @param vault The cold wallet who issued the delegation
         * @return addresses Array of wallet-level delegates for a given vault
         */
        function getDelegatesForAll(address vault) external view returns (address[] memory);
    
        /**
         * @notice Returns an array of contract-level delegates for a given vault and contract
         * @param vault The cold wallet who issued the delegation
         * @param contract_ The address for the contract you're delegating
         * @return addresses Array of contract-level delegates for a given vault and contract
         */
        function getDelegatesForContract(address vault, address contract_) external view returns (address[] memory);
    
        /**
         * @notice Returns an array of contract-level delegates for a given vault's token
         * @param vault The cold wallet who issued the delegation
         * @param contract_ The address for the contract holding the token
         * @param tokenId The token id for the token you're delegating
         * @return addresses Array of contract-level delegates for a given vault's token
         */
        function getDelegatesForToken(address vault, address contract_, uint256 tokenId)
            external
            view
            returns (address[] memory);
    
        /**
         * @notice Returns all contract-level delegations for a given vault
         * @param vault The cold wallet who issued the delegations
         * @return delegations Array of ContractDelegation structs
         */
        function getContractLevelDelegations(address vault)
            external
            view
            returns (ContractDelegation[] memory delegations);
    
        /**
         * @notice Returns all token-level delegations for a given vault
         * @param vault The cold wallet who issued the delegations
         * @return delegations Array of TokenDelegation structs
         */
        function getTokenLevelDelegations(address vault) external view returns (TokenDelegation[] memory delegations);
    
        /**
         * @notice Returns true if the address is delegated to act on the entire vault
         * @param delegate The hotwallet to act on your behalf
         * @param vault The cold wallet who issued the delegation
         */
        function checkDelegateForAll(address delegate, address vault) external view returns (bool);
    
        /**
         * @notice Returns true if the address is delegated to act on your behalf for a token contract or an entire vault
         * @param delegate The hotwallet to act on your behalf
         * @param contract_ The address for the contract you're delegating
         * @param vault The cold wallet who issued the delegation
         */
        function checkDelegateForContract(address delegate, address vault, address contract_)
            external
            view
            returns (bool);
    
        /**
         * @notice Returns true if the address is delegated to act on your behalf for a specific token, the token's contract or an entire vault
         * @param delegate The hotwallet to act on your behalf
         * @param contract_ The address for the contract you're delegating
         * @param tokenId The token id for the token you're delegating
         * @param vault The cold wallet who issued the delegation
         */
        function checkDelegateForToken(address delegate, address vault, address contract_, uint256 tokenId)
            external
            view
            returns (bool);
    }
    // File: .deps/MultiAuction 6/MultiAuction.sol
    
    
    
    pragma solidity ^0.8.17;
    
    
    
    
    contract MultiAuction {
      uint256 private constant BPS = 10_000;
      address private constant DELEGATION_REGISTRY = 0x00000000000076A84feF008CDAbe6409d2FE638B;
      address private constant FPP = 0xA8A425864dB32fCBB459Bf527BdBb8128e6abF21;
      uint256 private constant FPP_PROJECT_ID = 3;
      uint256 private constant MIN_BID = 0.01 ether;
      uint256 private constant MIN_BID_INCREASE = 1_000;
      uint256 private constant MINT_PASS_REBATE = 1_500;
      uint256 private constant SAFE_GAS_LIMIT = 30_000;
      IBaseContract public immutable BASE_CONTRACT;
      uint256 public immutable MAX_SUPPLY;
    
    
      uint256 public auctionStartTime;
      address public beneficiary1;
      address public beneficiary2;
      bool public paused;
      bytes32 public settlementRoot;
    
      struct Auction {
        uint24 offsetFromEnd;
        uint72 amount;
        address bidder;
      }
    
      mapping(uint256 => Auction) public tokenIdToAuction;
    
      event BidMade(uint256 indexed tokenId, address bidder, uint256 amount, uint256 timestamp);
      event Settled(uint256 indexed tokenId, uint256 timestamp);
    
      constructor(
        address baseContract,
        uint256 startTime,
        uint256 maxSupply
      ) {
        BASE_CONTRACT = IBaseContract(baseContract);
        auctionStartTime = startTime;
        MAX_SUPPLY = maxSupply;
        beneficiary1 = msg.sender;
        beneficiary2 = msg.sender;
      }
    
      function bid(
        uint256 tokenId
      ) external payable {
        require(!paused, 'Bidding is paused');
        require(isAuctionActive(tokenId), 'Auction Inactive');
        require(0 < tokenId && tokenId <= MAX_SUPPLY, 'Invalid tokenId');
    
        Auction memory highestBid = tokenIdToAuction[tokenId];
    
        require(
          msg.value >= (highestBid.amount * (BPS + MIN_BID_INCREASE) / BPS)
          && msg.value >= MIN_BID,
          'Bid not high enough'
        );
    
        uint256 refundAmount;
        address refundBidder;
        uint256 offset = highestBid.offsetFromEnd;
        uint256 endTime = auctionEndTime(tokenId);
    
        if (highestBid.amount > 0) {
          refundAmount = highestBid.amount;
          refundBidder = highestBid.bidder;
        }
    
        if (endTime - block.timestamp < 15 minutes) {
          offset += block.timestamp + 15 minutes - endTime;
        }
    
        tokenIdToAuction[tokenId] = Auction(uint24(offset), uint72(msg.value), msg.sender);
    
        emit BidMade(tokenId, msg.sender, msg.value, block.timestamp);
    
        if (refundAmount > 0) {
          SafeTransferLib.forceSafeTransferETH(refundBidder, refundAmount, SAFE_GAS_LIMIT);
        }
      }
    
      function bidOnFavs(
        uint256[] calldata favorites,
        uint256[] calldata expectedPrices
      ) external payable {
        require(!paused, 'Bidding is paused');
        require(favorites.length == expectedPrices.length);
    
        uint256 totalFailed; uint256 expectedTotal;
        for(uint256 i; i < favorites.length; ++i) {
          uint256 tokenId = favorites[i];
          uint256 expectedPrice = expectedPrices[i];
          expectedTotal += expectedPrice;
          require(0 < tokenId && tokenId <= MAX_SUPPLY, 'Invalid tokenId');
          if(!isAuctionActive(tokenId)) {
            totalFailed += expectedPrice;
            break;
          }
    
          Auction memory highestBid = tokenIdToAuction[tokenId];
          if (
            expectedPrice >= (highestBid.amount * (BPS + MIN_BID_INCREASE) / BPS)
            && expectedPrice >= MIN_BID
          ) {
            uint256 refundAmount;
            address refundBidder;
            uint256 offset = highestBid.offsetFromEnd;
            uint256 endTime = auctionEndTime(tokenId);
    
            if (highestBid.amount > 0) {
              refundAmount = highestBid.amount;
              refundBidder = highestBid.bidder;
            }
    
            if (endTime - block.timestamp < 15 minutes) {
              offset += block.timestamp + 15 minutes - endTime;
            }
    
            tokenIdToAuction[tokenId] = Auction(uint24(offset), uint72(expectedPrice), msg.sender);
    
            emit BidMade(tokenId, msg.sender, expectedPrice, block.timestamp);
    
            if (refundAmount > 0) {
              SafeTransferLib.forceSafeTransferETH(refundBidder, refundAmount, SAFE_GAS_LIMIT);
            }
          } else{
            totalFailed += expectedPrice;
          }
        }
    
        require(msg.value >= expectedTotal);
        if (totalFailed > 0) {
          SafeTransferLib.forceSafeTransferETH(msg.sender, totalFailed, SAFE_GAS_LIMIT);
        }
      }
    
      function settleAuction(
        uint256 tokenId,
        uint256 mintPassId,
        bytes32[] calldata proof
      ) external payable {
        require(settlementRoot != bytes32(0));
        Auction memory highestBid = tokenIdToAuction[tokenId];
        require(highestBid.bidder == msg.sender || owner() == msg.sender);
        require(0 < tokenId && tokenId <= MAX_SUPPLY, 'Invalid tokenId');
        require(isAuctionOver(tokenId), 'Auction for this tokenId is still active');
    
        uint256 amountToPay = highestBid.amount;
        if (amountToPay > 0) {
          BASE_CONTRACT.mint(highestBid.bidder, tokenId);
        } else {
          require(msg.sender == owner(), 'Ownable: caller is not the owner');
          require(msg.value >= MIN_BID, 'Bid not high enough');
          amountToPay = msg.value;
    
          BASE_CONTRACT.mint(msg.sender, tokenId);
        }
    
        uint256 totalRebate = 0;
        bool mintPassValid;
        if (mintPassId < 1_000) {
          address passHolder = IFPP(FPP).ownerOf(mintPassId);
          mintPassValid = mintPassId < 1_000 && IFPP(FPP).passUses(mintPassId, FPP_PROJECT_ID) < 1 && (
            passHolder == highestBid.bidder ||
            IDelegationRegistry(DELEGATION_REGISTRY).checkDelegateForToken(
              highestBid.bidder,
              passHolder,
              FPP,
              mintPassId
            )
          ) && (
            MerkleProofLib.verify(proof, settlementRoot, keccak256(abi.encodePacked(passHolder, mintPassId)))
          );
        }
    
        if (mintPassValid) {
          IFPP(FPP).logPassUse(mintPassId, FPP_PROJECT_ID);
          totalRebate = amountToPay * (MINT_PASS_REBATE) / BPS;
        }
    
        tokenIdToAuction[tokenId].bidder = address(0);
        emit Settled(tokenId, block.timestamp);
    
        if (totalRebate > 0) {
          SafeTransferLib.forceSafeTransferETH(highestBid.bidder, totalRebate, SAFE_GAS_LIMIT);
          SafeTransferLib.forceSafeTransferETH(beneficiary2, amountToPay - totalRebate, SAFE_GAS_LIMIT);
        } else {
          SafeTransferLib.forceSafeTransferETH(beneficiary1, amountToPay, SAFE_GAS_LIMIT);
        }
      }
    
      function settleAll(
        uint256 startId,
        uint256 endId,
        bytes calldata passData
      ) external payable onlyOwner {
        require(settlementRoot == bytes32(0), 'settleAll not active');
        require(passData.length == 2 * (endId - startId + 1), 'Invalid passData length');
        require(0 < startId && endId <= MAX_SUPPLY, 'Invalid tokenId');
    
        uint256 unclaimedCost; uint256 amountForBene1; uint256 amountForBene2;
        for (uint256 tokenId = startId; tokenId <= endId; ++tokenId) {
          Auction memory highestBid = tokenIdToAuction[tokenId];
          require(isAuctionOver(tokenId), 'Auction for this tokenId is still active');
    
          uint256 amountToPay = highestBid.amount;
          if (amountToPay > 0) {
            BASE_CONTRACT.mint(highestBid.bidder, tokenId);
          } else {
            amountToPay = MIN_BID;
            unclaimedCost += MIN_BID;
            BASE_CONTRACT.mint(msg.sender, tokenId);
          }
    
          uint256 totalRebate = 0;
          uint256 mintPassId = uint16(bytes2(passData[(tokenId - 1) * 2: tokenId * 2]));
          bool mintPassValid;
          if (mintPassId < 1_000) {
            address passHolder = IFPP(FPP).ownerOf(mintPassId);
            mintPassValid = mintPassId < 1_000 && IFPP(FPP).passUses(mintPassId, FPP_PROJECT_ID) < 1 && (
              passHolder == highestBid.bidder ||
              IDelegationRegistry(DELEGATION_REGISTRY).checkDelegateForToken(
                highestBid.bidder,
                passHolder,
                FPP,
                mintPassId
              )
            );
          }
      
          if (mintPassValid) {
            IFPP(FPP).logPassUse(mintPassId, FPP_PROJECT_ID);
            totalRebate = amountToPay * (MINT_PASS_REBATE) / BPS;
          }
      
          tokenIdToAuction[tokenId].bidder = address(0);
          emit Settled(tokenId, block.timestamp);
      
          if (totalRebate > 0) {
            SafeTransferLib.forceSafeTransferETH(highestBid.bidder, totalRebate, SAFE_GAS_LIMIT);
            amountForBene2 += amountToPay - totalRebate;
          } else {
            amountForBene1 += amountToPay;
          }
        }
    
        require(msg.value >= unclaimedCost, "Insufficient funds sent for unclaimed");
        SafeTransferLib.forceSafeTransferETH(beneficiary1, amountForBene1, SAFE_GAS_LIMIT);
        SafeTransferLib.forceSafeTransferETH(beneficiary2, amountForBene2, SAFE_GAS_LIMIT);
      }
    
      function owner() public view returns (address) {
        return BASE_CONTRACT.owner();
      }
    
      modifier onlyOwner {
        require(msg.sender == owner(), 'Ownable: caller is not the owner');
        _;
      }
    
      function emergencyWithdraw() external onlyOwner {
        require(block.timestamp > auctionStartTime + 48 hours);
        (bool success,) = msg.sender.call{value: address(this).balance}("");
        require(success);
      }
    
      function enableSelfSettlement(
        bytes32 root
      ) external onlyOwner {
        settlementRoot = root;
      }
    
      function rescheduele(
        uint256 newStartTime
      ) external onlyOwner {
        require(auctionStartTime > block.timestamp);
        auctionStartTime = newStartTime;
      }
    
      function setBeneficiary(
        address _beneficiary1,
        address _beneficiary2
      ) external onlyOwner {
        beneficiary1 = _beneficiary1;
        beneficiary2 = _beneficiary2;
      }
    
      function setPaused(
        bool _paused
      ) external onlyOwner {
        paused = _paused;
      }
    
      function auctionEndTime(
        uint256 tokenId
      ) public view returns (uint256) {
        return auctionStartTime + 24 hours + tokenIdToAuction[tokenId].offsetFromEnd;
      }
    
      function isAuctionActive(
        uint256 tokenId
      ) public view returns (bool) {
        uint256 endTime = auctionEndTime(tokenId);
        return (block.timestamp >= auctionStartTime && block.timestamp < endTime);
      }
    
      function isAuctionOver(
        uint256 tokenId
      ) public view returns (bool) {
        uint256 endTime = auctionEndTime(tokenId);
        return (block.timestamp >= endTime);
      }
    }
    
    interface IFPP {
      function logPassUse(uint256 tokenId, uint256 projectId) external;
      function ownerOf(uint256 tokenId) external returns (address);
      function passUses(uint256 tokenId, uint256 projectId) external returns (uint256);
    }
    
    interface IBaseContract {
      function mint(address to, uint256 tokenId) external;
      function owner() external view returns (address);
    }