Skip to content

Add TIP20 Extension to frxUSDOFTUpgradeable#126

Open
dhruvinparikh wants to merge 61 commits intoFraxFinance:masterfrom
dhruvinparikh:feat/frxusd-tip20
Open

Add TIP20 Extension to frxUSDOFTUpgradeable#126
dhruvinparikh wants to merge 61 commits intoFraxFinance:masterfrom
dhruvinparikh:feat/frxusd-tip20

Conversation

@dhruvinparikh
Copy link
Contributor

This PR extends functionality of frxUSDOFTUpgradeable.

TIP20 is native token standard for stablecoin on tempo

Refer : https://docs.tempo.xyz/protocol/tip20/overview

@dhruvinparikh dhruvinparikh marked this pull request as draft December 10, 2025 21:40
@dhruvinparikh
Copy link
Contributor Author

UPDATE: As per discussion with Tempo team, the only way to deploy TIP20 compliant frxUSD is via TIP20 factory pre-compile else

  • token wouldn't be able to be used for gas fees
  • couldn't be traded on the stablecoin DEX
  • couldn't use the payment lane, etc

by the way TIP20 is not a standard but a pre-compile as per Tempo. We would still require Adapter similar to FraxOFTMintableAdapterUpgradeable

- Deploy TIP20 token via factory in deployment script
- Add FrxUSDPolicyAdminTempo for freeze/thaw management
- Swap innerToken to PATH_USD in _lzSend when user pays fees in innerToken
- Use tempo-std ITIP403Registry instead of local interface
- add TempoTestHelpers.sol with TIP20 creation and DEX utilities
- update adapter to support any TIP20 for gas fees
- refactor FraxOFTMintableAdapterUpgradeableTIP20Test
- refactor FrxUSDPolicyAdminTempoTest
- refactor StablecoinExchangePOCTest
- Add Tempo testnet deployment scripts for frxUSD
- Add FraxOFTMintableAdapterUpgradeableTIP20 for TIP20 token bridging
- Add FrxUSDPolicyAdminTempo for TIP-403 freeze/thaw management
- Add DEX liquidity helper for gas token swaps
- Add tempo-specs README documentation
- Remove deprecated FrxUSDOFTTIP20Upgradeable (using adapter pattern instead)
- Remove TIP20Module and TIP20RolesAuthUpgradeable (using tempo-std)
- Update foundry.toml src path
- Override _payNative to handle TIP20 gas tokens on Tempo
- Swap user's TIP20 gas token to PATH_USD via StablecoinDEX
- Transfer PATH_USD to endpoint (EndpointV2Alt uses ERC20 balance as native)
- Add comprehensive tests for swap flow with event/state assertions
- Add MockLzEndpoint simulating EndpointV2Alt behavior
- Add recoverERC20 with onlyOwner access control and RecoveredERC20 event
- Add IERC20 and SafeERC20 imports
- Add tests: recover() callable by anyone, recoverERC20 onlyOwner
- Add event assertions for token transfers, burns, and DEX swaps
- Optimize _payNative to transfer PATH_USD directly to endpoint
…-chain OFT tests; remove old test, rename new test, ensure all contracts and tests pass
@dhruvinparikh dhruvinparikh marked this pull request as ready for review January 20, 2026 20:48
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also add the _userTokenAmount calculation to a view to support gas cost estimations? How do you think we should approach quotes on gas spent before sends?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overriding quoteSend() can serve as a view for _userTokenAmount calculations

- Add _quote override to FraxOFTUpgradeableTempo and FraxOFTMintableAdapterUpgradeableTIP20
- Query endpoint.nativeToken() dynamically instead of hardcoding PATH_USD
- Add IEndpointV2Alt interface with nativeToken() function
- Add _endpointNativeToken() helper for caching endpoint native token
- Convert fees from endpoint native token to user's TIP20 gas token via DEX quote
- Add quoteSend tests for fee conversion scenarios
- Update TempoTestHelpers to use ITIP20Factory with salt parameter
- Add mock quote() function to LZ test endpoints
- Override send() in FraxOFTMintableAdapterUpgradeableTIP20 and FraxOFTUpgradeableTempo
- Revert with OFTAltCore__msg_value_not_zero when msg.value > 0 (security check)
- EndpointV2Alt uses ERC20 for gas, not native ETH
- Add tests for send() revert on msg.value and success with valid receipts
- Add ILZEndpointDollar interface (wrap, unwrap, isWhitelistedToken, decimals)
- Update FraxOFTMintableAdapterUpgradeableTIP20 and FraxOFTUpgradeableTempo:
  - Change nativeToken from address to ILZEndpointDollar
  - Add UnsupportedGasToken error
  - Update _quote and _payNative with whitelist logic:
    - If userToken is whitelisted -> wrap directly
    - If PATH_USD is whitelisted -> swap to PATH_USD, then wrap
    - Otherwise revert
