ERC-6909 最小多代币标准

ERC-6909 Token标准是 ERC-1155 Token标准的一种简化替代方案。

ERC-1155 标准引入了一种多Token接口,使得单个智能合约能够结合可替代的和不可替代的Token(即,​ERC20 和 ERC721)。

ERC-1155 解决了多个挑战,例如降低部署成本、最小化以太坊区块链上的冗余字节码,以及简化多Token交易的Token批准流程。

然而,由于每次转账都强制要求回调、强制包含批量转账,以及缺乏对单操作员批准方案的细粒度控制,它引入了一些膨胀和气体低效问题。ERC-6909 通过消除合约级回调和批量转账,并用混合(限额-操作员)权限方案替代单操作员的凭证方案,从而解决了这些缺点,以实现颗粒化的Token管理。

注意: 以下部分假设读者对 ERC-1155 标准及其概念有一定的了解。如果你不熟悉,请在继续之前阅读相关内容。

ERC-6909 和 ERC-1155 标准的对比

ERC-6909 移除转账的回调要求

ERC-1155 规范要求 safeTransferFrom 和 safeBatchTransferFrom 检查接收账户是否为合约。如果是,则必须在接收合约账户上调用 ERC1155TokenReceiver 接口函数(onERC1155ReceivedonERC1155BatchReceived)以检查其是否接受转账。

这些回调在某些情况下是有用的。然而,对于希望不使用这种行为的接收方,它们是不必要的外部调用。回调影响接收合约账户的Gas成本和代码大小,因为它们需要实现多个回调(即,通过 onERC1155ReceivedonERC1155BatchReceived)并返回魔术的 4 字节值以接收Token。相比之下,ERC-6909 的实现者可以自定义他们的回调架构。

ERC-6909 省略了批量转账逻辑

尽管批量转账有时是有益的,但在 ERC-6909 标准中故意省略,以允许开发者根据特定执行环境实施批量转账逻辑。开发者可以根据自己的需要实现批量转账,而无需仅仅为了遵循标准而添加额外的批量转账函数。

下面展示的 safeBatchTransferFrom 函数在 ERC-1155 标准中执行批量转账。然而,其强制的包含为不需要它们的应用程序增加了膨胀:

// ERC-1155
function safeBatchTransferFrom(address _from,address _to,uint256[] calldata _ids,uint256[] calldata _values,bytes calldata _data
) external;

​以下是 ERC-6909 transferFrom 函数。我们可以看到批量特性和 _data 参数已被删除。

// ERC-6909
function transferFrom(address sender,address receiver,uint256 id,uint256 amount
) public returns (bool) {if (sender != msg.sender && !isOperator[sender][msg.sender]) {uint256 senderAllowance = allowance[sender][msg.sender][id];if (senderAllowance < amount) revert InsufficientPermission();if (senderAllowance != type(uint256).max) {allowance[sender][msg.sender][id] = senderAllowance - amount;}}if (balanceOf[sender][id] < amount) revert InsufficientBalance();balanceOf[sender][id] -= amount;balanceOf[receiver][id] += amount;emit Transfer(msg.sender, sender, receiver, id, amount);return true;
}

ERC-6909 同时支持全局批准和细粒度限额

// 在 ERC-1155 →
function setApprovalForAll(address _operator,bool _approved
) external;

上面展示的 setApprovalForAll 函数是 ERC-1155 中的全局操作员模型,允许一个账户授权另一个账户管理(作为操作员)其所有Token ID 的操作。一旦被授权,操作员可以随意转移授权账户拥有的任何数量的任何Token ID。

虽然这种方法简化了委托,但缺乏细粒度控制:

  • 没有办法授予特定于单个Token ID 或数量的权限。
  • 这种全有或全无的方法不适合需要受控权限的场景。

为引入细粒度控制,ERC-6909 混合操作员权限方案包含以下内容:

  • 来自 ERC-1155 的操作员模型,
  • 和受 ERC-20 启发的限额模型。

