2个不稳定版本
0.3.0 | 2024年6月4日 |
---|---|
0.2.0 | 2024年6月3日 |
0.1.1 |
|
0.1.0 |
|
68KB
1.5K SLoC
rustsol
描述
rustsol
是一个用于生成Ethereum智能合约Rust存储绑定的工具。这些绑定可以用来检索合约中所有存储变量的存储槽、偏移量和大小,包括存储在映射和数组中的对象。当使用slots_getter
初始化时,生成的结构体可以用来方便地访问这些存储变量的值。
绑定示例使用
获取合约变量的存储位置
let contract = generated_contract::UniswapV3Pool::new();
let (slot, offset, size_bytes) = contract.observations.at(42).tickCumulative.position();
println!("slot={}, offset={}, size_bytes={}", slot, offset, size_bytes);
// Output:
// slot=50, offset=4, size_bytes=7
使用提供的槽获取器获取合约变量的存储值
let contract = generated_contract::UniswapV3Pool::new();
contract.set_slots_getter(my_slots_getter);
let tick_value = contract.ticks.at(-92110).get_value().unwrap();
println!("{:?}", tick_value);
// Output (prettified):
// TickInfoValue {
// liquidityGross: 398290794261,
// liquidityNet: 398290794261,
// feeGrowthOutside0X128: 0x0000000000000000000000000000000000000b73d798604f1b0cd4f1d544c646_U256,
// feeGrowthOutside1X128: 0x000000000000000000000000000000f2a960acbe8891e526c025b819077f15ae_U256,
// tickCumulativeOutside: 622572156443,
// secondsPerLiquidityOutsideX128: 0x0000000000000000000000000000000000000001e576ee66a9d9f002e36fad4c_U256,
// secondsOutside: 1623419923,
// initialized: true
// }
生成的结构体
生成的绑定结构体将类似于以下内容
pub struct UniswapV3Pool {
__slot: U256,
__slots_getter: Option<Arc<dyn SlotsGetter>>,
pub slot0: UniswapV3PoolSlot0,
pub feeGrowthGlobal0X128: Primitive<32, U256>,
pub feeGrowthGlobal1X128: Primitive<32, U256>,
pub protocolFees: UniswapV3PoolProtocolFees,
pub liquidity: Primitive<16, u128>,
pub ticks: Mapping<i32, TickInfo>,
pub tickBitmap: Mapping<i16, Primitive<32, U256>>,
pub positions: Mapping<U256, PositionInfo>,
pub observations: StaticArray<2097120, OracleObservation>,
}
安装
cargo install rustsol
设置和使用
1. 获取合约存储布局
要为合约生成存储绑定,您首先需要合约的存储布局JSON格式。对于Solidity合约,可以使用solc
编译器生成。 rustsol
提供了一个简单的Python脚本来协助此过程。请参阅原始仓库中的说明。
2. 生成绑定
要生成绑定,请使用以下命令
rustsol generate_storage_bindings your_solc_output.json contract_path contract_name generated_contract.rs
要了解contract_path
和contract_name
的含义,让我们看看一个示例存储布局JSON
{
"contracts": {
"UniswapV3Pool.sol": {
"UniswapV3Pool": {
"storageLayout": {
...
}
}
}
}
}
在这里,UniswapV3Pool.sol
是合约路径,UniswapV3Pool
是合约名称。
对于提供的示例,将是
rustsol generate_storage_bindings example/solc_output_uniswap3pool.json UniswapV3Pool.sol UniswapV3Pool example/src/generated_contract_uniswap3pool.rs
运行以上命令后,生成的结构体将在generated_contract.rs
文件中。请参阅原始仓库中的示例。
类型映射
以太坊智能合约语言(Solidity)与Rust语言的映射
Solidity中的变量类型被映射到Rust的绑定类型。这种映射在下面的表格中展示。在这里,value_type
对应于(可能嵌套的)rustsol
绑定类型,例如Primitive
或Mapping
。而native_type
是将实际槽位值转换成的类型,例如u64
,bool
和U256
。请注意,Mappings
的键也是原生类型。
Solidity类型 | 生成的Rust类型 |
---|---|
所有整数类型,布尔值,枚举, 地址,合约,小字节1..32 |
原始类型<字节大小,原生类型> |
字符串,字节 | Bytes<String> ,Bytes<Vec<u8>> |
静态数组 | StaticArray<字节大小,值类型> |
动态数组 | DynamicArray<值类型> |
映射 | Mapping<键原生类型,值类型> |
结构体 | CustomNamedStructWithCorrespondingFields |
请注意,所有枚举都映射到Primitive<byte_size, U256>
。使用原生Rust枚举作为native_type
可能更好,但这需要更深入的对Solidity合约的分析,因为枚举字段名称的信息无法从存储布局中获得。
值类型映射
使用get_value()
获得的变量值根据下面的表格转换为原生类型。
rustsol 类型 |
生成的Rust类型 |
---|---|
原始类型<_,原生类型> |
原生类型 |
Bytes<String> |
String |
Bytes<Vec<u8>> |
Vec<u8> |
StaticArray<值类型> |
Vec<value_type的递归原生类型> |
DynamicArray |
Vec<value_type的递归原生类型> |
Mapping |
Mapping<key_native_type, value_type> 获取器 |
SomeStruct |
SomeStructValue |
请注意,Mapping
类型实际上映射到相同的Mapping
。这是因为无法获取Solidity映射的所有元素。因此,我们返回一个值获取器而不是具体值。
许可证
本项目受MIT许可证许可。
依赖项
~8MB
~139K SLoC