库(Libraries)
库类似合约,实现仅在专门地址部署一次,使用EVM的DELEGATECALL的功能重复使用的目的。意思是当库函数被调用后,代码执行在被调用的合约的环境。例如,使用this调用合约,可以访问的调用合约的storage.孤立的库代码仅能访问变量,不能修改变量
pragma solidity ^0.4.16;
library Set {
struct Data {
mapping(uint => bool) flags;
}
function insert(Data storage self, uint value) public returns (bool) {
if (self.flags[value])
return false;
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value) public returns (bool) {
if (!self.flags[value])
return false;
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value) public view returns (bool) {
return self.flags[value];
}
}
contract C {
Set.Data knownValues;
function register(uint value) public {
require(Set.insert(knownValues, value));
}
// In this contract, we can also directly access knownValues.flags, if we want.
}
如何使用库的memory类型和内部函数实现自定义类型,而无须使用外部方法调用
pragma solidity ^0.4.16;
library BigInt {
struct bigint {
uint[] limbs;
}
function fromUint(uint x) internal pure returns (bigint r) {
r.limbs = new uint[](1);
r.limbs[0] = x;
}
function add(bigint _a, bigint _b) internal pure returns (bigint r) {
r.limbs = new uint[](max(_a.limbs.length, _b.limbs.length));
uint carry = 0;
for (uint i = 0; i < r.limbs.length; ++i) {
uint a = limb(_a, i);
uint b = limb(_b, i);
r.limbs[i] = a + b + carry;
if (a + b < a || (a + b == uint(-1) && carry > 0))
carry = 1;
else
carry = 0;
}
if (carry > 0) {
// too bad, we have to add a limb
uint[] memory newLimbs = new uint[](r.limbs.length + 1);
for (i = 0; i < r.limbs.length; ++i)
newLimbs[i] = r.limbs[i];
newLimbs[i] = carry;
r.limbs = newLimbs;
}
}
function limb(bigint _a, uint _limb) internal pure returns (uint) {
return _limb < _a.limbs.length ? _a.limbs[_limb] : 0;
}
function max(uint a, uint b) private pure returns (uint) {
return a > b ? a : b;
}
}
contract C {
using BigInt for BigInt.bigint;
function f() public pure {
var x = BigInt.fromUint(7);
var y = BigInt.fromUint(uint(-1));
var z = x.add(y);
}
}
关键字Using For
using A for B 附加库函数A到类型B,类似python的self
using A for * 附加库函数A到所有类型
pragma solidity ^0.4.16;
library Set {
struct Data {
mapping(uint => bool) flags;
}
function insert(Data storage self, uint value) public returns (bool) {
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
function remove(Data storage self, uint value) public returns (bool) {
if (!self.flags[value])
return false; // not there
self.flags[value] = false;
return true;
}
function contains(Data storage self, uint value) public view returns (bool) {
return self.flags[value];
}
}
contract C {
using Set for Set.Data; // this is the crucial change
Set.Data knownValues;
function register(uint value) public {
require(knownValues.insert(value));
}
}
使用另外方式扩展基本类型
pragma solidity ^0.4.16;
library Search {
function indexOf(uint[] storage self, uint value) public view returns (uint) {
for (uint i = 0; i < self.length; i++)
if (self[i] == value) return i;
return uint(-1);
}
}
contract C {
using Search for uint[];
uint[] data;
function append(uint value) public {
data.push(value);
}
function replace(uint _old, uint _new) public {
uint index = data.indexOf(_old);
if (index == uint(-1))
data.push(_new);
else
data[index] = _new;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix