@bananapus/router-terminal-v6 0.0.10 → 0.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/STYLE_GUIDE.md
CHANGED
|
@@ -197,7 +197,7 @@ interface IJBExample is IJBBase {
|
|
|
197
197
|
| Public/external function | `camelCase` | `cashOutTokensOf` |
|
|
198
198
|
| Internal/private function | `_camelCase` | `_processFee` |
|
|
199
199
|
| Internal storage | `_camelCase` | `_accountingContextForTokenOf` |
|
|
200
|
-
| Function parameter | `camelCase` | `projectId`, `cashOutCount` |
|
|
200
|
+
| Function parameter | `camelCase` (no underscores) | `projectId`, `cashOutCount` |
|
|
201
201
|
|
|
202
202
|
## NatSpec
|
|
203
203
|
|
|
@@ -253,9 +253,12 @@ uint256 public constant MAX_RESERVED_PERCENT = 10_000;
|
|
|
253
253
|
|
|
254
254
|
## Function Calls
|
|
255
255
|
|
|
256
|
-
Use named
|
|
256
|
+
Use named arguments for all function calls with 2 or more arguments — in both `src/` and `script/`:
|
|
257
257
|
|
|
258
258
|
```solidity
|
|
259
|
+
// Good — named arguments
|
|
260
|
+
token.mint({account: beneficiary, amount: count});
|
|
261
|
+
_transferOwnership({newOwner: address(0), projectId: 0});
|
|
259
262
|
PERMISSIONS.hasPermission({
|
|
260
263
|
operator: sender,
|
|
261
264
|
account: account,
|
|
@@ -264,8 +267,18 @@ PERMISSIONS.hasPermission({
|
|
|
264
267
|
includeRoot: true,
|
|
265
268
|
includeWildcardProjectId: true
|
|
266
269
|
});
|
|
270
|
+
|
|
271
|
+
// Bad — positional arguments with 2+ args
|
|
272
|
+
token.mint(beneficiary, count);
|
|
273
|
+
_transferOwnership(address(0), 0);
|
|
267
274
|
```
|
|
268
275
|
|
|
276
|
+
Single-argument calls use positional style: `_burn(amount)`.
|
|
277
|
+
|
|
278
|
+
This also applies to constructor calls, struct literals, and inherited/library calls (e.g., OZ `_mint`, `_safeMint`, `safeTransfer`, `allowance`, `Clones.cloneDeterministic`).
|
|
279
|
+
|
|
280
|
+
Named argument keys must use **camelCase** — never underscores. If a function's parameter names use underscores, rename them to camelCase first.
|
|
281
|
+
|
|
269
282
|
## Multiline Signatures
|
|
270
283
|
|
|
271
284
|
```solidity
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bananapus/router-terminal-v6",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"artifacts": "source ./.env && npx sphinx artifacts --org-id 'ea165b21-7cdc-4d7b-be59-ecdd4c26bee4' --project-name 'nana-router-terminal-v6'"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@bananapus/core-v6": "^0.0.
|
|
21
|
-
"@bananapus/permission-ids-v6": "^0.0.
|
|
20
|
+
"@bananapus/core-v6": "^0.0.16",
|
|
21
|
+
"@bananapus/permission-ids-v6": "^0.0.9",
|
|
22
22
|
"@openzeppelin/contracts": "^5.6.1",
|
|
23
23
|
"@uniswap/permit2": "github:Uniswap/permit2",
|
|
24
24
|
"@uniswap/v3-core": "github:Uniswap/v3-core#0.8",
|
package/script/Deploy.s.sol
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
2
|
pragma solidity 0.8.26;
|
|
3
3
|
|
|
4
|
-
import "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
|
|
4
|
+
import {CoreDeployment, CoreDeploymentLib} from "@bananapus/core-v6/script/helpers/CoreDeploymentLib.sol";
|
|
5
5
|
|
|
6
6
|
import {Sphinx} from "@sphinx-labs/contracts/contracts/foundry/SphinxPlugin.sol";
|
|
7
7
|
import {Script} from "forge-std/Script.sol";
|
|
@@ -18,8 +18,8 @@ contract DeployScript is Script, Sphinx {
|
|
|
18
18
|
CoreDeployment core;
|
|
19
19
|
|
|
20
20
|
/// @notice the salts that are used to deploy the contracts.
|
|
21
|
-
bytes32 ROUTER_TERMINAL = "JBRouterTerminalV6";
|
|
22
|
-
bytes32 ROUTER_TERMINAL_REGISTRY = "JBRouterTerminalRegistryV6";
|
|
21
|
+
bytes32 constant ROUTER_TERMINAL = "JBRouterTerminalV6";
|
|
22
|
+
bytes32 constant ROUTER_TERMINAL_REGISTRY = "JBRouterTerminalRegistryV6";
|
|
23
23
|
|
|
24
24
|
/// @notice tracks the addresses that are required for the chain we are deploying to.
|
|
25
25
|
address weth;
|
|
@@ -38,7 +38,9 @@ contract DeployScript is Script, Sphinx {
|
|
|
38
38
|
// Get the deployment addresses for the nana CORE for this chain.
|
|
39
39
|
// We want to do this outside of the `sphinx` modifier.
|
|
40
40
|
core = CoreDeploymentLib.getDeployment(
|
|
41
|
-
vm.envOr(
|
|
41
|
+
vm.envOr({
|
|
42
|
+
name: "NANA_CORE_DEPLOYMENT_PATH", defaultValue: string("node_modules/@bananapus/core-v6/deployments/")
|
|
43
|
+
})
|
|
42
44
|
);
|
|
43
45
|
|
|
44
46
|
trustedForwarder = core.permissions.trustedForwarder();
|
|
@@ -95,22 +97,26 @@ contract DeployScript is Script, Sphinx {
|
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
function deploy() public sphinx {
|
|
98
|
-
JBRouterTerminalRegistry registry = new JBRouterTerminalRegistry{salt: ROUTER_TERMINAL_REGISTRY}(
|
|
99
|
-
|
|
100
|
-
|
|
100
|
+
JBRouterTerminalRegistry registry = new JBRouterTerminalRegistry{salt: ROUTER_TERMINAL_REGISTRY}({
|
|
101
|
+
permissions: core.permissions,
|
|
102
|
+
projects: core.projects,
|
|
103
|
+
permit2: IPermit2(permit2),
|
|
104
|
+
owner: safeAddress(),
|
|
105
|
+
trustedForwarder: trustedForwarder
|
|
106
|
+
});
|
|
101
107
|
|
|
102
|
-
JBRouterTerminal terminal = new JBRouterTerminal{salt: ROUTER_TERMINAL}(
|
|
103
|
-
core.directory,
|
|
104
|
-
core.permissions,
|
|
105
|
-
core.projects,
|
|
106
|
-
core.tokens,
|
|
107
|
-
IPermit2(permit2),
|
|
108
|
-
safeAddress(),
|
|
109
|
-
IWETH9(weth),
|
|
110
|
-
IUniswapV3Factory(factory),
|
|
111
|
-
IPoolManager(poolManager),
|
|
112
|
-
trustedForwarder
|
|
113
|
-
);
|
|
108
|
+
JBRouterTerminal terminal = new JBRouterTerminal{salt: ROUTER_TERMINAL}({
|
|
109
|
+
directory: core.directory,
|
|
110
|
+
permissions: core.permissions,
|
|
111
|
+
projects: core.projects,
|
|
112
|
+
tokens: core.tokens,
|
|
113
|
+
permit2: IPermit2(permit2),
|
|
114
|
+
owner: safeAddress(),
|
|
115
|
+
weth: IWETH9(weth),
|
|
116
|
+
factory: IUniswapV3Factory(factory),
|
|
117
|
+
poolManager: IPoolManager(poolManager),
|
|
118
|
+
trustedForwarder: trustedForwarder
|
|
119
|
+
});
|
|
114
120
|
|
|
115
121
|
// Set the terminal as the default for the registry.
|
|
116
122
|
registry.setDefaultTerminal(terminal);
|
|
@@ -17,6 +17,7 @@ struct RouterTerminalDeployment {
|
|
|
17
17
|
library RouterTerminalDeploymentLib {
|
|
18
18
|
// Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.
|
|
19
19
|
address internal constant VM_ADDRESS = address(uint160(uint256(keccak256("hevm cheat code"))));
|
|
20
|
+
// forge-lint: disable-next-line(screaming-snake-case-const)
|
|
20
21
|
Vm internal constant vm = Vm(VM_ADDRESS);
|
|
21
22
|
|
|
22
23
|
function getDeployment(string memory path) internal returns (RouterTerminalDeployment memory deployment) {
|
|
@@ -30,7 +31,7 @@ library RouterTerminalDeploymentLib {
|
|
|
30
31
|
|
|
31
32
|
for (uint256 _i; _i < networks.length; _i++) {
|
|
32
33
|
if (networks[_i].chainId == chainId) {
|
|
33
|
-
return getDeployment(path, networks[_i].name);
|
|
34
|
+
return getDeployment({path: path, networkName: networks[_i].name});
|
|
34
35
|
}
|
|
35
36
|
}
|
|
36
37
|
|
|
@@ -39,17 +40,28 @@ library RouterTerminalDeploymentLib {
|
|
|
39
40
|
|
|
40
41
|
function getDeployment(
|
|
41
42
|
string memory path,
|
|
42
|
-
string memory
|
|
43
|
+
string memory networkName
|
|
43
44
|
)
|
|
44
45
|
internal
|
|
45
46
|
view
|
|
46
47
|
returns (RouterTerminalDeployment memory deployment)
|
|
47
48
|
{
|
|
48
|
-
deployment.terminal =
|
|
49
|
-
|
|
49
|
+
deployment.terminal = IJBRouterTerminal(
|
|
50
|
+
_getDeploymentAddress({
|
|
51
|
+
path: path,
|
|
52
|
+
projectName: "nana-router-terminal-v6",
|
|
53
|
+
networkName: networkName,
|
|
54
|
+
contractName: "JBRouterTerminal"
|
|
55
|
+
})
|
|
56
|
+
);
|
|
50
57
|
|
|
51
58
|
deployment.registry = IJBRouterTerminalRegistry(
|
|
52
|
-
_getDeploymentAddress(
|
|
59
|
+
_getDeploymentAddress({
|
|
60
|
+
path: path,
|
|
61
|
+
projectName: "nana-router-terminal-v6",
|
|
62
|
+
networkName: networkName,
|
|
63
|
+
contractName: "JBRouterTerminalRegistry"
|
|
64
|
+
})
|
|
53
65
|
);
|
|
54
66
|
}
|
|
55
67
|
|
|
@@ -60,8 +72,8 @@ library RouterTerminalDeploymentLib {
|
|
|
60
72
|
/// @return The address of the contract.
|
|
61
73
|
function _getDeploymentAddress(
|
|
62
74
|
string memory path,
|
|
63
|
-
string memory
|
|
64
|
-
string memory
|
|
75
|
+
string memory projectName,
|
|
76
|
+
string memory networkName,
|
|
65
77
|
string memory contractName
|
|
66
78
|
)
|
|
67
79
|
internal
|
|
@@ -69,7 +81,8 @@ library RouterTerminalDeploymentLib {
|
|
|
69
81
|
returns (address)
|
|
70
82
|
{
|
|
71
83
|
string memory deploymentJson =
|
|
72
|
-
|
|
73
|
-
|
|
84
|
+
// forge-lint: disable-next-line(unsafe-cheatcode)
|
|
85
|
+
vm.readFile(string.concat(path, projectName, "/", networkName, "/", contractName, ".json"));
|
|
86
|
+
return stdJson.readAddress({json: deploymentJson, key: ".address"});
|
|
74
87
|
}
|
|
75
88
|
}
|
package/src/JBRouterTerminal.sol
CHANGED
|
@@ -98,10 +98,13 @@ contract JBRouterTerminal is
|
|
|
98
98
|
|
|
99
99
|
/// @notice The fee tiers to search when auto-discovering V3 pools, ordered by commonality.
|
|
100
100
|
/// 3000 = 0.3%, 500 = 0.05%, 10000 = 1%, 100 = 0.01%.
|
|
101
|
+
// forge-lint: disable-next-line(mixed-case-variable)
|
|
101
102
|
uint24[4] internal _FEE_TIERS = [uint24(3000), uint24(500), uint24(10_000), uint24(100)];
|
|
102
103
|
|
|
103
104
|
/// @notice The fee/tickSpacing pairings to search for V4 vanilla pools.
|
|
105
|
+
// forge-lint: disable-next-line(mixed-case-variable)
|
|
104
106
|
uint24[4] internal _V4_FEES = [uint24(3000), uint24(500), uint24(10_000), uint24(100)];
|
|
107
|
+
// forge-lint: disable-next-line(mixed-case-variable)
|
|
105
108
|
int24[4] internal _V4_TICK_SPACINGS = [int24(60), int24(10), int24(200), int24(1)];
|
|
106
109
|
|
|
107
110
|
//*********************************************************************//
|
|
@@ -186,6 +189,7 @@ contract JBRouterTerminal is
|
|
|
186
189
|
override
|
|
187
190
|
returns (JBAccountingContext memory context)
|
|
188
191
|
{
|
|
192
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
189
193
|
context = JBAccountingContext({token: token, decimals: 18, currency: uint32(uint160(token))});
|
|
190
194
|
}
|
|
191
195
|
|
|
@@ -339,7 +343,7 @@ contract JBRouterTerminal is
|
|
|
339
343
|
}
|
|
340
344
|
|
|
341
345
|
/// @notice Empty implementation to satisfy the interface. This terminal has no balance to migrate.
|
|
342
|
-
function migrateBalanceOf(uint256, address, IJBTerminal) external override returns (uint256 balance) {
|
|
346
|
+
function migrateBalanceOf(uint256, address, IJBTerminal) external pure override returns (uint256 balance) {
|
|
343
347
|
return 0;
|
|
344
348
|
}
|
|
345
349
|
|
|
@@ -408,17 +412,18 @@ contract JBRouterTerminal is
|
|
|
408
412
|
|
|
409
413
|
// Verify caller is a legitimate pool via the factory.
|
|
410
414
|
uint24 fee = IUniswapV3Pool(msg.sender).fee();
|
|
411
|
-
address expectedPool = FACTORY.getPool(normalizedTokenIn, normalizedTokenOut, fee);
|
|
415
|
+
address expectedPool = FACTORY.getPool({tokenA: normalizedTokenIn, tokenB: normalizedTokenOut, fee: fee});
|
|
412
416
|
if (msg.sender != expectedPool) revert JBRouterTerminal_CallerNotPool(msg.sender);
|
|
413
417
|
|
|
414
418
|
// Calculate the amount of tokens to send to the pool (the positive delta).
|
|
419
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
415
420
|
uint256 amountToSendToPool = amount0Delta < 0 ? uint256(amount1Delta) : uint256(amount0Delta);
|
|
416
421
|
|
|
417
422
|
// Wrap native tokens if needed.
|
|
418
423
|
if (tokenIn == JBConstants.NATIVE_TOKEN) WETH.deposit{value: amountToSendToPool}();
|
|
419
424
|
|
|
420
425
|
// Transfer the tokens to the pool.
|
|
421
|
-
IERC20(normalizedTokenIn).safeTransfer(msg.sender, amountToSendToPool);
|
|
426
|
+
IERC20(normalizedTokenIn).safeTransfer({to: msg.sender, value: amountToSendToPool});
|
|
422
427
|
}
|
|
423
428
|
|
|
424
429
|
/// @notice The Uniswap V4 unlock callback. Called by the PoolManager during `unlock()`.
|
|
@@ -447,10 +452,14 @@ contract JBRouterTerminal is
|
|
|
447
452
|
int128 delta0 = delta.amount0();
|
|
448
453
|
int128 delta1 = delta.amount1();
|
|
449
454
|
if (zeroForOne) {
|
|
455
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
450
456
|
amountIn = uint256(uint128(-delta0));
|
|
457
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
451
458
|
amountOut = uint256(uint128(delta1));
|
|
452
459
|
} else {
|
|
460
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
453
461
|
amountIn = uint256(uint128(-delta1));
|
|
462
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
454
463
|
amountOut = uint256(uint128(delta0));
|
|
455
464
|
}
|
|
456
465
|
}
|
|
@@ -459,11 +468,11 @@ contract JBRouterTerminal is
|
|
|
459
468
|
|
|
460
469
|
// Settle input (pay what we owe to the PoolManager).
|
|
461
470
|
Currency inputCurrency = zeroForOne ? key.currency0 : key.currency1;
|
|
462
|
-
_settleV4(inputCurrency, amountIn);
|
|
471
|
+
_settleV4({currency: inputCurrency, amount: amountIn});
|
|
463
472
|
|
|
464
473
|
// Take output (receive what the PoolManager owes us).
|
|
465
474
|
Currency outputCurrency = zeroForOne ? key.currency1 : key.currency0;
|
|
466
|
-
_takeV4(outputCurrency, amountOut);
|
|
475
|
+
_takeV4({currency: outputCurrency, amount: amountOut});
|
|
467
476
|
|
|
468
477
|
return abi.encode(amountOut);
|
|
469
478
|
}
|
|
@@ -554,7 +563,7 @@ contract JBRouterTerminal is
|
|
|
554
563
|
if (token == JBConstants.NATIVE_TOKEN) return amount;
|
|
555
564
|
|
|
556
565
|
// Otherwise, set the appropriate allowance for the recipient.
|
|
557
|
-
IERC20(token).safeIncreaseAllowance(to, amount);
|
|
566
|
+
IERC20(token).safeIncreaseAllowance({spender: to, value: amount});
|
|
558
567
|
|
|
559
568
|
return 0;
|
|
560
569
|
}
|
|
@@ -758,7 +767,8 @@ contract JBRouterTerminal is
|
|
|
758
767
|
// Search V3.
|
|
759
768
|
for (uint256 i; i < 4; i++) {
|
|
760
769
|
// slither-disable-next-line calls-loop
|
|
761
|
-
address poolAddr =
|
|
770
|
+
address poolAddr =
|
|
771
|
+
FACTORY.getPool({tokenA: normalizedTokenIn, tokenB: normalizedTokenOut, fee: _FEE_TIERS[i]});
|
|
762
772
|
|
|
763
773
|
if (poolAddr == address(0)) continue;
|
|
764
774
|
|
|
@@ -851,11 +861,7 @@ contract JBRouterTerminal is
|
|
|
851
861
|
|
|
852
862
|
if (pool.isV4) {
|
|
853
863
|
return _executeV4Swap({
|
|
854
|
-
key: pool.v4Key,
|
|
855
|
-
normalizedTokenIn: normalizedTokenIn,
|
|
856
|
-
normalizedTokenOut: normalizedTokenOut,
|
|
857
|
-
amount: amount,
|
|
858
|
-
minAmountOut: minAmountOut
|
|
864
|
+
key: pool.v4Key, normalizedTokenIn: normalizedTokenIn, amount: amount, minAmountOut: minAmountOut
|
|
859
865
|
});
|
|
860
866
|
} else {
|
|
861
867
|
return _executeV3Swap({
|
|
@@ -886,8 +892,11 @@ contract JBRouterTerminal is
|
|
|
886
892
|
(int256 amount0, int256 amount1) = pool.swap({
|
|
887
893
|
recipient: address(this),
|
|
888
894
|
zeroForOne: zeroForOne,
|
|
895
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
889
896
|
amountSpecified: int256(amount),
|
|
890
|
-
sqrtPriceLimitX96: JBSwapLib.sqrtPriceLimitFromAmounts(
|
|
897
|
+
sqrtPriceLimitX96: JBSwapLib.sqrtPriceLimitFromAmounts({
|
|
898
|
+
amountIn: amount, minimumAmountOut: minAmountOut, zeroForOne: zeroForOne
|
|
899
|
+
}),
|
|
891
900
|
data: callbackData
|
|
892
901
|
});
|
|
893
902
|
|
|
@@ -899,7 +908,6 @@ contract JBRouterTerminal is
|
|
|
899
908
|
function _executeV4Swap(
|
|
900
909
|
PoolKey memory key,
|
|
901
910
|
address normalizedTokenIn,
|
|
902
|
-
address normalizedTokenOut,
|
|
903
911
|
uint256 amount,
|
|
904
912
|
uint256 minAmountOut
|
|
905
913
|
)
|
|
@@ -911,11 +919,14 @@ contract JBRouterTerminal is
|
|
|
911
919
|
bool zeroForOne = Currency.unwrap(key.currency0) == v4In;
|
|
912
920
|
|
|
913
921
|
// Use sqrtPriceLimitFromAmounts for partial-fill protection, consistent with V3 path.
|
|
914
|
-
uint160 sqrtPriceLimitX96 = JBSwapLib.sqrtPriceLimitFromAmounts(
|
|
922
|
+
uint160 sqrtPriceLimitX96 = JBSwapLib.sqrtPriceLimitFromAmounts({
|
|
923
|
+
amountIn: amount, minimumAmountOut: minAmountOut, zeroForOne: zeroForOne
|
|
924
|
+
});
|
|
915
925
|
|
|
916
926
|
// V4 sign convention: negative = exact input, positive = exact output.
|
|
917
927
|
bytes memory result =
|
|
918
|
-
|
|
928
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
929
|
+
POOL_MANAGER.unlock(abi.encode(key, zeroForOne, -int256(amount), sqrtPriceLimitX96, minAmountOut));
|
|
919
930
|
|
|
920
931
|
amountOut = abi.decode(result, (uint256));
|
|
921
932
|
}
|
|
@@ -1022,8 +1033,9 @@ contract JBRouterTerminal is
|
|
|
1022
1033
|
uint160 sqrtP = TickMath.getSqrtRatioAtTick(arithmeticMeanTick);
|
|
1023
1034
|
if (sqrtP == 0) return SLIPPAGE_DENOMINATOR;
|
|
1024
1035
|
|
|
1025
|
-
uint256 impact =
|
|
1026
|
-
|
|
1036
|
+
uint256 impact =
|
|
1037
|
+
JBSwapLib.calculateImpact({amountIn: amountIn, liquidity: liquidity, sqrtP: sqrtP, zeroForOne: zeroForOne});
|
|
1038
|
+
return JBSwapLib.getSlippageTolerance({impact: impact, poolFeeBps: poolFeeBps});
|
|
1027
1039
|
}
|
|
1028
1040
|
|
|
1029
1041
|
/// @notice Get a TWAP-based quote with dynamic slippage for a V3 pool.
|
|
@@ -1044,8 +1056,11 @@ contract JBRouterTerminal is
|
|
|
1044
1056
|
uint256 twapWindow = DEFAULT_TWAP_WINDOW;
|
|
1045
1057
|
if (oldestObservation < twapWindow) twapWindow = oldestObservation;
|
|
1046
1058
|
|
|
1047
|
-
(
|
|
1048
|
-
|
|
1059
|
+
(
|
|
1060
|
+
int24 arithmeticMeanTick,
|
|
1061
|
+
uint128 liquidity
|
|
1062
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1063
|
+
) = OracleLibrary.consult({pool: address(pool), secondsAgo: uint32(twapWindow)});
|
|
1049
1064
|
|
|
1050
1065
|
if (liquidity == 0) revert JBRouterTerminal_NoLiquidity();
|
|
1051
1066
|
|
|
@@ -1064,6 +1079,7 @@ contract JBRouterTerminal is
|
|
|
1064
1079
|
if (amount > type(uint128).max) revert JBRouterTerminal_AmountOverflow(amount);
|
|
1065
1080
|
minAmountOut = OracleLibrary.getQuoteAtTick({
|
|
1066
1081
|
tick: arithmeticMeanTick,
|
|
1082
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1067
1083
|
baseAmount: uint128(amount),
|
|
1068
1084
|
baseToken: normalizedTokenIn,
|
|
1069
1085
|
quoteToken: normalizedTokenOut
|
|
@@ -1124,7 +1140,11 @@ contract JBRouterTerminal is
|
|
|
1124
1140
|
|
|
1125
1141
|
if (amount > type(uint128).max) revert JBRouterTerminal_AmountOverflow(amount);
|
|
1126
1142
|
minAmountOut = OracleLibrary.getQuoteAtTick({
|
|
1127
|
-
tick: tick,
|
|
1143
|
+
tick: tick,
|
|
1144
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1145
|
+
baseAmount: uint128(amount),
|
|
1146
|
+
baseToken: normalizedTokenIn,
|
|
1147
|
+
quoteToken: normalizedTokenOut
|
|
1128
1148
|
});
|
|
1129
1149
|
|
|
1130
1150
|
minAmountOut -= (minAmountOut * slippageTolerance) / SLIPPAGE_DENOMINATOR;
|
|
@@ -1357,7 +1377,7 @@ contract JBRouterTerminal is
|
|
|
1357
1377
|
} else {
|
|
1358
1378
|
// ERC20: sync then transfer then settle.
|
|
1359
1379
|
POOL_MANAGER.sync(currency);
|
|
1360
|
-
IERC20(Currency.unwrap(currency)).safeTransfer(address(POOL_MANAGER), amount);
|
|
1380
|
+
IERC20(Currency.unwrap(currency)).safeTransfer({to: address(POOL_MANAGER), value: amount});
|
|
1361
1381
|
// slither-disable-next-line unused-return
|
|
1362
1382
|
POOL_MANAGER.settle();
|
|
1363
1383
|
}
|
|
@@ -1365,7 +1385,7 @@ contract JBRouterTerminal is
|
|
|
1365
1385
|
|
|
1366
1386
|
/// @notice Take the output side of a V4 swap (receive tokens from PoolManager).
|
|
1367
1387
|
function _takeV4(Currency currency, uint256 amount) internal {
|
|
1368
|
-
POOL_MANAGER.take(currency, address(this), amount);
|
|
1388
|
+
POOL_MANAGER.take({currency: currency, to: address(this), amount: amount});
|
|
1369
1389
|
|
|
1370
1390
|
// If native ETH output, wrap to WETH (downstream _handleSwap unwraps if needed).
|
|
1371
1391
|
if (Currency.unwrap(currency) == address(0)) {
|
|
@@ -1381,19 +1401,20 @@ contract JBRouterTerminal is
|
|
|
1381
1401
|
function _transferFrom(address from, address payable to, address token, uint256 amount) internal {
|
|
1382
1402
|
if (from == address(this)) {
|
|
1383
1403
|
// If the token is native token, assume the `sendValue` standard.
|
|
1384
|
-
if (token == JBConstants.NATIVE_TOKEN) return Address.sendValue(to, amount);
|
|
1404
|
+
if (token == JBConstants.NATIVE_TOKEN) return Address.sendValue({recipient: to, amount: amount});
|
|
1385
1405
|
|
|
1386
1406
|
// If the transfer is from this terminal, use `safeTransfer`.
|
|
1387
|
-
return IERC20(token).safeTransfer(to, amount);
|
|
1407
|
+
return IERC20(token).safeTransfer({to: to, value: amount});
|
|
1388
1408
|
}
|
|
1389
1409
|
|
|
1390
1410
|
// If there's sufficient approval, transfer normally.
|
|
1391
1411
|
if (IERC20(token).allowance({owner: address(from), spender: address(this)}) >= amount) {
|
|
1392
|
-
return IERC20(token).safeTransferFrom(from, to, amount);
|
|
1412
|
+
return IERC20(token).safeTransferFrom({from: from, to: to, value: amount});
|
|
1393
1413
|
}
|
|
1394
1414
|
|
|
1395
1415
|
// Otherwise, attempt to use the `permit2` method.
|
|
1396
|
-
|
|
1416
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
1417
|
+
PERMIT2.transferFrom({from: from, to: to, amount: uint160(amount), token: token});
|
|
1397
1418
|
}
|
|
1398
1419
|
|
|
1399
1420
|
//*********************************************************************//
|
|
@@ -442,7 +442,7 @@ contract JBRouterTerminalRegistry is IJBRouterTerminalRegistry, JBPermissioned,
|
|
|
442
442
|
if (token == JBConstants.NATIVE_TOKEN) return amount;
|
|
443
443
|
|
|
444
444
|
// Otherwise, set the appropriate allowance for the recipient.
|
|
445
|
-
IERC20(token).safeIncreaseAllowance(to, amount);
|
|
445
|
+
IERC20(token).safeIncreaseAllowance({spender: to, value: amount});
|
|
446
446
|
|
|
447
447
|
return 0;
|
|
448
448
|
}
|
|
@@ -455,18 +455,19 @@ contract JBRouterTerminalRegistry is IJBRouterTerminalRegistry, JBPermissioned,
|
|
|
455
455
|
function _transferFrom(address from, address payable to, address token, uint256 amount) internal virtual {
|
|
456
456
|
if (from == address(this)) {
|
|
457
457
|
// If the token is native token, assume the `sendValue` standard.
|
|
458
|
-
if (token == JBConstants.NATIVE_TOKEN) return Address.sendValue(to, amount);
|
|
458
|
+
if (token == JBConstants.NATIVE_TOKEN) return Address.sendValue({recipient: to, amount: amount});
|
|
459
459
|
|
|
460
460
|
// If the transfer is from this terminal, use `safeTransfer`.
|
|
461
|
-
return IERC20(token).safeTransfer(to, amount);
|
|
461
|
+
return IERC20(token).safeTransfer({to: to, value: amount});
|
|
462
462
|
}
|
|
463
463
|
|
|
464
464
|
// If there's sufficient approval, transfer normally.
|
|
465
465
|
if (IERC20(token).allowance({owner: address(from), spender: address(this)}) >= amount) {
|
|
466
|
-
return IERC20(token).safeTransferFrom(from, to, amount);
|
|
466
|
+
return IERC20(token).safeTransferFrom({from: from, to: to, value: amount});
|
|
467
467
|
}
|
|
468
468
|
|
|
469
469
|
// Otherwise, attempt to use the `permit2` method.
|
|
470
|
-
|
|
470
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
471
|
+
PERMIT2.transferFrom({from: from, to: to, amount: uint160(amount), token: token});
|
|
471
472
|
}
|
|
472
473
|
}
|
|
@@ -54,7 +54,7 @@ library JBSwapLib {
|
|
|
54
54
|
|
|
55
55
|
// Sigmoid: minSlippage + (maxSlippage - minSlippage) * impact / (impact + K)
|
|
56
56
|
uint256 range = MAX_SLIPPAGE - minSlippage;
|
|
57
|
-
uint256 tolerance = minSlippage + mulDiv(range, impact, impact + SIGMOID_K);
|
|
57
|
+
uint256 tolerance = minSlippage + mulDiv({x: range, y: impact, denominator: impact + SIGMOID_K});
|
|
58
58
|
|
|
59
59
|
return tolerance;
|
|
60
60
|
}
|
|
@@ -82,11 +82,11 @@ library JBSwapLib {
|
|
|
82
82
|
{
|
|
83
83
|
if (liquidity == 0 || sqrtP == 0) return 0;
|
|
84
84
|
|
|
85
|
-
uint256 base = mulDiv(amountIn, IMPACT_PRECISION, uint256(liquidity));
|
|
85
|
+
uint256 base = mulDiv({x: amountIn, y: IMPACT_PRECISION, denominator: uint256(liquidity)});
|
|
86
86
|
|
|
87
87
|
impact = zeroForOne
|
|
88
|
-
? mulDiv(base, uint256(sqrtP), uint256(1) << 96)
|
|
89
|
-
: mulDiv(base, uint256(1) << 96, uint256(sqrtP));
|
|
88
|
+
? mulDiv({x: base, y: uint256(sqrtP), denominator: uint256(1) << 96})
|
|
89
|
+
: mulDiv({x: base, y: uint256(1) << 96, denominator: uint256(sqrtP)});
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
//*********************************************************************//
|
|
@@ -130,11 +130,11 @@ library JBSwapLib {
|
|
|
130
130
|
return zeroForOne ? TickMath.MIN_SQRT_RATIO + 1 : TickMath.MAX_SQRT_RATIO - 1;
|
|
131
131
|
} else if (num / den >= (uint256(1) << 64)) {
|
|
132
132
|
// Extended range: use ratioX128 to avoid mulDiv overflow, then shift.
|
|
133
|
-
uint256 ratioX128 = mulDiv(num, uint256(1) << 128, den);
|
|
133
|
+
uint256 ratioX128 = mulDiv({x: num, y: uint256(1) << 128, denominator: den});
|
|
134
134
|
sqrtResult = Math.sqrt(ratioX128) * (uint256(1) << 32);
|
|
135
135
|
} else {
|
|
136
136
|
// Normal range: full precision via ratioX192.
|
|
137
|
-
uint256 ratioX192 = mulDiv(num, uint256(1) << 192, den);
|
|
137
|
+
uint256 ratioX192 = mulDiv({x: num, y: uint256(1) << 192, denominator: den});
|
|
138
138
|
sqrtResult = Math.sqrt(ratioX192);
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -145,6 +145,7 @@ library JBSwapLib {
|
|
|
145
145
|
if (sqrtResult >= uint256(TickMath.MAX_SQRT_RATIO)) {
|
|
146
146
|
return TickMath.MAX_SQRT_RATIO - 1;
|
|
147
147
|
}
|
|
148
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
148
149
|
return uint160(sqrtResult);
|
|
149
150
|
} else {
|
|
150
151
|
if (sqrtResult >= uint256(TickMath.MAX_SQRT_RATIO)) {
|
|
@@ -153,6 +154,7 @@ library JBSwapLib {
|
|
|
153
154
|
if (sqrtResult <= uint256(TickMath.MIN_SQRT_RATIO)) {
|
|
154
155
|
return TickMath.MIN_SQRT_RATIO + 1;
|
|
155
156
|
}
|
|
157
|
+
// forge-lint: disable-next-line(unsafe-typecast)
|
|
156
158
|
return uint160(sqrtResult);
|
|
157
159
|
}
|
|
158
160
|
}
|