Conversation
# Conflicts: # ccv/chains/evm/deployment/latest/operations/lombard_token_pool/lombard_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/burn_from_mint_token_pool/burn_from_mint_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/burn_mint_token_pool/burn_mint_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/burn_mint_with_lock_release_flag_token_pool/burn_mint_with_lock_release_flag_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/burn_to_address_mint_token_pool/burn_to_address_mint_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/cctp_through_ccv_token_pool/cctp_through_ccv_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/lock_release_token_pool/lock_release_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/siloed_lock_release_token_pool/siloed_lock_release_token_pool.go # ccv/chains/evm/deployment/v2_0_0/operations/siloed_usdc_token_pool/siloed_usdc_token_pool.go # ccv/chains/evm/gobindings/generated/latest/burn_from_mint_token_pool/burn_from_mint_token_pool.go # ccv/chains/evm/gobindings/generated/latest/burn_mint_token_pool/burn_mint_token_pool.go # ccv/chains/evm/gobindings/generated/latest/burn_mint_with_lock_release_flag_token_pool/burn_mint_with_lock_release_flag_token_pool.go # ccv/chains/evm/gobindings/generated/latest/burn_to_address_mint_token_pool/burn_to_address_mint_token_pool.go # ccv/chains/evm/gobindings/generated/latest/burn_with_from_mint_token_pool/burn_with_from_mint_token_pool.go # ccv/chains/evm/gobindings/generated/latest/cctp_through_ccv_token_pool/cctp_through_ccv_token_pool.go # ccv/chains/evm/gobindings/generated/latest/lock_release_token_pool/lock_release_token_pool.go # ccv/chains/evm/gobindings/generated/latest/lombard_token_pool/lombard_token_pool.go # ccv/chains/evm/gobindings/generated/latest/siloed_lock_release_token_pool/siloed_lock_release_token_pool.go # ccv/chains/evm/gobindings/generated/latest/siloed_usdc_token_pool/siloed_usdc_token_pool.go # ccv/chains/evm/gobindings/generated/latest/token_pool_factory/token_pool_factory.go # chains/evm/.gas-snapshot # chains/evm/gobindings/generation/generated-wrapper-dependency-versions-do-not-edit.txt
Also adds (IERC20Metadata).interfaceId
…ry-to-futureOwner send tokens from factory to futureOwner
…en-fixes # Conflicts: # chains/evm/contracts/tokens/BaseERC20.sol
…-token-fixes Minor cross chain pool token fixes
# Conflicts: # chains/evm/contracts/tokens/BaseERC20.sol
TokenPoolFactory improvement
# Conflicts: # ccv/chains/evm/gobindings/generated/latest/mock_lbtc_token_pool/mock_lbtc_token_pool.go # chains/evm/.gas-snapshot # chains/evm/contracts/pools/TokenPool.sol
There was a problem hiding this comment.
Pull request overview
This PR introduces new cross-chain-friendly token and “pool-is-token” primitives, migrates the factory deployment flow to those primitives (including a new futureOwner handoff parameter), and updates compilation, bindings, and tests to remove the legacy factory-minted ERC20.
Changes:
- Add
BaseERC20/CrossChainToken(role-based burn/mint + CCIP admin) andCrossChainPoolToken(token pool that is also the ERC20). - Refactor
TokenPoolFactoryto deploy/configureCrossChainToken-based deployments, addfutureOwner, and forward any factory-held premint to that owner. - Update build scripts, Go bindings generation inputs, and tests/mocks to use
CrossChainTokeninstead ofBurnMintERC20/FactoryBurnMintERC20, plus add new unit + e2e coverage.
Reviewed changes
Copilot reviewed 93 out of 96 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| chains/evm/scripts/compile_all | Add compilation targets/optimizer override for new CrossChain pool/token artifacts; switch factory compile target. |
| chains/evm/gobindings/go_generate.go | Update go:generate wrappers: remove FactoryBurnMintERC20, add CrossChainPoolToken and CrossChainToken. |
| chains/evm/gobindings/generation/generated-wrapper-dependency-versions-do-not-edit.txt | Add new wrapper dependencies and update factory wrapper hash. |
| chains/evm/contracts/tokens/CrossChainToken.sol | New role-based burn/mint token built on BaseERC20 + OZ AccessControl default admin rules. |
| chains/evm/contracts/tokens/BaseERC20.sol | New ERC20 base with max-supply guardrails and explicit CCIP admin role management. |
| chains/evm/contracts/tokenAdminRegistry/TokenPoolFactory/FactoryBurnMintERC20.sol | Remove legacy factory-deployed burn/mint token implementation. |
| chains/evm/contracts/test/tokens/CrossChainToken/CrossChainTokenSetup.t.sol | Add CrossChainToken test setup fixture. |
| chains/evm/contracts/test/tokens/CrossChainToken/CrossChainToken.setCCIPAdmin.t.sol | Add setCCIPAdmin behavior + access control tests. |
| chains/evm/contracts/test/tokens/CrossChainToken/CrossChainToken.mint.t.sol | Add mint behavior tests incl maxSupply + invalid receiver + role checks. |
| chains/evm/contracts/test/tokens/CrossChainToken/CrossChainToken.grantMintAndBurnRoles.t.sol | Add helper role-granting test. |
| chains/evm/contracts/test/tokens/CrossChainToken/CrossChainToken.constructor.t.sol | Add constructor invariants + supportsInterface + typeAndVersion tests. |
| chains/evm/contracts/test/tokens/CrossChainToken/CrossChainToken.burn.t.sol | Add burn/burnFrom tests and role-gating coverage. |
| chains/evm/contracts/test/tokens/BaseERC20/BaseERC20Setup.t.sol | Add BaseERC20 test setup fixture. |
| chains/evm/contracts/test/tokens/BaseERC20/BaseERC20.transfer.t.sol | Add transfer/approve-to-self revert tests for BaseERC20. |
| chains/evm/contracts/test/tokens/BaseERC20/BaseERC20.setCCIPAdmin.t.sol | Add CCIP admin transfer behavior + revert coverage for BaseERC20. |
| chains/evm/contracts/test/tokens/BaseERC20/BaseERC20.constructor.t.sol | Add BaseERC20 constructor invariants + revert coverage. |
| chains/evm/contracts/test/tokenAdminRegistry/TokenPoolFactory/TokenPoolFactorySetup.t.sol | Remove legacy setup that depended on FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/RegistryModuleOwnerCustom/RegistryModuleOwnerCustomSetup.t.sol | Update registry module tests to use CrossChainToken instead of BurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.transfer.t.sol | Remove legacy FactoryBurnMintERC20 transfer tests. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.supportsInterface.t.sol | Remove legacy FactoryBurnMintERC20 supportsInterface tests. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.mint.t.sol | Remove legacy FactoryBurnMintERC20 mint tests. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.increaseApproval.t.sol | Remove legacy approval-increase test for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantRole.t.sol | Remove legacy role grant/revoke tests for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.grantMintAndBurnRoles.t.sol | Remove legacy grantMintAndBurnRoles test for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.getCCIPAdmin.t.sol | Remove legacy CCIP admin tests for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.decreaseApproval.t.sol | Remove legacy approval-decrease test for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.constructor.t.sol | Remove legacy constructor tests for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFromAlias.t.sol | Remove legacy burn alias test for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burnFrom.t.sol | Remove legacy burnFrom test for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.burn.t.sol | Remove legacy burn tests for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/FactoryBurnMintERC20.approve.t.sol | Remove legacy approve tests for FactoryBurnMintERC20. |
| chains/evm/contracts/test/tokenAdminRegistry/FactoryBurnMintERC20/BurnMintERC20Setup.t.sol | Remove legacy FactoryBurnMintERC20 test fixture. |
| chains/evm/contracts/test/pools/USDC/USDCTokenPoolProxy/USDCTokenPoolProxy.withdrawFeeTokens.t.sol | Update fee token test wiring to use CrossChainToken. |
| chains/evm/contracts/test/pools/USDC/USDCSetup.t.sol | Use CrossChainToken as the USDC test token. |
| chains/evm/contracts/test/pools/USDC/SiloedUSDCTokenPool/SiloedUSDCTokenPoolSetup.sol | Update role granting callsites to CrossChainToken. |
| chains/evm/contracts/test/pools/TokenPool/TokenPoolSetup.t.sol | Use CrossChainToken for test token creation. |
| chains/evm/contracts/test/pools/TokenPool/TokenPool.withdrawFee.t.sol | Use CrossChainToken for additional fee token in tests. |
| chains/evm/contracts/test/pools/TokenPool/TokenPool.applyChainUpdates.t.sol | Use CrossChainToken in pool chain-update tests. |
| chains/evm/contracts/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPoolSetup.t.sol | Use CrossChainToken for pool/lockbox tests. |
| chains/evm/contracts/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.getAllLockBoxConfigs.t.sol | Use CrossChainToken for lockbox config enumeration test. |
| chains/evm/contracts/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.constructor.t.sol | Use CrossChainToken in constructor test. |
| chains/evm/contracts/test/pools/SiloedLockReleaseTokenPool/SiloedLockReleaseTokenPool.configureLockBoxes.t.sol | Use CrossChainToken for lockbox configuration tests. |
| chains/evm/contracts/test/pools/LombardTokenPool/LombardTokenPool.constructor.t.sol | Switch Lombard token tests to CrossChainToken and BaseTest. |
| chains/evm/contracts/test/pools/LombardTokenPool/LombardTokenPool._getTokenDecimals.t.sol | Use CrossChainToken in token decimals helper test. |
| chains/evm/contracts/test/pools/LockReleaseTokenPool/LockReleaseTokenPoolSetup.t.sol | Use CrossChainToken for lock/release pool setup. |
| chains/evm/contracts/test/pools/LockReleaseTokenPool/LockReleaseTokenPool.constructor.t.sol | Use CrossChainToken in constructor and invalid token tests. |
| chains/evm/contracts/test/pools/ERC20LockBox/ERC20LockBoxSetup.t.sol | Use CrossChainToken for lockbox setup. |
| chains/evm/contracts/test/pools/ERC20LockBox/ERC20LockBox.deposit.t.sol | Update unsupported-token test to use CrossChainToken. |
| chains/evm/contracts/test/pools/CrossChainPoolToken/CrossChainPoolTokenSetup.t.sol | Add setup fixture for the new pool-is-token contract. |
| chains/evm/contracts/test/pools/CrossChainPoolToken/CrossChainPoolToken.setCCIPAdmin.t.sol | Add CCIP admin setter tests for CrossChainPoolToken. |
| chains/evm/contracts/test/pools/CrossChainPoolToken/CrossChainPoolToken.sendReceive.t.sol | Add full lifecycle send/receive simulation tests for pool-is-token flows. |
| chains/evm/contracts/test/pools/CrossChainPoolToken/CrossChainPoolToken.releaseOrMint.t.sol | Add releaseOrMint tests for CrossChainPoolToken incl maxSupply/curse/chain gating. |
| chains/evm/contracts/test/pools/CrossChainPoolToken/CrossChainPoolToken.lockOrBurn.t.sol | Add lockOrBurn burn-from-self tests + RMN/chain gating coverage. |
| chains/evm/contracts/test/pools/CrossChainPoolToken/CrossChainPoolToken.constructor.t.sol | Add constructor invariants for CrossChainPoolToken. |
| chains/evm/contracts/test/pools/BurnWithFromMintTokenPool/BurnWithFromMintTokenPool.lockOrBurn.t.sol | Update role granting to CrossChainToken. |
| chains/evm/contracts/test/pools/BurnToAddressMintTokenPool/BurnToAddressMintTokenPoolSetup.t.sol | Update role granting to CrossChainToken. |
| chains/evm/contracts/test/pools/BurnMintWithLockReleaseFlagTokenPool/BurnMintWithLockReleaseFlagTokenPoolSetup.t.sol | Use CrossChainToken and update role granting in USDC-like setup. |
| chains/evm/contracts/test/pools/BurnMintTokenPool/BurnMintTokenPool.releaseOrMint.t.sol | Update role granting to CrossChainToken. |
| chains/evm/contracts/test/pools/BurnMintTokenPool/BurnMintTokenPool.lockOrBurn.t.sol | Update role granting to CrossChainToken. |
| chains/evm/contracts/test/pools/BurnFromMintTokenPool/BurnFromMintTokenPoolSetup.t.sol | Update role granting to CrossChainToken. |
| chains/evm/contracts/test/pools/AdvancedPoolHooks/AdvancedPoolHooksSetup.t.sol | Use CrossChainToken for token setup. |
| chains/evm/contracts/test/onRamp/OnRamp/OnRamp.withdrawFeeTokens.t.sol | Use CrossChainToken for fee token tests. |
| chains/evm/contracts/test/offRamp/OffRamp/OffRamp.releaseOrMintSingleToken.t.sol | Update role granting to CrossChainToken. |
| chains/evm/contracts/test/offRamp/OffRamp/OffRamp.executeSingleMessage.t.sol | Use CrossChainToken as destination token in offRamp execution tests. |
| chains/evm/contracts/test/mocks/test/MockRouterTest.t.sol | Loosened revert expectation for allowance error (needs tightening). |
| chains/evm/contracts/test/mocks/MockE2EUSDCTransmitterCCTPV2.sol | Update mock transmitter token type to CrossChainToken. |
| chains/evm/contracts/test/mocks/MockE2EUSDCTransmitter.sol | Update mock transmitter token type to CrossChainToken. |
| chains/evm/contracts/test/libraries/FeeTokenHandler/FeeTokenHandler.withdrawFeeTokens.t.sol | Use CrossChainToken for fee token in handler tests. |
| chains/evm/contracts/test/feeQuoter/FeeQuoterSetup.t.sol | Adjust FeeQuoter test constants to accommodate updated limits/overheads. |
| chains/evm/contracts/test/executor/Executor/ExecutorSetup.t.sol | Use CrossChainToken as fee token in executor tests. |
| chains/evm/contracts/test/executor/Executor/Executor.withdrawFeeTokens.t.sol | Use CrossChainToken as secondary fee token in executor tests. |
| chains/evm/contracts/test/e2e/e2e.feeWithdraw.t.sol | Use CrossChainToken as test token in e2e fee-withdraw flow. |
| chains/evm/contracts/test/e2e/e2e.factoryDeployedPool.t.sol | Add e2e coverage for factory-deployed token+pool and remote deployment via CCIP. |
| chains/evm/contracts/test/e2e/e2e.cctp.t.sol | Use CrossChainToken for USDC token in CCTP e2e tests and role granting. |
| chains/evm/contracts/test/ccvs/components/BaseVerifier/BaseVerifierSetup.t.sol | Use CrossChainToken as source fee token in verifier setup. |
| chains/evm/contracts/test/ccvs/VersionedVerifierResolver/VersionedVerifierResolver.withdrawFeeTokens.t.sol | Use CrossChainToken for fee token tests. |
| chains/evm/contracts/test/ccvs/LombardVerifier/LombardVerifierSetup.t.sol | Use CrossChainToken for supported token setup. |
| chains/evm/contracts/test/ccvs/LombardVerifier/LombardVerifier.updateSupportedTokens.t.sol | Use CrossChainToken in supported token update tests and allowance checks. |
| chains/evm/contracts/test/ccvs/LombardVerifier/LombardVerifier.forwardToVerifier.t.sol | Use CrossChainToken in adapter forwarding tests. |
| chains/evm/contracts/test/ccvs/CommitteeVerifier/CommitteeVerifier.withdrawFeeTokens.t.sol | Use CrossChainToken for fee token tests. |
| chains/evm/contracts/test/ccvs/CCTPVerifier/CCTPVerifierSetup.t.sol | Use CrossChainToken as USDC token and update role granting. |
| chains/evm/contracts/test/ccvs/CCTPVerifier/CCTPVerifier.withdrawFeeTokens.t.sol | Use CrossChainToken for fee token tests. |
| chains/evm/contracts/test/applications/EtherSenderReceiver/EtherSenderReceiverTestSetup.t.sol | Use CrossChainToken as LINK fee token in app tests. |
| chains/evm/contracts/test/applications/EtherSenderReceiver/EtherSenderReceiverTest.ccipSend.t.sol | Loosened revert expectation for allowance error (needs tightening). |
| chains/evm/contracts/test/TokenSetup.t.sol | Add helper to deploy CrossChainToken and migrate shared token setup to it. |
| chains/evm/contracts/test/TokenPoolFactory/TokenPoolFactorySetup.t.sol | Add new TokenPoolFactory test setup aligned with new contract location + CrossChainToken init code. |
| chains/evm/contracts/test/TokenPoolFactory/TokenPoolFactory.deployTokenAndTokenPool.t.sol | Update factory tests for new API (futureOwner), CrossChainToken roles, and expanded ownership/permission assertions. |
| chains/evm/contracts/test/TokenPoolFactory/TokenPoolFactory.constructor.t.sol | Update imports and constructor test inputs for new factory location. |
| chains/evm/contracts/test/Router/Router.ccipSend.t.sol | Loosened revert expectation for allowance error (needs tightening). |
| chains/evm/contracts/test/Proxy/Proxy.withdrawFeeTokens.t.sol | Use CrossChainToken for fee token tests. |
| chains/evm/contracts/pools/CrossChainPoolToken.sol | New pool contract that is also the ERC20 token (burn/mint via internal ERC20 ops). |
| chains/evm/contracts/TokenPoolFactory.sol | Refactor factory for CrossChainToken-based deployments, add futureOwner, register via CCIP admin, and forward premint balance. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
| function burn( | ||
| address account, | ||
| uint256 amount | ||
| ) public virtual override { |
There was a problem hiding this comment.
I am not a huge fan of delegating the validation to burnFrom. Like this is secure, but if a future dev were to override this function and use some custom logic that doesn't call burnFrom it could be a trivial thing to miss.
Given that this contracts size is only 6.3kB, and burnFrom already heavily uses internal logic, we could just do this.
function burn(
address account,
uint256 amount
) public virtual override onlyRole(BURNER_ROLE) {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}There was a problem hiding this comment.
If they override, wouldn't they override with some equally secure implementation? This way we reduce code dup and ensure consistency between calls. This burn with an account is just a "wrong" burnFrom with the name burn. We purely add this to allow for compatibility, and it should be exactly equal to BurnFrom (the more correct name). I think given that, it makes sense that this calls into BurnFrom.
| /// @param burnAndMinter The address to be granted both the MINTER_ROLE and BURNER_ROLE. | ||
| /// @dev calls public functions so this function does not require | ||
| /// access controls. This is handled in the inner functions. | ||
| function grantMintAndBurnRoles( |
There was a problem hiding this comment.
Same nit as above, just add the validation and then make grantRole into _grantRole
| address token = Create2.deploy(0, salt, tokenInitCode); | ||
|
|
||
| LocalPoolConfig memory localConfig = LocalPoolConfig({ | ||
| token: token, localTokenDecimals: localTokenDecimals, localPoolType: localPoolType, lockBox: lockBox, salt: salt |
There was a problem hiding this comment.
Nit add validation that localTokenDecimals actually matches token.decimals() to prevent silent misconfigure.
This PR introduces new tokens and a new pool
Tokens
The BaseERC20 is a basic mint-once LockRelease token. It serves as the base implementation of the new CrossChainToken and the CrossChainPoolToken.
The CrossChainToken (CCT) is the new primary CCIP token. It supports everything needed to fully support CCIP integration: ccipAdmin, burning/minting and safe ownership roles.
Pool
The new pool is a pool/token combo. This makes management and deployment easier: there's nothing to configure. The token exposes it burn/mint functions through the fully CCIP compatible TokenPool interface (ready for CCIPv2) and no token related config/permissions have to be set post deployment.
Factory
The token pool factory is updated to work with the new CrossChainToken. It should not support significantly more flexible ownership/premint/permission options, and has better security guards against dangling permissions or tokens being locked in the factory contact.