跳至正文
Wener Notes

Ethereum

约 14 分钟阅读

EIP

EIPNameStatusNotes
EIP-20Token StandardFinalERC-20 - Fungible Token/同质货币
[EIP-137]Ethereum Domain Name ServiceFinal
EIP-155Simple replay attack protectionFinalfork block 2,675,000 - hash(transaction) 包含 chainId
EIP-165Standard Interface DetectionFinalERC-165 - 检测合约是否实现 接口
EIP-191Signed Data StandardFinal
EIP-165Standard Interface DetectionFinal
EIP-712Ethereum typed structured data hashing and signingRevieweth_signTypedData
EIP-721Non-Fungible Token StandardFinal&EIP-165
EIP-777Token StandardFinalERC-20+ - Hooks,Decimals
[EIP-1066]Status Codes
[EIP-1102]Opt-in Account Exposure
[EIP-1155]Multi Token StandardFinal合约支持多种货币 - BNB,BNB, BAT
EIP-1167Minimal Proxy ContractFinal实现代理合约
EIP-1193Ethereum Provider JavaScript APIwindow.ethereum
EIP-1363Payable TokenFinalpayable
[EIP-1400]
[EIP-1474]Remote Procedure Call Specification
[EIP-1559]Fee market change for ETH 1.0 chainFinal
[EIP-1767]GraphQL Interface to Ethereum Node Data
EIP-1820Pseudo-introspection Registry ContractERC-165+
[EIP-1822]Universal Upgradeable Proxy Standard/UUPS
EIP-1967Proxy Storage Slots
[EIP-2718]Typed Transaction EnvelopeFinal
[EIP-2255]Wallet Permissions
EIP-2612permitReviewERC-20+ERC-712
EIP-2981NFT Royalty StandardFinal
EIP-3722Poster: A ridiculously simple general purpose social media smart contract
EIP-4626Tokenized Vault StandardFinal
[EIP-4675]Multi-Fractional Non-Fungible Token Standard
[EIP-6093]Custom errors for commonly-used tokens
EIP-7928Block-Level Access Lists, BALs

EIP <-> ERC

  • EIP = ERC
  • EIP - Ethereum Improvement Proposals
  • ERC - Ethereum Request for Comments

Fungible Token/同质货币

  • 可交换 / transfer
InterfaceERC-165 ID
ERC1650x01ffc9a7
ERC7210x80ac58cd
ERC721TokenReceiver0x150b7a02
ERC721Metadata0x5b5e139f
ERC721Enumerable0x780e9d63

RPC

TypeScript
interface RPC {
  // EIP-2255
  wallet_requestPermissions(request: { eth_accounts: object }): Promise<object>;
  wallet_getPermissions(
    request: Record<string, { requiredMethods: string[] }>,
  ): Promise<Array<{ invoker: string; parentCapability: string; caveats: Array<{ type: string; value: string }> }>>;
  // EIP-747
  wallet_watchAsset(request: {
    type: 'ERC:20';
    options: { address: string; image?: string; decimals?: number; symbol?: string };
  }): Promise<boolean>;
}

EIP-155

EIP-165

  • 检测合约是否实现 接口
  • interfaceID - bytes4(keccak256('supportsInterface(bytes4)'))=0x01ffc9a7
  • < 30,000 gas
  • 多个接口为 xor
solidity
interface ERC165 {
  function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

EIP-191

versioneiptitle
0x00EIP-191Data with intended validator
0x01EIP-712Structured data
0x45EIP-191personal_sign messages
  • signed_data - 0x19 <1 byte version> <version specific data> <data to sign>.

EIP-712

结构化签名数据

  • eth_signTypedData(address,typedData) - 增强 eth_sendTransaction 和 eth_sign 的签名能力
    • sign(keccak256("\x19Ethereum Signed Message:\n" + len(message) + message)))
  • domainSeparator = hashStruct(eip712Domain)
solidity
struct EIP712Domain {
  string name;
  string version;
  uint256 chainId; //  EIP-155
  address verifyingContract;
  bytes32 salt;
}
TypedData
{
  "type": "object",
  "properties": {
    "types": {
      "type": "object",
      "properties": {
        "EIP712Domain": { "type": "array" }
      },
      "additionalProperties": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "name": { "type": "string" },
            "type": { "type": "string" }
          },
          "required": ["name", "type"]
        }
      },
      "required": ["EIP712Domain"]
    },
    "primaryType": { "type": "string" },
    "domain": { "type": "object" },
    "message": { "type": "object" }
  },
  "required": ["types", "primaryType", "domain", "message"]
}

ERC-1155