ERC-6909 中的操作员模型

在下面的 ERC-6909 setOperator 函数中,spender 变量被设置为操作员,并被授权无条件的权限,以转移账户所拥有的所有Token ID 而没有限额限制。

function setOperator(address spender, bool approved) public returns (bool) {isOperator[msg.sender][spender] = approved;emit OperatorSet(msg.sender, spender, approved);return true;
}

ERC-6909 中的限额模型

限额模型引入了一种特定于Token和数量的控制系统,其中一个账户可以为特定Token ID 设置有限的限额。

例如,Alice 可以允许 Bob 转移 100 个 ID 为 42 的Token,而不授予对其他Token ID 或不受限制的数量的访问权限,使用下一个展示的 ERC-6909 中的 approve 函数。

function approve(address spender, uint256 id, uint256 amount) public returns (bool) {allowance[msg.sender][spender][id] = amount;emit Approval(msg.sender, spender, id, amount);return true;
}

在 approve 中的 spender 变量是被授权代表Token所有者转移特定金额的特定Token ID 的账户。

例如,Token所有者可以允许 spender 转移 <= 100 个特定Token ID。或者,他们还可以通过将限额设置为 type(uint256).max 来为特定Token ID 授予无限制的批准。

ERC-6909 并没有指定是否应扣减设置为 type(uint256).max 的限额。相反,这种行为留给实现者的自由裁量权,类似于 ERC-20。

核心数据结构

ERC-6909 实现使用三个映射来更新账户余额和批准状态。

balanceOf:ID 的所有者余额

balanceOf 映射跟踪特定Token ID 由地址 (owner) 持有的余额。映射中的 owner => (id => amount) 结构表示单个所有者可以持有多个Token,并通过各自的 ID 跟踪其余额。

mapping(address owner => mapping(uint256 id => uint256 amount)) public balanceOf;

allowance:ID 的支出者限额

允许映射定义支出者在所有者的授权下可以转移多少特定Token(ID)。它促进了对Token支出的细粒度控制。

mapping(address owner => mapping(address spender => mapping(uint256 id => uint256 amount))) public allowance;

例如,allowance[0xDEF...][0x123...][5] 将返回所有者 0xDEF... 允许支出者 0x123... 转移的Token(ID 为 5)的数量。

isOperator:操作员批准状态

mapping(address owner => mapping(address operator => bool isOperator)) public isOperator;

该映射跟踪支出者是否被批准作为拥有地址的所有Token的操作员。例如,isOperator[0x123...][0xABC...] 返回 true 如果地址 0xABC... 被允许支出地址 0x123... 所拥有的Token;否则返回 false

核心 ERC-6909 功能及其数据参数

转账函数

该规范并未遵循 ERC-721 和 ERC-1155 中的“安全转账机制”,因为由于其向任意合约的外部调用被认为是误导性的。ERC-6909 使用 transfer 和 transferFrom 函数,详情如下。

转账:

ERC-6909 的 transfer 函数表现得与 ERC-20 的 transfer 相同,只不过它适用于特定的Token ID。该函数接受接收地址、Token的 ID 和要转移的金额作为输入参数,并使用 balanceOf 映射更新余额。与 ERC-20 转账函数类似,成功执行事务时返回 true 是必要的。

// ERC-20 接口转账函数function transfer(address _to, uint256 _value) public returns (bool)// ERC-6909 转账函数参考实现// @notice 将数量 id 从调用者转移至接收者。// @param receiver 接收者的地址。// @param id Token的 ID。// @param amount Token的数量。function transfer(address receiver, uint256 id, uint256 amount) public returns (bool) {if (balanceOf[msg.sender][id] < amount) revert InsufficientBalance(msg.sender, id);balanceOf[msg.sender][id] -= amount;balanceOf[receiver][id] += amount;emit Transfer(msg.sender, msg.sender, receiver, id, amount);return true;}

transferFrom:

ERC-6909 的 transferFrom 函数与 ERC-20 的不同之处在于它要求提供一个Token ID。此外,它还检查操作员的批准以及限额。

该函数首先检查 if (sender != msg.sender && !isOperator[sender][msg.sender]),确保调用者 (msg.sender) 是:

  • 所有者sender),或者
  • 已批准的操作员isOperator[sender][msg.sender] == true)。

如果 msg.sender 不是所有者也不是已批准的操作员,函数将检查调用者是否具有 足够的限额 以进行转移。如果有限额但未设置为无限制type(uint256).max),则从限额中扣除转移的 amount

此外,标准规定如果调用者是操作员或 sender,则该函数不应扣减调用者对于Token id 的 allowance 中的 amount

// ERC-6909 transferFromfunction transferFrom(address sender, address receiver, uint256 id, uint256 amount) public returns (bool) {if (sender != msg.sender && !isOperator[sender][msg.sender]) {uint256 senderAllowance = allowance[sender][msg.sender][id];if (senderAllowance < amount) revert InsufficientPermission();if (senderAllowance != type(uint256).max) {allowance[sender][msg.sender][id] = senderAllowance - amount;}}if (balanceOf[sender][id] < amount) revert InsufficientBalance();balanceOf[sender][id] -= amount;balanceOf[receiver][id] += amount;emit Transfer(msg.sender, sender, receiver, id, amount);return true;
}

approve:

approve 函数允许调用者(msg.sender)向支出者授予特定Token(ID)的特定限额。这会更新限额映射以反映新的限额并发出 Approval 事件。

function approve(address spender, uint256 id, uint256 amount) public returns (bool) {allowance[msg.sender][spender][id] = amount;emit Approval(msg.sender, spender, id, amount);return true;
}

setOperator:

setOperator 函数允许调用者(msg.sender)通过将批准参数设置为 true 或 false 来授予或撤销特定地址(spender)的操作员权限。该函数会相应地更新 isOperator 映射,并发出 OperatorSet 事件,以通知外部监听器有关更改的情况。

function setOperator(address spender, bool approved) public returns (bool) {isOperator[msg.sender][spender] = approved;emit OperatorSet(msg.sender, spender, approved);return true;
}

ERC-6909 中的事件与日志

ERC-6909 定义了关键事件,以跟踪多Token合约中的Token转移、批准及操作员权限。

1. 转移事件:

/// @notice 转移发生时发出的事件。event Transfer(address caller, address indexed sender, address indexed receiver, uint256 indexed id, uint256 amount);

ERC-6909 中的 Transfer 事件用于跟踪Token的移动,必须在以下条件下发出:

  • 转移Token id 的 amount 从一个账户到另一个账户时,将记录 senderreceivertoken ID 和转移的 amount
  • 当创建新Token时,事件必须以 sender 为零地址(0x0)发出。
  • 当Token被销毁时,事件必须以接收方为零地址(0x0)发出,以表示Token被移除。

2. OperatorSet 事件:

/// @notice 操作员被设置时发出的事件。
event OperatorSet(address indexed owner, address indexed spender, bool approved);

OperatorSet 事件每当所有者分配或撤销另一个地址的操作员权限时都会发出。事件记录所有者的地址、支出者的地址以及更新的批准状态(true 表示授予,false 表示撤销)。

3. Approval 事件:

/// @notice 批准发生时发出的事件。
event Approval(address indexed owner, address indexed spender, uint256 indexed id, uint256 amount);

当所有者设置或更新支出者转移特定金额的特定Token ID 的批准时,必须发出 Approval 事件。事件记录 ownerspender、Token id 和批准的 amount

现在我们已经探讨了 ERC-6909 与 ERC-1155 之间的差异,以及 ERC-6909 中的核心方法和事件,让我们看看标准的一些实际应用。

Uniswap v4 PoolManager 怎样实现 ERC-6909。

在 Uniswap v3 中,工厂/池模型通过使用 UniswapV3Factory 合约为每个池部署一个单独的合约来创建新的Token对。这种方法增加了Gas成本,因为每个新池都需要新的合约部署。

