账户
0x79...322c
0x79...322c

0x79...322c

$500
此合同的源代码已经过验证!
合同元数据
编译器
0.8.24+commit.e11b9ed9
语言
Solidity
合同源代码
文件 1 的 11:Assign.sol
// SPDX-License-Identifier: MIT OR Apache-2

pragma solidity ^0.8.24;

import "@openzeppelin/contracts/access/Ownable.sol";

import "./interface/IInfra.sol";
import "./interface/IAssign.sol";
import "./interface/IPriceOracle.sol";
import "./libraries/IdProvider.sol";

contract Assign is IAssign, Ownable {
    using IdProvider for IdProvider.Ids;

    /**
     * @dev The infra contract, for combined create/assign and update/assign.
     */
    IInfra immutable self_infra;

    /**
     * @dev An ID provider which reuses IDs when possible
     */
    IdProvider.Ids private self_ids;

    /**
     * @dev All assignments
     */
    mapping(uint => Assignment) self_assignments;
    
    /**
     * @dev Assignment ID by hash(owner + unit)
     */
    mapping(bytes => uint) self_assignmentIdByOwnerUnit;

    /**
     * @dev The source of price of the asset.
     */
    IPriceOracle private self_priceOracle;

    /**
     * @param infra The infra contract
     */
    constructor(address infra, address priceOracle) Ownable(msg.sender) {
        self_infra = IInfra(infra);
        self_ids.init();
        self_priceOracle = IPriceOracle(priceOracle);
    }

    function assignByOwnerUnit(address owner, uint unitId) public override view returns (uint) {
        return self_assignmentIdByOwnerUnit[abi.encode(owner, unitId)];
    }

    function assignYc(uint unitId, uint256 yieldCredits) public override
    {
        uint aid = assignByOwnerUnit(msg.sender, unitId);
        uint valueUsd = self_priceOracle.getUpdatePriceUsd();
        if (aid == 0) {
            if (yieldCredits == 0) {
                return;
            }
            aid = self_ids.take();
            Assignment storage ass = self_assignments[aid];
            ass.owner = msg.sender;
            ass.unitId = unitId;
            ass.yieldCredits = yieldCredits;
            ass.valueUsd = valueUsd;
            ass.timestamp = uint64(block.timestamp);
            self_assignmentIdByOwnerUnit[abi.encode(msg.sender, unitId)] = aid;
        } else if (yieldCredits == 0) {
            delete self_assignmentIdByOwnerUnit[abi.encode(msg.sender, unitId)];
            delete self_assignments[aid];
            self_ids.release(aid);
        } else {
            Assignment storage ass = self_assignments[aid];
            ass.yieldCredits = yieldCredits;
            ass.valueUsd = valueUsd;
            ass.timestamp = uint64(block.timestamp);
        }
        emit Assign(aid, msg.sender, unitId, yieldCredits, uint64(block.timestamp), valueUsd);
    }

    function getAssign(uint id) external override view returns (
        address owner,
        uint256 yieldCredits,
        uint unitId,
        uint64 timestamp,
        uint valueUsd
    ) {
        Assignment memory ass = self_assignments[id];
        owner = ass.owner;
        yieldCredits = ass.yieldCredits;
        unitId = ass.unitId;
        timestamp = ass.timestamp;
        valueUsd = ass.valueUsd;
    }

    function getAssigns(uint[] calldata ids) external override view returns (Assignment[] memory out) {
        out = new Assignment[](ids.length);
        for (uint i = 0; i < ids.length; i++) {
           out[i] = self_assignments[ids[i]];
        }
    }

    function registerAndAssign(
        IInfra.UnitType t,
        uint64 parentDomain,
        string calldata name,
        uint yieldCredits,
        address to
    ) external override returns (uint) {
        uint unitId = self_infra.registerUnit(t, parentDomain, name, to);
        assignYc(unitId, yieldCredits);
        return unitId;
    }

    function updateAndAssign(
        uint unitId,
        uint8 update,
        IInfra.UnitType t,
        uint64 parentDomain,
        string calldata name,
        uint yieldCredits
    ) external override {
        self_infra.updateUnit(unitId, update, t, parentDomain, name, msg.sender);
        assignYc(unitId, yieldCredits);
    }

    function deleteUnit(uint unitId) external override {
        self_infra.deleteUnit(unitId, msg.sender);
        assignYc(unitId, 0);
    }

    function nextId() external override view returns (uint) {
        return self_ids.nextId;
    }

    function idFreeList(uint64 last) external override view returns (uint) {
        return self_ids.freeList[last];
    }

    function setPriceOracle(address priceOracle) external onlyOwner {
        self_priceOracle = IPriceOracle(priceOracle);
    }
}
合同源代码
文件 2 的 11:Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
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;
    }
}
合同源代码
文件 3 的 11:IAssign.sol
// SPDX-License-Identifier: MIT OR Apache-2