solidity
function balanceOfBatch(address[] calldata _owners, uint256[] calldata _ids) external view returns (uint256[] memory);

function setApprovalForAll(address _operator, bool _approved) external;

function isApprovedForAll(address _owner, address _operator) external view returns (bool);

function onERC1155BatchReceived(
  address _operator,
  address _from,
  uint256[] calldata _ids,
  uint256[] calldata _values,
  bytes calldata _data
) external returns (bytes4);

EIP-1167

solidity
contract ThingFactory is Ownable, CloneFactory {
  address public libraryAddress;

  event ThingCreated(address newThingAddress);

  function ThingFactory(address _libraryAddress) public {
    libraryAddress = _libraryAddress;
  }

  function setLibraryAddress(address _libraryAddress) public onlyOwner {
    libraryAddress = _libraryAddress;
  }

  function createThing(string _name, uint256 _value) public onlyOwner {
    // 创建副本你
    address clone = createClone(libraryAddress);
    Thing(clone).init(_name, _value);
    ThingCreated(clone);
  }
}

EIP-1363

  • payable
  • ERC-20
solidity
/* is ERC20, ERC165 */
interface ERC1363 {
  /**
   * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @return true unless throwing
   */
  function transferAndCall(address to, uint256 value) external returns (bool);

  /**
   * @notice Transfer tokens from `msg.sender` to another address and then call `onTransferReceived` on receiver
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @param data bytes Additional data with no specified format, sent in call to `to`
   * @return true unless throwing
   */
  function transferAndCall(
    address to,
    uint256 value,
    bytes memory data
  ) external returns (bool);

  /**
   * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @return true unless throwing
   */
  function transferFromAndCall(
    address from,
    address to,
    uint256 value
  ) external returns (bool);

  /**
   * @notice Transfer tokens from one address to another and then call `onTransferReceived` on receiver
   * @param from address The address which you want to send tokens from
   * @param to address The address which you want to transfer to
   * @param value uint256 The amount of tokens to be transferred
   * @param data bytes Additional data with no specified format, sent in call to `to`
   * @return true unless throwing
   */
  function transferFromAndCall(
    address from,
    address to,
    uint256 value,
    bytes memory data
  ) external returns (bool);

  /**
   * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
   * and then call `onApprovalReceived` on spender.
   * @param spender address The address which will spend the funds
   * @param value uint256 The amount of tokens to be spent
   */
  function approveAndCall(address spender, uint256 value) external returns (bool);

  /**
   * @notice Approve the passed address to spend the specified amount of tokens on behalf of msg.sender
   * and then call `onApprovalReceived` on spender.
   * @param spender address The address which will spend the funds
   * @param value uint256 The amount of tokens to be spent
   * @param data bytes Additional data with no specified format, sent in call to `spender`
   */
  function approveAndCall(
    address spender,
    uint256 value,
    bytes memory data
  ) external returns (bool);
}

interface ERC20 {
  function totalSupply() external view returns (uint256);

  function balanceOf(address account) external view returns (uint256);

  function transfer(address recipient, uint256 amount) external returns (bool);

  function transferFrom(
    address sender,
    address recipient,
    uint256 amount
  ) external returns (bool);

  function allowance(address owner, address spender) external view returns (uint256);

  function approve(address spender, uint256 amount) external returns (bool);

  event Transfer(address indexed from, address indexed to, uint256 value);
  event Approval(address indexed owner, address indexed spender, uint256 value);
}

interface ERC165 {
  function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

/**
 * @title ERC1363Receiver interface
 * @dev Interface for any contract that wants to support `transferAndCall` or `transferFromAndCall`
 *  from ERC1363 token contracts.
 */
interface ERC1363Receiver {
  /*
   * Note: the ERC-165 identifier for this interface is 0x88a7ca5c.
   * 0x88a7ca5c === bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))
   */

  /**
   * @notice Handle the receipt of ERC1363 tokens
   * @dev Any ERC1363 smart contract calls this function on the recipient
   * after a `transfer` or a `transferFrom`. This function MAY throw to revert and reject the
   * transfer. Return of other than the magic value MUST result in the
   * transaction being reverted.
   * Note: the token contract address is always the message sender.
   * @param operator address The address which called `transferAndCall` or `transferFromAndCall` function
   * @param from address The address which are token transferred from
   * @param value uint256 The amount of tokens transferred
   * @param data bytes Additional data with no specified format
   * @return `bytes4(keccak256("onTransferReceived(address,address,uint256,bytes)"))`
   *  unless throwing
   */
  function onTransferReceived(
    address operator,
    address from,
    uint256 value,
    bytes memory data
  ) external returns (bytes4);
}

/**
 * @title ERC1363Spender interface
 * @dev Interface for any contract that wants to support `approveAndCall`
 *  from ERC1363 token contracts.
 */
interface ERC1363Spender {
  /*
   * Note: the ERC-165 identifier for this interface is 0x7b04a2d0.
   * 0x7b04a2d0 === bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))
   */

