Skip to content

Commit

Permalink
Fix hardhat tests and set up foundery tests on the BNB chain.
Browse files Browse the repository at this point in the history
  • Loading branch information
gnarlycow committed Mar 31, 2024
1 parent 48a4751 commit 6ad9db3
Show file tree
Hide file tree
Showing 12 changed files with 118 additions and 965 deletions.
13 changes: 11 additions & 2 deletions .github/workflows/foundry.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ jobs:
forge build
id: build

- name: Run Forge tests
- name: Run Forge tests on Ethereum mainnet
run: |
forge test -vvv
id: test
env:
CHAIN_ID: 1
id: testMainnet

- name: Run Forge tests on BNB mainnet
run: |
forge test -vvv
env:
CHAIN_ID: 56
id: testBNB
4 changes: 2 additions & 2 deletions contracts/EphemeralPoolSlots.sol
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ contract EphemeralPCSV3PoolSlots is PoolUtils {

/// @notice Get the static storage slots of a pool
/// @dev Public function to expose the abi for easier decoding using TypeChain
/// @param pool The Uniswap v3 pool
/// @param pool The PancakeSwap v3 pool
/// @return slots An array of storage slots and their raw data
function getSlots(V3PoolCallee pool) public payable returns (Slot[] memory slots) {
unchecked {
Expand All @@ -116,7 +116,7 @@ contract EphemeralPCSV3PoolSlots is PoolUtils {
uint256 slot0;
uint256 slot1;
assembly {
slot0 := or(shl(216, observationCardinalityNext), slot0)
slot0 := shl(216, observationCardinalityNext)
slot0 := or(shl(200, observationCardinality), slot0)
slot0 := or(shl(184, observationIndex), slot0)
slot0 := or(shl(160, and(0xffffff, tick)), slot0)
Expand Down
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ runs = 16

[rpc_endpoints]
mainnet = "${MAINNET_RPC_URL}"
bnb_smart_chain = "${BNB_RPC_URL}"

# See more config options https://github.com/foundry-rs/foundry/tree/master/config
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,11 @@
"viem": "^2.9.5"
},
"devDependencies": {
"@aperture_finance/uniswap-v3-automation-sdk": "^2.4.33",
"@ethersproject/abi": "5.7.0",
"@ethersproject/providers": "5.7.2",
"@nomicfoundation/hardhat-foundry": "^1.1.1",
"@nomiclabs/hardhat-ethers": "^2.2.3",
"@pancakeswap/v3-sdk":"^3.8.0",
"@pancakeswap/v3-sdk": "^3.8.0",
"@typechain/ethers-v5": "^11.1.2",
"@typechain/hardhat": "^9.1.0",
"@types/chai": "^4.3.14",
Expand Down
35 changes: 19 additions & 16 deletions test/foundry/Base.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import "@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.so
import "forge-std/Test.sol";
import "solady/src/utils/SafeTransferLib.sol";

enum DEX {
UniswapV3,
PancakeSwapV3
}

abstract contract BaseTest is
Test,
IPancakeV3MintCallback,
Expand All @@ -33,8 +38,10 @@ abstract contract BaseTest is
uint160 internal constant MIN_SQRT_RATIO_PLUS_ONE = TickMath.MIN_SQRT_RATIO + 1;
uint160 internal constant MAX_SQRT_RATIO_MINUS_ONE = 1461446703485210103287273052203988822378723970342 - 1;

DEX internal dex;

// Uniswap v3 position manager
INPM internal npm = INPM(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
INPM internal npm;

uint256 internal chainId;
address internal WETH;
Expand All @@ -59,15 +66,15 @@ abstract contract BaseTest is
if (chainId == 1) {
blockNumber = 17000000;
USDC = 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48;
} else if (chainId == 5) {
blockNumber = 9000000;
USDC = 0xD87Ba7A50B2E7E660f678A895E4B72E7CB4CCd9C;
} else if (chainId == 10) {
blockNumber = 20000000;
USDC = 0x7F5c764cBc14f9669B88837ca1490cCa17c31607;
} else if (chainId == 42161) {
blockNumber = 70000000;
USDC = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;
npm = dex == DEX.PancakeSwapV3
? INPM(0x46A15B0b27311cedF172AB29E4f4766fbE7F4364)
: INPM(0xC36442b4a4522E871399CD717aBDD847Ab11FE88);
} else if (chainId == 56) {
blockNumber = 37460000;
USDC = 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d;
npm = dex == DEX.PancakeSwapV3
? INPM(0x46A15B0b27311cedF172AB29E4f4766fbE7F4364)
: INPM(0x7b8A01B39D58278b5DE7e48c8449c9f4F5170613);
} else {
revert("Unsupported chain");
}
Expand All @@ -78,14 +85,10 @@ abstract contract BaseTest is
factory = npm.factory();
WETH = npm.WETH9();
(token0, token1) = (WETH < USDC).switchIf(USDC, WETH);
initPoolInfo();
token0Unit = 10 ** IERC20Metadata(token0).decimals();
token1Unit = 10 ** IERC20Metadata(token1).decimals();
}

function initPoolInfo() internal virtual {
pool = IUniswapV3Factory(factory).getPool(token0, token1, fee);
tickSpacing = V3PoolCallee.wrap(pool).tickSpacing();
token0Unit = 10 ** IERC20Metadata(token0).decimals();
token1Unit = 10 ** IERC20Metadata(token1).decimals();
}

function setUp() public virtual {
Expand Down
6 changes: 3 additions & 3 deletions test/foundry/PoolLens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ contract PoolLensTest is BaseTest, PoolUtils {
}

contract PCSV3PoolLensTest is BaseTest, PoolUtils {
function initPoolInfo() internal override {
pool = IPancakeV3Factory(0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865).getPool(token0, token1, fee);
tickSpacing = V3PoolCallee.wrap(pool).tickSpacing();
function setUp() public override {
dex = DEX.PancakeSwapV3;
super.setUp();
}

function test_GetSlots() public {
Expand Down
49 changes: 4 additions & 45 deletions test/foundry/PositionLens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,6 @@ contract PositionLensTest is BaseTest {
assertEq(collect1, amount1);
}

function getPoolSlot0(
address pool
)
internal
view
virtual
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint32 feeProtocol,
bool unlocked
)
{
return IUniswapV3Pool(pool).slot0();
}

function verifyPosition(PositionState memory pos) internal {
{
assertEq(pos.owner, npm.ownerOf(pos.tokenId), "owner");
Expand All @@ -132,7 +113,7 @@ contract PositionLensTest is BaseTest {
uint16 observationCardinalityNext,
uint32 feeProtocol,
bool unlocked
) = getPoolSlot0(pool);
) = IPancakeV3Pool(pool).slot0();
assertEq(sqrtPriceX96, pos.slot0.sqrtPriceX96, "sqrtPriceX96");
assertEq(tick, pos.slot0.tick, "tick");
assertEq(observationIndex, pos.slot0.observationIndex, "observationIndex");
Expand Down Expand Up @@ -187,36 +168,14 @@ contract PositionLensTest is BaseTest {

contract PCSV3PositionLensTest is PositionLensTest {
function setUp() public override {
npm = INPM(0x46A15B0b27311cedF172AB29E4f4766fbE7F4364);
dex = DEX.PancakeSwapV3;
super.setUp();
}

function getPoolSlot0(
address pool
)
internal
view
override
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint32 feeProtocol,
bool unlocked
)
{
return IPancakeV3Pool(pool).slot0();
}

// Trivially override so that the "forge-config" settings are applied.
/// forge-config: default.fuzz.runs = 16
/// forge-config: ci.fuzz.runs = 16
function testFuzz_GetPosition(uint256 tokenId) public override {
tokenId = bound(tokenId, 1, 300);
try new EphemeralGetPosition(npm, tokenId) {} catch (bytes memory returnData) {
PositionState memory pos = abi.decode(returnData, (PositionState));
verifyPosition(pos);
}
super.testFuzz_GetPosition(tokenId);
}
}
8 changes: 4 additions & 4 deletions test/foundry/StorageLens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "contracts/EphemeralStorageLens.sol";
import "./Base.t.sol";

contract StorageLensTest is BaseTest {
function setUp() public override {
function setUp() public virtual override {
super.setUp();
vm.etch(pool, vm.getDeployedCode("EphemeralStorageLens.sol"));
}
Expand Down Expand Up @@ -34,8 +34,8 @@ contract StorageLensTest is BaseTest {
}

contract PCSV3StorageLensTest is StorageLensTest {
function initPoolInfo() internal override {
pool = IPancakeV3Factory(0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865).getPool(token0, token1, fee);
tickSpacing = V3PoolCallee.wrap(pool).tickSpacing();
function setUp() public override {
dex = DEX.PancakeSwapV3;
super.setUp();
}
}
6 changes: 3 additions & 3 deletions test/foundry/TickLens.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ contract TickLensTest is BaseTest, PoolUtils {
}

contract PCSV3TickLensTest is TickLensTest {
function initPoolInfo() internal override {
pool = IPancakeV3Factory(0x0BFbCF9fa4f9C56B0F40a671Ad40E0805A091865).getPool(token0, token1, fee);
tickSpacing = V3PoolCallee.wrap(pool).tickSpacing();
function setUp() public override {
dex = DEX.PancakeSwapV3;
super.setUp();
}
}
19 changes: 12 additions & 7 deletions test/hardhat/pcsv3_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
EphemeralGetPositions__factory,
EphemeralPoolSlots__factory,
INonfungiblePositionManager__factory,
IUniswapV3Pool__factory,
IPancakeV3Pool__factory,
} from "../../typechain";
import { computePoolAddress } from "@pancakeswap/v3-sdk";
import { Token } from "@pancakeswap/sdk";
Expand All @@ -44,7 +44,7 @@ describe("Pool lens test with PCSV3 on BSC", () => {
});
const poolContract = getContract({
address: pool,
abi: IUniswapV3Pool__factory.abi,
abi: IPancakeV3Pool__factory.abi,
client: publicClient,
});
const npm = getContract({
Expand All @@ -54,7 +54,7 @@ describe("Pool lens test with PCSV3 on BSC", () => {
});

before(async () => {
blockNumber = await publicClient.getBlockNumber();
blockNumber = (await publicClient.getBlockNumber()) - 64n;
console.log(`Running PCSV3 tests on the BNB chain at block number ${blockNumber}...`);
});

Expand Down Expand Up @@ -85,22 +85,27 @@ describe("Pool lens test with PCSV3 on BSC", () => {
);
});

/*
it("Test getting position details", async () => {
const {
tokenId,
position: { token0, token1, fee },
slot0: { sqrtPriceX96, tick },
} = await getPositionDetails(PCSV3_NPM, 4n, publicClient, blockNumber);
expect(tokenId).to.be.eq(4n);
const poolAddress = computePoolAddress({
deployerAddress: PCSV3_DEPLOYER,
tokenA: new Token(bsc.id, token0, 0, "NOT_USED"),
tokenB: new Token(bsc.id, token1, 0, "NOT_USED"),
fee,
});
const [_sqrtPriceX96, _tick] = await getContract({
address: computePoolAddress(uniswap_v3_factory, token0, token1, fee),
abi: IUniswapV3Pool__factory.abi,
address: poolAddress,
abi: IPancakeV3Pool__factory.abi,
client: publicClient,
}).read.slot0({ blockNumber });
expect(sqrtPriceX96).to.be.eq(_sqrtPriceX96);
expect(tick).to.be.eq(_tick);
});*/
});

async function verifyPositionDetails(posArr: ContractFunctionReturnType<typeof EphemeralGetPositions__factory.abi>) {
await Promise.all(
Expand Down
Loading

0 comments on commit 6ad9db3

Please sign in to comment.