与此相比,Uniswap v4 引入了一个单例合约(PoolManager.sol),该合约将所有流动性池管理作为其内部状态的一部分,而不是要求单独的合约部署。这一设计显著降低了池创建的Gas成本。

此外,以前版本中涉及 多个 Uniswap 池 的交易需要跨多个合约的Token转移和冗余状态更新。在 Uniswap v4 中,PoolManager 合约可以集中持有用户的 ERC-6909 表示的 ERC-20 Token,而不需要在池中往返转移 ERC-20 Token。

例如,如果用户为Token A 提供流动性,他们后来可以选择提取其股份并接收Token A 作为转移到其钱包的 ERC-20。然而,如果他们选择不提取Token,那么 Uniswap v4 的 PoolManager 可以 铸造其Token余额的 ERC-6909 表示,而无需从合约转移 ERC-20 Token——节省了跨合约调用。这些 ERC-6909 余额允许用户在协议中交易或互动,而无需在钱包之间移动Token。

这意味着当用户后来将Token A 兑换为Token B 时,Uniswap 只是更新他们在池中的 ERC-6909 余额

注意:ERC-6909 在 Uniswap v4 中不作为 LP 代币使用。

ERC-6909 元数据在单例 DeFi 架构和 NFT 系列中的考虑

以下是 IERC6909Metadata 接口,它定义了如何将 ERC-6909 标准和单独Token相关联的元数据,例如名称、符号和小数,其函数可以根据 id 的不同发展,允许 ERC-6909 中不同的Token具有不同的名称、符号和小数。

/// @notice 包含单个Token元数据的合同。
interface IERC6909Metadata is IERC6909 {/// @notice 给定Token的名称。/// @param id Token的 id。/// @return name Token的名字。function name(uint256 id) external view returns (string memory);/// @notice 给定Token的 символ。/// @param id Token的 id。/// @return symbol Token的符号。function symbol(uint256 id) external view returns (string memory);/// @notice 给定Token的小数位数。/// @param id Token的 id。/// @return decimals Token的小数位数。function decimals(uint256 id) external view returns (uint8);
}

对于 DeFi 协议,我们可能有多个 LP 代币,并且我们可能希望将其标准化为都具有相同的小数,例如 18。然而,我们可能希望名称和符号能够反映池中持有的不同资产。

相比之下,对于 NFT,decimals 值应始终设置为 1,因为 NFT 是不可分割的。

在典型的 NFT 系列(例如 ERC-721)中,所有Token共享相同的名字和符号,以表示整个系列(例如 "CryptoPunks" 和符号 "PUNK")。ERC-6909 使我们能够遵循 ERC-712 规范,其中所有 NFT 在同一系列中共享相同的元数据。

ERC-6909 非同质化Token的实现示例。

ERC-6909 规范并没有明确规定支持非同质化Token的独特方法。但是,可以使用 ERC-1155 规范中描述的 ID 位拆分技术在 ERC-6909 中实现非同质化Token。这种方法使用 位移和加法运算 将集合 ID 和项目 ID 编码在一个 uint256 Token ID 中。

function getTokenId(uint256 collectionId, uint256 itemId) public pure returns (uint256) {return (collectionId << 128) + itemId;
}

下面的 ERC6909MultiCollectionNFT 合约是一个使用 getTokenId 根据 collectionId 和 itemId 生成Token ID 的非同质化Token(NFT)实现示例。

mintNFT 函数确保每个 tokenId 只能被铸造一次,无论地址如何。它使用 mintedTokens 映射跟踪 NFT tokenId 是否已被全球铸造。

由于在 mintNFT 中将 amount 变量设置为 1,因此函数中的 _mint(to, tokenId, amount) 调用将对 tokenId 铸造一份。在任何情况下,如果 amount > 1,Token将变为可替代,而不是非同质化。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;import "./ERC6909.sol";contract ERC6909MultiCollectionNFT is ERC6909 {struct NFT {string uri;}mapping(uint256 => NFT) private _tokens;mapping(uint256 => string) private _collectionURIs;mapping(uint256 => bool) public mintedTokens;event MintedNFT(address indexed to, uint256 indexed collectionId, uint256 indexed itemId, uint256 tokenId, string uri);// 通过连接 collectionId 和 itemId 计算 Token IDfunction getTokenId(uint256 collectionId, uint256 itemId) public pure returns (uint256) {return (collectionId << 128) + itemId;}function _mint(address to, uint256 tokenId, uint256 amount) internal {balanceOf[to][tokenId] += amount;emit Transfer(msg.sender, address(0), to, tokenId, amount);}function mintNFT(address to, uint256 collectionId, uint256 itemId, string memory uri) external {uint256 amount = 1;uint256 tokenId = getTokenId(collectionId, itemId);require(!mintedTokens[tokenId], "ERC6909MultiCollectionNFT: Token already minted");require(amount == 1, "ERC6909MultiCollectionNFT: Token copies must be 1");_tokens[tokenId] = NFT(uri);mintedTokens[tokenId] = true; // 标记为已铸造_mint(to, tokenId, amount); // amount 被定义为 1。emit MintedNFT(to, collectionId, itemId, tokenId, uri);}function nftBalanceOf(address owner, uint256 tokenId) public view returns (uint256) {return balanceOf[owner][tokenId];}
}

请记住,上面 mintNFT 中的 _mint 调用将余额映射更新为 1,因为这些铸造的Token完全是非同质化的。因此,在此合约中,如果 owner 地址确实铸造了 tokenIdnftBalanceOf 函数预计总是返回 1。

为了转移Token的所有权,下面的 nftTransfer 函数确保只有 NFT 所有者可以通过验证其余额启动转移,才能允许唯一存在的单位转移。

function nftTransfer(address to, uint256 tokenId) external {require(balanceOf[tokenId][msg.sender] == 1, "ERC6909MultiCollectionNFT: This should be non-fungible.");require(to != address(0), "ERC6909MultiCollectionNFT: transfer to zero address");transfer(to, tokenId, 1);// 在此情况下,数量等于 1。emit Transfer(msg.sender, address(0), to, tokenId, 1);
}

ERC-6909 内容 URI 扩展与元数据 URI JSON 模式

为了标准化 ERC-6909 中的元数据访问,可选的 IERC6909ContentURI 接口为检索合约和Token层次的元数据定义了两个 URI 函数(contractURI 和 tokenURI)。ERC-6909 标准并不强制Token需要关联 URI 元数据。然而,如果实现中包含这些 URI 函数,返回的 URI 应该指向遵循 ERC-6909 元数据 URI JSON 架构的 JSON 文件。

pragma solidity ^0.8.19;import "./IERC6909.sol";/// @title ERC6909 内容 URI 接口
interface IERC6909ContentURI is IERC6909 {/// @notice 合同级别 URI/// @return uri 合同级别的 URI。function contractURI() external view returns (string memory);/// @notice Token级别 URI/// @param id Token的 ID。/// @return uri Token级别的 URI。function tokenURI(uint256 id) external view returns (string memory);
}

如上所示,ERC-6909 IERC6909ContentURI 接口定义了两个可选的 URI 函数,即 contractURI 和 tokenURI;每个函数都有其相应的 URI JSON 模式。contractURI 函数(不带参数)返回指向合约级别元数据的单个 URI,而 tokenURI() 返回每个Token ID 特定的 URI。

以下是根据 ERC-6909 标准构造合约 URI JSON 架构的示例。

{"title": "Contract Metadata","type": "object","properties": {"name": {"type": "string","description": "The name of the contract."},"description": {"type": "string","description": "The description of the contract."},"image_url": {"type": "string","format": "uri","description": "The URL of the image representing the contract."},"banner_image_url": {"type": "string","format": "uri","description": "The URL of the banner image of the contract."},"external_link": {"type": "string","format": "uri","description": "The external link of the contract."},"editors": {"type": "array","items": {"type": "string","description": "An Ethereum address representing an authorized editor of the contract."},"description": "An array of Ethereum addresses representing editors (authorized editors) of the contract."},"animation_url": {"type": "string","description": "An animation URL for the contract."}},"required": ["name"]
}

