Skip to content

Uniswap V3 routing tests for contract PaymentHub, added fixed routes - #221

Open
0xPuddi wants to merge 3 commits into
masterfrom
routing-tests
Open

Uniswap V3 routing tests for contract PaymentHub, added fixed routes#221
0xPuddi wants to merge 3 commits into
masterfrom
routing-tests

Conversation

@0xPuddi

@0xPuddi 0xPuddi commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Route Testing

The objective was to test and implement different routing paths from external tokens and native ETH to be exchanged by the Uniswap V3 router to ZCHF.

Testing is separated into, basic functionality testing of DirectInvestment.sol, native ETH payment and programmatic testing of external currencies defined within EXTERNAL_TOKENS in test/Routing.ts.

Routes

Routes are defined within EXTERNAL_TOKENS and with the interface:

type ExternalTokenName = "WETH" | "WBTC" | "USDC" | "USDT" | "DAI";

type Address = `0x${string}`;
type V3Path = `0x${string}` | `${number}`;

type ExternalToken = {
  imperFunder_ADDRESS: Address;
  imperFunder_AMOUNT: number;
  address: Address;
  path: V3Path[];
  pools: Address[];
};

type ExternalTokens<T extends string> = {
  [K in T]: ExternalToken;
};

const EXTERNAL_TOKENS: ExternalTokens<ExternalTokenName> = //...

I spend some words about it because a new entry will generate a new test case.

  • imperFunder_ADDRESS: "0x...", is the address we can impersonificate to fund the investor address with the external token.
  • imperFunder_AMOUNT: number, is the amount of token to be sent to the investor from the impersonificated address. Note that as shares increase in price as the investor buys them you need to account for such increase, I recommend to fund with an amount of 1000.- with an increase of 200.- for each new token, increase is cumulative by order of keys definition. Consider it with no decimals, the decimal normalization is taken care of.

It is important to note that for imperFunder_ADDRESS and imperFunder_AMOUNT you need to consider quantities and prices of block 25464800.

  • address: "0x.." is the address of the external token.
  • path: ["address", "uint24", "address", "uint24", "address", ...], is where the first address is the output token, the last address the input token and the "unit24" is the fee of the pool between the two adjacent token addresses. Note: you need to follow exactOutput format, so from the out token to the input token.
  • pools: ["0x...", "0x..."], the address of pools that are used within the path, following also the same order.

Routes can be used by the frontend to execute swaps.

USDT Approval

For routing we need to allow PaymentHub.sol contract to spend the external token in order to swap it through the Uniswap V3 pool based on path. For any proposed external token it worked fine, but for USDT the approve function does not return a boolean as prescribed by the ERC20 standard, which makes ethers fail to send and execute the transaction. To address it I tried a workaround within the ethers client but it did not work. To make it function, I added a INoReturnApprove interface with a silent approve and defined new public function silentApproveERC20, this might be a problem since there would need to be a new deployment of the contract for the USDT token. Could be worth to spend more time if it is possible address it client side.

Packages

I added @uniswap/v3-core to the packages to have the UniswapV3Pool ABI.

Small Misecllaneous Changes

Added .DS_Store to .gitignore. Formatted PaymentHub.sol. Added sepolia to KEYS_TEMPALTE.ts to run tests correctly. Formatted hardhat.config.ts and added mainnet fork with fixed block mainnetForkAtBlock25464800 for routing testings, I did so as tests rely on exchange rates and EOA balances for funding.

Notes

I omitted testing for unused withdrawToken and multiPay from PaymentHub.sol.

@0xPuddi
0xPuddi requested a review from muratogat July 14, 2026 11:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant