Skip to content

Commit 3a180cd

Browse files
authored
Adds GMX long position test (#5)
1 parent 37de777 commit 3a180cd

11 files changed

+183
-3
lines changed

.env.example

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export ALCHEMY_KEY=XXXXX
2+
export ALCHEMY_KEY_ARBITRUM=YYYYY

.github/workflows/ci.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
run: |
3232
cat << EOF >> .env
3333
export ALCHEMY_KEY=${{ secrets.ALCHEMY_KEY }}
34+
export ALCHEMY_KEY_ARBITRUM=${{ secrets.ALCHEMY_KEY_ARBITRUM }}
3435
EOF
3536
3637
- name: Source env file

foundry.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ remappings = [
1212
]
1313
[profile.default.rpc_endpoints]
1414
eth = 'https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}'
15+
arbi = 'https://arb-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY_ARBITRUM}'

test/Call.fork.t.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import "./calls/SupplyBorrowMorpho.sol";
1515
import "./calls/DepositBorrowAave.sol";
1616

1717
import "./Utils.sol";
18-
import "./Constants.sol";
18+
import "./ConstantsEthereum.sol";
1919

2020
import "./ILens.sol";
2121

test/ConstantsArbitrum.sol

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// SPDX-License-Identifier: Unlicense
2+
pragma solidity ^0.8.15;
3+
4+
address constant WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
5+
address constant DAI = 0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1;
6+
address constant USDC = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;
7+
address constant ZERO_ADDRESS = address(0);
File renamed without changes.

test/GMX.forkArbi.t.sol

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity ^0.8.13;
3+
import "foundry-huff/HuffDeployer.sol";
4+
import "forge-std/Test.sol";
5+
import "./Utils.sol";
6+
import "./calls/CallNvm.sol";
7+
import "./calls/GMXLong.sol";
8+
import "./calls/IGMX.sol";
9+
import "./ConstantsArbitrum.sol";
10+
11+
contract GMXTest is Test {
12+
address nvm;
13+
address doubleSwapHuff;
14+
address owner;
15+
uint256 balance = 1000 * 1e6;
16+
CallNvm callNvm;
17+
GMXLong gmxLong;
18+
bytes gmxLongNvmBytecode;
19+
20+
// ===== Set up =====
21+
function setUp() public {
22+
vm.createSelectFork(vm.rpcUrl("arbi"));
23+
owner = address(this);
24+
nvm = HuffDeployer.deploy("NVM");
25+
callNvm = new CallNvm();
26+
gmxLong = new GMXLong();
27+
gmxLongNvmBytecode = type(GMXLong).runtimeCode;
28+
}
29+
30+
receive() external payable {}
31+
32+
function testGMXLongNative() public {
33+
// PositionRouter
34+
IGMXPositionRouter positionRouter = IGMXPositionRouter(
35+
0x3D6bA331e3D9702C5e8A8d254e5d8a285F223aba
36+
);
37+
// Admin of the Position Router
38+
address positionRouterAdmin = address(
39+
0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8
40+
);
41+
// Deal USDC and ETH to contract that will open a long position
42+
deal(USDC, address(gmxLong), 1000000000 * 10**6);
43+
deal(address(gmxLong), 1000000000 * 10**18);
44+
// opens long position
45+
gmxLong.gmxLong();
46+
// Keeper that will execute the requests
47+
address keeper = address(123);
48+
// balance before for the keeper
49+
uint256 balanceBefore = keeper.balance;
50+
// Set keeper address as a keeper for the positionRouter
51+
// Only admin fuction
52+
changePrank(positionRouterAdmin);
53+
positionRouter.setPositionKeeper(keeper, true);
54+
// Execute transaction
55+
// The transaction is identified by a requestKey
56+
changePrank(keeper);
57+
bytes32 key = positionRouter.getRequestKey(
58+
address(gmxLong),
59+
uint256(1)
60+
);
61+
positionRouter.executeIncreasePosition(key, payable(keeper));
62+
// Balance of the keeper after
63+
uint256 balanceAfter = keeper.balance;
64+
// Verify keeper received fees
65+
assertEq(balanceAfter > balanceBefore, true);
66+
}
67+
68+
function testGMXLongNvm() public {
69+
// PositionRouter
70+
IGMXPositionRouter positionRouter = IGMXPositionRouter(
71+
0x3D6bA331e3D9702C5e8A8d254e5d8a285F223aba
72+
);
73+
// Admin of the Position Router
74+
address positionRouterAdmin = address(
75+
0x5F799f365Fa8A2B60ac0429C48B153cA5a6f0Cf8
76+
);
77+
// Deal USDC and ETH to contract that will open a long position
78+
deal(USDC, address(callNvm), 1000000000 * 10**6);
79+
deal(address(callNvm), 1000000000 * 10**18);
80+
// replace "gmxLong" selector and bypass calldata size check
81+
bytes memory finalBytecode = Utils
82+
.replaceSelectorBypassCalldataSizeCheck(
83+
gmxLongNvmBytecode,
84+
hex"9507c78f"
85+
);
86+
// CallNvm
87+
callNvm.callNvm(nvm, finalBytecode);
88+
// Keeper that will execute the requests
89+
address keeper = address(123);
90+
// balance before for the keeper
91+
uint256 balanceBefore = keeper.balance;
92+
// Set keeper address as a keeper for the positionRouter
93+
// Only admin fuction
94+
changePrank(positionRouterAdmin);
95+
positionRouter.setPositionKeeper(keeper, true);
96+
// Execute transaction
97+
// The transaction is identified by a requestKey
98+
changePrank(keeper);
99+
bytes32 key = positionRouter.getRequestKey(
100+
address(callNvm),
101+
uint256(1)
102+
);
103+
positionRouter.executeIncreasePosition(key, payable(keeper));
104+
// Balance of the keeper after
105+
uint256 balanceAfter = keeper.balance;
106+
// Verify keeper received fees
107+
assertEq(balanceAfter > balanceBefore, true);
108+
}
109+
}

test/calls/DepositBorrowAave.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
pragma solidity ^0.8.15;
33
import "./IERC20.sol";
44
import "./ILendingPool.sol";
5-
import "../Constants.sol";
5+
import "../ConstantsEthereum.sol";
66

77
contract DepositBorrowAave {
88
ILendingPool private constant lendingPool =

test/calls/GMXLong.sol

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// SPDX-License-Identifier: Unlicense
2+
pragma solidity ^0.8.15;
3+
import "./IERC20.sol";
4+
5+
import "./IGMX.sol";
6+
7+
import "./../ConstantsArbitrum.sol";
8+
9+
contract GMXLong {
10+
11+
uint256 private constant amountUSDC = 1000 * 10**6;
12+
IGMXRouter private constant GMXRouter = IGMXRouter(0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064);
13+
IGMXPositionRouter private constant positionRouter = IGMXPositionRouter(0x3D6bA331e3D9702C5e8A8d254e5d8a285F223aba);
14+
15+
constructor(){}
16+
17+
function gmxLong() public {
18+
IERC20(USDC).approve(address(GMXRouter), type(uint256).max);
19+
IERC20(USDC).approve(address(positionRouter), type(uint256).max);
20+
GMXRouter.approvePlugin(address(positionRouter));
21+
// USD amounts are multiplied by (10 ** 30)
22+
address[] memory path = new address[](2);
23+
path[0] = USDC;
24+
path[1] = WETH;
25+
positionRouter.createIncreasePosition{value: 3000_000_000_000_000 }(
26+
path, // [tokenIn, collateralToken] _path
27+
WETH, // _indexToken (token we want to long)
28+
100 * 10**6, // _amountIn
29+
0, // minOut
30+
600 * 10**30, // _sizeDelta the USD value of the change in position size
31+
true, // _isLong
32+
3000 * 10**30, // _acceptablePrice
33+
3000_000_000_000_000, // _executionFee
34+
bytes32(0)); // _referralCode
35+
}
36+
receive() external payable {}
37+
}

test/calls/IGMX.sol

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: Unlicense
2+
pragma solidity ^0.8.15;
3+
4+
interface IGMXPositionRouter {
5+
function createIncreasePosition(
6+
address[] memory _path,
7+
address _indexToken,
8+
uint256 _amountIn,
9+
uint256 _minOut,
10+
uint256 _sizeDelta,
11+
bool _isLong,
12+
uint256 _acceptablePrice,
13+
uint256 _executionFee,
14+
bytes32 _referralCode
15+
) external payable;
16+
17+
function executeIncreasePosition(bytes32 _key, address payable _executionFeeReceiver) external returns (bool);
18+
function getRequestKey(address _account, uint256 _index) external pure returns (bytes32);
19+
function setPositionKeeper(address _account, bool _isActive) external;
20+
}
21+
22+
interface IGMXRouter {
23+
function approvePlugin(address _plugin) external;
24+
}

test/calls/SupplyBorrowMorpho.sol

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ pragma solidity ^0.8.15;
33

44
import "./IERC20.sol";
55
import "./IMorpho.sol";
6-
import "../Constants.sol";
6+
import "../ConstantsEthereum.sol";
77

88
contract SupplyBorrowMorpho {
99
IMorpho private constant morpho =

0 commit comments

Comments
 (0)