tokenURI 函数则接受一个 uint256 参数 id,并返回该Token的 URI。如果Token id 不存在,该函数可以回滚。与合约级别的 URI 一样,客户在与合约交互时 必须 替换 URI 中每处 {id} 的出现为实际的Token ID,以访问与该Token相关的正确元数据。

以下是 tokenURI 函数的实现,返回遵循占位符格式的 静态 URI 模板

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;import "./ERC6909.sol";
import "./interfaces/IERC6909ContentURI.sol";contract ERC6909ContentURI is ERC6909, IERC6909ContentURI {/// @notice 合同级 URI。string public contractURI;/// @notice 每个 id 的 URI。/// @return Token的 URI。function tokenURI(uint256) public pure override returns (string memory) {return "<baseuri>/{id}";}
}

以下是根据 ERC-6909 标准构造 URI JSON 架构的示例。

{"title": "Asset Metadata","type": "object","properties": {"name": {"type": "string","description": "Identifies the token"},"description": {"type": "string","description": "Describes the token"},"image": {"type": "string","description": "A URI pointing to an image resource."},"animation_url": {"type": "string","description": "An animation URL for the token."}},"required": ["name", "description", "image"]
}

ERC-6909 规范中的限额和操作员歧义。

考虑一个场景,其中一个账户(A)授予另一个账户(B)操作员权限,并为 B 设置可转移特定金额的Token的限额。

如果 B 代表 A 发起转移,则实现必须确定检查的正确顺序以及限额如何与操作员权限互动。

歧义涉及检查的顺序。合约应该:

  1. 首先检查限额,如果不足则回滚,即使 B 具有操作员权限。
  2. 首先检查操作员权限,无论限额如何都允许转移。

在下面的 allowanceFirst 合约中,如果账户 B 具有操作员权限,但限额不足,限额检查将失败,从而导致事务回滚。这可能是反直观的,因为操作员权限通常意味着无限制访问,用户可能会期望事务成功。

相反,在 operatorFirst 合约中,如果实现首先检查操作员权限,将绕过限额检查,事务将基于操作员的无限制访问而成功。

contract operatorFirst {function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public {// 首先检查 `isOperator`if (msg.sender != sender && !isOperator[sender][msg.sender]) {require(allowance[sender][msg.sender][id] >= amount, "insufficient allowance");allowance[sender][msg.sender][id] -= amount;}// -- 剪切 --}
}contract allowanceFirst{function transferFrom(address sender, address receiver, uint256 id, uint256 amount) public {// 首先检查限额是否充足if (msg.sender != sender && allowance[sender][msg.sender][id] < amount) {require(isOperator[sender][msg.sender], "insufficient allowance");}// 错误:当限额不足时,由于算术下溢而发生恐慌,无论调用者是否具有操作员权限。allowance[sender][msg.sender][id] -= amount;// -- 剪切 --}
}

该标准故意将权限检查的决定留给实现者,这给实现者提供灵活性。在一个账户同时拥有操作员权限和不足的限额时,转账行为取决于检查的顺序。

结论

ERC-6909 标准通过移除转账函数中的批量和强制回调,显著提高了 ERC-1155 的效率。去除批量处理允许逐个案例优化,特别是对于汇总或气体敏感的环境。

它还通过混合操作员权限方案引入了可扩展的Token批准控制,更多信息,,https://t.me/+_QibemQqIIg1OTY1。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/35466.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

docker的使用

时间&#xff1a;2025.3.17 一、当我们想要运行一个容器时&#xff0c;不是在containers处&#xff0c;而是需要在images处找对应容器的镜像 操作步骤&#xff1a; 1.找容器镜像 2.找到容器镜像&#xff0c;通过pull下载到当前主机中 3.下载成功后进行运行 4.运行时的容器镜像…

本地部署deepseek-r1建立向量知识库和知识库检索实践【代码】

目录 一、本地部署DS 二、建立本地知识库 1.安装python和必要的库 2.设置主目录工作区 3.编写文档解析脚本 4.构建向量数据库 三、基于DS,使用本地知识库检索 本地部署DS,其实非常简单,我写了一篇操作记录,我终于本地部署了DeepSeek-R1(图文全过程)-CSDN博客 安装…

Matlab 汽车传动系统的振动特性分析

1、内容简介 Matlab 186-汽车传动系统的振动特性分析 可以交流、咨询、答疑 2、内容说明 略 摘要&#xff1a;汽车动力传动系统是一个具有多自由度的、连续的、有阻尼系统。传动系统的振动主要有横向振动、扭转振动、纵向振动。并且汽车传动系统的扭转振动是一个非常重要的振…

【C++】树和二叉树的实现(上)

本篇博客给大家带来的是用C语言来实现数据结构树和二叉树的实现&#xff01; &#x1f41f;&#x1f41f;文章专栏&#xff1a;数据结构 &#x1f680;&#x1f680;若有问题评论区下讨论&#xff0c;我会及时回答 ❤❤欢迎大家点赞、收藏、分享&#xff01; 今日思想&#xff…

k8s环境部署

四台机器 分别是 k8s-master&#xff1a;172.25.254.100 k8s-node1&#xff1a;172.25.254.10 k8s-node2&#xff1a;172.25.254.20 docker-harbor&#xff1a;172.25.254.200 reg.timinglee.org 四台机器分别配置好网络和软件仓库 做好地址解析 scp -r /etc/hosts/ root17…

transformer bert 多头自注意力

输入的&#xff08;a1,a2,a3,a4&#xff09;是最终嵌入&#xff0c;是一个(512,768)的矩阵&#xff1b;而a1是一个token&#xff0c;尺寸是768 a1通过Wq权重矩阵&#xff0c;经过全连接变换得到查询向量q1&#xff1b;a2通过Wk权重矩阵得到键向量k2&#xff1b;q和k点乘就是值…

它,让机器人与HMI屏无缝对接

随着工业自动化向智能化发展&#xff0c;机器人与HMI屏的通信变得至关重要。本文将为您介绍一款创新的解决方案&#xff0c;它打破了通信协议的壁垒&#xff0c;实现机器人与HMI屏的无缝连接。 随着工业自动化向智能化的迈进&#xff0c;生产制造业正加速引入大量工业机器人以替…

MySQL 锁

MySQL中最常见的锁有全局锁、表锁、行锁。 全局锁 全局锁用于锁住当前库中的所有实例&#xff0c;也就是说会将所有的表都锁住。一般用于做数据库备份的时候就需要添加全局锁&#xff0c;数据库备份的时候是一个表一个表备份&#xff0c;如果没有加锁的话在备份的时候会有其他的…

win10 c++ VsCode 配置PCL open3d并显示

win10 c VsCode配置PCL open3d并显示 一、效果图二、配置步骤2.1 安装vscode2.2 pcl-open3d配置2.3 vscode中设置 三、测试代码四、注意事项及后续 一、效果图 二、配置步骤 2.1 安装vscode vscode下载链接 下载中文插件、c相关插件 2.2 pcl-open3d配置 1&#xff09;下载…

Python----计算机视觉处理(Opencv:图像颜色替换)

一、开运算 开运算就是对图像先进行腐蚀操作&#xff0c; 然后进行膨胀操作。开运算可以去除二值化图中的小的噪点&#xff0c;并分离相连的物体。 其主要目的就是消除那些小白点 在开运算组件中&#xff0c;有一个叫做kernel的参数&#xff0c;指的是核的大小&#xff0c;通常…

泰勒·斯威夫特(Taylor Swift)的音乐影响力与商业版图深度研究

泰勒斯威夫特的音乐影响力与商业版图深度研究 简介 泰勒斯威夫特&#xff08;Taylor Swift&#xff09;是当今流行音乐领域最具影响力的全球巨星之一。自少年时期出道以来&#xff0c;她在音乐风格、形象和商业战略上不断演变&#xff0c;从乡村音乐新人成长为引领流行文化的…

完全托管的DeepSeek-R1模型正式登陆Amazon Bedrock:安全部署与使用指南

文章目录 摘要一、核心优势&#xff1a;完全托管与企业级安全二、部署注意事项三、实践指南&#xff1a;从接入到调用四、支持区域与定价五、结语 摘要 DeepSeek-R1模型已在Amazon Bedrock平台正式上线&#xff0c;支持通过Bedrock Marketplace和自定义模型导入功能调用。 该模…

Matlab 汽车ABS实现模糊pid和pid控制

1、内容简介 Matlab 181-汽车ABS实现模糊pid和pid控制 可以交流、咨询、答疑 2、内容说明 略 实现汽车防抱死制动系统&#xff08;ABS&#xff09;的控制算法&#xff0c;通常涉及到传统的PID控制和模糊PID控制两种方法。下面将分别介绍这两种控制策略的基本概念以及如何在M…

Spring IOC(五个类注解)

controller、service、Repository、Component 、Configurationpackage com.java.ioc;import com.java.ioc.Controller.HelloController; import com.java.ioc.rep.UserRepository; import com.java.ioc.service.UserService; import org.springframework.boot.SpringApplicatio…

[Java实战]Spring Boot服务CPU 100%问题排查:从定位到解决

Spring Boot服务CPU 100%问题排查&#xff1a;从定位到解决 1. 引言 当Spring Boot服务出现CPU占用率100%时&#xff0c;系统性能会急剧下降&#xff0c;甚至导致服务不可用。本文将通过真实代码案例&#xff0c;详细讲解如何快速定位问题根源&#xff0c;并提供解决方案。无…

机器学习扫盲系列(2)- 深入浅出“反向传播”-1

系列文章目录 机器学习扫盲系列&#xff08;1&#xff09;- 序 机器学习扫盲系列&#xff08;2&#xff09;- 深入浅出“反向传播”-1 文章目录 前言一、神经网络的本质二、线性问题解析解的不可行性梯度下降与随机梯度下降链式法则 三、非线性问题激活函数 前言 反向传播(Ba…

LabVIEW 线性拟合

该 LabVIEW 程序实现了 线性拟合&#xff08;Linear Fit&#xff09;&#xff0c;用于计算给定一组数据点的斜率&#xff08;Slope&#xff09;和截距&#xff08;Intercept&#xff09;&#xff0c;并将结果可视化于 XY Graph 中。本案例适用于数据拟合、实验数据分析、传感器…

XSS漏洞靶场---(复现)

XSS漏洞靶场—&#xff08;复现&#xff09; 反射型 XSS 的特点是攻击者诱导用户点击包含恶意脚本的 URL&#xff0c;服务器接收到请求后将恶意脚本反射回响应页面&#xff0c;浏览器执行该脚本从而造成攻击&#xff0c;恶意脚本不会在服务器端存储。 Level 1(反射型XSS) 此漏…

优选算法系列(2.滑动窗口 _ 上)

目录 解法⼀&#xff08;暴力求解&#xff09;&#xff08;不会超时&#xff0c;可以通过&#xff09;&#xff1a;一.长度最小的子数组&#xff08;medium&#xff09; 题目链接209. 长度最小的子数组 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 代码&#…

ELK(Elasticsearch、Logstash、Kbana)安装及Spring应用

Elasticsearch安装及Spring应用 一、引言二、基本概念1.索引&#xff08;Index&#xff09;2.类型&#xff08;Type&#xff09;3.文档&#xff08;Document&#xff09;4.分片&#xff08;Shard&#xff09;5.副本&#xff08;Replica&#xff09; 二、ELK搭建1.创建挂载的文件…