[H-2] Create order will always revert because of different address in approving and transfering funds
Vulnerability Details:
In createOrder function different address is used to approve and send token, This will cause revert when an address is approved to transfer tokens and a different address now transfered the token
In below code address(gmxRouter)
was approved to transfer tokens and gExchangeRouter
address is used to transfer the token
function createOrder(
if (
orderType == Order.OrderType.MarketSwap ||
orderType == Order.OrderType.MarketIncrease
) {
IERC20(orderData.initialCollateralToken).safeApprove(
-
address(gmxRouter),
orderData.amountIn
);
gExchangeRouter.sendTokens(
orderData.initialCollateralToken,
orderVault,
orderData.amountIn
);
And according to the GmxProxy script both address are diffrent address
"0x7452c558d45f8afC8c83dAe62C3f8A5BE19c71f6",
"0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8",
Impact:
This will lead to createOrder unable to work , causing reverts on createOrder
Proof of Concept:
GMX proxy Deployment script
async function main() {
const GmxProxy = await hre.ethers.getContractFactory("GmxProxy");
const gmxProxy = await upgrades.deployProxy(
GmxProxy,
[
"0xB0Fc2a48b873da40e7bc25658e5E6137616AC2Ee",
"0x08A902113F7F41a8658eBB1175f9c847bf4fB9D8",
"0x26BC03c944A4800299B4bdfB5EdCE314dD497511",
"0x69C527fC77291722b52649E45c838e41be8Bf5d5",
"0x7452c558d45f8afC8c83dAe62C3f8A5BE19c71f6",
"0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8",
"0x31eF83a530Fde1B38EE9A18093A333D8Bbbc40D5",
"0x5Ca84c34a381434786738735265b9f3FD814b824",
"0xe6fab3F0c7199b0d34d7FbE83394fc0e0D06e99d"
]
);
initialize function
function initialize(
address _orderHandler,
address _liquidationHandler,
address _adlHandler,
address _gExchangeRouter,
address _gmxRouter,
address _dataStore,
address _orderVault,
address _gmxReader,
address _referralStorage
) external initializer {
__Ownable2Step_init();
orderHandler = _orderHandler;
liquidationHandler = _liquidationHandler;
adlHandler = _adlHandler;
gExchangeRouter = IExchangeRouter(_gExchangeRouter);
gmxRouter = _gmxRouter;
dataStore = IDataStore(_dataStore);
orderVault = _orderVault;
gmxReader = IGmxReader(_gmxReader);
referralStorage = _referralStorage;
minEth = 0.002 ether;
}
function createOrder(
Order.OrderType orderType,
IGmxProxy.OrderData memory orderData
) public returns (bytes32) {
require(msg.sender == perpVault, "invalid caller");
uint256 positionExecutionFee = getExecutionGasLimit(
orderType,
orderData.callbackGasLimit
) * tx.gasprice;
require(
address(this).balance >= positionExecutionFee,
"insufficient eth balance"
);
bytes32 executeOrderFeatureKey = keccak256(
abi.encode(
EXECUTE_ORDER_FEATURE_DISABLED,
orderHandler,
orderType
)
);
require(
dataStore.getBool(executeOrderFeatureKey) == false,
"gmx execution disabled"
);
gExchangeRouter.sendWnt{value: positionExecutionFee}(
orderVault,
positionExecutionFee
);
if (
orderType == Order.OrderType.MarketSwap ||
orderType == Order.OrderType.MarketIncrease
) {
IERC20(orderData.initialCollateralToken).safeApprove(
address(gmxRouter),
orderData.amountIn
);
gExchangeRouter.sendTokens(
orderData.initialCollateralToken,
orderVault,
orderData.amountIn
);
}
Recommended Mitigation:
Kindly fix the code to allow same address to approve and send
IERC20(orderData.initialCollateralToken).safeApprove(
address(gmxRouter),
orderData.amountIn
);
- gExchangeRouter.sendTokens(
+ gmxRouter.sendTokens(
orderData.initialCollateralToken,
orderVault,
orderData.amountIn
);