Skip to content

Commit 31cdecd

Browse files
committed
Merge branch 'gasless' into multichain
# Conflicts: # contracts/error/Errors.sol
2 parents 5178204 + 8c685aa commit 31cdecd

29 files changed

+1940
-70
lines changed

config/general.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ export default async function ({ network }: HardhatRuntimeEnvironment) {
5959
liquidationFeeReceiverFactor: 0,
6060

6161
skipBorrowingFeeForSmallerSide: false,
62+
63+
ignoreOpenInterestForUsageFactor: false,
6264
};
6365
}
6466

@@ -115,6 +117,8 @@ export default async function ({ network }: HardhatRuntimeEnvironment) {
115117
liquidationFeeReceiverFactor: decimalToFloat(37, 2), // 37%
116118

117119
skipBorrowingFeeForSmallerSide: true,
120+
121+
ignoreOpenInterestForUsageFactor: false,
118122
};
119123

120124
const networkConfig = {
@@ -127,7 +131,7 @@ export default async function ({ network }: HardhatRuntimeEnvironment) {
127131
arbitrum: {
128132
maxAutoCancelOrders: 11,
129133
maxTotalCallbackGasLimitForAutoCancelOrders: 10_000_000,
130-
maxCallbackGasLimit: 5_000_000,
134+
maxCallbackGasLimit: 4_000_000,
131135
estimatedGasPerOraclePrice: false,
132136
executionGasPerOraclePrice: false,
133137
estimatedGasFeeBaseAmount: false,

config/glvs.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,13 +262,13 @@ export default async function ({ network }: HardhatRuntimeEnvironment) {
262262
},
263263
{
264264
indexToken: "XRP",
265-
glvMaxMarketTokenBalanceAmount: expandDecimals(243_461, 18),
266-
glvMaxMarketTokenBalanceUsd: decimalToFloat(447_897),
265+
glvMaxMarketTokenBalanceAmount: expandDecimals(345_810, 18),
266+
glvMaxMarketTokenBalanceUsd: decimalToFloat(644_971),
267267
},
268268
{
269269
indexToken: "DOGE",
270-
glvMaxMarketTokenBalanceAmount: expandDecimals(107_647, 18),
271-
glvMaxMarketTokenBalanceUsd: decimalToFloat(288_000),
270+
glvMaxMarketTokenBalanceAmount: expandDecimals(129_404, 18),
271+
glvMaxMarketTokenBalanceUsd: decimalToFloat(345_000),
272272
},
273273
{
274274
indexToken: "LTC",

config/markets.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -443,8 +443,8 @@ const config: {
443443
...fundingRateConfig_Low,
444444
...borrowingRateConfig_LowMax_WithLowerBase,
445445

446-
reserveFactor: percentageToFloat("205%"),
447-
openInterestReserveFactor: percentageToFloat("200%"),
446+
reserveFactor: percentageToFloat("235%"),
447+
openInterestReserveFactor: percentageToFloat("230%"),
448448

449449
maxLongTokenPoolAmount: expandDecimals(2200, 8),
450450
maxShortTokenPoolAmount: expandDecimals(110_000_000, 6),
@@ -465,7 +465,7 @@ const config: {
465465
// minCollateralFactor of 0.005 (0.5%) when open interest is 83,000,000 USD
466466
minCollateralFactorForOpenInterestMultiplier: exponentToFloat("6e-11"),
467467

468-
maxOpenInterest: decimalToFloat(74_000_000),
468+
maxOpenInterest: decimalToFloat(60_000_000),
469469
},
470470
{
471471
tokens: { indexToken: "BTC", longToken: "WBTC.e", shortToken: "WBTC.e" },
@@ -1500,9 +1500,9 @@ const config: {
15001500

15011501
maxOpenInterest: decimalToFloat(1_000_000),
15021502

1503-
maxPoolUsdForDeposit: decimalToFloat(4_500_000),
1504-
maxLongTokenPoolAmount: expandDecimals(1430, 18),
1505-
maxShortTokenPoolAmount: expandDecimals(5_000_000, 6),
1503+
maxPoolUsdForDeposit: decimalToFloat(9_000_000),
1504+
maxLongTokenPoolAmount: expandDecimals(2960, 18),
1505+
maxShortTokenPoolAmount: expandDecimals(10_000_000, 6),
15061506
},
15071507
{
15081508
tokens: { indexToken: "SEI", longToken: "WETH", shortToken: "USDC" },
@@ -2080,8 +2080,8 @@ const config: {
20802080
// minCollateralFactor of 0.01 (1%)
20812081
minCollateralFactorForOpenInterestMultiplier: exponentToFloat("2.5e-9"),
20822082

2083-
reserveFactor: percentageToFloat("105%"), // default is 95%
2084-
openInterestReserveFactor: percentageToFloat("100%"), // default is 90%
2083+
reserveFactor: percentageToFloat("135%"), // default is 95%
2084+
openInterestReserveFactor: percentageToFloat("130%"), // default is 90%
20852085

20862086
maxPnlFactorForTraders: percentageToFloat("90%"), // default is 60%
20872087

contracts/config/Config.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,9 @@ contract Config is ReentrancyGuard, RoleModule, BasicMulticall {
518518
allowedLimitedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;
519519
allowedLimitedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;
520520

521+
allowedLimitedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_USD] = true;
522+
allowedLimitedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT] = true;
523+
521524
allowedLimitedBaseKeys[Keys.PRO_TRADER_TIER] = true;
522525
}
523526

contracts/data/Keys.sol

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,7 @@ library Keys {
405405
bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode("AFFILIATE_REWARD"));
406406
// @dev key for max allowed subaccount action count
407407
bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT"));
408+
bytes32 public constant SUBACCOUNT_EXPIRES_AT = keccak256(abi.encode("SUBACCOUNT_EXPIRES_AT"));
408409
// @dev key for subaccount action count
409410
bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("SUBACCOUNT_ACTION_COUNT"));
410411
// @dev key for subaccount auto top up amount
@@ -1756,6 +1757,15 @@ library Keys {
17561757
));
17571758
}
17581759

1760+
function subaccountExpiresAtKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {
1761+
return keccak256(abi.encode(
1762+
SUBACCOUNT_EXPIRES_AT,
1763+
account,
1764+
subaccount,
1765+
actionType
1766+
));
1767+
}
1768+
17591769
function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {
17601770
return keccak256(abi.encode(
17611771
SUBACCOUNT_ACTION_COUNT,

contracts/error/Errors.sol

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ library Errors {
197197
// Oracle errors
198198
error SequencerDown();
199199
error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);
200-
error EmptyValidatedPrices();
200+
error EmptyValidatedPrices(); // not used, kept for compatibility
201201
error InvalidOracleProvider(address provider);
202202
error InvalidOracleProviderForToken(address provider, address expectedProvider);
203203
error GmEmptySigner(uint256 signerIndex);
@@ -356,10 +356,13 @@ library Errors {
356356

357357
// SubaccountRouter errors
358358
error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);
359+
error InvalidCancellationReceiverForSubaccountOrder(address cancellationReceiver, address expectedCancellationReceiver);
359360

360361
// SubaccountUtils errors
361362
error SubaccountNotAuthorized(address account, address subaccount);
362363
error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);
364+
error SubaccountApprovalExpired(address account, address subaccount, uint256 deadline, uint256 currentTimestamp);
365+
error InvalidSubaccount(address subaccount, address msgSender);
363366

364367
// TokenUtils errors
365368
error TokenTransferError(address token, address receiver, uint256 amount);
@@ -430,4 +433,17 @@ library Errors {
430433
error InvalidMultichainProviderSignature();
431434
error InvalidStargatePool();
432435
error InvalidLzEndpoint();
436+
437+
// Gelato relay errors
438+
error InvalidSignature();
439+
// User sent incorrect fee token or incorrect swap path
440+
error UnexpectedRelayFeeTokenAfterSwap(address feeToken, address expectedFeeToken);
441+
// Contract received unsupported fee token from Gelato relay
442+
error UnsupportedRelayFeeToken(address feeToken, address expectedFeeToken);
443+
error InvalidPermitSpender(address spender, address expectedSpender);
444+
error InvalidUserNonce(uint256 storedUserNonce, uint256 userNonce);
445+
error SubaccountApprovalDeadlinePassed(uint256 currentTimestamp, uint256 deadline);
446+
error InvalidSubaccountApprovalNonce(uint256 storedNonce, uint256 nonce);
447+
error DeadlinePassed(uint256 currentTimestamp, uint256 deadline);
448+
error InsufficientRelayFee(uint256 requiredRelayFee, uint256 feeAmount);
433449
}

contracts/mock/MintableToken.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
pragma solidity ^0.8.0;
44

5-
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
66

77
// @title MintableToken
88
// @dev Mock mintable token for testing and testnets
9-
contract MintableToken is ERC20 {
9+
contract MintableToken is ERC20Permit {
1010
uint8 private _decimals;
1111

12-
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {
12+
constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) ERC20Permit(name_) {
1313
_decimals = decimals_;
1414
}
1515

contracts/mock/MockGelatoRelay.sol

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// SPDX-License-Identifier: BUSL-1.1
2+
3+
pragma solidity ^0.8.0;
4+
5+
import "../data/DataStore.sol";
6+
import "../event/EventEmitter.sol";
7+
import "../exchange/IOrderHandler.sol";
8+
import "../order/OrderVault.sol";
9+
import "../router/Router.sol";
10+
import "../router/relay/GelatoRelayRouter.sol";
11+
12+
contract MockGelatoRelayRouter is GelatoRelayRouter {
13+
struct Nested {
14+
uint256 foo;
15+
bool bar;
16+
}
17+
18+
constructor(
19+
Router _router,
20+
DataStore _dataStore,
21+
EventEmitter _eventEmitter,
22+
Oracle _oracle,
23+
IOrderHandler _orderHandler,
24+
OrderVault _orderVault
25+
)
26+
GelatoRelayRouter(_router, _dataStore, _eventEmitter, _oracle, _orderHandler, _orderVault)
27+
{}
28+
29+
function testCancelOrderSignature(
30+
RelayParams calldata relayParams,
31+
bytes32 key,
32+
address account,
33+
bytes calldata signature,
34+
uint256 userNonce,
35+
uint256 deadline,
36+
uint256 chainId
37+
) external view {
38+
bytes32 structHash = _getCancelOrderStructHash(relayParams, key, userNonce, deadline);
39+
_handleSignature(structHash, signature, account, chainId);
40+
}
41+
42+
function testSimpleSignature(address account, bytes calldata signature, uint256 chainId) external view {
43+
bytes32 structHash = keccak256(abi.encode(keccak256(bytes("PrimaryStruct(address account)")), account));
44+
_handleSignature(structHash, signature, account, chainId);
45+
}
46+
47+
function testNestedSignature(
48+
Nested memory nested,
49+
address account,
50+
bytes calldata signature,
51+
uint256 chainId
52+
) external view {
53+
bytes32 nestedStructHash = keccak256(
54+
abi.encode(keccak256(bytes("Nested(uint256 foo,bool bar)")), nested.foo, nested.bar)
55+
);
56+
bytes32 structHash = keccak256(
57+
abi.encode(
58+
keccak256(bytes("PrimaryStruct(address account,Nested nested)Nested(uint256 foo,bool bar)")),
59+
account,
60+
nestedStructHash
61+
)
62+
);
63+
_handleSignature(structHash, signature, account, chainId);
64+
}
65+
66+
function testArraySignature(
67+
address[] memory array,
68+
address account,
69+
bytes calldata signature,
70+
uint256 chainId
71+
) external view {
72+
bytes32 structHash = keccak256(
73+
abi.encode(
74+
keccak256(bytes("PrimaryStruct(address account,address[] array)")),
75+
account,
76+
keccak256(abi.encodePacked(array))
77+
)
78+
);
79+
_handleSignature(structHash, signature, account, chainId);
80+
}
81+
82+
function _handleSignature(
83+
bytes32 structHash,
84+
bytes calldata signature,
85+
address account,
86+
uint256 chainId
87+
) internal view {
88+
bytes32 domainSeparator = _getDomainSeparator(chainId);
89+
bytes32 digest = ECDSA.toTypedDataHash(domainSeparator, structHash);
90+
91+
_validateSignature(digest, signature, account);
92+
}
93+
}

contracts/mock/WNT.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
pragma solidity ^0.8.0;
44

5-
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
5+
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol";
66

77
// @title WNT
88
// @dev similar implementation as WETH but since some networks
99
// might have a different native token we use WNT for a more general reference name
10-
contract WNT is ERC20 {
11-
constructor() ERC20("Wrapped Native Token", "WNT") {}
10+
contract WNT is ERC20Permit {
11+
constructor() ERC20("Wrapped Native Token", "WNT") ERC20Permit("Wrapped Native Token") {}
1212

1313
error TransferFailed(address account, uint256 amount);
1414

contracts/oracle/Oracle.sol

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -179,13 +179,14 @@ contract Oracle is RoleModule {
179179
// @param params OracleUtils.SetPricesParams
180180
function _setPrices(
181181
OracleUtils.ValidatedPrice[] memory prices
182-
) internal returns (OracleUtils.ValidatedPrice[] memory) {
183-
if (tokensWithPrices.length() != 0) {
184-
revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());
182+
) internal {
183+
// in case of gasless relay the prices are not required if there is no need to swap fee tokens
184+
if (prices.length == 0) {
185+
return;
185186
}
186187

187-
if (prices.length == 0) {
188-
revert Errors.EmptyValidatedPrices();
188+
if (tokensWithPrices.length() != 0) {
189+
revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());
189190
}
190191

191192
uint256 _minTimestamp = prices[0].timestamp;
@@ -223,8 +224,6 @@ contract Oracle is RoleModule {
223224

224225
minTimestamp = _minTimestamp;
225226
maxTimestamp = _maxTimestamp;
226-
227-
return prices;
228227
}
229228

230229
function _validatePrices(
@@ -241,6 +240,10 @@ contract Oracle is RoleModule {
241240

242241
OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);
243242

243+
if (params.tokens.length == 0) {
244+
return prices;
245+
}
246+
244247
uint256 maxPriceAge = dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);
245248
uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);
246249

0 commit comments

Comments
 (0)