Base Sepolia Testnet

Contract

0x75DA61536510BA0bCa0C9Af21311A1Fc035DCf4e

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Update Curator194876692024-12-21 1:13:46123 days ago1734743626IN
0x75DA6153...c035DCf4e
0 ETH0.000000040.00100035
Update Curator194870552024-12-21 0:53:18123 days ago1734742398IN
0x75DA6153...c035DCf4e
0 ETH0.000000030.00094123
Register Curator194744222024-12-20 17:52:12123 days ago1734717132IN
0x75DA6153...c035DCf4e
0 ETH0.000000120.00100032
Update Service S...194677542024-12-20 14:09:56123 days ago1734703796IN
0x75DA6153...c035DCf4e
0 ETH0.000000020.00094133
Update Domain Se...193835852024-12-18 15:24:18125 days ago1734535458IN
0x75DA6153...c035DCf4e
0 ETH00.00010035

Parent Transaction Hash Block From To
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AxisMetadataRegistry

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 14 : MetadataRegistry.sol
// SPDX-License-Identifier: TBD
pragma solidity 0.8.19;

import {Ownable} from "@openzeppelin/access/Ownable.sol";
import {SignatureChecker} from "@openzeppelin/utils/cryptography/SignatureChecker.sol";

import {IAuctionHouse} from "@axis-core/interfaces/IAuctionHouse.sol";

contract AxisMetadataRegistry is Ownable {
    // ========== ERRORS ========== //

    error AlreadyAssigned();
    error InvalidParam(string param);
    error InvalidSignature();
    error NotAuthorized();

    // ========== EVENTS ========== //

    event AuctionRegistered(address auctionHouse, uint96 lotId, string ipfsCID);
    event CuratorRegistered(address curator, uint256 xId, string ipfsCID);
    event CuratorUpdated(uint256 xId, string ipfsCID);

    // ========== DATA STRUCTURES ========== //

    struct CuratorRegistration {
        address curator;
        uint256 xId;
        string ipfsCID;
    }

    struct AuctionRegistration {
        address auctionHouse;
        uint96 lotId;
        string ipfsCID;
    }

    // ========== STATE VARIABLES ========== //

    // Typed Data Variables
    uint256 public chainId;
    bytes32 internal domainSeparator;

    bytes32 internal constant CURATOR_REGISTRATION_TYPEHASH =
        keccak256("CuratorRegistration(address curator,uint256 xId,string ipfsCID)");

    /// @notice Address that signs registration payloads after being verified by an offchain service
    address public serviceSigner;

    mapping(address => bool) public isAuctionHouse;
    mapping(address curator => uint256 xId) public curatorId;
    mapping(uint256 xId => string ipfsCID) public curatorMetadata;

    mapping(address auctionHouse => mapping(uint96 lotId => string ipfsCID)) public auctionMetadata;

    // ========== CONSTRUCTOR ========== //

    constructor(address serviceSigner_, address[] memory auctionHouses_) {
        for (uint256 i = 0; i < auctionHouses_.length; i++) {
            isAuctionHouse[auctionHouses_[i]] = true;
        }

        serviceSigner = serviceSigner_;
    }

    // ========== INIT ========== //

    function registerCurator(CuratorRegistration calldata payload_, bytes calldata signature_) external {
        // Validate the sender is the curator listed in the payload
        if (msg.sender != payload_.curator) revert NotAuthorized();

        // Validate the xId is not zero
        if (payload_.xId == 0) revert InvalidParam("payload.xId");

        // Validate that the curator address is not already assigned an xId
        if (curatorId[payload_.curator] != 0) revert AlreadyAssigned();

        // Validate that the ipfsCID string is not empty
        if (bytes(payload_.ipfsCID).length == 0) revert InvalidParam("payload.ipfsCID");

        // Validate the service signer signed the payload
        if (!isValidSignature(serviceSigner, payload_, signature_)) revert InvalidSignature();

        // Store the curator's xId
        curatorId[payload_.curator] = payload_.xId;

        // Store the metadata
        curatorMetadata[payload_.xId] = payload_.ipfsCID;

        // Emit event
        emit CuratorRegistered(payload_.curator, payload_.xId, payload_.ipfsCID);
    }

    // This function allows an auction to be registered multiple times, which allows updating the data
    function registerAuction(address auctionHouse_, uint96 lotId_, string calldata ipfsCID_) external {
        // Validate the auction house is supported
        if (!isAuctionHouse[auctionHouse_]) revert InvalidParam("auctionHouse");
        IAuctionHouse auctionHouse = IAuctionHouse(auctionHouse_);

        // Validate the lotId is valid on the auction house by comparing against the lotCounter
        if (lotId_ >= auctionHouse.lotCounter()) revert InvalidParam("lotId");

        // Validate the caller is the seller of the lot
        (address seller,,,,,,,,) = auctionHouse.lotRouting(lotId_);
        if (msg.sender != seller) revert NotAuthorized();

        // Validate the ipfsCID string is not empty
        if (bytes(ipfsCID_).length == 0) revert InvalidParam("ipfsCID");

        // Store the metadata
        auctionMetadata[auctionHouse_][lotId_] = ipfsCID_;

        // Emit event
        emit AuctionRegistered(auctionHouse_, lotId_, ipfsCID_);
    }

    // ========== UPDATE ========== //

    function updateCurator(uint256 xId_, string calldata ipfsCID_) external {
        // Validate the xId is not zero
        if (xId_ == 0) revert InvalidParam("xId");

        // Validate the caller is the curator
        if (curatorId[msg.sender] != xId_) revert NotAuthorized();

        // Validate the ipfsCID string is not empty
        if (bytes(ipfsCID_).length == 0) revert InvalidParam("ipfsCID");

        // Store the metadata
        curatorMetadata[xId_] = ipfsCID_;

        // Emit event
        emit CuratorUpdated(xId_, ipfsCID_);
    }

    function addCuratorAddress(uint256 xId_, address curator_) external {
        // Validate the xId is not zero
        if (xId_ == 0) revert InvalidParam("xId");

        // Validate the caller is a currently a valid address for the curator
        if (curatorId[msg.sender] != xId_) revert NotAuthorized();

        // Validate the curator address is not already assigned an xId
        if (curatorId[curator_] != 0) revert AlreadyAssigned();

        // Store the curator's xId
        curatorId[curator_] = xId_;
    }

    function removeCuratorAddress(uint256 xId_, address curator_) external {
        // Validate the xId is not zero
        if (xId_ == 0) revert InvalidParam("xId");

        // Validate the caller is a currently a valid address for the curator
        if (curatorId[msg.sender] != xId_) revert NotAuthorized();

        // Validate the curator address is assigned to the xId
        if (curatorId[curator_] != xId_) revert InvalidParam("curator");

        // Remove the curator's xId
        delete curatorId[curator_];
    }

    // ========== ADMIN ========== //

    function updateServiceSigner(address serviceSigner_) external onlyOwner {
        serviceSigner = serviceSigner_;
    }

    function addAuctionHouse(address auctionHouse_) external onlyOwner {
        isAuctionHouse[auctionHouse_] = true;
    }

    function removeAuctionHouse(address auctionHouse_) external onlyOwner {
        delete isAuctionHouse[auctionHouse_];
    }

    // ========== SIGNATURE VALIDATION ========== //

    function isValidSignature(address signer_, CuratorRegistration calldata payload_, bytes calldata signature_)
        public
        view
        returns (bool)
    {
        return SignatureChecker.isValidSignatureNow(signer_, getDigest(payload_), signature_);
    }

    function getDigest(CuratorRegistration calldata payload_) public view returns (bytes32) {
        return keccak256(
            abi.encodePacked(
                hex"1901",
                DOMAIN_SEPARATOR(),
                keccak256(
                    abi.encode(
                        CURATOR_REGISTRATION_TYPEHASH,
                        payload_.curator,
                        payload_.xId,
                        keccak256(bytes(payload_.ipfsCID))
                    )
                )
            )
        );
    }

    /* ========== DOMAIN SEPARATOR ========== */

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == chainId ? domainSeparator : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256("Axis Metadata Registry"),
                keccak256("v1.0.0"),
                block.chainid,
                address(this)
            )
        );
    }

    function updateDomainSeparator() external {
        require(block.chainid != chainId, "DOMAIN_SEPARATOR_ALREADY_UPDATED");

        chainId = block.chainid;

        domainSeparator = computeDomainSeparator();
    }
}

File 2 of 14 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 3 of 14 : SignatureChecker.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/SignatureChecker.sol)

pragma solidity ^0.8.0;

import "./ECDSA.sol";
import "../../interfaces/IERC1271.sol";

/**
 * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA
 * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like
 * Argent and Gnosis Safe.
 *
 * _Available since v4.1._
 */
library SignatureChecker {
    /**
     * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the
     * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
        (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);
        return
            (error == ECDSA.RecoverError.NoError && recovered == signer) ||
            isValidERC1271SignatureNow(signer, hash, signature);
    }

    /**
     * @dev Checks if a signature is valid for a given signer and data hash. The signature is validated
     * against the signer smart contract using ERC1271.
     *
     * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus
     * change through time. It could return true at block N and false at block N+1 (or the opposite).
     */
    function isValidERC1271SignatureNow(
        address signer,
        bytes32 hash,
        bytes memory signature
    ) internal view returns (bool) {
        (bool success, bytes memory result) = signer.staticcall(
            abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)
        );
        return (success &&
            result.length >= 32 &&
            abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
    }
}

File 4 of 14 : IAuctionHouse.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;

// Interfaces
import {IAuction} from "./modules/IAuction.sol";
import {ICallback} from "./ICallback.sol";
import {IDerivative} from "./modules/IDerivative.sol";

// Internal dependencies
import {Keycode, Veecode} from "../modules/Keycode.sol";

/// @title  IAuctionHouse
/// @notice Interface for the Axis AuctionHouse contracts
interface IAuctionHouse {
    // ========= ERRORS ========= //

    error InvalidParams();
    error InvalidLotId(uint96 id_);
    error InvalidState();
    error InvalidCallback();

    /// @notice     Used when the caller is not permitted to perform that action
    error NotPermitted(address caller_);

    // ========= EVENTS ========= //

    /// @notice         Emitted when a new auction lot is created
    ///
    /// @param          lotId       ID of the auction lot
    /// @param          auctionRef  Auction module, represented by its Veecode
    /// @param          infoHash    IPFS hash of the auction information
    event AuctionCreated(uint96 indexed lotId, Veecode indexed auctionRef, string infoHash);

    /// @notice         Emitted when an auction lot is cancelled
    ///
    /// @param          lotId       ID of the auction lot
    /// @param          auctionRef  Auction module, represented by its Veecode
    event AuctionCancelled(uint96 indexed lotId, Veecode indexed auctionRef);

    /// @notice         Emitted when a curator accepts curation of an auction lot
    ///
    /// @param          lotId       ID of the auction lot
    /// @param          curator     Address of the curator
    event Curated(uint96 indexed lotId, address indexed curator);

    // ========= DATA STRUCTURES ========== //

    /// @notice     Auction routing information provided as input parameters
    ///
    /// @param      auctionType         Auction type, represented by the Keycode for the auction submodule
    /// @param      baseToken           Token provided by seller. Declared as an address to avoid dependency hell.
    /// @param      quoteToken          Token to accept as payment. Declared as an address to avoid dependency hell.
    /// @param      curator             (optional) Address of the proposed curator
    /// @param      referrerFee         (optional) Percent of bid/purchase amount received paid to a referrer in basis points, i.e. 1% = 100.
    /// @param      callbacks           (optional) Callbacks implementation for extended functionality
    /// @param      callbackData        (optional) abi-encoded data to be sent to the onCreate callback function
    /// @param      derivativeType      (optional) Derivative type, represented by the Keycode for the derivative submodule
    /// @param      derivativeParams    (optional) abi-encoded data to be used to create payout derivatives on a purchase. The format of this is dependent on the derivative module.
    /// @param      wrapDerivative      (optional) Whether to wrap the derivative in a ERC20 token instead of the native ERC6909 format
    struct RoutingParams {
        Keycode auctionType;
        address baseToken;
        address quoteToken;
        address curator;
        uint48 referrerFee;
        ICallback callbacks;
        bytes callbackData;
        Keycode derivativeType;
        bytes derivativeParams;
        bool wrapDerivative;
    }

    /// @notice     Auction routing information for a lot
    ///
    /// @param      seller              Lot seller
    /// @param      baseToken           ERC20 token provided by seller
    /// @param      quoteToken          ERC20 token to accept as payment
    /// @param      auctionReference    Auction module, represented by its Veecode
    /// @param      funding             The amount of base tokens in funding remaining
    /// @param      callbacks           (optional) Callbacks implementation for extended functionality
    /// @param      derivativeReference (optional) Derivative module, represented by its Veecode
    /// @param      wrapDerivative      (optional) Whether to wrap the derivative in a ERC20 token instead of the native ERC6909 format
    /// @param      derivativeParams    (optional) abi-encoded data to be used to create payout derivatives on a purchase
    struct Routing {
        address seller; // 20 bytes
        address baseToken; // 20 bytes
        address quoteToken; // 20 bytes
        Veecode auctionReference; // 7 bytes
        uint256 funding; // 32 bytes
        ICallback callbacks; // 20 bytes
        Veecode derivativeReference; // 7 bytes
        bool wrapDerivative; // 1 byte
        bytes derivativeParams;
    }

    /// @notice     Fee information for a lot
    /// @dev        This is split into a separate struct, otherwise the Routing struct would be too large
    ///             and would throw a "stack too deep" error.
    ///
    ///             Fee information is set at the time of auction creation, in order to prevent subsequent inflation.
    ///             The fees are cached in order to prevent:
    ///             - Reducing the amount of base tokens available for payout to the winning bidders
    ///             - Reducing the amount of quote tokens available for payment to the seller
    ///
    /// @param      curator     Address of the proposed curator
    /// @param      curated     Whether the curator has approved the auction
    /// @param      curatorFee  The fee charged by the curator
    /// @param      protocolFee The fee charged by the protocol
    /// @param      referrerFee The fee charged by the referrer
    struct FeeData {
        address curator; // 20 bytes
        bool curated; // 1 byte
        uint48 curatorFee; // 6 bytes
        uint48 protocolFee; // 6 bytes
        uint48 referrerFee; // 6 bytes
    }

    // ========== AUCTION MANAGEMENT ========== //

    /// @notice     Creates a new auction lot
    ///
    /// @param      routing_    Routing information for the auction lot
    /// @param      params_     Auction parameters for the auction lot
    /// @param      infoHash_   IPFS hash of the auction information
    /// @return     lotId       ID of the auction lot
    function auction(
        RoutingParams calldata routing_,
        IAuction.AuctionParams calldata params_,
        string calldata infoHash_
    ) external returns (uint96 lotId);

    /// @notice     Cancels an auction lot
    ///
    /// @param      lotId_          ID of the auction lot
    /// @param      callbackData_   (optional) abi-encoded data to be sent to the onCancel callback function
    function cancel(uint96 lotId_, bytes calldata callbackData_) external;

    /// @notice     Accept curation request for a lot.
    /// @notice     If the curator wishes to charge a fee, it must be set before this function is called.
    /// @notice     Access controlled. Must be proposed curator for lot.
    ///
    /// @param      lotId_           Lot ID
    /// @param      callbackData_    (optional) abi-encoded data to be sent to the onCurate callback function
    function curate(uint96 lotId_, bytes calldata callbackData_) external;

    // ========== AUCTION INFORMATION ========== //

    /// @notice     The counter tracks the total number of auction lots
    function lotCounter() external view returns (uint96 lotCount);

    /// @notice     Mapping of lot IDs to their routing information
    /// @dev        See the `Routing` struct for more information
    ///
    /// @param      lotId   ID of the auction lot
    function lotRouting(
        uint96 lotId
    )
        external
        view
        returns (
            address seller,
            address baseToken,
            address quoteToken,
            Veecode auctionReference,
            uint256 funding,
            ICallback callbacks,
            Veecode derivativeReference,
            bool wrapDerivative,
            bytes memory derivativeParams
        );

    /// @notice     Mapping of lot IDs to their fee information
    /// @dev        See the `FeeData` struct for more information
    ///
    /// @param      lotId   ID of the auction lot
    function lotFees(
        uint96 lotId
    )
        external
        view
        returns (
            address curator,
            bool curated,
            uint48 curatorFee,
            uint48 protocolFee,
            uint48 referrerFee
        );

    /// @notice     Mapping auction and derivative references to the condenser that is used to pass data between them
    ///
    /// @param      auctionRef      Versioned keycode for the auction module
    /// @param      derivativeRef   Versioned keycode for the derivative module
    /// @return     condenserRef    Versioned keycode for the condenser module
    function condensers(
        Veecode auctionRef,
        Veecode derivativeRef
    ) external view returns (Veecode condenserRef);

    /// @notice     Gets the auction module for a given lot ID
    ///
    /// @param      lotId_  ID of the auction lot
    /// @return     module  The auction module
    function getAuctionModuleForId(uint96 lotId_) external view returns (IAuction module);

    /// @notice     Gets the derivative module for a given lot ID
    /// @dev        Will revert if the lot does not have a derivative module
    ///
    /// @param      lotId_  ID of the auction lot
    /// @return     module  The derivative module
    function getDerivativeModuleForId(uint96 lotId_) external view returns (IDerivative module);
}

File 5 of 14 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 6 of 14 : ECDSA.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.0;

import "../Strings.sol";

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV // Deprecated in v4.8
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) {
        bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
        uint8 v = uint8((uint256(vs) >> 255) + 27);
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, "\x19Ethereum Signed Message:\n32")
            mstore(0x1c, hash)
            message := keccak256(0x00, 0x3c)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from `s`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) {
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, "\x19\x01")
            mstore(add(ptr, 0x02), domainSeparator)
            mstore(add(ptr, 0x22), structHash)
            data := keccak256(ptr, 0x42)
        }
    }

    /**
     * @dev Returns an Ethereum Signed Data with intended validator, created from a
     * `validator` and `data` according to the version 0 of EIP-191.
     *
     * See {recover}.
     */
    function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x00", validator, data));
    }
}

File 7 of 14 : IERC1271.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC1271 standard signature validation method for
 * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
 *
 * _Available since v4.1._
 */
interface IERC1271 {
    /**
     * @dev Should return whether the signature provided is valid for the provided data
     * @param hash      Hash of the data to be signed
     * @param signature Signature byte array associated with _data
     */
    function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}

File 8 of 14 : IAuction.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;

/// @title  IAuction
/// @notice Interface for all auction modules used in the Axis AuctionHouse
/// @dev    This contract defines the external functions and data that are required for an auction module to be installed in an AuctionHouse.
///
///         The implementing contract should define the following additional areas:
///         - Any un-implemented functions
///         - State variables for storage and configuration
///
///         Data storage:
///         - Each auction lot will have common data that is stored using the `Lot` struct. Inheriting auction modules may store additional data outside of the struct.
interface IAuction {
    // ========== ERRORS ========== //

    error Auction_LotNotActive(uint96 lotId);
    error Auction_LotActive(uint96 lotId);
    error Auction_InvalidStart(uint48 start_, uint48 minimum_);
    error Auction_InvalidDuration(uint48 duration_, uint48 minimum_);
    error Auction_InvalidLotId(uint96 lotId);
    error Auction_OnlyLotOwner();
    error Auction_AmountLessThanMinimum();
    error Auction_InvalidParams();
    error Auction_NotAuthorized();
    error Auction_NotImplemented();
    error Auction_InsufficientCapacity();
    error Auction_LotNotConcluded(uint96 lotId);

    // ========== DATA STRUCTURES ========== //

    /// @notice     Types of auctions
    enum AuctionType {
        Atomic,
        Batch
    }

    /// @notice     Parameters when creating an auction lot
    ///
    /// @param      start           The timestamp when the auction starts
    /// @param      duration        The duration of the auction (in seconds)
    /// @param      capacityInQuote Whether or not the capacity is in quote tokens
    /// @param      capacity        The capacity of the lot
    /// @param      implParams      Abi-encoded implementation-specific parameters
    struct AuctionParams {
        uint48 start;
        uint48 duration;
        bool capacityInQuote;
        uint256 capacity;
        bytes implParams;
    }

    /// @notice     Core data for an auction lot
    ///
    /// @param      start               The timestamp when the auction starts
    /// @param      conclusion          The timestamp when the auction ends
    /// @param      quoteTokenDecimals  The quote token decimals
    /// @param      baseTokenDecimals   The base token decimals
    /// @param      capacityInQuote     Whether or not the capacity is in quote tokens
    /// @param      capacity            The capacity of the lot
    /// @param      sold                The amount of base tokens sold
    /// @param      purchased           The amount of quote tokens purchased
    struct Lot {
        uint48 start; // 6 +
        uint48 conclusion; // 6 +
        uint8 quoteTokenDecimals; // 1 +
        uint8 baseTokenDecimals; // 1 +
        bool capacityInQuote; // 1 = 15 - end of slot 1
        uint256 capacity; // 32 - slot 2
        uint256 sold; // 32 - slot 3
        uint256 purchased; // 32 - slot 4
    }

    // ========== STATE VARIABLES ========== //

    /// @notice Minimum auction duration in seconds
    function minAuctionDuration() external view returns (uint48);

    /// @notice General information pertaining to auction lots
    /// @dev    See the `Lot` struct for more information on the return values
    ///
    /// @param  lotId   The lot ID
    function lotData(
        uint96 lotId
    )
        external
        view
        returns (
            uint48 start,
            uint48 conclusion,
            uint8 quoteTokenDecimals,
            uint8 baseTokenDecimals,
            bool capacityInQuote,
            uint256 capacity,
            uint256 sold,
            uint256 purchased
        );

    // ========== AUCTION MANAGEMENT ========== //

    /// @notice     Create an auction lot
    /// @dev        The implementing function should handle the following:
    ///             - Validate the lot parameters
    ///             - Store the lot data
    ///
    /// @param      lotId_                  The lot id
    /// @param      params_                 The auction parameters
    /// @param      quoteTokenDecimals_     The quote token decimals
    /// @param      baseTokenDecimals_      The base token decimals
    function auction(
        uint96 lotId_,
        AuctionParams memory params_,
        uint8 quoteTokenDecimals_,
        uint8 baseTokenDecimals_
    ) external;

    /// @notice     Cancel an auction lot
    /// @dev        The implementing function should handle the following:
    ///             - Validate the lot parameters
    ///             - Update the lot data
    ///
    /// @param      lotId_              The lot id
    function cancelAuction(uint96 lotId_) external;

    // ========== AUCTION INFORMATION ========== //

    /// @notice     Returns whether the auction is currently accepting bids or purchases
    /// @dev        The implementing function should handle the following:
    ///             - Return true if the lot is accepting bids/purchases
    ///             - Return false if the lot has ended, been cancelled, or not started yet
    ///
    /// @param      lotId_  The lot id
    /// @return     bool    Whether or not the lot is active
    function isLive(uint96 lotId_) external view returns (bool);

    /// @notice     Returns whether the auction is upcoming
    /// @dev        The implementing function should handle the following:
    ///             - Return true if the lot has not started yet AND has not been cancelled
    ///             - Return false if the lot is active, has ended, or was cancelled
    ///
    /// @param      lotId_  The lot id
    /// @return     bool    Whether or not the lot is upcoming
    function isUpcoming(uint96 lotId_) external view returns (bool);

    /// @notice     Returns whether the auction has ended
    /// @dev        The implementing function should handle the following:
    ///             - Return true if the lot is not accepting bids/purchases and will not at any point
    ///             - Return false if the lot hasn't started or is actively accepting bids/purchases
    ///
    /// @param      lotId_  The lot id
    /// @return     bool    Whether or not the lot is active
    function hasEnded(uint96 lotId_) external view returns (bool);

    /// @notice     Get the remaining capacity of a lot
    /// @dev        The implementing function should handle the following:
    ///             - Return the remaining capacity of the lot
    ///
    /// @param      lotId_  The lot id
    /// @return     uint96 The remaining capacity of the lot
    function remainingCapacity(uint96 lotId_) external view returns (uint256);

    /// @notice     Get whether or not the capacity is in quote tokens
    /// @dev        The implementing function should handle the following:
    ///             - Return true if the capacity is in quote tokens
    ///             - Return false if the capacity is in base tokens
    ///
    /// @param      lotId_  The lot id
    /// @return     bool    Whether or not the capacity is in quote tokens
    function capacityInQuote(uint96 lotId_) external view returns (bool);

    /// @notice     Get the lot data for a given lot ID
    ///
    /// @param     lotId_  The lot ID
    function getLot(uint96 lotId_) external view returns (Lot memory);

    /// @notice     Get the auction type
    function auctionType() external view returns (AuctionType);
}

File 9 of 14 : ICallback.sol
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

/// @title  ICallback
/// @notice Interface for callback contracts use in the Axis system
interface ICallback {
    /// @notice Callback configuration. Used by AuctionHouse to know which functions are implemented on this contract.
    /// @dev 8-bit map of which callbacks are implemented on this contract.
    ///     The last two bits designate whether the callback should be expected send base tokens and receive quote tokens.
    ///     If the contract does not send/receive, then the AuctionHouse will expect the tokens to be sent/received directly by the seller wallet.
    ///     Bit 1: onCreate
    ///     Bit 2: onCancel
    ///     Bit 3: onCurate
    ///     Bit 4: onPurchase
    ///     Bit 5: onBid
    ///     Bit 6: onSettle
    ///     Bit 7: Receives quote tokens
    ///     Bit 8: Sends base tokens (and receives them if refunded)

    // General functions that can be used by all auctions

    /// @notice Called when an auction is created. Reverts if validation fails.
    /// @dev    The implementing function should:
    ///         - Register the lot ID on the Callback contract
    ///         - Validate that the seller is allowed to use the Callback contract
    ///
    /// @param  lotId         The ID of the lot
    /// @param  seller        The address of the seller
    /// @param  baseToken     The address of the base token
    /// @param  quoteToken    The address of the quote token
    /// @param  capacity      The capacity of the auction
    /// @param  preFund       If true, the calling contract expects base tokens to be sent to it
    /// @param  callbackData  Custom data provided by the seller
    function onCreate(
        uint96 lotId,
        address seller,
        address baseToken,
        address quoteToken,
        uint256 capacity,
        bool preFund,
        bytes calldata callbackData
    ) external returns (bytes4);