- Update test mocks with MockLZEndpointDollar for wrapping
- Update test assertions to check LZEndpointDollar balance at endpoint
- Delete unused ITIP20Factory interface
- Add chain IDs 143, 988, 4217 to SendMockFrax destinations
- Add Tempo Fraxtal (pathUSD) LZ scan link to README
- Include SetupMockFrax and SendMockFrax broadcast artifacts for chain 252
- _quote() no longer converts fee to user-token units (was causing double-conversion in _payNative)
- fee.nativeFee stays in LZEndpointDollar units throughout the flow
- added quoteUserTokenFee() view for UIs to get cost in user's gas token
- replaced hardcoded PATH_USD with dynamic _findSwapTarget() across all whitelisted tokens
- added getWhitelistedTokens() to ILZEndpointDollar interface
- fixed missing approve before wrap in whitelisted path (Tempo OFT)
- updated tests and mocks (32/32 pass)
…early return on zero fee

- Extract shared ERC20 gas payment logic into TempoAltTokenBase abstract base
- Add _resolveUserToken() with PATH_USD fallback (mirrors FeeManager cascading)
- Add _findSwapTarget() for dynamic whitelisted token selection
- Add quoteUserTokenFee(address, uint256) for off-chain fee estimation
- Add _validateQuoteSwapPath() for swap path validation in _quote()
- Add early return in _payNativeAltToken when _nativeFee == 0
- Refactor FraxOFTUpgradeableTempo and FraxOFTMintableAdapterUpgradeableTIP20 to use base
- Update tests for new signatures and base contract error selectors
- Remove broadcastAs(oftDeployerPK) and broadcastAs(configDeployerPK) modifiers
- Add GCS_DEPLOYER constant (0x54F9b12743A7DeeC0ea48721683cbebedC6E17bC)
- Replace vm.addr(configDeployerPK) and vm.addr(oftDeployerPK) with msg.sender
- Add vm.startBroadcast()/vm.stopBroadcast() in deploy and setup functions
- Add require(msg.sender == GCS_DEPLOYER) check after proxyAdmin deploy
- Update CREATE2 salt generation to use msg.sender / GCS_DEPLOYER
- Remove Mock FPI deploy+pop block from DeployFraxOFTProtocol (historical nonce artifact unnecessary with CREATE2)
- Remove deployFraxOFTUpgradeablesAndProxies() override from Tempo script (parent now correct)
- Simplify postDeployChecks() override to only skip wallet assertion
- Make postDeployChecks() virtual in DeployFraxOFTFraxtalHub
- Add SetupSourceFraxOFTFraxtalHubTempo with broadcastAs override (GCP KMS)
  and _validateFrxUsdAddr override (OFTAdapter-based frxUSD)
- Extract _validateFrxUsdAddr() virtual hook in SetupSourceFraxOFTFraxtalHub
- Make broadcastAs modifier virtual in BaseL0Script
- Register Tempo chain (4217) in L0Constants with 6 OFT proxy addresses
- Update L0Config.json proxyAdmin for Tempo
- Include deploy and setup broadcast artifacts (49 setup txs on chain 4217)
- SendFraxOFTFraxtalToTempo: bridge 6 OFTs from Fraxtal to Tempo (eid 30410)
- SendFraxOFTTempoToFraxtal: bridge 6 OFTs from Tempo back to Fraxtal with ERC20 gas
- Update SendFraxOFTFraxtalHub: add Tempo chain ID + RPC env var resolution
- Skip precompile validation for Tempo (Foundry cannot simulate TIP20 precompiles)
…caling

- Route through FraxOFTWalletUpgradeableTempo.batchBridgeWithTIP20FeeFromWallet()
  instead of sending directly from deployer (which had no token balance)
- Extract virtual _executeBatchBridge() hook in parent for Tempo override
- Extract virtual _getsendParamsForfrxUSD() hook for 18->6 decimal scaling
- Fix pass-by-reference bug: return new SendParam struct to avoid mutating
  the shared _sendParam used by all 6 OFTs
- Approve wallet for PATH_USD gas token per OFT and frxUSD TIP20 spending
- Add broadcast artifacts from successful dry-run
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.

3 participants