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...
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!