Uniswap V4 BalanceDelta 是一种自定义类型,用于同时表示两个代币的余额变化,分别用高低位的方式存储。同时提供了运算符重载和相关方法,以便于进行加减法和比较操作。此外,BalanceDeltaLibrary 提供了获取各个代币数量的方法,方便使用。
BalanceDelta 类型用一个 int256 类型同时表示 token0 和 token1 的余额变化值。
/// @dev Two `int128` values packed into a single `int256` where the upper 128 bits represent the amount0
/// and the lower 128 bits represent the amount1.
type BalanceDelta is int256;
其中,高 128 位表示 token0 的余额变化值 amount0,低 128 位表示 token1 的余额变化值 amount1。
通过以下代码声明了 BalanceDelta 类型的运算符重载:
using {add as +, sub as -, eq as ==, neq as !=} for BalanceDelta global;
当对 BalanceDelta 类型的变量使用 +、-、==、!= 运算符时,会调用对应 add、sub、eq、neq 方法。
将两个 int128 类型的 amount0 和 amount1 拼凑成 BalanceDelta 类型。
function toBalanceDelta(int128 _amount0, int128 _amount1) pure returns (BalanceDelta balanceDelta) {
assembly ("memory-safe") {
balanceDelta := or(shl(128, _amount0), and(sub(shl(128, 1), 1), _amount1))
}
}
shl(128, _amount0) 将 _amount0 左移 128 位,即将 _amount0 放到高 128 位,低 128 位设置为 0。
sub(shl(128, 1), 1) 将 1 左移 128 位,然后减去 1,将低 128 位设置为 1。
and(sub(shl(128, 1), 1), _amount1) 将 _amount1 与低 128 位 1 进行与操作,即只保留 _amount1 的低 128 位,高 128 位为 0。
最后,通过 or 将 _amount0 和 _amount1 拼凑成 BalanceDelta 类型。
将两个 BalanceDelta 类型的变量相加,得到 BalanceDelta 类型的结果。
function add(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
int256 res0;
int256 res1;
assembly ("memory-safe") {
let a0 := sar(128, a)
let a1 := signextend(15, a)
let b0 := sar(128, b)
let b1 := signextend(15, b)
res0 := add(a0, b0)
res1 := add(a1, b1)
}
return toBalanceDelta(res0.toInt128(), res1.toInt128());
}
首先,通过 sar(128, a) 将 a 算数右移 128 位,即取出 a 的高 128 位 a0。
然后,通过 signextend(15, a) 将 a 的低 128 位符号扩展为 256 位,即取出 a 的低 128 位 a1,并保持符号位不变。
同理,取出 b 的高 128 位 b0 和低 128 位 b1。
接着,将 a0 和 b0 相加得到 res0,将 a1 和 b1 相加得到 res1。
最后,通过 toBalanceDelta 方法将 res0 和 res1 拼凑成 BalanceDelta 类型。
将两个 BalanceDelta 类型的变量相减,得到 BalanceDelta 类型的结果。
function sub(BalanceDelta a, BalanceDelta b) pure returns (BalanceDelta) {
int256 res0;
int256 res1;
assembly ("memory-safe") {
let a0 := sar(128, a)
let a1 := signextend(15, a)
let b0 := sar(128, b)
let b1 := signextend(15, b)
res0 := sub(a0, b0)
res1 := sub(a1, b1)
}
return toBalanceDelta(res0.toInt128(), res1.toInt128());
}
与 add 方法类似,只是将 a0 和 b0 相减得到 res0,将 a1 和 b1 相减得到 res1。
判断两个 BalanceDelta 类型的变量是否相等。
function eq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
return BalanceDelta.unwrap(a) == BalanceDelta.unwrap(b);
}
通过 unwrap 方法将 a 和 b 解包成 int256 类型,然后比较是否相等。
判断两个 BalanceDelta 类型的变量是否不相等。
function neq(BalanceDelta a, BalanceDelta b) pure returns (bool) {
return BalanceDelta.unwrap(a) != BalanceDelta.unwrap(b);
}
通过 unwrap 方法将 a 和 b 解包成 int256 类型,然后比较是否不相等。
BalanceDeltaLibrary 提供了 amount0 和 amount1 方法,用于获取 BalanceDelta 类型的变量的 amount0 和 amount1 值。
/// @notice Library for getting the amount0 and amount1 deltas from the BalanceDelta type
library BalanceDeltaLibrary {
/// @notice A BalanceDelta of 0
BalanceDelta public constant ZERO_DELTA = BalanceDelta.wrap(0);
function amount0(BalanceDelta balanceDelta) internal pure returns (int128 _amount0) {
assembly ("memory-safe") {
_amount0 := sar(128, balanceDelta)
}
}
function amount1(BalanceDelta balanceDelta) internal pure returns (int128 _amount1) {
assembly ("memory-safe") {
_amount1 := signextend(15, balanceDelta)
}
}
}
获取 BalanceDelta 类型的变量的 amount0 值。
通过 sar(128, balanceDelta) 将 balanceDelta 算数右移 128 位,即取出 balanceDelta 的高 128 位。
获取 BalanceDelta 类型的变量的 amount1 值。
通过 signextend(15, balanceDelta) 将 balanceDelta 的低 128 位符号扩展为 256 位,即取出 balanceDelta 的低 128 位,并保持符号位不变。
- 本文转载自: github.com/adshao/public...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!