Definition and Detection of Defects in NFT Smart Contracts论文解读、复现
背景知识\定义
NFT
- 是数字或物理资产所有权的区块链表示。
- 不仅限于数字图片,视频和画作等艺术品也可以转化为 NFT 进行交易。
- 近年来受到广泛关注,2021 年 NFT 交易额达到约 410 亿美元。
智能合约
- 是在区块链上运行的图灵完备程序。
- 支持各种去中心化应用 (DApp) 的部署。
- 是 NFT 项目的底层技术。
- 开发人员可以使用智能合约编码 NFT 交易规则。
- 允许用户在交易市场上铸造和转移 NFT。
场景:
假设 Alice 想要购买一个 NFT,而 Bob 想要出售自己的 NFT。
-
传统方式:
Alice 和 Bob 需要找到一个中介机构,例如拍卖行或交易平台。
他们需要签订一份合同,并支付手续费。
中介机构负责验证交易并确保双方履行合同。
交易完成后,中介机构将 NFT 转移给 Alice,并将资金转移给 Bob。 -
智能合约方式:
Alice 和 Bob 可以使用智能合约来执行交易。
他们将 NFT 和资金存入智能合约。
智能合约会自动验证交易条件,例如价格和数量。
如果条件满足,智能合约会将 NFT 转移给 Alice,并将资金转移给 Bob。
如果条件不满足,智能合约会自动退还 NFT 和资金。
EVM
EVM(以太坊虚拟机)是运行在以太坊区块链上的虚拟机,它负责执行智能合约代码。
-
EVM 的执行机制:
EVM 将智能合约的字节码拆分成操作码 (opcode)。
EVM 遵循操作码的指令执行相应的操作,例如读取和写入状态变量、调用其他合约等。
EVM 的执行过程是顺序执行的,但也可以通过跳转指令进行分支执行。 -
EVM 字节码的特点:
跳转位置无法静态确定:EVM 的跳转指令 (例如 jump, jumpi) 的目标地址需要在运行时动态确定,这增加了智能合约代码的复杂性和安全性。
没有返回指令:EVM 没有类似于函数调用的返回指令,而是通过状态转换完成函数调用和返回。 -
智能合约中的数据存储:
存储 (Storage): 用于存储永久数据,例如 NFT 的所有权信息、DeFi 合约的余额等。
内存 (Memory): 用于存储临时数据,例如函数调用的参数和返回值、循环变量等。
calldata: 用于存储函数调用的输入数据,例如交易数据、NFT 的 ID 等。 -
智能合约中的状态变量:
每个可变状态变量在编译时都会被分配一个 slot ID,指示其在存储空间中的位置。
slot ID 帮助 EVM 在执行时确定状态变量的存储位置。
对于复杂的数据类型,例如映射 (mapping) 和动态数组,需要结合 slot ID 和哈希计算来确定存储位置。
ERC-721
用于在智能合约中跟踪NFTs的一套规则和接口。
-
ERC-721 标准:
- 由以太坊改进提案(EIPs)定义,用于在智能合约中实现 NFT 的标准 API。
- ERC-721 标准适用于非同质化、不可分割且独特的代币,这些代币代表特定数字或物理资产的所有权。
- 与 ERC-20 标准不同,后者适用于可互换的同质化代币。
-
ERC-721 的关键功能:
- approve:允许代币所有者授权另一个地址(_approved)管理特定的代币(_tokenId)。
- setApprovalForAll:允许代币所有者授权一个操作者(_operator)管理他们所有的代币。
- transferFrom:允许代币所有者、授权操作者或特定代币操作者转移代币所有权。
- safeTransferFrom:与 transferFrom 类似,但增加了安全检查,确保接收方能够处理代币。
-
ERC-721 的接口:
- ERC-721 标准定义了强制性和可选性的接口。
- 开发者必须遵循 ERC-721 提出的开发注释来实现每个接口。
- 每个 ERC-721 兼容的智能合约都应该实现 ERC-721 和 ERC-165 接口。
-
安全性和元数据:
- safeTransferFrom 函数会调用 onERC721Received 接口,确保接收方能够处理代币。
- 钱包或代币接收者必须实现 onERC721Received 接口以支持代币转移。
- ERC721Metadata 扩展允许代币所有者在铸造新代币时设置代币 URI,用户可以通过此接口查询代币代表的资产详情
- ERC721Enumerable 接口允许 NFT 智能合约发布其完整的 NFT 列表,并使其可被发现。
存在的问题
the high value of NFTs also makes them a target for attackers. The defects in NFT smart contracts could be exploited by attackers to harm the security and reliability of the NFT ecosystem
NFT 的高价值也使其成为攻击者的目标。NFT 智能合约中的缺陷可能被攻击者利用,从而损害 NFT 生态系统的安全性和可靠性。
In addition, due to the immutability of smart contracts, it is critical to ensure that the NFT smart contract is bugfree before it is deployed on the blockchain.
智能合约的不可变性意味着一旦部署,就无法修改。因此,在将 NFT 智能合约部署到区块链之前,必须确保其没有缺陷。
Although a set of smart contract defects have been reported
in previous work [21], many scenarios cannot be covered due to
the increasing complexity and security requirements of smart contracts, e.g., NFT smart contracts
尽管之前的工作已经报告了一些智能合约缺陷,但无法涵盖 NFT 智能合约等复杂场景下的所有情况。
创新点
提出5种缺陷
- 数据收集:通过收集StackOverflow 帖子(使用“NFT”和“ERC721”标签进行过滤,我们获得了 672 个与 NFT 相关的 StackOverflow 帖子)和安全分析报告(例如 Medium、Twitter 以及知名区块链安全团队如 SlowMist 和 PeckShield 的官方网站,88份)
- 数据分析:
1. Risky Mutable Proxy(风险可变代理):
- 背景:
* OpenSea 是 NFT 生态系统中最大、最受欢迎的交易市场。
* OpenSea 使用 Wyvern 协议来促进 NFT 的去中心化交易。
* 当卖家首次在 OpenSea 上列出他们的 NFT 时,一个代理注册合约会创建一个智能合约,称为 OwnableDelegateProxy。
* 这个合约存储了卖家的地址,代理注册合约可以使用这个新合约代表卖家采取行动并调用其他合约的方法。
* 当卖家在他们 NFT 智能合约中列出任何项目时,他们会授权代理注册合约转移他们的代币。
* 因此,用户不需要为每个 NFT 支付额外的 gas 费用以获取额外批准,使得交易变得简单。 - 示例:
* 如果代理注册合约的地址可以被修改,那么所有用户的代币都可能被转移到攻击者手中。
* 攻击者可以通过代理设置功能更改代理注册地址,而无需获得权限。
缺陷代码:
-
setProxyRegistryAddress 函数
function setProxyRegistryAddress(address proxyAddress) external onlyOwner {proxyRegistryAddress = proxyAddress; }
- 这个函数允许合约的所有者设置一个新的代理合约地址。这是通过简单地将传入的
proxyAddress
赋值给状态变量proxyRegistryAddress
来实现的。 - 问题在于,如果合约的所有者是恶意的,或者所有者的私钥被泄露,那么攻击者可以利用这个函数将代理合约地址更改为一个他们控制的地址。
- 这个函数允许合约的所有者设置一个新的代理合约地址。这是通过简单地将传入的
-
isApprovedForAll 函数
function isApprovedForAll(address owner, address operator) override public view returns (bool) {ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);if (address(proxyRegistry.proxies(owner)) == operator) {return true;}return super.isApprovedForAll(owner, operator); }
- 这个函数检查一个操作者是否有权代表所有者进行操作。它首先尝试通过代理合约来验证操作者是否被授权。
- 如果
proxyRegistry.proxies(owner)
返回的地址与operator
相匹配,那么函数返回true
,表示操作者被授权。 - 如果不匹配,它会调用父合约的
isApprovedForAll
函数来检查是否有其他形式的授权。
安全风险
- 代理地址可修改性: 由于
setProxyRegistryAddress
函数允许修改代理合约地址,这可能被恶意行为者利用。如果代理合约地址被更改为攻击者控制的合约,那么攻击者可以通过这个代理合约来控制所有通过它授权的NFT。 - 权限管理漏洞:
isApprovedForAll
函数的逻辑可能会导致未经授权的操作者获得对NFT的控制权,尤其是当代理合约的地址被恶意更改后。
防范措施
- 限制代理地址修改权限: 应该限制或完全禁止修改代理合约地址的功能,或者确保只有通过多重签名或其他安全机制才能更改代理地址。
- 增强权限检查: 在
isApprovedForAll
函数中增加更严格的权限检查,确保只有经过严格验证的操作者才能被授权。
2. ERC-721 Reentrancy(ERC-721可重入):
- 定义: 在外部调用后修改状态变量。
- 示例: 描述了一种情况,其中智能合约在调用外部合约(如在
safeTransferFrom
函数中)后,没有正确地锁定状态变量,导致可以重新进入(reentering)并修改状态,这可能会破坏合约的逻辑。
缺陷代码
function mintNFT(uint256 _numOfTokens, bytes memory _signature) public payable {// 预检查地址是否已经铸造过NFT(bool success, string memory reason) = canMint(msg.sender, _signature);require(success, reason);for (uint i = 0; i < _numOfTokens; i++) {_safeMint(msg.sender, totalSupply() + 1);}addressMinted[msg.sender] = true;
}
-
函数定义:
mintNFT
函数接受两个参数:_numOfTokens
表示要铸造的NFT数量,_signature
表示一些验证信息。- 该函数是
payable
的,意味着它可以接收以太币。
-
预检查:
canMint
函数被调用来检查msg.sender
(调用者地址)是否有权限铸造NFT。这个检查基于传入的签名。- 如果
canMint
返回success
为false
,则函数会停止执行并显示错误信息reason
。
-
铸造NFT:
- 通过一个循环,为每个要铸造的NFT调用
_safeMint
函数。 _safeMint
函数是安全铸造NFT的标准实践,它调用接收合约的onERC721Received
钩子函数,以确保接收方合约能够接受NFT。
- 通过一个循环,为每个要铸造的NFT调用
-
标记已铸造:
- 循环结束后,将
addressMinted[msg.sender]
设置为true
,表示该地址已经铸造过NFT。
- 循环结束后,将
安全风险:
- 可重入调用: 在
_safeMint
调用期间,如果接收NFT的合约(可能是恶意的)实现了onERC721Received
函数,它可以在_safeMint
调用期间再次调用mintNFT
函数。 - 状态竞争条件: 因为
addressMinted[msg.sender]
在循环结束后才被设置为true
,如果在_safeMint
调用期间mintNFT
被重新调用,那么canMint
的检查可能会被绕过,允许用户铸造超过限制的NFT。大多数情况下,这种重入调用会导致铸造的 NFT 数量超过稀有度阈值,损害其他买家的利益。
防范措施
- 互斥锁: 在
mintNFT
函数开始时,设置一个互斥锁,确保在铸造过程中不能再次进入mintNFT
函数。 - 状态检查提前: 在循环内部,在每次调用
_safeMint
之前,立即更新addressMinted[msg.sender]
的状态,以防止重入。
3. Unlimited Minting(无限铸造):
- 定义: 在铸造NFT时不检查NFT的最大供应量。
- 示例: 合约中没有适当的检查来限制铸造的NFT数量,可能导致超过预定数量的NFT被铸造,影响NFT的稀缺性和价值。
缺陷代码解析
function reserveApes() public onlyOwner {uint supply = totalSupply();uint i;for (i = 0; i < 30; i++) {_safeMint(msg.sender, supply + i);}
}
-
函数定义:
reserveApes
函数没有参数,并且只能由合约的所有者(onlyOwner
)调用。
-
获取当前供应量:
- 调用
totalSupply()
函数获取当前已铸造的NFT总量,并将其存储在变量supply
中。
- 调用
-
铸造NFT:
- 通过一个循环,每次循环调用
_safeMint
函数来铸造一个新的NFT。 _safeMint
函数接受两个参数:接收者地址(在这里是msg.sender
,即合约所有者)和要铸造的NFT的ID(在这里是supply + i
)。
- 通过一个循环,每次循环调用
安全风险:
- 无限制铸造: 这个函数没有检查每次铸造后是否超出了项目的预定最大供应量。由于在循环中连续调用
_safeMint
,每次铸造的NFT ID都是基于当前供应量(supply
),这可能导致铸造的NFT数量超出了项目的预定限制。 - 潜在的经济影响: 如果攻击者或合约所有者滥用这个功能,他们可以无限制地铸造新的NFT,这将破坏NFT的稀缺性,从而对项目的货币价值和市场信任造成重大损害。
防范措施
- 最大供应量检查: 在铸造每个NFT之前,应该检查当前供应量加上预定铸造的数量是否超出了项目的最大供应量限制。
- 事件记录: 记录每次铸造的事件,包括铸造的数量和铸造后的总供应量,以便于审计和监控。
- 权限管理: 限制能够调用
reserveApes
函数的地址,确保只有经过严格验证的合约所有者或管理者可以执行此操作。
4. Missing Requirements(缺少要求):
- 定义: 未遵循ERC-721标准接口的开发注释。
- 示例: 开发者在实现合约时没有遵循ERC-721标准的要求,例如在
approve
函数中没有进行必要的权限检查,这可能导致安全问题。
缺陷代码解析
/* ERC-721 annotations on approve function */
// Throws unless msg.sender is the current NFT owner, or an authorized operator of the current owner.
function approve(address to, uint256 tokenId) public virtual override {address owner = ERC721.ownerOf(tokenId);require(to != owner, "ERC721: approval to current owner");/* missing requirement of checking msg.sender */_approve(to, tokenId);
}
-
函数注释:
- 注释说明了
approve
函数的预期行为:除非msg.sender
是当前NFT的所有者或被授权的操作者,否则应抛出异常。
- 注释说明了
-
获取NFT所有者:
owner
变量通过调用ERC721.ownerOf(tokenId)
获取指定NFT的所有者地址。
-
检查接收者:
- 使用
require
函数检查被授权的地址 (to
) 是否不等于NFT的所有者 (owner
)。如果是,将抛出异常,因为逻辑上不应该将NFT授权给其所有者。
- 使用
-
缺少调用者检查:
- 注释中提到缺少对
msg.sender
的检查,这是ERC-721标准中approve
函数的一个重要要求。msg.sender
应该是NFT的所有者或被授权的操作者。
- 注释中提到缺少对
-
实际授权:
- 调用
ERC721
合约的内部函数_approve
来实际设置授权,允许地址to
转移或操作指定的tokenId
。
- 调用
安全风险:
- 授权给非所有者或非授权操作者: 由于缺少对
msg.sender
的检查,任何人都可以调用此approve
函数尝试授权自己为特定NFT的操作者。如果这个缺陷被利用,攻击者可以授权自己操作他人的NFT,然后转移或以其他方式滥用这些NFT。
防范措施
- 调用者检查: 在
approve
函数中添加对msg.sender
的检查,确保只有NFT的所有者或已授权的操作者可以调用此函数。require(msg.sender == owner || isApprovedForAll(owner, msg.sender), "ERC721: approve caller is not owner nor authorized");
- 遵循ERC-721标准: 确保实现符合ERC-721标准的所有要求,包括对调用者身份的验证。
5. Public Burn(公开销毁):
- 定义: 在销毁NFT的操作中未检查调用者权限。
- 示例: 合约中的
burn
函数是公开的,没有适当的权限检查,任何用户都可以调用它来销毁他人的NFT,这显然违背了NFT所有权的基本原则。
缺陷代码解析
function burn(uint256 tokenId) public {_burn(tokenId);
}function _burn(uint256 tokenId) internal virtual {address owner = ERC721.ownerOf(tokenId);// Clear approvals_approve(address(0), tokenId);_balances[owner] -= 1;delete _owners[tokenId];
}
-
burn 函数:
burn
函数是公开的,意味着任何外部调用者都可以触发这个函数。- 它接受一个
tokenId
参数,代表要销毁的NFT的ID。 - 函数内部直接调用了一个内部函数
_burn
,传递了相同的tokenId
。
-
_burn 函数:
_burn
函数是内部的(internal
),意味着它只能在合约内部或继承合约中被调用。- 它首先获取NFT的所有者地址。
- 然后调用
_approve
函数,将NFT的授权地址设置为0,这表示撤销所有对该NFT的授权。 - 接下来,减少所有者账户的余额计数。
- 最后,使用
delete
语句从_owners
映射中移除该NFT,实际上销毁了这个NFT。
安全风险:
- 公开销毁权限:
burn
函数是公开的,没有对调用者进行检查,这意味着任何外部调用者都可以销毁任何NFT,而不仅仅是他们自己的。这显然是一个严重的安全漏洞,因为它允许任何人销毁他人的资产。 - 所有权检查缺失: 在
_burn
函数中,尽管获取了NFT的所有者地址,但没有检查调用burn
函数的地址是否与NFT的所有者地址相同。这导致了上述的安全风险。
防范措施
- 权限检查: 在
burn
函数中添加对调用者身份的检查,确保只有NFT的所有者可以销毁自己的NFT。function burn(uint256 tokenId) public {require(ownerOf(tokenId) == msg.sender, "Only the owner can burn the NFT");_burn(tokenId); }
- 增强安全性: 考虑为销毁操作添加额外的安全措施,例如权限列表或销毁操作的确认机制。
设计NFTGuard 工具
NFTGuard工具概述
-
主要组件:
- Inputter: 负责接收和处理输入的Solidity源代码。
- Feature Detector: 用于检测合约中的关键特征,如映射存储、删除操作和外部调用。
- CFG Builder: 基于符号执行构建控制流图(CFG),用于分析合约的执行路径。
- Defect Identifier: 根据预定义的规则和模式识别和报告检测到的缺陷。
-
工作流程:
- 用户输入Solidity源代码,该代码被编译成EVM字节码和抽象语法树(AST)以供进一步分析。
- Inputter组件从AST中提取源映射信息,并使用槽映射来存储变量与它们槽ID之间的映射关系。
- 通过Geth API将合约字节码反汇编成操作码(opcodes),然后动态构建CFG。
- 在符号执行过程中,Feature Detector检测关键的操作特征,如映射存储、删除操作和外部调用。
- Defect Identifier根据预定义的模式和规则报告检测到的缺陷。
-
结合源代码和字节码信息:
- NFTGuard利用从源代码和字节码中提取的关键信息来提高检测的准确性和覆盖率。
- 通过分析AST,NFTGuard能够获取状态变量的槽ID和数据类型,这些信息在符号执行期间用于监控特定变量的操作。
-
设计动机:
- 使用源代码信息的目的是为了在执行特定操作码时定位缺陷代码,这有助于更有效地检测复杂的NFT智能合约。
-
扩展性:
- NFTGuard被设计为一个可扩展的框架,支持最新的Solidity编译器版本(例如v0.8+),并允许开发者添加新的检测模式来识别更多类型的缺陷。
实验
数据集
Smart Contract Sanctuary 是一个专为在 Etherscan 上验证过的 Ethereum 智能合约提供存储的仓库。
作者通过关键词“NFT”或“ERC721”过滤,提取了 NFT 智能合约。
由于这篇论文撰写时最新的 Solidity 编译器版本是 0.8.16,作者选择了这个版本,并移除了无法编译的合约。
最终,作者获得了 16,527 个智能合约,并进行了大规模的实验。
评估效果
- 合约缺陷(Contract Defect):这列列出了NFTGuard检测到的缺陷类型。
- # Defects:这列显示了数据集中每个缺陷类型的数量。
- Per(%):这列显示了数据集中每个缺陷类型的百分比。
- # Samples:这列显示了为评估每个缺陷类型而随机抽取的样本数量。
- # TP:这列显示了每个缺陷类型中,被正确检测为缺陷的样本数量(真阳性)。
- # FP:这列显示了每个缺陷类型中,被错误检测为缺陷的样本数量(假阳性)。
- Prec(%):这列显示了每个缺陷类型的精确率,即真阳性与真阳性加假阳性总数之比。
关于随机抽取
作者通过以下步骤来评估 NFTGuard 的性能:
- 随机抽样:从每个缺陷的检测结果中随机抽取一定数量的合约。这些合约是 NFTGuard 报告为阳性的合约。
- 样本大小确定:为了确定每个缺陷的样本大小,作者采用了基于置信区间的抽样方法。这种方法旨在从总体中推断出特定缺陷的缺陷数量。
- 置信区间和置信水平:作者设定了 10% 的置信区间和 95% 的置信水平,并计算了需要收集的样本数量。
- 样本数量计算:根据计算结果,作者为五个缺陷分别计算了所需的样本数量,分别为 13、81、86、44 和 30。
- 数据集抽样和手动标注:根据计算结果,作者对数据集进行了抽样,并由两位作者仔细手动标注了这些样本。
- 真阳性和假阳性分离:在标注过程中,作者将样本分为真阳性和假阳性,以便分析 NFTGuard 的性能。
- 相关工作的采用:这种评估方法也被其他相关研究采用,以评估智能合约缺陷检测工具的性能。
通过这种方法,作者能够评估 NFTGuard 在检测 NFT 智能合约缺陷方面的性能,包括其精确率和误报情况,从而回答 RQ2。
相关文章:

Definition and Detection of Defects in NFT Smart Contracts论文解读、复现
背景知识\定义 NFT 是数字或物理资产所有权的区块链表示。不仅限于数字图片,视频和画作等艺术品也可以转化为 NFT 进行交易。近年来受到广泛关注,2021 年 NFT 交易额达到约 410 亿美元。 智能合约 是在区块链上运行的图灵完备程序。支持各种去中心化…...

Neo4j图数据库
文章目录 一、Neo4J相关介绍1.为什么需要图数据库方案1:Google方案2:Facebook 2.特定和优势3.什么是Neo4j4.Neo4j数据模型图论基础属性图模型Neo4j的构建元素 5.软件安装 二、CQL语句1.CQL简介2.CREATE 命令3.MATCH 命令4.RETURN 子句5.MATCH和RETURN6.C…...

k8s API资源对象
API资源对象Deployment 最小的资源是pod,deployment是多个pod的集合(多个副本实现高可用、负载均衡等)。 使用yaml文件来配置、部署资源对象。 Deployment YAML示例: vi ng-deploy.yaml apiVersion: apps/v1 kind: Deployment…...

GB/T28181规范解读之编码规则详解
GB/T28181,即《安全防范视频监控联网系统信息传输、交换、控制技术要求》,是我国安防行业的重要标准之一。该标准详细规定了城市监控报警联网系统中信息传输、交换、控制的互联结构、通信协议结构,以及传输、交换、控制的基本要求和安全性要求…...

Vue封装的过度与动画(transition-group、animate.css)
目录 1. Vue封装的过度与动画1.1 动画效果11.2 动态效果21.3 使用第三方动画库animate.css 1. Vue封装的过度与动画 作用:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名 1.1 动画效果1 Test1.vue: transition内部只能包含一个子标签。…...

免费云服务器申请教程
免费云服务器的申请流程通常包括以下几个步骤,但请注意,不同云服务提供商的具体步骤可能略有不同。以下是一个通用的申请流程: 一、选择合适的云服务提供商 首先,需要选择一家提供免费云服务器服务的云服务提供商。 免费云服务器汇…...

Spring Cloud Gateway中的常见配置
问题 最近用到了Spring Cloud Gateway,这里记录一下这个服务的常见配置。 spring:data:redis:host: ${REDIS_HOST:xxx.xxx.xxx.xxx}port: ${REDIS_PORT:2345wsd}password: ${REDIS_PASS:sdfsdfgh}database: ${REDIS_DB:8}session:redis:flush-mode: on_savenamespa…...

SelectDB 多计算集群核心设计要点揭秘与场景应用
需求起源 SelectDB 设计多计算集群架构初衷主要源于两类典型的使用场景: 写入与读取隔离:传统数仓架构中,数据的写入和读取在同一个计算集群,当遇到业务写入高峰期或突增的写入压力时,容易因资源相互抢占影响查询服务…...

Docker 清理和查看镜像与容器占用情况
查看容器占用磁盘大小 docker system df 查看单个image、container大小: docker system df -v 清理所有废弃镜像与Build Cache docker system prune -a...

如何在Android 12 aosp系统源码中添加三指下滑截图功能
如何在Android 12 aosp系统源码中添加三指下滑截图功能 系统中截图api非常简单: private static ScreenshotHelper sScreenshotHelper;sScreenshotHelper new ScreenshotHelper(mContext);//调用 sScreenshotHelper.takeScreenshot(WindowManager.TAKE_SCREENSHO…...

使用SQL语句查询MySQL数据表
6.1 创建单表基本查询 1.Select 语句的语法格式及其功能 (1)Select 语句的一般格式。 Select < 字段名称或表达式列表 > From < 数据表名称或视图名称 > [ Where < 条件表达式 > ] [ Group By < 分组的字段名称…...

【AI绘画、换脸、写作、办公】从零开始:使用AIStarter启动器发布AI应用
随着人工智能技术的快速发展,越来越多的开发者希望通过自己的创意来构建和分享AI应用。AIStarter启动器正是为此而设计的一个强大工具,它可以帮助开发者轻松打包并发布自己的AI应用项目。本文将详细介绍如何使用AIStarter启动器来实现这一目标。 注册账…...

eeprom使用 cubemx STM32F407ZGT6【IIC驱动AT24C02】
存储器的简单介绍 ROM(只读存储器)、RAM(随机存取存储器)、Flash(闪存)、和EEPROM(电可擦可编程只读存储器)是四种不同类型的存储介质。ROM用于存储固件或永久数据,不易…...

STL-stack/queue/deque(容器适配器)
目录 编辑 STL-stack 150. 逆波兰表达式求值 stack queue std::stack deque 性能测试 结构 STL-stack 栈的压入、弹出序列_牛客题霸_牛客网输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假。题目…...

NVDLA专题15:Runtime environment-核心模式驱动
核心模式驱动(Kernel Mode Driver) KMD主入口点在内存中接收一个推理作业,从多个可用的作业中选择要执行的作业(如果在多进程系统上),并将其提交给核心引擎调度程序。该核心引擎调度程序负责处理来自NVDLA的中断,调度每…...

计算机毕业设计选题推荐-班级管理系统-教务管理系统-Java/Python项目实战
✨作者主页:IT研究室✨ 个人简介:曾从事计算机专业培训教学,擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Python…...

推荐一款开源、高效、灵活的Redis桌面管理工具:Tiny RDM!支持调试与分析功能!
1、引言 在大数据和云计算快速发展的今天,Redis作为一款高性能的内存键值存储系统,在数据缓存、实时计算、消息队列等领域发挥着重要作用。然而,随着Redis集群规模的扩大和复杂度的增加,如何高效地管理和运维Redis数据库成为了许…...

Java项目: 基于SpringBoot+mybatis+maven新闻推荐系统(含源码+数据库+毕业论文)
一、项目简介 本项目是一套基于SpringBootmybatismaven新闻推荐系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简单、…...

《Python读取 Excel 数据》
关于如何在 Python 中读取excel数据。 方法一: 我们可以使用 pandas 库来读取 Excel 数据。 通过以下命令安装: pip install pandas 以下是读取 Excel 数据的代码: import pandas as pd # 读取 Excel 文件 data pd.read_excel(…...

Druid连接池
一.什么是Druid连接池? Druid 是阿里巴巴开源的一款数据库连接池(Database Connection Pool),具有高效、稳定、安全等特点。除了连接池的功能外,Druid 还提供了强大的 SQL 监控、统计、日志记录、防火墙等功能。它主要…...

Python3网络爬虫开发实战(14)资讯类页面智能解析
文章目录 一、详细页智能解析算法1.1 提取标题1.2 提取正文1.3 提取时间 二、列表页智能解析算法三、智能分辨列表页和详细页四、完整的库4.1 参考文献4.2 Project 页面智能解析就是利用算法从页面的 HTML 代码中提取想要的内容,算法会自动计算出目标内容在代码中的…...

社交媒体的未来:Facebook如何通过AI技术引领潮流
在数字化时代的浪潮中,社交媒体平台不断演变,以适应用户需求和技术发展的变化。作为全球领先的社交媒体平台,Facebook在这一进程中扮演了重要角色。尤其是人工智能(AI)技术的应用,正在深刻地改变Facebook的…...

Java 面试题:从源码理解 ThreadLocal 如何解决内存泄漏 ConcurrentHashMap 如何保证并发安全 --xunznux
文章目录 ThreadLocalThreadLocal 的基本原理ThreadLocal 的实现细节内存泄漏源码使用场景 ConcurrentHashMap 怎么实现线程安全的CAS初始化源码添加元素putVal方法 ThreadLocal ThreadLocal 是 Java 中的一种用于在多线程环境下存储线程局部变量的机制,它可以为每…...

使用人力劳务灵工安全高效的发薪工具
实现企业、劳务、蓝领工人三方的需求撮合、劳务交付、日结考勤、薪费结算一体化闭环,全面为人力企业降低用工成本、提高用工效率。 发薪难 日结/周结/临时工人员难管理,考勤难统计,发薪耗时间 发薪慢 人工核算时间长,微信转账发薪容易限额…...

使用W外链创建微信短链接的方法
创建短链是将长链接转换为更短、更易于分享和记忆的链接的过程。W外链是一个提供短链接生成服务的平台,它支持多种功能,包括但不限于: 短链制作:用户可以将长链接缩短为易于分享的短链接,还支持自定义短链后缀。防红防…...

【人工智能学习笔记】4_4 深度学习基础之生成对抗网络
生成对抗网络(Generative Adversarial Network, GAN) 一种深度学习模型,通过判别模型(Discriminative Model)和生成模型(Generative Model)的相互博弈学习,生成接近真实数据的数据分…...

基于MinerU的PDF解析API
基于MinerU的PDF解析API - MinerU的GPU镜像构建 - 基于FastAPI的PDF解析接口支持一键启动,已经打包到镜像中,自带模型权重,支持GPU推理加速,GPU速度相比CPU每页解析要快几十倍不等 主要功能 删除页眉、页脚、脚注、页码等元素&…...

猫头虎分享:看完百度内部讲话,整理出李彦宏关于大模型的10个判断
🦁 猫头虎分享:看完百度内部讲话,整理出李彦宏关于大模型的10个判断 📢 大家好!我是猫头虎技术团队的首席写作官。今天为大家带来一篇重量级内容:从百度内部讲话中,整理了李彦宏对大模型的10大…...

vue3透传、注入
属性透传 传递给子组件时,没有被子组件消费的属性或事件,常见的如id、class 注意1 1.class、style是合并的,style中如果出现重复的样式,以透传属性为准2.id属性是以透传属性为准,其他情况透传属性名相同,…...

数模原理精解【9】
文章目录 混合高斯分布概述定义性质参数估计计算Julia实现 详述定义原理 核心参数1. 均值(Means)2. 协方差矩阵(Covariance Matrices)3. 权重(Weights)4. 聚类个数(高斯模型个数,K&a…...