  /**
   * @notice Handle the approval of ERC1363 tokens
   * @dev Any ERC1363 smart contract calls this function on the recipient
   * after an `approve`. This function MAY throw to revert and reject the
   * approval. Return of other than the magic value MUST result in the
   * transaction being reverted.
   * Note: the token contract address is always the message sender.
   * @param owner address The address which called `approveAndCall` function
   * @param value uint256 The amount of tokens to be spent
   * @param data bytes Additional data with no specified format
   * @return `bytes4(keccak256("onApprovalReceived(address,uint256,bytes)"))`
   *  unless throwing
   */
  function onApprovalReceived(
    address owner,
    uint256 value,
    bytes memory data
  ) external returns (bytes4);
}

EIP-1820

  • ERC1820Registry
  • 0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24
  • interfaceHash
  • 实现 - 返回 ERC1820_ACCEPT_MAGIC=keccak256(abi.encodePacked("ERC1820_ACCEPT_MAGIC"))
  • ERC###XXXXX
    • ### 为编号
    • XXXXX 为接口名字
text
keccak256("ERC20Token")
keccak256("ERC777Token")
keccak256("ERC777TokensSender")
keccak256("ERC777TokensRecipient")

实现需要实现的接口

solidity
interface _implementer {
  function canImplementInterfaceForAddress(bytes32 interfaceHash, address addr) external view returns (bytes32);
}

注册中心

  • setInterfaceImplementer - 为地址设置实现
    • _addr 与 _implementer 不同时 则 _implementer 必须实现 ERC1820ImplementerInterface
solidity
interface ERC1820Registry {
  event InterfaceImplementerSet(address indexed addr, bytes32 indexed interfaceHash, address indexed implementer);
  event ManagerChanged(address indexed addr, address indexed newManager);

  function getInterfaceImplementer(address _addr, bytes32 _interfaceHash) external view returns (address);

  function setInterfaceImplementer(
    address _addr,
    bytes32 _interfaceHash,
    address _implementer
  ) external;

  function setManager(address _addr, address _newManager) external;

  function getManager(address _addr) public view returns (address);

  function interfaceHash(string calldata _interfaceName) external pure returns (bytes32);
}

EIP-1967

solidity
/**
 * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an
 * implementation address that can be changed. This address is stored in storage in the location specified by
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the
 * implementation behind the proxy.
 */
contract ERC1967Proxy is Proxy, ERC1967Upgrade {
    /**
     * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.
     *
     * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded
     * function call, and allows initializing the storage of the proxy like a Solidity constructor.
     */
    constructor(address _logic, bytes memory _data) payable {
        assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1));
        _upgradeToAndCall(_logic, _data, false);
    }

    /**
     * @dev Returns the current implementation address.
     */
    function _implementation() internal view virtual override returns (address impl) {
        return ERC1967Upgrade._getImplementation();
    }
}

/**
 * @dev This abstract contract provides getters and event emitting update functions for
 * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
 */
