Skip to content

Commit

Permalink
feat: latest code on gasless trading
Browse files Browse the repository at this point in the history
  • Loading branch information
john-xina-p88 committed May 10, 2024
1 parent 438babf commit 272b863
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 40 deletions.
9 changes: 8 additions & 1 deletion src/handlers/IntentHandler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,14 @@ contract IntentHandler is OwnableUpgradeable, ReentrancyGuardUpgradeable, EIP712
}
continue;
}
try gasService.collectExecutionFeeFromCollateral(_localVars.mainAccount, _localVars.subAccountId) {} catch {
try
gasService.collectExecutionFeeFromCollateral(
_localVars.mainAccount,
_localVars.subAccountId,
_vars.order.marketIndex,
HMXLib.abs(_vars.order.sizeDelta)
)
{} catch {
emit LogCollectExecutionFeeFailed(_localVars.key);
unchecked {
++_i;
Expand Down
9 changes: 7 additions & 2 deletions src/helpers/TradeOrderHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ contract TradeOrderHelper is Ownable, ITradeOrderHelper {

function execute(
IIntentHandler.ExecuteTradeOrderVars memory vars
) external returns (uint256 _oraclePrice, uint256 _executedPrice, bool _isFullClose) {
) external onlyWhitelistedCaller returns (uint256 _oraclePrice, uint256 _executedPrice, bool _isFullClose) {
// Retrieve existing position
vars.positionId = HMXLib.getPositionId(
HMXLib.getSubAccount(vars.order.account, vars.order.subAccountId),
Expand All @@ -131,10 +131,15 @@ contract TradeOrderHelper is Ownable, ITradeOrderHelper {
vars.positionIsLong = _existingPosition.positionSizeE30 > 0;
vars.isNewPosition = _existingPosition.positionSizeE30 == 0;

// Check if the order is TP/SL, then make the sizeDelta = -positionSize
int256 revisedSizeDelta = vars.order.sizeDelta;
bool isDecreasePosition = !vars.isNewPosition &&
((vars.positionIsLong && vars.order.sizeDelta < 0) || (!vars.positionIsLong && vars.order.sizeDelta > 0));
if (isDecreasePosition && HMXLib.abs(vars.order.sizeDelta) > HMXLib.abs(_existingPosition.positionSizeE30)) {
if (
isDecreasePosition &&
vars.order.reduceOnly &&
HMXLib.abs(vars.order.sizeDelta) > HMXLib.abs(_existingPosition.positionSizeE30)
) {
if (vars.order.sizeDelta > 0) {
revisedSizeDelta = int256(HMXLib.abs(_existingPosition.positionSizeE30));
} else {
Expand Down
120 changes: 83 additions & 37 deletions src/services/GasService.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ contract GasService is ReentrancyGuardUpgradeable, OwnableUpgradeable, IGasServi
ConfigStorage public configStorage;
uint256 public executionFeeInUsd;
address public executionFeeTreasury;
uint256 public subsidizedExecutionFeeValue; // The total value of gas fee that is subsidized by the platform in E30
uint256 public waviedExecutionFeeMinTradeSize; // The minimum trade size (E30) that we will waive exeuction fee

function initialize(
address _vaultStorage,
address _configStorage,
uint256 _executionFeeInUsd,
address _executionFeeTreasury
) external initializer {
OwnableUpgradeable.__Ownable_init();
ReentrancyGuardUpgradeable.__ReentrancyGuard_init();

vaultStorage = VaultStorage(_vaultStorage);
configStorage = ConfigStorage(_configStorage);
executionFeeInUsd = _executionFeeInUsd;
Expand All @@ -46,53 +51,88 @@ contract GasService is ReentrancyGuardUpgradeable, OwnableUpgradeable, IGasServi
/**
* Functions
*/
struct VarsCollectExecutionFeeFromCollateral {
address subAccount;
address[] traderTokens;
uint256 len;
OracleMiddleware oracle;
uint256 executionFeeToBePaidInUsd;
bytes32 assetId;
ConfigStorage.AssetConfig assetConfig;
address token;
uint256 userBalance;
uint256 tokenPrice;
uint8 tokenDecimal;
uint256 payAmount;
uint256 payValue;
}

function collectExecutionFeeFromCollateral(
address _primaryAccount,
uint8 _subAccountId
uint8 _subAccountId,
uint256 _marketIndex,
uint256 _absSizeDelta
) external onlyWhitelistedExecutor {
address _subAccount = HMXLib.getSubAccount(_primaryAccount, _subAccountId);
address[] memory _traderTokens = vaultStorage.getTraderTokens(_subAccount);
uint256 _len = _traderTokens.length;
OracleMiddleware _oracle = OracleMiddleware(configStorage.oracle());

emit LogCollectExecutionFeeValue(executionFeeInUsd);
uint256 _executionFeeToBePaidInUsd = executionFeeInUsd;
for (uint256 _i; _i < _len; ) {
bytes32 _assetId = configStorage.tokenAssetIds(_traderTokens[_i]);
ConfigStorage.AssetConfig memory _assetConfig = configStorage.getAssetConfig(_assetId);
address _token = _assetConfig.tokenAddress;
uint256 _userBalance = vaultStorage.traderBalances(_subAccount, _token);

if (_userBalance > 0) {
(uint256 _tokenPrice, ) = _oracle.getLatestPrice(_assetConfig.assetId, false);
uint8 _tokenDecimal = _assetConfig.decimals;

(uint256 _payAmount, uint256 _payValue) = _getPayAmount(
_userBalance,
_executionFeeToBePaidInUsd,
_tokenPrice,
_tokenDecimal
);
emit LogCollectExecutionFeeAmount(_token, _payAmount);

vaultStorage.decreaseTraderBalance(_subAccount, _token, _payAmount);
vaultStorage.increaseTraderBalance(executionFeeTreasury, _token, _payAmount);

_executionFeeToBePaidInUsd -= _payValue;

if (_executionFeeToBePaidInUsd == 0) {
break;
VarsCollectExecutionFeeFromCollateral memory vars;

vars.subAccount = HMXLib.getSubAccount(_primaryAccount, _subAccountId);
vars.traderTokens = vaultStorage.getTraderTokens(vars.subAccount);
vars.len = vars.traderTokens.length;
vars.oracle = OracleMiddleware(configStorage.oracle());

if (_absSizeDelta >= waviedExecutionFeeMinTradeSize) {
emit LogSubsidizeExecutionFee(vars.subAccount, _marketIndex, executionFeeInUsd);
subsidizedExecutionFeeValue += executionFeeInUsd;
} else {
emit LogCollectExecutionFeeValue(vars.subAccount, _marketIndex, executionFeeInUsd);
vars.executionFeeToBePaidInUsd = executionFeeInUsd;
for (uint256 _i; _i < vars.len; ) {
vars.assetId = configStorage.tokenAssetIds(vars.traderTokens[_i]);
vars.assetConfig = configStorage.getAssetConfig(vars.assetId);
vars.token = vars.assetConfig.tokenAddress;
vars.userBalance = vaultStorage.traderBalances(vars.subAccount, vars.token);

if (vars.userBalance > 0) {
(vars.tokenPrice, ) = vars.oracle.getLatestPrice(vars.assetConfig.assetId, false);
vars.tokenDecimal = vars.assetConfig.decimals;

(vars.payAmount, vars.payValue) = _getPayAmount(
vars.userBalance,
vars.executionFeeToBePaidInUsd,
vars.tokenPrice,
vars.tokenDecimal
);
emit LogCollectExecutionFeeAmount(vars.subAccount, _marketIndex, vars.token, vars.payAmount);

vaultStorage.decreaseTraderBalance(vars.subAccount, vars.token, vars.payAmount);
vaultStorage.increaseTraderBalance(executionFeeTreasury, vars.token, vars.payAmount);

vars.executionFeeToBePaidInUsd -= vars.payValue;

if (vars.executionFeeToBePaidInUsd == 0) {
break;
}
}

unchecked {
++_i;
}
}

unchecked {
++_i;
if (vars.executionFeeToBePaidInUsd > 0) {
vaultStorage.addTradingFeeDebt(vars.subAccount, vars.executionFeeToBePaidInUsd);
}
}
}

if (_executionFeeToBePaidInUsd > 0) {
revert GasService_NotEnoughCollateral();
function adjustSubsidizedExecutionFeeValue(int256 deltaValueE30) external onlyWhitelistedExecutor {
uint256 previousValue = subsidizedExecutionFeeValue;
if (deltaValueE30 >= 0) {
subsidizedExecutionFeeValue += uint256(deltaValueE30);
} else {
subsidizedExecutionFeeValue -= uint256(-deltaValueE30);
}
emit LogAdjustSubsidizedExecutionFeeValue(previousValue, subsidizedExecutionFeeValue, deltaValueE30);
}

function _getPayAmount(
Expand All @@ -119,4 +159,10 @@ contract GasService is ReentrancyGuardUpgradeable, OwnableUpgradeable, IGasServi

emit LogSetParams(_executionFeeInUsd, _executionFeeTreasury);
}

function setWaviedExecutionFeeMinTradeSize(uint256 _waviedExecutionFeeMinTradeSize) external onlyOwner {
waviedExecutionFeeMinTradeSize = _waviedExecutionFeeMinTradeSize;

emit LogSetWaviedExecutionFeeMinTradeSize(waviedExecutionFeeMinTradeSize);
}
}

0 comments on commit 272b863

Please sign in to comment.