pragma solidity ^0.8.24;

import "./IInfra.sol";

interface IAssign {
    /// The Assignment structure that is used internally.
    struct Assignment {
        /// Number of yield credits assigned
        uint yieldCredits;
        /// The unit that the credits are assigned to
        uint unitId;
        /// Who assigned the credits
        address owner;
        /// The timestamp when the assignment was created or updated
        uint64 timestamp;
        /// The USD value of 1 credit at the time the assignment was created/updated (per the PriceOracle)
        uint valueUsd;
    }

    /// An assignment has been created/updated/deleted
    ///
    /// @param id The ID of the assignment
    /// @param owner Who created the assignment
    /// @param unitId The unit that the credits were assigned to
    /// @param yieldCredits The number of credits that were assigned, 0 means deleted.
    /// @param timestamp The block timestamp when the assignment was created/updated
    /// @param valueUsd The value of 1 credit at the time of the assignment
    event Assign(uint id, address owner, uint unitId, uint256 yieldCredits, uint64 timestamp, uint valueUsd);


    function assignByOwnerUnit(address owner, uint unitId) external view returns (uint);

    function assignYc(uint unitId, uint256 yieldCredits) external;

    function getAssign(uint id) external view returns (
        address owner,
        uint256 yieldCredits,
        uint unitId,
        uint64 timestamp,
        uint valueUsd
    );

    function getAssigns(uint[] calldata ids) external view returns (Assignment[] memory out);

    function registerAndAssign(
        IInfra.UnitType t,
        uint64 parentDomain,
        string calldata name,
        uint yieldCredits,
        address to
    ) external returns (uint);

    function updateAndAssign(
        uint unitId,
        uint8 update,
        IInfra.UnitType t,
        uint64 parentDomain,
        string calldata name,
        uint yieldCredits
    ) external;

    function deleteUnit(uint unitId) external;

    /// @return The next higher Assign id to issue
    function nextId() external view returns (uint);

    /// Access the free list of unit IDs.
    ///
    /// @param last The last ID, if zero then this gives the list head
    /// @return id The next ID in the list
    function idFreeList(uint64 last) external view returns (uint id);
}
合同源代码
文件 4 的 11:IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
合同源代码
文件 5 的 11:IERC721.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Required interface of an ERC721 compliant contract.
 */
interface IERC721 is IERC165 {
    /**
     * @dev Emitted when `tokenId` token is transferred from `from` to `to`.
     */
    event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
     */
    event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);

    /**
     * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
     */
    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /**
     * @dev Returns the number of tokens in ``owner``'s account.
     */
    function balanceOf(address owner) external view returns (uint256 balance);

    /**
     * @dev Returns the owner of the `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function ownerOf(uint256 tokenId) external view returns (address owner);

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

    /**
     * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
     * are aware of the ERC721 protocol to prevent tokens from being forever locked.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must exist and be owned by `from`.
     * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
     *   {setApprovalForAll}.
     * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
     *   a safe transfer.
     *
     * Emits a {Transfer} event.
     */
    function safeTransferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Transfers `tokenId` token from `from` to `to`.
     *
     * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
     * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
     * understand this adds an external call which potentially creates a reentrancy vulnerability.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `tokenId` token must be owned by `from`.
     * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 tokenId) external;

    /**
     * @dev Gives permission to `to` to transfer `tokenId` token to another account.
     * The approval is cleared when the token is transferred.
     *
     * Only a single account can be approved at a time, so approving the zero address clears previous approvals.
     *
     * Requirements:
     *
     * - The caller must own the token or be an approved operator.
     * - `tokenId` must exist.
     *
     * Emits an {Approval} event.
     */
    function approve(address to, uint256 tokenId) external;

    /**
     * @dev Approve or remove `operator` as an operator for the caller.
     * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
     *
     * Requirements:
     *
     * - The `operator` cannot be the address zero.
     *
     * Emits an {ApprovalForAll} event.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns the account approved for `tokenId` token.
     *
     * Requirements:
     *
     * - `tokenId` must exist.
     */
    function getApproved(uint256 tokenId) external view returns (address operator);

    /**
     * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
     *
     * See {setApprovalForAll}
     */
    function isApprovedForAll(address owner, address operator) external view returns (bool);
}
合同源代码
文件 6 的 11:IERC721Enumerable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/extensions/IERC721Enumerable.sol)

pragma solidity ^0.8.20;

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

/**
 * @title ERC-721 Non-Fungible Token Standard, optional enumeration extension
 * @dev See https://eips.ethereum.org/EIPS/eip-721
 */
interface IERC721Enumerable is IERC721 {
    /**
     * @dev Returns the total amount of tokens stored by the contract.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns a token ID owned by `owner` at a given `index` of its token list.
     * Use along with {balanceOf} to enumerate all of ``owner``'s tokens.
     */
    function tokenOfOwnerByIndex(address owner, uint256 index) external view returns (uint256);

    /**
     * @dev Returns a token ID at a given `index` of all the tokens stored by the contract.
     * Use along with {totalSupply} to enumerate all tokens.
     */
    function tokenByIndex(uint256 index) external view returns (uint256);
}
合同源代码
文件 7 的 11:IERC721Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC721Metadata.sol)

pragma solidity ^0.8.20;

import {IERC721Metadata} from "../token/ERC721/extensions/IERC721Metadata.sol";
合同源代码
文件 8 的 11:IInfra.sol
// SPDX-License-Identifier: MIT OR Apache-2

pragma solidity ^0.8.24;

import "@openzeppelin/contracts/interfaces/IERC721Metadata.sol";
import "@openzeppelin/contracts/interfaces/IERC721Enumerable.sol";

// The contract for representing Infrastructure Units
// (cjdns nodes, domains VPNs, nameservers, and route servers)
// This contract is essentially declarative. You can enter anything you want and
// it will only really have effect after it's checked if the unit is actually operational.
// Each Unit is an NFT so once you create one, you can administer it.
// The contract is also Ownable and the owner can:
// 1. Nominate "trusted" contracts which can act on others' behalf.
// 2. Set the base URI for the NFT images.
//
interface IInfra is IERC721Metadata, IERC721Enumerable {
    // The type of the infra unit
    enum UnitType {

        // Unit type zero is not valid
        Invalid,

        // Cjdns public peer with VPN disabled
        Cjdns,

        // Cjdns VPN with public peering disabled
        Vpn,

        // Cjdns public peer with VPN enabled
        CjdnsVpn,

        // Cjdns private node with VPN disabled (does not yield)
        PrivateCjdns,

        // Public domain name (e.g. pkt.wiki)
        Domain,

        // Domain name which is willing to resolve blacklisted domains
        DomainDangerous,

        // Nameserver
        Nameserver,

        // Route Server
        RouteServer,

        // Invalid item
        InvalidTooHigh
    }

    // The structure which represents an infra unit
    struct Unit {
        // For cjdns/vpn/nameserver/routeserver
        //     * Non-zero = the domain to hang this node off of
        //     * Zero = .no-name.pkt special domain
        // For domains -> Always zero
        uint64 parentDomain;

        // The type of the unit
        UnitType unitType;

        // For cjdns/vpn/nameserver/routeserver -> The hostname/subdomain
        // For domains -> The FQDN
        string name;
    }

    /**
     * Emitted when a new unit is registered, anyone can cause this to be emitted
     * it does NOT mean any infrastructure actually exists.
     * @param sender The address which make the call
     * @param newId The ID of the new unit
     * @param creator Who invoked the function
     * @param recipient Who will receive the NFT of the unit and therefore yield on it
     * @param t The type of the unit
     * @param parentDomain The ID of the domain which the unit is associated with (0 = none)
     * @param name The name of the unit
     */
    event RegisterUnit(address sender, uint newId, address creator, address recipient, UnitType t,
        uint64 parentDomain, string name);