abstract contract ERC1967Upgrade {
    // This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;

    /**
     * @dev Storage slot with the address of the current implementation.
     * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;

    /**
     * @dev Emitted when the implementation is upgraded.
     */
    event Upgraded(address indexed implementation);

    /**
     * @dev Returns the current implementation address.
     */
    function _getImplementation() internal view returns (address) {
        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 implementation slot.
     */
    function _setImplementation(address newImplementation) private {
        require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
    }

    /**
     * @dev Perform implementation upgrade
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeTo(address newImplementation) internal {
        _setImplementation(newImplementation);
        emit Upgraded(newImplementation);
    }

    /**
     * @dev Perform implementation upgrade with additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCall(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        _upgradeTo(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }
    }

    /**
     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
     *
     * Emits an {Upgraded} event.
     */
    function _upgradeToAndCallSecure(
        address newImplementation,
        bytes memory data,
        bool forceCall
    ) internal {
        address oldImplementation = _getImplementation();

        // Initial upgrade and setup call
        _setImplementation(newImplementation);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(newImplementation, data);
        }

        // Perform rollback test if not already in progress
        StorageSlot.BooleanSlot storage rollbackTesting = StorageSlot.getBooleanSlot(_ROLLBACK_SLOT);
        if (!rollbackTesting.value) {
            // Trigger rollback using upgradeTo from the new implementation
            rollbackTesting.value = true;
            Address.functionDelegateCall(
                newImplementation,
                abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
            );
            rollbackTesting.value = false;
            // Check rollback was effective
            require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
            // Finally reset to the new implementation and log the upgrade
            _upgradeTo(newImplementation);
        }
    }

    /**
     * @dev Storage slot with the admin of the contract.
     * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
     * validated in the constructor.
     */
    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    /**
     * @dev Emitted when the admin account has changed.
     */
    event AdminChanged(address previousAdmin, address newAdmin);

    /**
     * @dev Returns the current admin.
     */
    function _getAdmin() internal view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }

    /**
     * @dev Stores a new address in the EIP1967 admin slot.
     */
    function _setAdmin(address newAdmin) private {
        require(newAdmin != address(0), "ERC1967: new admin is the zero address");
        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
    }

    /**
     * @dev Changes the admin of the proxy.
     *
     * Emits an {AdminChanged} event.
     */
    function _changeAdmin(address newAdmin) internal {
        emit AdminChanged(_getAdmin(), newAdmin);
        _setAdmin(newAdmin);
    }

    /**
     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
     */
    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;

    /**
     * @dev Emitted when the beacon is upgraded.
     */
    event BeaconUpgraded(address indexed beacon);

    /**
     * @dev Returns the current beacon.
     */
    function _getBeacon() internal view returns (address) {
        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;
    }

    /**
     * @dev Stores a new beacon in the EIP1967 beacon slot.
     */
    function _setBeacon(address newBeacon) private {
        require(Address.isContract(newBeacon), "ERC1967: new beacon is not a contract");
        require(
            Address.isContract(IBeacon(newBeacon).implementation()),
            "ERC1967: beacon implementation is not a contract"
        );
        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;
    }

    /**
     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
     *
     * Emits a {BeaconUpgraded} event.
     */
    function _upgradeBeaconToAndCall(
        address newBeacon,
        bytes memory data,
        bool forceCall
    ) internal {
        _setBeacon(newBeacon);
        emit BeaconUpgraded(newBeacon);
        if (data.length > 0 || forceCall) {
            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
        }
    }
}

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internal call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback() external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive() external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overridden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {}
}

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly {
            r.slot := slot
        }
    }
}

EIP-2612

transaction-less token approvals

solidity
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external
function nonces(address owner) external view returns (uint)
function DOMAIN_SEPARATOR() external view returns (bytes32)

EIP-2981

  • 获取 NFT 版税信息
    • receiver 接受人
    • royaltyAmount 售价版税
  • IERC165 0x2a55205a
solidity
interface IERC2981 is IERC165 {
  function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
    external
    view
    returns (address receiver, uint256 royaltyAmount);
}

EIP-3722

EIP-4626

EIP-7928

  • Block-Level Access Lists, BALs
  • 引入一种机制,允许并行处理交易和区块验证,从而显著提升以太坊主网(L1)的可扩展性
  • 引入
    • 区块访问列表(BAL):一个映射,包含了交易将访问的地址、存储插槽及其执行后的值。
    • 交易索引(Transaction Indices):用于精确定位区块内每项操作的位置。
    • 执行后值(Post-Execution Values):每笔交易在网络全局状态上留下的最终结果。
  • 验证节点可以实现并行磁盘读取和并行交易验证,从而大幅提升执行效率和区块验证速度 。
  • “读写无知”(read-write oblivious)-> “读写感知”(read-write aware)

FAQ

ERC-20 vs ERC-777

  • ERC-20
    • 基础可用
    • tranfer 地址错误可能丢失
  • ERC-777
    • made aware - 验证接收者

ERC-721 vs ERC-1155

  • ERC-721 - NFT 标准 - non-fungible
    • 专用于 NFT - 信息完善
  • ERC-1155 - 多 Token 标准 - 可实现 NFT - semi-fungible
    • 一个合约支持多种 Token - 不仅限于 NFT
    • semi-fungible - 支持 Token-NFT 互换
    • 批量操作
    • 比 ERC-721 少存储一些信息
    • low gas fee

关联信息

反向链接、本文链接的其他页面和外部资料。

反向链接

  • 区块链
    笔记 · ETH

    区块链 本身并没有什么特殊的地方,但其 immutable 的特性用于记账,使其发展成为去中心化金融。 · Web3 基于 Ethereum 的 EVM,合约作为核心业务逻辑,发展出来新的方向。 · 基于 Ethereum 的区块链成为新的现行标准。

参考资料

GitHub5 条
其他外链6 条
最近更新commit a5d2b15编辑