feat: Don't encode min amount for USV4
We aren't checking min amount for any other executor. This would be overkill (since we are already checking in the main router) and also inconsistent.
This commit is contained in:
@@ -39,7 +39,6 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
(
|
(
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
uint256 amountOutMin,
|
|
||||||
bool zeroForOne,
|
bool zeroForOne,
|
||||||
address callbackExecutor,
|
address callbackExecutor,
|
||||||
bytes4 callbackSelector,
|
bytes4 callbackSelector,
|
||||||
@@ -68,12 +67,12 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
poolKey: key,
|
poolKey: key,
|
||||||
zeroForOne: zeroForOne,
|
zeroForOne: zeroForOne,
|
||||||
amountIn: uint128(amountIn),
|
amountIn: uint128(amountIn),
|
||||||
amountOutMinimum: uint128(amountOutMin),
|
amountOutMinimum: uint128(0),
|
||||||
hookData: bytes("")
|
hookData: bytes("")
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
params[1] = abi.encode(key.currency0, amountIn);
|
params[1] = abi.encode(key.currency0, amountIn);
|
||||||
params[2] = abi.encode(key.currency1, amountOutMin);
|
params[2] = abi.encode(key.currency1, uint256(0));
|
||||||
swapData = abi.encode(actions, params);
|
swapData = abi.encode(actions, params);
|
||||||
} else {
|
} else {
|
||||||
PathKey[] memory path = new PathKey[](pools.length);
|
PathKey[] memory path = new PathKey[](pools.length);
|
||||||
@@ -101,11 +100,11 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
currencyIn: currencyIn,
|
currencyIn: currencyIn,
|
||||||
path: path,
|
path: path,
|
||||||
amountIn: uint128(amountIn),
|
amountIn: uint128(amountIn),
|
||||||
amountOutMinimum: uint128(amountOutMin)
|
amountOutMinimum: uint128(0)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
params[1] = abi.encode(currencyIn, amountIn);
|
params[1] = abi.encode(currencyIn, amountIn);
|
||||||
params[2] = abi.encode(Currency.wrap(tokenOut), amountOutMin);
|
params[2] = abi.encode(Currency.wrap(tokenOut), uint256(0));
|
||||||
swapData = abi.encode(actions, params);
|
swapData = abi.encode(actions, params);
|
||||||
}
|
}
|
||||||
bytes memory fullData =
|
bytes memory fullData =
|
||||||
@@ -141,27 +140,25 @@ contract UniswapV4Executor is IExecutor, V4Router {
|
|||||||
returns (
|
returns (
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
uint256 amountOutMin,
|
|
||||||
bool zeroForOne,
|
bool zeroForOne,
|
||||||
address callbackExecutor,
|
address callbackExecutor,
|
||||||
bytes4 callbackSelector,
|
bytes4 callbackSelector,
|
||||||
UniswapV4Pool[] memory pools
|
UniswapV4Pool[] memory pools
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (data.length < 123) {
|
if (data.length < 91) {
|
||||||
revert UniswapV4Executor__InvalidDataLength();
|
revert UniswapV4Executor__InvalidDataLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenIn = address(bytes20(data[0:20]));
|
tokenIn = address(bytes20(data[0:20]));
|
||||||
tokenOut = address(bytes20(data[20:40]));
|
tokenOut = address(bytes20(data[20:40]));
|
||||||
amountOutMin = uint256(bytes32(data[40:72]));
|
zeroForOne = (data[40] != 0);
|
||||||
zeroForOne = (data[72] != 0);
|
callbackExecutor = address(bytes20(data[41:61]));
|
||||||
callbackExecutor = address(bytes20(data[73:93]));
|
callbackSelector = bytes4(data[61:65]);
|
||||||
callbackSelector = bytes4(data[93:97]);
|
|
||||||
|
|
||||||
uint256 poolsLength = (data.length - 97) / 26; // 26 bytes per pool object
|
uint256 poolsLength = (data.length - 65) / 26; // 26 bytes per pool object
|
||||||
pools = new UniswapV4Pool[](poolsLength);
|
pools = new UniswapV4Pool[](poolsLength);
|
||||||
bytes memory poolsData = data[97:];
|
bytes memory poolsData = data[65:];
|
||||||
uint256 offset = 0;
|
uint256 offset = 0;
|
||||||
for (uint256 i = 0; i < poolsLength; i++) {
|
for (uint256 i = 0; i < poolsLength; i++) {
|
||||||
address intermediaryToken;
|
address intermediaryToken;
|
||||||
|
|||||||
@@ -753,7 +753,7 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
|||||||
// `5c2f5a71f67c01775180adc06909288b4c329308` with the one in this test
|
// `5c2f5a71f67c01775180adc06909288b4c329308` with the one in this test
|
||||||
// `f62849f9a0b5bf2913b396098f7c7019b51a820a`
|
// `f62849f9a0b5bf2913b396098f7c7019b51a820a`
|
||||||
(bool success,) = tychoRouterAddr.call(
|
(bool success,) = tychoRouterAddr.call(
|
||||||
hex"d499aa88000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000067ddee9e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067b668a6000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041bdf91011918dcb5f59ab3588212a035c770a2839fe2c19060491370fa89685b8469def9e83c7b9cf8f0ef5088a3179556a6ba1096cefbe83c09a1182981c93e41c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b400b20001000000f62849f9a0b5bf2913b396098f7c7019b51a820abd0625aba0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d2311933000000000000000000000000000000000000000000000000000000000000000000f62849f9a0b5bf2913b396098f7c7019b51a820a91dd73460000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f4000000000000000000000000"
|
hex"d499aa88000000000000000000000000000000000000000000000000000000003b9aca00000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000006982508145454ce325ddbe47a25d4ec3d23119330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000cd09f75e2bf2a4d11f3ab23f1389fcc1621c0cc2000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000003b9aca000000000000000000000000000000000000000000000000000000000067ddee9e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ede3eca2a72b3aecc820e955b36f38437d013950000000000000000000000000000000000000000000000000000000067b668a6000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002800000000000000000000000000000000000000000000000000000000000000041bdf91011918dcb5f59ab3588212a035c770a2839fe2c19060491370fa89685b8469def9e83c7b9cf8f0ef5088a3179556a6ba1096cefbe83c09a1182981c93e41c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009400920001000000f62849f9a0b5bf2913b396098f7c7019b51a820abd0625aba0b86991c6218b36c1d19d4a2e9eb0ce3606eb486982508145454ce325ddbe47a25d4ec3d231193300f62849f9a0b5bf2913b396098f7c7019b51a820a91dd73460000000000000000000000000000000000000000000bb800003c6982508145454ce325ddbe47a25d4ec3d23119330061a80001f4000000000000000000000000"
|
||||||
);
|
);
|
||||||
|
|
||||||
vm.stopPrank();
|
vm.stopPrank();
|
||||||
@@ -924,7 +924,6 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
|||||||
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
|
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
|
||||||
USDE_ADDR,
|
USDE_ADDR,
|
||||||
USDT_ADDR,
|
USDT_ADDR,
|
||||||
uint256(1),
|
|
||||||
true,
|
true,
|
||||||
address(usv4Executor),
|
address(usv4Executor),
|
||||||
SafeCallback.unlockCallback.selector,
|
SafeCallback.unlockCallback.selector,
|
||||||
@@ -970,7 +969,6 @@ contract TychoRouterTest is TychoRouterTestSetup {
|
|||||||
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
|
bytes memory protocolData = UniswapV4Utils.encodeExactInput(
|
||||||
USDE_ADDR,
|
USDE_ADDR,
|
||||||
WBTC_ADDR,
|
WBTC_ADDR,
|
||||||
uint256(1),
|
|
||||||
true,
|
true,
|
||||||
address(usv4Executor),
|
address(usv4Executor),
|
||||||
SafeCallback.unlockCallback.selector,
|
SafeCallback.unlockCallback.selector,
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ contract UniswapV4ExecutorExposed is UniswapV4Executor {
|
|||||||
returns (
|
returns (
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
uint256 amountOutMin,
|
|
||||||
bool zeroForOne,
|
bool zeroForOne,
|
||||||
address callbackExecutor,
|
address callbackExecutor,
|
||||||
bytes4 callbackSelector,
|
bytes4 callbackSelector,
|
||||||
@@ -44,7 +43,6 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function testDecodeParams() public view {
|
function testDecodeParams() public view {
|
||||||
uint256 minAmountOut = 100;
|
|
||||||
bool zeroForOne = true;
|
bool zeroForOne = true;
|
||||||
uint24 pool1Fee = 500;
|
uint24 pool1Fee = 500;
|
||||||
int24 tickSpacing1 = 60;
|
int24 tickSpacing1 = 60;
|
||||||
@@ -67,7 +65,6 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
bytes memory data = UniswapV4Utils.encodeExactInput(
|
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||||
USDE_ADDR,
|
USDE_ADDR,
|
||||||
USDT_ADDR,
|
USDT_ADDR,
|
||||||
minAmountOut,
|
|
||||||
zeroForOne,
|
zeroForOne,
|
||||||
address(uniswapV4Exposed),
|
address(uniswapV4Exposed),
|
||||||
SafeCallback.unlockCallback.selector,
|
SafeCallback.unlockCallback.selector,
|
||||||
@@ -77,7 +74,6 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
(
|
(
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
uint256 amountOutMin,
|
|
||||||
bool zeroForOneDecoded,
|
bool zeroForOneDecoded,
|
||||||
address callbackExecutor,
|
address callbackExecutor,
|
||||||
bytes4 callbackSelector,
|
bytes4 callbackSelector,
|
||||||
@@ -86,7 +82,6 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
|
|
||||||
assertEq(tokenIn, USDE_ADDR);
|
assertEq(tokenIn, USDE_ADDR);
|
||||||
assertEq(tokenOut, USDT_ADDR);
|
assertEq(tokenOut, USDT_ADDR);
|
||||||
assertEq(amountOutMin, minAmountOut);
|
|
||||||
assertEq(zeroForOneDecoded, zeroForOne);
|
assertEq(zeroForOneDecoded, zeroForOne);
|
||||||
assertEq(callbackExecutor, address(uniswapV4Exposed));
|
assertEq(callbackExecutor, address(uniswapV4Exposed));
|
||||||
assertEq(callbackSelector, SafeCallback.unlockCallback.selector);
|
assertEq(callbackSelector, SafeCallback.unlockCallback.selector);
|
||||||
@@ -117,7 +112,6 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
bytes memory data = UniswapV4Utils.encodeExactInput(
|
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||||
USDE_ADDR,
|
USDE_ADDR,
|
||||||
USDT_ADDR,
|
USDT_ADDR,
|
||||||
uint256(1),
|
|
||||||
true,
|
true,
|
||||||
address(uniswapV4Exposed),
|
address(uniswapV4Exposed),
|
||||||
SafeCallback.unlockCallback.selector,
|
SafeCallback.unlockCallback.selector,
|
||||||
@@ -137,7 +131,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
// USDE -> USDT
|
// USDE -> USDT
|
||||||
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_simple_swap
|
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_simple_swap
|
||||||
bytes memory protocolData =
|
bytes memory protocolData =
|
||||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec70000000000000000000000000000000000000000000000000000000000000001015615deb798bb3e4dfa0139dfa1b3d433cc23b72f91dd7346dac17f958d2ee523a2206206994597c13d831ec7000064000001";
|
hex"4c9edd5852cd905f086c759e8383e09bff1e68b3dac17f958d2ee523a2206206994597c13d831ec701f62849f9a0b5bf2913b396098f7c7019b51a820a91dd7346dac17f958d2ee523a2206206994597c13d831ec7000064000001";
|
||||||
|
|
||||||
uint256 amountIn = 100 ether;
|
uint256 amountIn = 100 ether;
|
||||||
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||||
@@ -178,7 +172,6 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
bytes memory data = UniswapV4Utils.encodeExactInput(
|
bytes memory data = UniswapV4Utils.encodeExactInput(
|
||||||
USDE_ADDR,
|
USDE_ADDR,
|
||||||
WBTC_ADDR,
|
WBTC_ADDR,
|
||||||
uint256(1),
|
|
||||||
true,
|
true,
|
||||||
address(uniswapV4Exposed),
|
address(uniswapV4Exposed),
|
||||||
SafeCallback.unlockCallback.selector,
|
SafeCallback.unlockCallback.selector,
|
||||||
@@ -200,7 +193,7 @@ contract UniswapV4ExecutorTest is Test, Constants {
|
|||||||
// USDE -> USDT -> WBTC
|
// USDE -> USDT -> WBTC
|
||||||
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_sequential_swap
|
// Generated by the Tycho swap encoder - test_encode_uniswap_v4_sequential_swap
|
||||||
bytes memory protocolData =
|
bytes memory protocolData =
|
||||||
hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c5990000000000000000000000000000000000000000000000000000000000000001015615deb798bb3e4dfa0139dfa1b3d433cc23b72f91dd7346dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c";
|
hex"4c9edd5852cd905f086c759e8383e09bff1e68b32260fac5e5542a773aa44fbcfedf7c193bc2c59901f62849f9a0b5bf2913b396098f7c7019b51a820a91dd7346dac17f958d2ee523a2206206994597c13d831ec70000640000012260fac5e5542a773aa44fbcfedf7c193bc2c599000bb800003c";
|
||||||
|
|
||||||
uint256 amountIn = 100 ether;
|
uint256 amountIn = 100 ether;
|
||||||
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
deal(USDE_ADDR, address(uniswapV4Exposed), amountIn);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ library UniswapV4Utils {
|
|||||||
function encodeExactInput(
|
function encodeExactInput(
|
||||||
address tokenIn,
|
address tokenIn,
|
||||||
address tokenOut,
|
address tokenOut,
|
||||||
uint256 amountOutMin,
|
|
||||||
bool zeroForOne,
|
bool zeroForOne,
|
||||||
address callbackExecutor,
|
address callbackExecutor,
|
||||||
bytes4 callbackSelector,
|
bytes4 callbackSelector,
|
||||||
@@ -27,7 +26,6 @@ library UniswapV4Utils {
|
|||||||
return abi.encodePacked(
|
return abi.encodePacked(
|
||||||
tokenIn,
|
tokenIn,
|
||||||
tokenOut,
|
tokenOut,
|
||||||
amountOutMin,
|
|
||||||
zeroForOne,
|
zeroForOne,
|
||||||
callbackExecutor,
|
callbackExecutor,
|
||||||
bytes4(callbackSelector),
|
bytes4(callbackSelector),
|
||||||
|
|||||||
@@ -981,9 +981,9 @@ mod tests {
|
|||||||
|
|
||||||
let expected_swaps = String::from(concat!(
|
let expected_swaps = String::from(concat!(
|
||||||
// length of ple encoded swaps without padding
|
// length of ple encoded swaps without padding
|
||||||
"00000000000000000000000000000000000000000000000000000000000000b4",
|
"0000000000000000000000000000000000000000000000000000000000000094",
|
||||||
// ple encoded swaps
|
// ple encoded swaps
|
||||||
"00b2", // Swap length
|
"0092", // Swap length
|
||||||
"00", // token in index
|
"00", // token in index
|
||||||
"01", // token out index
|
"01", // token out index
|
||||||
"000000", // split
|
"000000", // split
|
||||||
@@ -993,7 +993,6 @@ mod tests {
|
|||||||
// Protocol data
|
// Protocol data
|
||||||
"a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // group token in
|
"a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", // group token in
|
||||||
"6982508145454ce325ddbe47a25d4ec3d2311933", // group token in
|
"6982508145454ce325ddbe47a25d4ec3d2311933", // group token in
|
||||||
"0000000000000000000000000000000000000000000000000000000000000000", // amount out min
|
|
||||||
"00", // zero2one
|
"00", // zero2one
|
||||||
"f62849f9a0b5bf2913b396098f7c7019b51a820a", // executor address
|
"f62849f9a0b5bf2913b396098f7c7019b51a820a", // executor address
|
||||||
"91dd7346", // callback selector
|
"91dd7346", // callback selector
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use alloy_primitives::{Address, Bytes as AlloyBytes, U256};
|
use alloy_primitives::{Address, Bytes as AlloyBytes};
|
||||||
use alloy_sol_types::SolValue;
|
use alloy_sol_types::SolValue;
|
||||||
use tycho_core::Bytes;
|
use tycho_core::Bytes;
|
||||||
|
|
||||||
@@ -192,7 +192,6 @@ impl SwapEncoder for UniswapV4SwapEncoder {
|
|||||||
let group_token_in_address = bytes_to_address(&encoding_context.group_token_in)?;
|
let group_token_in_address = bytes_to_address(&encoding_context.group_token_in)?;
|
||||||
let group_token_out_address = bytes_to_address(&encoding_context.group_token_out)?;
|
let group_token_out_address = bytes_to_address(&encoding_context.group_token_out)?;
|
||||||
|
|
||||||
let amount_out_min = U256::from(0);
|
|
||||||
let zero_to_one = Self::get_zero_to_one(token_in_address, token_out_address);
|
let zero_to_one = Self::get_zero_to_one(token_in_address, token_out_address);
|
||||||
let callback_executor =
|
let callback_executor =
|
||||||
bytes_to_address(&Bytes::from_str(&self.executor_address).map_err(|_| {
|
bytes_to_address(&Bytes::from_str(&self.executor_address).map_err(|_| {
|
||||||
@@ -205,7 +204,6 @@ impl SwapEncoder for UniswapV4SwapEncoder {
|
|||||||
let args = (
|
let args = (
|
||||||
group_token_in_address,
|
group_token_in_address,
|
||||||
group_token_out_address,
|
group_token_out_address,
|
||||||
amount_out_min,
|
|
||||||
zero_to_one,
|
zero_to_one,
|
||||||
callback_executor,
|
callback_executor,
|
||||||
encode_function_selector(&self.callback_selector),
|
encode_function_selector(&self.callback_selector),
|
||||||
@@ -481,6 +479,7 @@ mod tests {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
let hex_swap = encode(&encoded_swap);
|
let hex_swap = encode(&encoded_swap);
|
||||||
|
|
||||||
|
println!("{}", hex_swap);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
hex_swap,
|
hex_swap,
|
||||||
String::from(concat!(
|
String::from(concat!(
|
||||||
@@ -488,8 +487,6 @@ mod tests {
|
|||||||
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
||||||
// group token out
|
// group token out
|
||||||
"dac17f958d2ee523a2206206994597c13d831ec7",
|
"dac17f958d2ee523a2206206994597c13d831ec7",
|
||||||
// amount out min
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
// zero for one
|
// zero for one
|
||||||
"01",
|
"01",
|
||||||
// executor address
|
// executor address
|
||||||
@@ -649,8 +646,6 @@ mod tests {
|
|||||||
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
"4c9edd5852cd905f086c759e8383e09bff1e68b3",
|
||||||
// group_token out
|
// group_token out
|
||||||
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
"2260fac5e5542a773aa44fbcfedf7c193bc2c599",
|
||||||
// amount out min
|
|
||||||
"0000000000000000000000000000000000000000000000000000000000000000",
|
|
||||||
// zero for one
|
// zero for one
|
||||||
"01",
|
"01",
|
||||||
// executor address
|
// executor address
|
||||||
|
|||||||
Reference in New Issue
Block a user