    /**
     * Emitted when someone updates some data about their infra unit.
     * @param sender The address which make the call
     * @param id The ID of the updated unit
     * @param updateMask A bitmask of items which are being updated,
     *                   see: Infra.UPDATE_TYPE, Infra.UPDATE_DOMAIN, Infra.UPDATE_NAME
     * @param t The unit type to change to, if applicable
     * @param parentDomain The new parent domain, if applicable
     * @param name The name to change to, if applicable
     */
    event UpdateUnit(address sender, uint id, uint8 updateMask, UnitType t, uint64 parentDomain, string name);

    /// Emitted when a unit is deleted
    /// 
    /// @param sender The address which make the call
    /// @param id The ID of the unit to be deleted
    event DeleteUnit(address sender, uint id);

    /// The unit got evicted by the domain holder.
    /// 
    /// @param sender The address which made the call
    /// @param id The ID of the unit that was evicted
    event DomainEvict(address sender, uint id);

    // Create/Update/Delete

    /**
     * Register a new unit.
     * Anyone can call this, it does not imply that the underlying infrastructure actually exists.
     *
     * @param t The type of the unit to register.
     * @param parentDomain The parent domain (0 = none), the caller must have authorization to
     *                     manipulate this domain, or if the caller is a trusted contract, the
     *                     recipient (to) must have same authority instead.
     * @param name The name / subdomain of the unit.
     * @param to Who will receive the resulting NFT and begin yielding on the infra unit.
     * @return The ID of the unit.
     */
    function registerUnit(
        UnitType t,
        uint64 parentDomain,
        string calldata name,
        address to
    ) external returns (uint);

    /**
     * Update data about an infra unit.
     *
     * @param id The ID of the unit to update, the caller must be authoritative over the unit.
     *           If the caller is a trusted contract (see trustContract()) then onBehalfOf may
     *           be substituted.
     * @param update The bitmask of fields to update
     *               see: Infra.UPDATE_TYPE, Infra.UPDATE_DOMAIN, Infra.UPDATE_NAME
     * @param t The type to change the item to, if applicable
     * @param parentDomain The parent domain to set, if applicable. The caller (or onBehalfOf) must
     *                     be authoritative over the domain in order to set it.
     * @param name The subdomain / name of the unit.
     * @param onBehalfOf If called from a trusted contract, authority to alter the Unit and associate
     *                   with the parentDomain will be based on this address, otherwise it is based on
     *                   the caller. If you're not a trusted contract, just pass zero.
     */
    function updateUnit(
        uint id,
        uint8 update,
        UnitType t,
        uint64 parentDomain,
        string calldata name,
        address onBehalfOf
    ) external;

    /**
     * Delete a unit.
     *
     * @param id The ID of the unit to delete.
     * @param onBehalfOf If this is being called by a trusted contract, this is the address to
     *                   impersonate, otherwise you may ignore it and pass address(0).
     */
    function deleteUnit(uint id, address onBehalfOf) external;

    /**
     * Evict a unit from being associated with your parentDomain.
     * This can be called by the owner of the domain, even if they do not have authority over the unit.
     * A possible reason why a domain holder would not have authority over the unit is because either
     * the domain, or the unit, was transferred. This allows the domain holder to evict the unit so it
     * will not affect their domain.
     *
     * @param id The ID of the unit to evict.
     */
    function domainEviction(uint id) external;

    // Read

    /**
     * Get a single unit by ID.
     *
     * @param id The ID of the unit to get.
     * @return t The type of the unit, if zero then this unit does not exist.
     * @return parentDomain The parent domain of the unit.
     * @return name The name of the unit.
     * @return owner The owner of the unit.
     */
    function getUnit(uint id) external view returns (
        UnitType t,
        uint64 parentDomain,
        string memory name,
        address owner
    );

    /**
     * Get multiple units by ID.
     *
     * @param ids An array of the IDs of units to get.
     * @return out An array of the resulting units.
     * @return owners An array of the owners of units, address(0) means there is a unit that was deleted.
     */
    function getUnits(
        uint[] calldata ids
    ) external view returns (
        Unit[] memory out,
        address[] memory owners
    );

    /**
     * Check whether an address is considered a trusted contract.
     * Trusted addresses can impersonate other addresses for the purpose of the
     * registerUnit() updateUnit() and deleteUnit() functions.
     * 
     * @param c The address to check
     * @return trusted whether or not the address is trusted to impersonate others
     */
    function isTrustedContract(address c) external view returns (bool trusted);

    /**
     * @return The next higher Unit id to issue
     */
    function nextId() external view returns (uint);