    /// @notice Called when an auction is cancelled.
    /// @dev    If the Callback is configured to receive tokens and the auction was prefunded, then the refund will be sent prior to the call.
    ///
    /// @param  lotId           The ID of the lot
    /// @param  refund          The refund amount
    /// @param  preFunded       If true, the calling contract will have sent base tokens prior to the call
    /// @param  callbackData    Custom data provided by the seller
    function onCancel(
        uint96 lotId,
        uint256 refund,
        bool preFunded,
        bytes calldata callbackData
    ) external returns (bytes4);

    /// @notice Called when curate is called for an auction.
    ///
    /// @param  lotId         The ID of the lot
    /// @param  curatorFee    The curator fee payout
    /// @param  preFund       If true, the calling contract expects base tokens to be sent to it
    /// @param  callbackData  Custom data provided by the seller
    function onCurate(
        uint96 lotId,
        uint256 curatorFee,
        bool preFund,
        bytes calldata callbackData
    ) external returns (bytes4);

    // Atomic Auction hooks

    /// @notice Called when a buyer purchases from an atomic auction. Reverts if validation fails.
    /// @dev    If the Callback is configured to receive quote tokens, then the user purchase amount of quote tokens will be sent prior to this call.
    ///         If the Callback is configured to send base tokens, then the AuctionHouse will expect the payout of base tokens to be sent back.
    ///
    /// @param  lotId         The ID of the lot
    /// @param  buyer         The address of the buyer
    /// @param  amount        The amount of quote tokens purchased
    /// @param  payout        The amount of base tokens to receive
    /// @param  preFunded     If true, the calling contract has already been provided the base tokens. Otherwise, they must be provided.
    /// @param  callbackData  Custom data provided by the buyer
    function onPurchase(
        uint96 lotId,
        address buyer,
        uint256 amount,
        uint256 payout,
        bool preFunded,
        bytes calldata callbackData
    ) external returns (bytes4);

    // Batch Auction hooks

    /// @notice Called when a buyer bids on a batch auction. Reverts if validation fails.
    ///
    /// @param  lotId         The ID of the lot
    /// @param  bidId         The ID of the bid
    /// @param  buyer         The address of the buyer
    /// @param  amount        The amount of quote tokens bid
    /// @param  callbackData  Custom data provided by the buyer
    function onBid(
        uint96 lotId,
        uint64 bidId,
        address buyer,
        uint256 amount,
        bytes calldata callbackData
    ) external returns (bytes4);

    /// @notice Called when a batch auction is settled.
    /// @dev    If the Callback is configured to receive tokens, then the proceeds and/or refund will be sent prior to the call.
    ///
    /// @param  lotId         The ID of the lot
    /// @param  proceeds      The proceeds amount
    /// @param  refund        The refund amount
    /// @param  callbackData  Custom data provided by the seller
    function onSettle(
        uint96 lotId,
        uint256 proceeds,
        uint256 refund,
        bytes calldata callbackData
    ) external returns (bytes4);
}

File 10 of 14 : IDerivative.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.0;

/// @title      IDerivative
/// @notice     Interface for Derivative functionality
/// @dev        Derivatives provide a mechanism to create synthetic assets that are backed by collateral, such as base tokens from an auction.
interface IDerivative {
    // ========== ERRORS ========== //

    error Derivative_NotImplemented();

    // ========== DATA STRUCTURES ========== //

    /// @notice     Metadata for a derivative token
    ///
    /// @param      exists          True if the token has been deployed
    /// @param      wrapped         Non-zero if an ERC20-wrapped derivative has been deployed
    /// @param      underlyingToken The address of the underlying token
    /// @param      supply          The total supply of the derivative token
    /// @param      data            Implementation-specific data
    struct Token {
        bool exists;
        address wrapped;
        address underlyingToken;
        uint256 supply;
        bytes data;
    }

    // ========== STATE VARIABLES ========== //

    /// @notice The metadata for a derivative token
    ///
    /// @param  tokenId         The ID of the derivative token
    /// @return exists          True if the token has been deployed
    /// @return wrapped         Non-zero if an ERC20-wrapped derivative has been deployed
    /// @return underlyingToken The address of the underlying token
    /// @return supply          The total supply of the derivative token
    /// @return data            Implementation-specific data
    function tokenMetadata(
        uint256 tokenId
    )
        external
        view
        returns (
            bool exists,
            address wrapped,
            address underlyingToken,
            uint256 supply,
            bytes memory data
        );

    // ========== DERIVATIVE MANAGEMENT ========== //

    /// @notice     Deploy a new derivative token. Optionally, deploys an ERC20 wrapper for composability.
    ///
    /// @param      underlyingToken_    The address of the underlying token
    /// @param      params_             ABI-encoded parameters for the derivative to be created
    /// @param      wrapped_            Whether (true) or not (false) the derivative should be wrapped in an ERC20 token for composability
    /// @return     tokenId_            The ID of the newly created derivative token
    /// @return     wrappedAddress_     The address of the ERC20 wrapped derivative token, if wrapped_ is true, otherwise, it's the zero address.
    function deploy(
        address underlyingToken_,
        bytes memory params_,
        bool wrapped_
    ) external returns (uint256 tokenId_, address wrappedAddress_);

    /// @notice     Mint new derivative tokens.
    /// @notice     Deploys the derivative token if it does not already exist.
    /// @notice     The module is expected to transfer the collateral token to itself.
    ///
    /// @param      to_                 The address to mint the derivative tokens to
    /// @param      underlyingToken_    The address of the underlying token
    /// @param      params_             ABI-encoded parameters for the derivative to be created
    /// @param      amount_             The amount of derivative tokens to create
    /// @param      wrapped_            Whether (true) or not (false) the derivative should be wrapped in an ERC20 token for composability
    /// @return     tokenId_            The ID of the newly created derivative token
    /// @return     wrappedAddress_     The address of the ERC20 wrapped derivative token, if wrapped_ is true, otherwise, it's the zero address.
    /// @return     amountCreated_      The amount of derivative tokens created
    function mint(
        address to_,
        address underlyingToken_,
        bytes memory params_,
        uint256 amount_,
        bool wrapped_
    ) external returns (uint256 tokenId_, address wrappedAddress_, uint256 amountCreated_);

    /// @notice     Mint new derivative tokens for a specific token ID
    ///
    /// @param      to_                 The address to mint the derivative tokens to
    /// @param      tokenId_            The ID of the derivative token
    /// @param      amount_             The amount of derivative tokens to create
    /// @param      wrapped_            Whether (true) or not (false) the derivative should be wrapped in an ERC20 token for composability
    /// @return     tokenId_            The ID of the derivative token
    /// @return     wrappedAddress_     The address of the ERC20 wrapped derivative token, if wrapped_ is true, otherwise, it's the zero address.
    /// @return     amountCreated_      The amount of derivative tokens created
    function mint(
        address to_,
        uint256 tokenId_,
        uint256 amount_,
        bool wrapped_
    ) external returns (uint256, address, uint256);

    /// @notice     Redeem all available derivative tokens for underlying collateral
    ///
    /// @param      tokenId_    The ID of the derivative token to redeem
    function redeemMax(uint256 tokenId_) external;

    /// @notice     Redeem derivative tokens for underlying collateral
    ///
    /// @param      tokenId_    The ID of the derivative token to redeem
    /// @param      amount_     The amount of derivative tokens to redeem
    function redeem(uint256 tokenId_, uint256 amount_) external;

    /// @notice     Determines the amount of redeemable tokens for a given derivative token
    ///
    /// @param      owner_      The owner of the derivative token
    /// @param      tokenId_    The ID of the derivative token
    /// @return     amount      The amount of redeemable tokens
    function redeemable(address owner_, uint256 tokenId_) external view returns (uint256 amount);

    /// @notice     Exercise a conversion of the derivative token per the specific implementation logic
    /// @dev        Used for options or other derivatives with convertible options, e.g. Rage vesting.
    ///
    /// @param      tokenId_    The ID of the derivative token to exercise
    /// @param      amount      The amount of derivative tokens to exercise
    function exercise(uint256 tokenId_, uint256 amount) external;

    /// @notice     Determines the cost to exercise a derivative token in the quoted token
    /// @dev        Used for options or other derivatives with convertible options, e.g. Rage vesting.
    ///
    /// @param      tokenId_    The ID of the derivative token to exercise
    /// @param      amount      The amount of derivative tokens to exercise
    /// @return     cost        The cost to exercise the derivative token
    function exerciseCost(uint256 tokenId_, uint256 amount) external view returns (uint256 cost);

    /// @notice     Reclaim posted collateral for a derivative token which can no longer be exercised
    /// @notice     Access controlled: only callable by the derivative issuer via the auction house.
    ///
    /// @param      tokenId_    The ID of the derivative token to reclaim
    function reclaim(uint256 tokenId_) external;

