Guardian's review of Polygon Deployment and Peer Verification for USDT0, published August 2025. The report records 11 findings, including 4 low and 7 informational.
- Published
- Review window
- August 5 to 7, 2025
- Language
- Solidity
- Chains
- Polygon, Ethereum
- Sector
- Stablecoins, Cross-chain
- 0 Critical
- 0 High
- 0 Medium
- 4 Low
- 7 Informational
Scope
Findings 11
-
L-01 Low Incorrect Pre-generated Calldata Logical Error Pending
Description
There is a rollback plan that aims to revert the proxies to the old implementation in case of a bug. This rollback plan uses pre-generated calldata. While the pre-generated calldata for the
ERC20Predicateuses theupdateImplementationmethod to schedule and execute the rollback, the calldata for theRootChainManageruses theupdateAndCallmethod with additional data to perform agrantRoleoperation after the rollback. However, thegrantRolefunction cannot be executed due to access control restrictions, and as a result, the current pre-generated calldata fails to deliver the rollback action in case a bug occurs.Recommendation
The pre-generated rollback calldata for
RootChainManagershould be updated to call only theupdateImplementationmethod. -
L-02 Low Avoid Using Private Keys Best Practices Acknowledged
Description
The current preparation scripts optionally deploy new implementation contracts for
RootChainManager,ERC20Predicate, andUChildUSDT. To deploy these contracts, aPRIVATE_KEYmust be specified in the .env file or via inline environment variable assignment. This approach risks exposing and compromising private keys.Recommendation
Use a hardware wallet or encrypted keystore file.
-
L-03 Low Missing Block Validation Validation Pending
Description
The
updateTokenMigrationStatuswill disable deposits and/or exits for a specific root token. Although theUpdateTokenMigrationStatusscript validates non zerolastExitBlockNumberwhen disabling exits, this is not the case for the on chain validation.Recommendation
Consider validating
lastExitBlockNumber > 0inupdateTokenMigrationStatusfunction. -
L-04 Low Incorrect Role Revoked In Rollback Logical Error Pending
Description
The USDT0 playbook includes rollback provisions intended for emergency scenarios. However, as per what documented, the
MIGRATION_MANAGER_ROLEaccess is revoked from the zero address (0x0) rather than the actual address to which permissions were granted. This oversight leaves the originally authorized address with unintended and unclear permissions.Recommendation
Consider revoking permissions from the address that was originally granted
MIGRATION_MANAGER_ROLEaccess. -
I-01 Informational Double Check JSON Inputs Configuration Pending
Description
The preparation and migration steps involve using different foundry scripts that heavily rely on a JSON file. Although the
inputs.json.exampleis not the final JSON that will be used during migration, it already contains wrong addresses.Recommendation
Due to the fact that scripts will heavily rely on this JSON file, extra care should be taken to verify that each value is correct.
-
I-02 Informational Warning About Using Same Script Informational Pending
Description
According to the upgrade
README, both theRootChainManagerandERC20Predicateimplementation upgrades will be performed using the sameUpdateImplementation.s.solscript. The script can be run either by providing an input string or without any input. In the former case, it reads the necessary data from the provided input string; in the latter, it reads data from a previously preparedinputs.jsonfile in thescripts/forgefolder. Since theinputs.jsonfile can only contain oneupgradeImplementationkey, and both upgrades use the same script, at least one of the upgrades must be performed using an input string, while the other can be read from theinputs.jsonfile. The same case applies forUpdateTokenMigrationStatusscript as well.Recommendation
Consider using separate scripts for each upgrade so that all inputs can be prepared beforehand in the
inputs.jsonfile. Alternatively, modify_readInputsto read different keys frominputs.jsonbased on whether the upgrade is forRootChainManagerorERC20Predicate. -
I-03 Informational Manual Script Steps Prone To Errors Informational Pending
Description
The current playbook describes the migration steps for USDT0. These include generating calldata for creating multisig transactions, reading from a JSON file, copy and pasting results from console, testing bridge deposits and exits. The amount of manual steps may lead to human errors, due to the amount of scripts to run, pasting the incorrect value in the JSON file or into the multisig UI for building the transaction.
Recommendation
Consider reducing the manual inputs as much as possible. Additionally, reduce the amount of scripts to run and/or use the forge script to write the output into the JSON file. If possible, create the multisig transaction directly in the script, using the generated calldata. This avoids any UI phishing as you will be interacting with the smart contract directly.
-
I-04 Informational Insolvency Risk For OFT Users Logical Error Resolved
Description
The
migrateBridgeFundswill transfer out USDT from theERC20Predicateaccording to the collected USDT supply value on Polygon during the upgrade. However, these funds will be sent to aMultisigaddress according to the playbook, instead of the the USDTOAdapter. Additionally, the playbook does not contain any extra steps regarding a subsequent deposit of USDT to another contract. This will create an insolvency case, as there will be more USDT0 circulating in LayerZero chains than the amount of USDT available in theOAdapterto be redeemed.Recommendation
After migrating USDT out of the
ERC20Predicate, transfer them to theOAdaptercontract, or set it as receiver in the encoded transfer call -
I-05 Informational Mismatch Between Readme And Code Informational Pending
Description
Step 8 of the playbook README mentions that exits should be blocked from the upgrade block: "New plan is to just run the upgrade in block x, block exits from block x on (so no tx from x is valid exit) and manually check for any valid exits before the upgrade". However, the code allows exits in the upgrade block and considers them valid Reference.
if (migrationStatus[rootToken].isExitDisabled && blockNumber > migrationStatus[rootToken].lastExitBlockNumber) { // @note: if the lastExitBlockNumber is the same as the current block number, exits are still allowed revert("RootChainManager: EXIT_DISABLED"); }Recommendation
Update the code accordingly if the README is correct and the intention is to disallow exits in the upgrade block. However, note that this change would cause exits within the same block to fail and require manual intervention. Otherwise, update the README to reflect the current behavior.
-
I-06 Informational Missing Migration Event Events Acknowledged
Description
During funds migration flow, neither
RootChainManager.migrateBridgeFundsorERC20Predicate.migrateTokensemit an event. This is a major state change that should emit relevant data, like it's currently done in theupdateTokenMigrationStatusfunction. Offchain services will likely need to inspect the migration transaction in order to read the USDT token receiver and amount withdrawn.Recommendation
Consider emitting an event either in
RootChainManagerorERC20Predicate, with the token receiver and amount. -
I-07 Informational Manager Actions Allowed After Migration Informational Pending
Description
The
MIGRATION_MANAGER_ROLEcan block deposit/exits and latermigrateBridgeFundsto withdraw tokens fromERC20Predicate. Blocking deposits/exits does not have any validation, and migration is only allowed if both deposits and exits are blocked. This means that manager may:- call
migrateBridgeFundsmultiple times - block deposits and exits to later migrate tokens, but re enable deposits or exits in the future again. This might be unexpected, as migration should be a one time action.
Recommendation
Consider setting a state mapping that tracks migrated tokens, preventing manager to re-migrate or re-enable deposits/exits after migration. If this is the expected behavior, document it in the
RootChainManagercontract. - call
No findings match.
More from USDT0
All 34 reportsPut your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.
