
Loading...
Loading
Loading...
LoadingLoading audit report...

WalletGuard.ai, powered by Gestalt Labs
Findings selected for deep verification. Where possible we generated a Solidity proof-of-concept and executed it against a forked mainnet.
contracts/tokenvault/ERC1155Vault.solFunction: _transferTokensLines: not precisely numbered but in _transferTokens private functionThe analyzed contract is part of the Taiko protocol, a ZK-rollup and cross-chain bridging system encompassing vault contracts, bridge message processing, SGX attestation, airdrop distribution, and governance infrastructure. The analysis identified 0 critical, 8 high, 14 medium, 9 low, and 4 informational findings across 40 total submissions, with 5 findings dropped after scope gate review. The single most dangerous pattern identified is the absence of replay protection in TimelockTokenPool withdrawal signatures, which allows any party who obtains a signed withdrawal message to drain a recipient's unlocked tokens at any time, combined with the TaikoTimelockController admin bypass that allows instant execution of governance operations including protocol upgrades. The overall risk level is high; the contract system should not be considered safe for production use without remediation of the signature replay, SGX attestation logic errors, and timelock bypass vulnerabilities.
The timelock contract is supposed to force a waiting period before governance changes take effect, giving users time to react. However, any address holding the admin role can execute any operation immediately with zero delay. This means the admin can upgrade contracts, change protocol parameters, or move funds without any notice or waiting period, completely undermining the security guarantee that a timelock is supposed to provide.
When a token grant recipient signs a message to authorize a withdrawal to a specific address, that signature has no expiry, no nonce, and no chain ID. Anyone who ever sees that signature, now or in the future, can use it to drain all of the recipient's unlocked tokens to the designated address. The recipient cannot revoke or cancel this authorization once the signature exists.
The code that parses SGX security certificates has a logic error in how it handles CPU security version numbers. If the special PCESVN entry appears anywhere other than the last position in the list, the code either crashes (denying all attestation for those certificates) or stores the wrong security values at the wrong positions, which could cause the system to accept SGX proofs from insufficiently secure hardware.
5 centralization points identified
The bypass is accessible to the TIMELOCK_ADMIN_ROLE holder (initially the owner), making this a privileged-role vulnerability; exploitation depends on the admin role being malicious or compromised.
getMinDelay()There is no transferOwnership function at all, making this a key-loss risk for the owner address; the impact is limited to inability to update trusted parameters if the owner key is lost.
constructor()The TIMELOCK_ADMIN_ROLE holder can bypass all time delays, making this a privileged centralization risk; it eliminates the security guarantee of the timelock for any operation initiated by or approved for the admin role.
getMinDelay()The double-claim path requires the owner to call setConfig with a new Merkle root; this is a privileged action that enables users to exceed their airdrop entitlement, making it a centralization risk for the airdrop administration.
claim()The function requires bridge_watchdog or owner permissions to call; the gas exhaustion risk is limited to privileged callers and does not expose user funds to theft.
suspendMessages()Finding 14 (incorrect notBefore tag validation) allows malformed X.509 certificates with invalid ASN.1 date tags to pass the date-check gate. Finding 4 (_findTcb off-by-one) can produce incorrect CPU SVN values when PCESVN is not in the last position. Finding 26 (fixed 3-byte RSA exponent assumption) can misparse the public key from a crafted certificate. An attacker who can supply a crafted certificate chain to the attestation flow can combine these three parsing weaknesses to pass certificate chain verification with a certificate that would otherwise be invalid, potentially allowing an untrusted SGX enclave to register as a valid prover.
Finding 7 (no chain ID or nonce in withdrawal signature) and Finding 11 (no validation that signer is an eligible recipient) together form a complete drain path. Once a recipient has ever signed a withdrawal message for any destination address, that signature can be replayed by any third party at any time to move all currently unlocked tokens to the pre-signed destination. Because there is no nonce, the attack can be executed repeatedly as more tokens vest. The victim has no on-chain mechanism to invalidate the signature.
Finding 1 (ERC1155 safeBatchTransferFrom callback fires during onMessageInvocation execution) combined with the fact that ERC20Vault and ERC721Vault share bridge state but maintain separate reentrancy locks creates a cross-contract reentrancy window. During the ERC1155 callback, a malicious recipient can call into ERC20Vault or ERC721Vault (which have independent nonReentrant guards), initiate a new bridge message, and manipulate bridge state before the original message execution completes. This can result in inconsistent token accounting or unauthorized token movements.
| Agent | Status | Findings | Severity | Confidence | Duration | Coverage |
|---|---|---|---|---|---|---|
| reentrancy | success | 5 | 2H1L | 62% | 1.2m | Cross-function reentrancy in Bridge.processMessage, recallMessage, retryMessage, ERC-1155 callback reentrancy in ERC1155Vault (onERC1155BatchReceived, safeBatchTransferFrom), ERC-721 safeTransferFrom callbacks in ERC721Vault._handleMessage, ERC-20 vault token transfer patterns and SafeERC20 usage, ReentrancyGuard implementation in EssentialContract (transient storage on L1, regular storage on L2), Cross-contract reentrancy between vault contracts sharing bridge state, TimelockTokenPool withdrawal logic and token transfer patterns, BridgedERC20Base mint/burn migration reentrancy paths, AutomataDcapV3Attestation view-only verification flow, PEMCertChainLib DER parsing bounds checking, SignalService state update ordering, TaikoL1 proposeBlock/proveBlock/verifyBlocks reentrancy, CrossChainOwned.onMessageInvocation re-entry pattern (explicitly noted as intentional), SgxVerifier instance replacement patterns, GuardianProver approval and proof submission flow, Airdrop contracts (ERC20Airdrop, ERC20Airdrop2, ERC721Airdrop) claim and withdrawal patterns, Bridge context management using transient storage vs regular storage, Flash loan callback patterns (none present), ERC-777 token risks in vault contracts |
| access control | success | 7 | 3M2L | 74% | 1.2m | Missing access modifiers on public/external functions across all contracts, Ownership and role patterns including single-step vs two-step transfer, Initializer protection and upgradeable contract patterns (EssentialContract with _disableInitializers in constructor), Signature authentication: ecrecover usage, chain ID, nonce, replay protection in TimelockTokenPool, Delegatecall safety in EssentialContract (UUPS pattern) and proxy patterns, Bridge message processing and reentrancy guards, ERC1155 callback-based reentrancy in ERC1155Vault, SGX instance registration and validation logic in SgxVerifier, TaikoTimelockController admin bypass, PEMCertChainLib array bounds in _findTcb, ERC20Airdrop and ERC20Airdrop2 claim and withdrawal logic, CrossChainOwned message validation, AutomataDcapV3Attestation owner management, TaikoGovernor proposal validation, tx.origin usage in LibAddress.isSenderEOA (intentional EOA check, not authorization bypass) |
| economic | success | 9 | 2H4M | 76% | 1.9m | Flash loan attack vectors - no token balance-based pricing found in core protocol, Oracle manipulation - no price feed oracle usage detected in any contract, Governance attacks - TaikoGovernor and TaikoTimelockController analyzed for quorum, timelock bypass, vote manipulation, MEV/sandwich exposure - Bridge processMessage, vault token operations, Reward manipulation - ERC20Airdrop, ERC20Airdrop2 withdrawal window logic, TimelockTokenPool vesting, Reentrancy - nonReentrant guards checked across Bridge, vaults, airdrop contracts, Access control - onlyOwner, onlyFromNamed, onlyFromBridge patterns reviewed, Signature authentication - ECDSA usage in TimelockTokenPool withdraw, SgxVerifier, ERC20Airdrop delegateBySig, Integer overflow/precision - LibProving bond calculations, ERC20Airdrop2 linear unlock, State machine - Bridge message status transitions (NEW->DONE/RETRIABLE/FAILED/RECALLED), Upgrade safety - UUPS proxy pattern via EssentialContract, storage gaps verified, Cross-chain trust - SignalService proof verification, Bridge context validation, ASN.1/DER parsing - PEMCertChainLib certificate parsing logic, SGX attestation verification - AutomataDcapV3Attestation TCB level checking, cert chain verification, EIP-1559 math - TaikoL2 gasExcess calculations, Lib1559Math exponential bonding curve, Fee-on-transfer token handling - ERC20Vault canonical vs bridged token paths, Transient storage usage - Bridge and EssentialContract context/reentry lock on mainnet vs L2 |
| logic validation | success | 8 | 1H3M2L | 78% | 1.7m | Input validation on all public/external function parameters, Arithmetic safety in LibDepositing, LibVerifying, TimelockTokenPool, Lib1559Math, ERC20Airdrop2, State machine integrity in Bridge message lifecycle (NEW->RETRIABLE->DONE/FAILED/RECALLED), Timestamp dependence in certificate validity checks, invocation delays, airdrop windows, DoS vectors including unbounded loops in suspendMessages, addRevokedCertSerialNum, Guardians.isApproved, Reentrancy protection via nonReentrant modifiers across all vault contracts, EIP-712 domain separator usage in SgxVerifier.getSignedHash, Integer overflow/underflow in unchecked blocks in LibDepositing, LibVerifying, LibProving, Precision loss in TimelockTokenPool cost calculation, ASN.1 parsing logic in PEMCertChainLib for certificate validation, SGX instance registration and deletion lifecycle, Bridge context storage using transient vs persistent storage, Token vault bridging logic for ERC20/ERC721/ERC1155, Governance proposal validation in TaikoGovernor, Access control in AutomataDcapV3Attestation owner functions, SignalService authorization and signal slot computation, MerkleClaimable claim hash construction for collision resistance, RsaVerify padding oracle resistance, Cross-chain message replay protection in Bridge.hashMessage |
| code quality | success | 12 | 82% | 2.2m | ERC-20 compliance (TaikoToken, BridgedERC20, BridgedERC20Base), ERC-721 compliance (BridgedERC721, ERC721Vault), ERC-1155 compliance (BridgedERC1155, ERC1155Vault), ERC-2771 context (CrossChainOwned, ERC2771 pattern), ERC-1967 proxy pattern (EssentialContract, UUPSUpgradeable), SGX attestation logic (AutomataDcapV3Attestation, PEMCertChainLib, SgxVerifier), Bridge message flow (Bridge.sol send/process/recall/retry), Reentrancy guards across all nonReentrant functions, Access control patterns (onlyOwner, onlyFromNamed, onlyFromOwnerOrNamed), Integer overflow/underflow (Solidity 0.8 checked arithmetic), Signature verification (SgxVerifier, TimelockTokenPool, LibAddress), Merkle proof verification (MerkleClaimable, SignalService), Token vault logic (ERC20Vault, ERC721Vault, ERC1155Vault), Cross-chain owned logic (CrossChainOwned), Airdrop claim logic (ERC20Airdrop, ERC20Airdrop2, ERC721Airdrop), TimelockTokenPool grant/withdraw/void logic, TaikoL1 block proposal/proving/verification, TaikoL2 anchor and EIP-1559 gas pricing, Guardian prover and Guardians contract, SignalService multi-hop proof verification, ASN.1/DER parsing in PEMCertChainLib and Asn1Decode, RsaVerify PKCS#1 v1.5 verification, X509DateUtils timestamp conversion, LibTrieProof Merkle Patricia trie verification | |
| compiler bugs | success | 4 | 1M | 63% | 1.2m | AutomataDcapV3Attestation - TCB verification logic, cert chain verification, enclave report sig verification, PEMCertChainLib - DER parsing, _findTcb CPU SVN index handling, certificate date validation, Bridge - processMessage, recallMessage, sendMessage, reentrancy protection, invocation delay logic, EssentialContract - transient storage reentry lock, chain-specific behavior for chainid==1, TimelockTokenPool - grant vesting math, withdrawal logic, cost token handling, SgxVerifier - instance management, proof verification, ECDSA signature recovery, SignalService - signal proof verification, hop proof chain, cache logic, ERC20Vault/ERC721Vault/ERC1155Vault - token bridging, message handling, canonical/bridged token mapping, BridgedERC20Base - migration status, mint/burn access control, TaikoL1/LibProposing/LibProving/LibVerifying - block lifecycle, bond management, tier system, CrossChainOwned - onMessageInvocation transaction ID ordering, MerkleClaimable - claim validation, double-claim prevention, TaikoL2 - anchor function, EIP-1559 base fee calculation, public input hash, Compiler bug patterns - pragma is 0.8.24, no ABIEncoderV2 explicit use in affected range, no applicable compiler bugs |
| assembly safety | success | 10 | 2H2L | 76% | 2.0m | Full codepoint-by-codepoint scan for non-ASCII characters in identifiers, function names, and string literals, Assembly blocks in BytesUtils.sol, SHA1.sol, EssentialContract.sol, Bridge.sol, SignalService.sol, TaikoL2.sol, RLPReader.sol, Bytes.sol, LibFixedPointMath.sol, ExcessivelySafeCall.sol - all checked for anti-patterns, Yul shift instruction ordering (shl/shr/sar argument order) - no reversed shifts found, tstore/tload usage in Bridge._storeContext and EssentialContract._storeReentryLock - named slot pattern used correctly, sstore/sload in SignalService._sendSignal and _loadSignalValue - computed slot pattern used correctly, assembly return() vs leave() patterns - no misuse found, delegatecall patterns - none found in assembly blocks, extcodesize/extcodehash usage for contract detection, Gas manipulation patterns using gas() opcode, Free memory pointer (0x40) overwrites in assembly, Calldataload at out-of-bounds offsets, RSA signature verification logic in RsaVerify.sol, SGX attestation flow in AutomataDcapV3Attestation.sol, Certificate chain parsing in PEMCertChainLib.sol, Bridge message processing and reentrancy patterns, Token vault logic (ERC20, ERC721, ERC1155) for access control and fund handling, Airdrop contract claim and withdrawal logic, TimelockTokenPool grant and withdrawal calculations, SgxVerifier instance management and proof verification, Cross-chain ownership pattern in CrossChainOwned |
| l2 specific | success | 11 | 2H3M2L | 72% | 2.5m | AutomataDcapV3Attestation: TCB verification logic, certificate chain validation, enclave identity verification, PEMCertChainLib: DER parsing, certificate decoding, date format validation, TCB info extraction loop bounds, SigVerifyLib: ES256 signature verification, assert usage on external call, Bridge: message lifecycle (send/process/recall/retry), reentrancy, fee handling, context storage, ERC20Vault: bridged token change, migration race conditions, token transfer handling, ERC1155Vault / ERC721Vault: NFT bridging, message invocation, token recall, SgxVerifier: instance registration, attestation, proof verification, instance expiry, TaikoTimelockController: minimum delay bypass for admin role, TaikoL1/LibProving/LibVerifying: block proving, contesting, liveness bonds, TCB level handling, TaikoL2: anchor function, basefee calculation, public input hash verification, SignalService: signal sending, cross-chain proof verification, hop proofs, ERC20Airdrop/ERC20Airdrop2: merkle claims, delegation, withdrawal windows, TimelockTokenPool: grant vesting, withdrawal, cost calculations, Guardians: guardian set management, approval bit manipulation, CrossChainOwned: cross-chain ownership enforcement, LibAddress: signature validation, EOA check, eth transfer, EssentialContract: reentrancy guard (transient storage on L1 vs storage on L2), pause mechanism, AddressManager/AddressResolver: address resolution security, BridgedERC20Base: migration status, mint/burn access control, LibDepositing: ETH deposit ring buffer, encoding |
| upgrade | success | 8 | 2M1L | 78% | 1.6m | ERC-1967 UUPS proxy pattern in EssentialContract - disableInitializers in constructor, _authorizeUpgrade access control, Storage layout collision analysis across EssentialContract inheritance chain, Initialization risks across all initializable contracts (Bridge, TaikoL1, TaikoToken, SignalService, etc.), Reentrancy guard implementation in EssentialContract (transient vs persistent storage), Bridge message processing logic and reentrancy in processMessage/recallMessage/retryMessage, Cross-chain ownership in CrossChainOwned.onMessageInvocation, AutomataDcapV3Attestation SGX quote verification logic, PEMCertChainLib certificate parsing logic for correctness issues, SgxVerifier instance management and proof verification, TimelockTokenPool grant calculation and withdrawal logic, TaikoTimelockController delay bypass via admin role, ERC20/ERC721/ERC1155 vault message encoding/decoding, Guardians approval mechanism and setGuardians access control, LibProving and LibVerifying token transfer logic, Bridge _invokeMessageCall selector restriction logic, SignalService authorization and signal sending, Diamond proxy pattern - not present, Beacon proxy pattern - not present |
This automated audit has inherent limitations. The following areas are not covered.
This report is an automated point-in-time assessment and does not guarantee protection against all possible attacks. It does not cover off-chain components, economic modeling, or business logic correctness unless explicitly noted. Changes to the contract after the audit commit are not reviewed. This is not financial or legal advice. WalletGuard, powered by Gestalt Labs, provides this analysis as-is with no warranty of completeness.
[](https://walletguard.ai/audit/9ca4a547-0c07-48fb-83fe-b7184b02dfea)
<a href="https://walletguard.ai/audit/9ca4a547-0c07-48fb-83fe-b7184b02dfea"> <img src="https://walletguard.ai/api/badge/9ca4a547-0c07-48fb-83fe-b7184b02dfea" alt="WalletGuard Audit Badge" /> </a>