    /**
     * Access the free list of unit IDs.
     *
     * @param last The last ID, if zero then this gives the list head
     * @return id The next ID in the list
     */
    function idFreeList(uint64 last) external view returns (uint id);

    // Administrative

    /**
     * Update the URI prefix for rendering of NFT images.
     * Can only be called by the owner of the contract.
     *
     * @param pfx New URI prefix.
     */
    function setUriPrefix(string calldata pfx) external;

    /**
     * Set the trusted status of an address. Trusted addresses (contracts) can impersonate other
     * addresses for the purpose of the registerUnit() updateUnit() and deleteUnit() functions.
     *
     * @param c The address
     * @param trusted True if the address should be trusted.
     */
    function trustContract(address c, bool trusted) external;

    /**
     * Change the DNS contract, in case it needs to be upgraded.
     *
     * @param pns The new PNS contract address.
     */
    function setPns(address pns) external;
}
合同源代码
文件 9 的 11:IPriceOracle.sol
// SPDX-License-Identifier: MIT OR Apache-2

pragma solidity ^0.8.24;

interface IPriceOracle {
    function getUpdatePriceUsd() external returns (uint256);
    function viewPriceUsd() external view returns (uint256);
}
合同源代码
文件 10 的 11:IdProvider.sol
// SPDX-License-Identifier: MIT OR Apache-2

pragma solidity ^0.8.24;

library IdProvider {
    struct Ids {
        mapping(uint => uint) freeList;
        uint nextId;
    }

    // Initialize the state for IDManager
    function init(Ids storage self) internal {
        self.nextId = 1; // Start the ID counter from 1 (or whatever number you'd like)
    }

    // Take an ID, either from the free list or by incrementing the next ID
    function take(Ids storage self) internal returns (uint id) {
        id = self.freeList[0];
        if (id > 0) {
            // Reuse an ID from the free list
            self.freeList[0] = self.freeList[id];
            delete self.freeList[id];
        } else {
            // No free IDs, use the next available ID
            id = self.nextId++;
        }
    }

    // Release an ID, adding it to the free list
    function release(Ids storage self, uint id) internal {
        uint fdid = self.freeList[0];
        if (fdid > 0) {
            self.freeList[id] = fdid;
        }
        self.freeList[0] = id;
    }
}
合同源代码
文件 11 的 11:Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

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

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

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

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    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 {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    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 {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
设置
{
  "compilationTarget": {
    "contracts/Assign.sol": "Assign"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"address","name":"infra","type":"address"},{"internalType":"address","name":"priceOracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"id","type":"uint256"},{"indexed":false,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"unitId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"yieldCredits","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"timestamp","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"valueUsd","type":"uint256"}],"name":"Assign","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":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"unitId","type":"uint256"}],"name":"assignByOwnerUnit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"unitId","type":"uint256"},{"internalType":"uint256","name":"yieldCredits","type":"uint256"}],"name":"assignYc","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unitId","type":"uint256"}],"name":"deleteUnit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getAssign","outputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"yieldCredits","type":"uint256"},{"internalType":"uint256","name":"unitId","type":"uint256"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint256","name":"valueUsd","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"ids","type":"uint256[]"}],"name":"getAssigns","outputs":[{"components":[{"internalType":"uint256","name":"yieldCredits","type":"uint256"},{"internalType":"uint256","name":"unitId","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint64","name":"timestamp","type":"uint64"},{"internalType":"uint256","name":"valueUsd","type":"uint256"}],"internalType":"struct IAssign.Assignment[]","name":"out","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"last","type":"uint64"}],"name":"idFreeList","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"enum IInfra.UnitType","name":"t","type":"uint8"},{"internalType":"uint64","name":"parentDomain","type":"uint64"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"yieldCredits","type":"uint256"},{"internalType":"address","name":"to","type":"address"}],"name":"registerAndAssign","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"priceOracle","type":"address"}],"name":"setPriceOracle","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"unitId","type":"uint256"},{"internalType":"uint8","name":"update","type":"uint8"},{"internalType":"enum IInfra.UnitType","name":"t","type":"uint8"},{"internalType":"uint64","name":"parentDomain","type":"uint64"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"yieldCredits","type":"uint256"}],"name":"updateAndAssign","outputs":[],"stateMutability":"nonpayable","type":"function"}]