    /// @notice     Transforms an existing derivative issued by this contract into something else. Derivative is burned and collateral sent to the auction house.
    /// @notice     Access controlled: only callable by the auction house.
    ///
    /// @param      tokenId_    The ID of the derivative token to transform
    /// @param      from_       The address of the owner of the derivative token
    /// @param      amount_     The amount of derivative tokens to transform
    function transform(uint256 tokenId_, address from_, uint256 amount_) external;

    /// @notice     Wrap an existing derivative into an ERC20 token for composability
    ///             Deploys the ERC20 wrapper if it does not already exist
    ///
    /// @param      tokenId_    The ID of the derivative token to wrap
    /// @param      amount_     The amount of derivative tokens to wrap
    function wrap(uint256 tokenId_, uint256 amount_) external;

    /// @notice     Unwrap an ERC20 derivative token into the underlying ERC6909 derivative
    ///
    /// @param      tokenId_    The ID of the derivative token to unwrap
    /// @param      amount_     The amount of derivative tokens to unwrap
    function unwrap(uint256 tokenId_, uint256 amount_) external;

    /// @notice     Validate derivative params for the specific implementation
    ///             The parameters should be the same as what is passed into `deploy()` or `mint()`
    ///
    /// @param      underlyingToken_    The address of the underlying token
    /// @param      params_             The params to validate
    /// @return     isValid             Whether or not the params are valid
    function validate(
        address underlyingToken_,
        bytes memory params_
    ) external view returns (bool isValid);

    // ========== DERIVATIVE INFORMATION ========== //

    /// @notice     Compute a unique token ID, given the parameters for the derivative
    ///
    /// @param      underlyingToken_    The address of the underlying token
    /// @param      params_             The parameters for the derivative
    /// @return     tokenId             The unique token ID
    function computeId(
        address underlyingToken_,
        bytes memory params_
    ) external pure returns (uint256 tokenId);

    /// @notice     Get the metadata for a derivative token
    ///
    /// @param      tokenId     The ID of the derivative token
    /// @return     tokenData   The metadata for the derivative token
    function getTokenMetadata(uint256 tokenId) external view returns (Token memory tokenData);
}

File 11 of 14 : Keycode.sol
// SPDX-License-Identifier: AGPL-3.0-or-later
pragma solidity >=0.8.19;

// Inspired by Default framework keycode management of dependencies and based on the Modules pattern

/// @notice     5 byte/character identifier for the Module
/// @dev        3-5 characters from A-Z
type Keycode is bytes5;

/// @notice     7 byte identifier for the Module, including version
/// @dev        2 characters from 0-9 (a version number), followed by Keycode
type Veecode is bytes7;

error InvalidVeecode(Veecode veecode_);

function toKeycode(bytes5 keycode_) pure returns (Keycode) {
    return Keycode.wrap(keycode_);
}

function fromKeycode(Keycode keycode_) pure returns (bytes5) {
    return Keycode.unwrap(keycode_);
}

// solhint-disable-next-line func-visibility
function wrapVeecode(Keycode keycode_, uint8 version_) pure returns (Veecode) {
    // Get the digits of the version
    bytes1 firstDigit = bytes1(version_ / 10 + 0x30);
    bytes1 secondDigit = bytes1((version_ % 10) + 0x30);

    // Pack everything and wrap as a Veecode
    return Veecode.wrap(bytes7(abi.encodePacked(firstDigit, secondDigit, keycode_)));
}

// solhint-disable-next-line func-visibility
function toVeecode(bytes7 veecode_) pure returns (Veecode) {
    return Veecode.wrap(veecode_);
}

// solhint-disable-next-line func-visibility
function fromVeecode(Veecode veecode_) pure returns (bytes7) {
    return Veecode.unwrap(veecode_);
}

function unwrapVeecode(Veecode veecode_) pure returns (Keycode, uint8) {
    bytes7 unwrapped = Veecode.unwrap(veecode_);

    // Get the version from the first 2 bytes
    if (unwrapped[0] < 0x30 || unwrapped[0] > 0x39 || unwrapped[1] < 0x30 || unwrapped[1] > 0x39) {
        revert InvalidVeecode(veecode_);
    }
    uint8 version = (uint8(unwrapped[0]) - 0x30) * 10;
    version += uint8(unwrapped[1]) - 0x30;

    // Get the Keycode by shifting the full Veecode to the left by 2 bytes
    Keycode keycode = Keycode.wrap(bytes5(unwrapped << 16));

    return (keycode, version);
}

function keycodeFromVeecode(Veecode veecode_) pure returns (Keycode) {
    (Keycode keycode,) = unwrapVeecode(veecode_);
    return keycode;
}

// solhint-disable-next-line func-visibility
function ensureValidVeecode(Veecode veecode_) pure {
    bytes7 unwrapped = Veecode.unwrap(veecode_);
    for (uint256 i; i < 7;) {
        bytes1 char = unwrapped[i];
        if (i < 2) {
            // First 2 characters must be the version, each character is a number 0-9
            if (char < 0x30 || char > 0x39) revert InvalidVeecode(veecode_);
        } else if (i < 5) {
            // Next 3 characters after the first 3 can be A-Z
            if (char < 0x41 || char > 0x5A) revert InvalidVeecode(veecode_);
        } else {
            // Last 2 character must be A-Z or blank
            if (char != 0x00 && (char < 0x41 || char > 0x5A)) revert InvalidVeecode(veecode_);
        }
        unchecked {
            i++;
        }
    }

    // Check that the version is not 0
    // This is because the version is by default 0 if the module is not installed
    (, uint8 moduleVersion) = unwrapVeecode(veecode_);
    if (moduleVersion == 0) revert InvalidVeecode(veecode_);
}

File 12 of 14 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)

pragma solidity ^0.8.0;

import "./math/Math.sol";
import "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _SYMBOLS = "0123456789abcdef";
    uint8 private constant _ADDRESS_LENGTH = 20;

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toString(int256 value) internal pure returns (string memory) {
        return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 13 of 14 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}

File 14 of 14 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // must be unchecked in order to support `n = type(int256).min`
            return uint256(n >= 0 ? n : -n);
        }
    }
}

Settings
{
  "remappings": [
    "@forge-std/=dependencies/forge-std-1.9.4/src/",
    "@openzeppelin/=dependencies/@openzeppelin-contracts-4.9.6/",
    "@axis-core/=dependencies/axis-core-1.0.1/src/",
    "@clones-with-immutable-args-1.1.1/=dependencies/axis-core-1.0.1/dependencies/clones-with-immutable-args-1.1.1/src/",
    "@forge-std-1.9.1/=dependencies/axis-core-1.0.1/dependencies/forge-std-1.9.1/src/",
    "@openzeppelin-contracts-4.9.2/=dependencies/axis-core-1.0.1/dependencies/@openzeppelin-contracts-4.9.2/",
    "@openzeppelin-contracts-4.9.6/=dependencies/@openzeppelin-contracts-4.9.6/",
    "@solady-0.0.124/=dependencies/axis-core-1.0.1/dependencies/solady-0.0.124/src/",
    "@solmate-6.7.0/=dependencies/axis-core-1.0.1/dependencies/solmate-6.7.0/src/",
    "axis-core-1.0.1/=dependencies/axis-core-1.0.1/src/",
    "forge-std-1.9.4/=dependencies/forge-std-1.9.4/src/",
    "forge-std/=lib/forge-std/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"serviceSigner_","type":"address"},{"internalType":"address[]","name":"auctionHouses_","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyAssigned","type":"error"},{"inputs":[{"internalType":"string","name":"param","type":"string"}],"name":"InvalidParam","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"auctionHouse","type":"address"},{"indexed":false,"internalType":"uint96","name":"lotId","type":"uint96"},{"indexed":false,"internalType":"string","name":"ipfsCID","type":"string"}],"name":"AuctionRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"curator","type":"address"},{"indexed":false,"internalType":"uint256","name":"xId","type":"uint256"},{"indexed":false,"internalType":"string","name":"ipfsCID","type":"string"}],"name":"CuratorRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"xId","type":"uint256"},{"indexed":false,"internalType":"string","name":"ipfsCID","type":"string"}],"name":"CuratorUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auctionHouse_","type":"address"}],"name":"addAuctionHouse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"xId_","type":"uint256"},{"internalType":"address","name":"curator_","type":"address"}],"name":"addCuratorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"auctionHouse","type":"address"},{"internalType":"uint96","name":"lotId","type":"uint96"}],"name":"auctionMetadata","outputs":[{"internalType":"string","name":"ipfsCID","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"chainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"curator","type":"address"}],"name":"curatorId","outputs":[{"internalType":"uint256","name":"xId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"xId","type":"uint256"}],"name":"curatorMetadata","outputs":[{"internalType":"string","name":"ipfsCID","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"curator","type":"address"},{"internalType":"uint256","name":"xId","type":"uint256"},{"internalType":"string","name":"ipfsCID","type":"string"}],"internalType":"struct AxisMetadataRegistry.CuratorRegistration","name":"payload_","type":"tuple"}],"name":"getDigest","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"isAuctionHouse","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"signer_","type":"address"},{"components":[{"internalType":"address","name":"curator","type":"address"},{"internalType":"uint256","name":"xId","type":"uint256"},{"internalType":"string","name":"ipfsCID","type":"string"}],"internalType":"struct AxisMetadataRegistry.CuratorRegistration","name":"payload_","type":"tuple"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"auctionHouse_","type":"address"},{"internalType":"uint96","name":"lotId_","type":"uint96"},{"internalType":"string","name":"ipfsCID_","type":"string"}],"name":"registerAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"curator","type":"address"},{"internalType":"uint256","name":"xId","type":"uint256"},{"internalType":"string","name":"ipfsCID","type":"string"}],"internalType":"struct AxisMetadataRegistry.CuratorRegistration","name":"payload_","type":"tuple"},{"internalType":"bytes","name":"signature_","type":"bytes"}],"name":"registerCurator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"auctionHouse_","type":"address"}],"name":"removeAuctionHouse","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"xId_","type":"uint256"},{"internalType":"address","name":"curator_","type":"address"}],"name":"removeCuratorAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"serviceSigner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"xId_","type":"uint256"},{"internalType":"string","name":"ipfsCID_","type":"string"}],"name":"updateCurator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"updateDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"serviceSigner_","type":"address"}],"name":"updateServiceSigner","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b5060405162001b4938038062001b49833981016040819052620000349162000159565b6200003f33620000d6565b60005b8151811015620000ae5760016004600084848151811062000067576200006762000242565b6020908102919091018101516001600160a01b03168252810191909152604001600020805460ff191691151591909117905580620000a58162000258565b91505062000042565b5050600380546001600160a01b0319166001600160a01b039290921691909117905562000280565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200013e57600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b600080604083850312156200016d57600080fd5b620001788362000126565b602084810151919350906001600160401b03808211156200019857600080fd5b818601915086601f830112620001ad57600080fd5b815181811115620001c257620001c262000143565b8060051b604051601f19603f83011681018181108582111715620001ea57620001ea62000143565b6040529182528482019250838101850191898311156200020957600080fd5b938501935b828510156200023257620002228562000126565b845293850193928501926200020e565b8096505050505050509250929050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200027957634e487b7160e01b600052601160045260246000fd5b5060010190565b6118b980620002906000396000f3fe608060405234801561001057600080fd5b50600436106101375760003560e01c806382a7576b116100b85780639a8a05921161007c5780639a8a05921461028c578063d212b5d314610295578063d7bcf546146102a8578063efed64be146102c8578063f2fde38b146102db578063faf8dbfb146102ee57600080fd5b806382a7576b1461022657806389ccfe89146102395780638da5cb5b1461024157806390eff5c414610266578063936525071461027957600080fd5b80634372ff85116100ff5780634372ff85146101c25780634f011a65146101d55780636704126f146101e8578063715018a6146101fb57806376e63bb01461020357600080fd5b806318cb9c1d1461013c57806320e4ff85146101515780632dd372e61461017957806331995fda1461018c5780633644e515146101ac575b600080fd5b61014f61014a366004611108565b610301565b005b61016461015f366004611192565b6103ab565b60405190151581526020015b60405180910390f35b61014f61018736600461120b565b6103ff565b61019f61019a366004611244565b610429565b60405161017091906112c2565b6101b46104ce565b604051908152602001610170565b61014f6101d036600461120b565b6104ed565b61014f6101e33660046112d5565b610519565b61014f6101f636600461133e565b610729565b61014f61099e565b61016461021136600461120b565b60046020526000908152604090205460ff1681565b61014f610234366004611108565b6109b2565b61014f610a6f565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610170565b6101b4610274366004611397565b610ad1565b61014f6102873660046113d4565b610bba565b6101b460015481565b60035461024e906001600160a01b031681565b6101b46102b636600461120b565b60056020526000908152604090205481565b61019f6102d6366004611413565b610c93565b61014f6102e936600461120b565b610cac565b61014f6102fc36600461120b565b610d25565b8160000361032b57604051634389d5ab60e01b81526004016103229061142c565b60405180910390fd5b33600090815260056020526040902054821461035a5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381166000908152600560205260409020541561039157604051639688dc5160e01b815260040160405180910390fd5b6001600160a01b0316600090815260056020526040902055565b60006103f6856103ba86610ad1565b85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610d4e92505050565b95945050505050565b610407610daf565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60076020908152600092835260408084209091529082529020805461044d90611449565b80601f016020809104026020016040519081016040528092919081815260200182805461047990611449565b80156104c65780601f1061049b576101008083540402835291602001916104c6565b820191906000526020600020905b8154815290600101906020018083116104a957829003601f168201915b505050505081565b600060015446146104e6576104e1610e09565b905090565b5060025490565b6104f5610daf565b6001600160a01b03166000908152600460205260409020805460ff19166001179055565b610526602084018461120b565b6001600160a01b0316336001600160a01b0316146105575760405163ea8e4eb560e01b815260040160405180910390fd5b826020013560000361059a57604051634389d5ab60e01b815260206004820152600b60248201526a1c185e5b1bd8590b9e125960aa1b6044820152606401610322565b600560006105ab602086018661120b565b6001600160a01b03168152602081019190915260400160002054156105e357604051639688dc5160e01b815260040160405180910390fd5b6105f0604084018461147d565b905060000361063457604051634389d5ab60e01b815260206004820152600f60248201526e1c185e5b1bd8590b9a5c199cd0d251608a1b6044820152606401610322565b60035461064c906001600160a01b03168484846103ab565b61066957604051638baa579f60e01b815260040160405180910390fd5b60208301803590600590600090610680908761120b565b6001600160a01b0316815260208101919091526040908101600020919091556106ab9084018461147d565b6020808601356000908152600690915260409020916106cb919083611529565b507f8d71b236876fe8aa8294fe7f3c63662bfc3fc1a240fdbe49488b37f3366958fc6106fa602085018561120b565b602085013561070c604087018761147d565b60405161071c9493929190611613565b60405180910390a1505050565b6001600160a01b03841660009081526004602052604090205460ff1661078157604051634389d5ab60e01b815260206004820152600c60248201526b61756374696f6e486f75736560a01b6044820152606401610322565b6000849050806001600160a01b031663c4ce88fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e8919061163b565b6001600160601b0316846001600160601b03161061083157604051634389d5ab60e01b81526020600482015260056024820152641b1bdd125960da1b6044820152606401610322565b604051634f17001d60e11b81526001600160601b03851660048201526000906001600160a01b03831690639e2e003a90602401600060405180830381865afa158015610881573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108a991908101906116f3565b50505050505050509050806001600160a01b0316336001600160a01b0316146108e55760405163ea8e4eb560e01b815260040160405180910390fd5b600083900361092157604051634389d5ab60e01b81526020600482015260076024820152661a5c199cd0d25160ca1b6044820152606401610322565b6001600160a01b03861660009081526007602090815260408083206001600160601b03891684529091529020610958848683611529565b507f18b40f4816934f1a7bd5ff51d87f48d9ddacbd7653b2cde31a904cbd3c30b5248686868660405161098e94939291906117c1565b60405180910390a1505050505050565b6109a6610daf565b6109b06000610eae565b565b816000036109d357604051634389d5ab60e01b81526004016103229061142c565b336000908152600560205260409020548214610a025760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381166000908152600560205260409020548214610a5457604051634389d5ab60e01b815260206004820152600760248201526631bab930ba37b960c91b6044820152606401610322565b6001600160a01b031660009081526005602052604081205550565b6001544603610ac05760405162461bcd60e51b815260206004820181905260248201527f444f4d41494e5f534550415241544f525f414c52454144595f555044415445446044820152606401610322565b46600155610acc610e09565b600255565b6000610adb6104ce565b7f1378000983868b9cd38cd6c7408ceb9051309140ca9bff5d199043ae5649938c610b09602085018561120b565b6020850135610b1b604087018761147d565b604051610b299291906117f5565b604051908190038120610b60949392916020019384526001600160a01b039290921660208401526040830152606082015260800190565b60405160208183030381529060405280519060200120604051602001610b9d92919061190160f01b81526002810192909252602282015260420190565b604051602081830303815290604052805190602001209050919050565b82600003610bdb57604051634389d5ab60e01b81526004016103229061142c565b336000908152600560205260409020548314610c0a5760405163ea8e4eb560e01b815260040160405180910390fd5b6000819003610c4657604051634389d5ab60e01b81526020600482015260076024820152661a5c199cd0d25160ca1b6044820152606401610322565b6000838152600660205260409020610c5f828483611529565b507f8d48f79a76a920c2d4e03ef6f1c031c427129a9bd429bb36523fc25cc1e4ea6883838360405161071c93929190611805565b6006602052600090815260409020805461044d90611449565b610cb4610daf565b6001600160a01b038116610d195760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610322565b610d2281610eae565b50565b610d2d610daf565b6001600160a01b03166000908152600460205260409020805460ff19169055565b6000806000610d5d8585610efe565b90925090506000816004811115610d7657610d7661181f565b148015610d945750856001600160a01b0316826001600160a01b0316145b80610da55750610da5868686610f43565b9695505050505050565b6000546001600160a01b031633146109b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610322565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f4873d266cc369576c1140f197e29f2f69e4e0a34e63dac384a5a61ccd6762dbb918101919091527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808251604103610f345760208301516040840151606085015160001a610f288782858561102f565b94509450505050610f3c565b506000905060025b9250929050565b6000806000856001600160a01b0316631626ba7e60e01b8686604051602401610f6d929190611835565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610fab919061184e565b600060405180830381855afa9150503d8060008114610fe6576040519150601f19603f3d011682016040523d82523d6000602084013e610feb565b606091505b5091509150818015610fff57506020815110155b8015610da557508051630b135d3f60e11b90611024908301602090810190840161186a565b149695505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561106657506000905060036110ea565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156110ba573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110e3576000600192509250506110ea565b9150600090505b94509492505050565b6001600160a01b0381168114610d2257600080fd5b6000806040838503121561111b57600080fd5b82359150602083013561112d816110f3565b809150509250929050565b60006060828403121561114a57600080fd5b50919050565b60008083601f84011261116257600080fd5b50813567ffffffffffffffff81111561117a57600080fd5b602083019150836020828501011115610f3c57600080fd5b600080600080606085870312156111a857600080fd5b84356111b3816110f3565b9350602085013567ffffffffffffffff808211156111d057600080fd5b6111dc88838901611138565b945060408701359150808211156111f257600080fd5b506111ff87828801611150565b95989497509550505050565b60006020828403121561121d57600080fd5b8135611228816110f3565b9392505050565b6001600160601b0381168114610d2257600080fd5b6000806040838503121561125757600080fd5b8235611262816110f3565b9150602083013561112d8161122f565b60005b8381101561128d578181015183820152602001611275565b50506000910152565b600081518084526112ae816020860160208601611272565b601f01601f19169290920160200192915050565b6020815260006112286020830184611296565b6000806000604084860312156112ea57600080fd5b833567ffffffffffffffff8082111561130257600080fd5b61130e87838801611138565b9450602086013591508082111561132457600080fd5b5061133186828701611150565b9497909650939450505050565b6000806000806060858703121561135457600080fd5b843561135f816110f3565b9350602085013561136f8161122f565b9250604085013567ffffffffffffffff81111561138b57600080fd5b6111ff87828801611150565b6000602082840312156113a957600080fd5b813567ffffffffffffffff8111156113c057600080fd5b6113cc84828501611138565b949350505050565b6000806000604084860312156113e957600080fd5b83359250602084013567ffffffffffffffff81111561140757600080fd5b61133186828701611150565b60006020828403121561142557600080fd5b5035919050565b6020808252600390820152621e125960ea1b604082015260600190565b600181811c9082168061145d57607f821691505b60208210810361114a57634e487b7160e01b600052602260045260246000fd5b6000808335601e1984360301811261149457600080fd5b83018035915067ffffffffffffffff8211156114af57600080fd5b602001915036819003821315610f3c57600080fd5b634e487b7160e01b600052604160045260246000fd5b601f82111561152457600081815260208120601f850160051c810160208610156115015750805b601f850160051c820191505b818110156115205782815560010161150d565b5050505b505050565b67ffffffffffffffff831115611541576115416114c4565b6115558361154f8354611449565b836114da565b6000601f84116001811461158957600085156115715750838201355b600019600387901b1c1916600186901b1783556115e3565b600083815260209020601f19861690835b828110156115ba578685013582556020948501946001909201910161159a565b50868210156115d75760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b0385168152836020820152606060408201526000610da56060830184866115ea565b60006020828403121561164d57600080fd5b81516112288161122f565b80516001600160c81b03198116811461167057600080fd5b919050565b600082601f83011261168657600080fd5b815167ffffffffffffffff808211156116a1576116a16114c4565b604051601f8301601f19908116603f011681019082821181831017156116c9576116c96114c4565b816040528381528660208588010111156116e257600080fd5b610da5846020830160208901611272565b60008060008060008060008060006101208a8c03121561171257600080fd5b895161171d816110f3565b60208b015190995061172e816110f3565b60408b015190985061173f816110f3565b965061174d60608b01611658565b955060808a0151945060a08a0151611764816110f3565b935061177260c08b01611658565b925060e08a0151801515811461178757600080fd5b6101008b015190925067ffffffffffffffff8111156117a557600080fd5b6117b18c828d01611675565b9150509295985092959850929598565b6001600160a01b03851681526001600160601b0384166020820152606060408201819052600090610da590830184866115ea565b8183823760009101908152919050565b8381526040602082015260006103f66040830184866115ea565b634e487b7160e01b600052602160045260246000fd5b8281526040602082015260006113cc6040830184611296565b60008251611860818460208701611272565b9190910192915050565b60006020828403121561187c57600080fd5b505191905056fea2646970667358221220c46037ef2a22106778ef28d541adf8fede783729a5f6b79ee15a9eb975d873fe64736f6c63430008130033000000000000000000000000b47c8e4beb28af80ede5e5bf474927b110ef2c0e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ba0000c28179ce533233a943d432eddd154e62a3

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101375760003560e01c806382a7576b116100b85780639a8a05921161007c5780639a8a05921461028c578063d212b5d314610295578063d7bcf546146102a8578063efed64be146102c8578063f2fde38b146102db578063faf8dbfb146102ee57600080fd5b806382a7576b1461022657806389ccfe89146102395780638da5cb5b1461024157806390eff5c414610266578063936525071461027957600080fd5b80634372ff85116100ff5780634372ff85146101c25780634f011a65146101d55780636704126f146101e8578063715018a6146101fb57806376e63bb01461020357600080fd5b806318cb9c1d1461013c57806320e4ff85146101515780632dd372e61461017957806331995fda1461018c5780633644e515146101ac575b600080fd5b61014f61014a366004611108565b610301565b005b61016461015f366004611192565b6103ab565b60405190151581526020015b60405180910390f35b61014f61018736600461120b565b6103ff565b61019f61019a366004611244565b610429565b60405161017091906112c2565b6101b46104ce565b604051908152602001610170565b61014f6101d036600461120b565b6104ed565b61014f6101e33660046112d5565b610519565b61014f6101f636600461133e565b610729565b61014f61099e565b61016461021136600461120b565b60046020526000908152604090205460ff1681565b61014f610234366004611108565b6109b2565b61014f610a6f565b6000546001600160a01b03165b6040516001600160a01b039091168152602001610170565b6101b4610274366004611397565b610ad1565b61014f6102873660046113d4565b610bba565b6101b460015481565b60035461024e906001600160a01b031681565b6101b46102b636600461120b565b60056020526000908152604090205481565b61019f6102d6366004611413565b610c93565b61014f6102e936600461120b565b610cac565b61014f6102fc36600461120b565b610d25565b8160000361032b57604051634389d5ab60e01b81526004016103229061142c565b60405180910390fd5b33600090815260056020526040902054821461035a5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381166000908152600560205260409020541561039157604051639688dc5160e01b815260040160405180910390fd5b6001600160a01b0316600090815260056020526040902055565b60006103f6856103ba86610ad1565b85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610d4e92505050565b95945050505050565b610407610daf565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60076020908152600092835260408084209091529082529020805461044d90611449565b80601f016020809104026020016040519081016040528092919081815260200182805461047990611449565b80156104c65780601f1061049b576101008083540402835291602001916104c6565b820191906000526020600020905b8154815290600101906020018083116104a957829003601f168201915b505050505081565b600060015446146104e6576104e1610e09565b905090565b5060025490565b6104f5610daf565b6001600160a01b03166000908152600460205260409020805460ff19166001179055565b610526602084018461120b565b6001600160a01b0316336001600160a01b0316146105575760405163ea8e4eb560e01b815260040160405180910390fd5b826020013560000361059a57604051634389d5ab60e01b815260206004820152600b60248201526a1c185e5b1bd8590b9e125960aa1b6044820152606401610322565b600560006105ab602086018661120b565b6001600160a01b03168152602081019190915260400160002054156105e357604051639688dc5160e01b815260040160405180910390fd5b6105f0604084018461147d565b905060000361063457604051634389d5ab60e01b815260206004820152600f60248201526e1c185e5b1bd8590b9a5c199cd0d251608a1b6044820152606401610322565b60035461064c906001600160a01b03168484846103ab565b61066957604051638baa579f60e01b815260040160405180910390fd5b60208301803590600590600090610680908761120b565b6001600160a01b0316815260208101919091526040908101600020919091556106ab9084018461147d565b6020808601356000908152600690915260409020916106cb919083611529565b507f8d71b236876fe8aa8294fe7f3c63662bfc3fc1a240fdbe49488b37f3366958fc6106fa602085018561120b565b602085013561070c604087018761147d565b60405161071c9493929190611613565b60405180910390a1505050565b6001600160a01b03841660009081526004602052604090205460ff1661078157604051634389d5ab60e01b815260206004820152600c60248201526b61756374696f6e486f75736560a01b6044820152606401610322565b6000849050806001600160a01b031663c4ce88fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107c4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e8919061163b565b6001600160601b0316846001600160601b03161061083157604051634389d5ab60e01b81526020600482015260056024820152641b1bdd125960da1b6044820152606401610322565b604051634f17001d60e11b81526001600160601b03851660048201526000906001600160a01b03831690639e2e003a90602401600060405180830381865afa158015610881573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526108a991908101906116f3565b50505050505050509050806001600160a01b0316336001600160a01b0316146108e55760405163ea8e4eb560e01b815260040160405180910390fd5b600083900361092157604051634389d5ab60e01b81526020600482015260076024820152661a5c199cd0d25160ca1b6044820152606401610322565b6001600160a01b03861660009081526007602090815260408083206001600160601b03891684529091529020610958848683611529565b507f18b40f4816934f1a7bd5ff51d87f48d9ddacbd7653b2cde31a904cbd3c30b5248686868660405161098e94939291906117c1565b60405180910390a1505050505050565b6109a6610daf565b6109b06000610eae565b565b816000036109d357604051634389d5ab60e01b81526004016103229061142c565b336000908152600560205260409020548214610a025760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381166000908152600560205260409020548214610a5457604051634389d5ab60e01b815260206004820152600760248201526631bab930ba37b960c91b6044820152606401610322565b6001600160a01b031660009081526005602052604081205550565b6001544603610ac05760405162461bcd60e51b815260206004820181905260248201527f444f4d41494e5f534550415241544f525f414c52454144595f555044415445446044820152606401610322565b46600155610acc610e09565b600255565b6000610adb6104ce565b7f1378000983868b9cd38cd6c7408ceb9051309140ca9bff5d199043ae5649938c610b09602085018561120b565b6020850135610b1b604087018761147d565b604051610b299291906117f5565b604051908190038120610b60949392916020019384526001600160a01b039290921660208401526040830152606082015260800190565b60405160208183030381529060405280519060200120604051602001610b9d92919061190160f01b81526002810192909252602282015260420190565b604051602081830303815290604052805190602001209050919050565b82600003610bdb57604051634389d5ab60e01b81526004016103229061142c565b336000908152600560205260409020548314610c0a5760405163ea8e4eb560e01b815260040160405180910390fd5b6000819003610c4657604051634389d5ab60e01b81526020600482015260076024820152661a5c199cd0d25160ca1b6044820152606401610322565b6000838152600660205260409020610c5f828483611529565b507f8d48f79a76a920c2d4e03ef6f1c031c427129a9bd429bb36523fc25cc1e4ea6883838360405161071c93929190611805565b6006602052600090815260409020805461044d90611449565b610cb4610daf565b6001600160a01b038116610d195760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610322565b610d2281610eae565b50565b610d2d610daf565b6001600160a01b03166000908152600460205260409020805460ff19169055565b6000806000610d5d8585610efe565b90925090506000816004811115610d7657610d7661181f565b148015610d945750856001600160a01b0316826001600160a01b0316145b80610da55750610da5868686610f43565b9695505050505050565b6000546001600160a01b031633146109b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610322565b604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f4873d266cc369576c1140f197e29f2f69e4e0a34e63dac384a5a61ccd6762dbb918101919091527f15124d26d1272f8d4d5266a24ca397811f414b8cd05a53b26b745f63af5ae2fc60608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000808251604103610f345760208301516040840151606085015160001a610f288782858561102f565b94509450505050610f3c565b506000905060025b9250929050565b6000806000856001600160a01b0316631626ba7e60e01b8686604051602401610f6d929190611835565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610fab919061184e565b600060405180830381855afa9150503d8060008114610fe6576040519150601f19603f3d011682016040523d82523d6000602084013e610feb565b606091505b5091509150818015610fff57506020815110155b8015610da557508051630b135d3f60e11b90611024908301602090810190840161186a565b149695505050505050565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561106657506000905060036110ea565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156110ba573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166110e3576000600192509250506110ea565b9150600090505b94509492505050565b6001600160a01b0381168114610d2257600080fd5b6000806040838503121561111b57600080fd5b82359150602083013561112d816110f3565b809150509250929050565b60006060828403121561114a57600080fd5b50919050565b60008083601f84011261116257600080fd5b50813567ffffffffffffffff81111561117a57600080fd5b602083019150836020828501011115610f3c57600080fd5b600080600080606085870312156111a857600080fd5b84356111b3816110f3565b9350602085013567ffffffffffffffff808211156111d057600080fd5b6111dc88838901611138565b945060408701359150808211156111f257600080fd5b506111ff87828801611150565b95989497509550505050565b60006020828403121561121d57600080fd5b8135611228816110f3565b9392505050565b6001600160601b0381168114610d2257600080fd5b6000806040838503121561125757600080fd5b8235611262816110f3565b9150602083013561112d8161122f565b60005b8381101561128d578181015183820152602001611275565b50506000910152565b600081518084526112ae816020860160208601611272565b601f01601f19169290920160200192915050565b6020815260006112286020830184611296565b6000806000604084860312156112ea57600080fd5b833567ffffffffffffffff8082111561130257600080fd5b61130e87838801611138565b9450602086013591508082111561132457600080fd5b5061133186828701611150565b9497909650939450505050565b6000806000806060858703121561135457600080fd5b843561135f816110f3565b9350602085013561136f8161122f565b9250604085013567ffffffffffffffff81111561138b57600080fd5b6111ff87828801611150565b6000602082840312156113a957600080fd5b813567ffffffffffffffff8111156113c057600080fd5b6113cc84828501611138565b949350505050565b6000806000604084860312156113e957600080fd5b83359250602084013567ffffffffffffffff81111561140757600080fd5b61133186828701611150565b60006020828403121561142557600080fd5b5035919050565b6020808252600390820152621e125960ea1b604082015260600190565b600181811c9082168061145d57607f821691505b60208210810361114a57634e487b7160e01b600052602260045260246000fd5b6000808335601e1984360301811261149457600080fd5b83018035915067ffffffffffffffff8211156114af57600080fd5b602001915036819003821315610f3c57600080fd5b634e487b7160e01b600052604160045260246000fd5b601f82111561152457600081815260208120601f850160051c810160208610156115015750805b601f850160051c820191505b818110156115205782815560010161150d565b5050505b505050565b67ffffffffffffffff831115611541576115416114c4565b6115558361154f8354611449565b836114da565b6000601f84116001811461158957600085156115715750838201355b600019600387901b1c1916600186901b1783556115e3565b600083815260209020601f19861690835b828110156115ba578685013582556020948501946001909201910161159a565b50868210156115d75760001960f88860031b161c19848701351681555b505060018560011b0183555b5050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60018060a01b0385168152836020820152606060408201526000610da56060830184866115ea565b60006020828403121561164d57600080fd5b81516112288161122f565b80516001600160c81b03198116811461167057600080fd5b919050565b600082601f83011261168657600080fd5b815167ffffffffffffffff808211156116a1576116a16114c4565b604051601f8301601f19908116603f011681019082821181831017156116c9576116c96114c4565b816040528381528660208588010111156116e257600080fd5b610da5846020830160208901611272565b60008060008060008060008060006101208a8c03121561171257600080fd5b895161171d816110f3565b60208b015190995061172e816110f3565b60408b015190985061173f816110f3565b965061174d60608b01611658565b955060808a0151945060a08a0151611764816110f3565b935061177260c08b01611658565b925060e08a0151801515811461178757600080fd5b6101008b015190925067ffffffffffffffff8111156117a557600080fd5b6117b18c828d01611675565b9150509295985092959850929598565b6001600160a01b03851681526001600160601b0384166020820152606060408201819052600090610da590830184866115ea565b8183823760009101908152919050565b8381526040602082015260006103f66040830184866115ea565b634e487b7160e01b600052602160045260246000fd5b8281526040602082015260006113cc6040830184611296565b60008251611860818460208701611272565b9190910192915050565b60006020828403121561187c57600080fd5b505191905056fea2646970667358221220c46037ef2a22106778ef28d541adf8fede783729a5f6b79ee15a9eb975d873fe64736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b47c8e4beb28af80ede5e5bf474927b110ef2c0e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ba0000c28179ce533233a943d432eddd154e62a3

-----Decoded View---------------
Arg [0] : serviceSigner_ (address): 0xB47C8e4bEb28af80eDe5E5bF474927b110Ef2c0e
Arg [1] : auctionHouses_ (address[]): 0xBA0000c28179CE533233a943d432eddD154E62A3

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000b47c8e4beb28af80ede5e5bf474927b110ef2c0e
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [3] : 000000000000000000000000ba0000c28179ce533233a943d432eddd154e62a3


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.