Quantum Audit Logo

Is Pendle Safe?

On-chain security analysis — is it a scam or legit?

Pendle PENDLE
0x0c88…c9e8
Arbitrum Not verifiedLast checked 3d ago 1 audit on record
How is this score calculated? → Medium Risk
Executive SummaryAI Copilot

The audit of the StandardArbERC20 contract, an implementation for an Arbitrum L2 ERC20 token deployed via a beacon proxy, reveals a well-structured and robust design. The contract correctly handles L1 token metadata parsing and integrates with the `Cloneable` pattern for proxy compatibility. Identified issues are primarily related to design choices and best practices, with no critical or high-severity vulnerabilities found. The overall risk level is assessed as Low.

1 Medium2 Low2 Informational
Volume 24h
$124.7K
Liquidity
$2.12M
Price
$1.9600
Token Age
3y
Top 10 Holders
41.8%

Security Findings

Medium

Revert on Missing ERC20 Metadata

M-01The `decimals()`, `name()`, and `symbol()` functions explicitly revert if the corresponding `ignore` flag (e.g., `availableGetters.ignoreDecimals`) is set, indicating that the metadata was not successfully parsed from the L1 token. While this behavior is intended to mimic L1 contracts where such functions might not exist, it deviates from standard ERC20 implementations which typically return a value (e.g., 0 for decimals, empty string for name/symbol) rather than reverting. This could cause issues for dApps or integrations that expect these standard ERC20 getters to always return a value and do not handle reverts gracefully.
IssueThe `decimals()`, `name()`, and `symbol()` functions explicitly revert if the corresponding `ignore` flag (e.g., `availableGetters.ignoreDecimals`) is set, indicating that the metadata was not successfully parsed from the L1 token. While this behavior is intended to mimic L1 contracts where such functions might not exist, it deviates from standard ERC20 implementations which typically return a value (e.g., 0 for decimals, empty string for name/symbol) rather than reverting. This could cause issues for dApps or integrations that expect these standard ERC20 getters to always return a value and do not handle reverts gracefully.
FixClearly document this specific behavior for integrators. Consider if returning a default value (e.g., 0 for decimals, empty string for name/symbol) is a more compatible approach for a broader range of ERC20 integrations, even if it deviates from the L1 mimicry. If reverting is critical for the design, ensure comprehensive testing of integrations under these conditions.
StatusUnresolved
Low

Implicit Trust in `L2GatewayToken` Initialization Logic

L-01The `bridgeInit` function calls `L2GatewayToken._initialize` to perform the core initialization logic. The security of preventing multiple initializations (a critical aspect for proxy contracts) relies entirely on `L2GatewayToken._initialize` correctly implementing an `initializer` pattern (e.g., using an `initialized` flag or `initializer` modifier). Without the source code for `L2GatewayToken`, this crucial protection is an assumption, introducing a dependency risk.
IssueThe `bridgeInit` function calls `L2GatewayToken._initialize` to perform the core initialization logic. The security of preventing multiple initializations (a critical aspect for proxy contracts) relies entirely on `L2GatewayToken._initialize` correctly implementing an `initializer` pattern (e.g., using an `initialized` flag or `initializer` modifier). Without the source code for `L2GatewayToken`, this crucial protection is an assumption, introducing a dependency risk.
FixVerify that the `L2GatewayToken._initialize` function rigorously enforces a single-call initialization to prevent re-initialization attacks. If possible, consider adding an explicit `initializer` modifier directly to `StandardArbERC20.bridgeInit` for defense in depth, even if `L2GatewayToken` provides its own protection.
StatusUnresolved
Low

Inline Assembly Usage in `BytesLib`

L-02The `BytesLib` library, used by `BytesParser` for decoding `_data`, extensively utilizes inline assembly (`assembly { ... }`) for byte manipulation. While assembly can be highly efficient for low-level operations, it is inherently more complex, error-prone, and harder to audit than high-level Solidity. Although the library includes `require` statements for bounds checking, subtle errors in assembly logic could lead to unexpected behavior or vulnerabilities.
IssueThe `BytesLib` library, used by `BytesParser` for decoding `_data`, extensively utilizes inline assembly (`assembly { ... }`) for byte manipulation. While assembly can be highly efficient for low-level operations, it is inherently more complex, error-prone, and harder to audit than high-level Solidity. Although the library includes `require` statements for bounds checking, subtle errors in assembly logic could lead to unexpected behavior or vulnerabilities.
FixEnsure that `BytesLib` has undergone thorough and independent security review, specifically focusing on its assembly code. Maintain comprehensive test coverage for all functions within `BytesLib` to validate correct behavior across various input scenarios.
StatusUnresolved
Info

`bridgeInit` Visibility and Explicit Initializer Pattern

I-01The `bridgeInit` function is declared as `public virtual`. While `L2GatewayToken._initialize` is expected to handle the single-call initialization, making `bridgeInit` `public` rather than `external` means it can be called internally, which is not strictly necessary for an initializer. Additionally, an explicit `initializer` modifier (e.g., from OpenZeppelin's `Initializable` pattern) is not directly applied to `bridgeInit` in `StandardArbERC20` itself, relying solely on the base contract.
IssueThe `bridgeInit` function is declared as `public virtual`. While `L2GatewayToken._initialize` is expected to handle the single-call initialization, making `bridgeInit` `public` rather than `external` means it can be called internally, which is not strictly necessary for an initializer. Additionally, an explicit `initializer` modifier (e.g., from OpenZeppelin's `Initializable` pattern) is not directly applied to `bridgeInit` in `StandardArbERC20` itself, relying solely on the base contract.
FixConsider changing `bridgeInit` to `external` if it's not intended for internal calls. For clarity and robustness, explicitly apply an `initializer` modifier to `bridgeInit` within `StandardArbERC20` if `L2GatewayToken` does not already provide a sufficiently robust and explicit mechanism, or if `StandardArbERC20` needs its own initialization state.
StatusUnresolved
Info

`Cloneable` `isMasterCopy` Storage Behavior in Proxy Context

I-02The `Cloneable` base contract initializes `isMasterCopy` to `true` in its constructor. In a proxy deployment, the constructor of the implementation contract (`StandardArbERC20`) is only called once when the implementation itself is deployed, not when proxy instances are initialized. Consequently, `isMasterCopy` will always be `true` in the implementation's storage slot. For proxy instances, this storage slot will be initialized to its default value (false) unless explicitly set during initialization. This is the intended behavior for the `Cloneable` pattern, where the implementation serves as the 'master copy' and clones are distinct.
IssueThe `Cloneable` base contract initializes `isMasterCopy` to `true` in its constructor. In a proxy deployment, the constructor of the implementation contract (`StandardArbERC20`) is only called once when the implementation itself is deployed, not when proxy instances are initialized. Consequently, `isMasterCopy` will always be `true` in the implementation's storage slot. For proxy instances, this storage slot will be initialized to its default value (false) unless explicitly set during initialization. This is the intended behavior for the `Cloneable` pattern, where the implementation serves as the 'master copy' and clones are distinct.
FixNo direct action is required as this is the designed behavior of the `Cloneable` pattern. However, it's important for developers and auditors to understand this distinction to avoid misinterpreting the state of `isMasterCopy` when analyzing proxy instances versus the master implementation.
StatusUnresolved

Category Ratings

TechnicalLow9/10

The `StandardArbERC20` contract implements an L2 ERC20 token, leveraging `L2GatewayToken` for core functionality and `Cloneable` for proxy compatibility. The `bridgeInit` function correctly decodes L1 token metadata using `BytesParser` and `BytesLib`, with robust bounds checks in assembly-level operations (7.2 Code Security). A notable design choice is the explicit revert in `decimals()`, `name()`, and `symbol()` if L1 metadata is unavailable, which deviates from typical ERC20 behavior and could impact integrations (7.6 External). The reliance on `L2GatewayToken` for proper initialization handling is a key architectural assumption (7.1 Architecture, 7.3 Access Control).

GovernanceMedium4/10

The contract primarily functions as a standard ERC20 token on Arbitrum, with no complex governance mechanisms or unique economic incentives defined within its scope (7.5 Governance, 7.4 Economic). The design allows for flexible handling of L1 token metadata, enabling the L2 token to adapt to varying L1 ERC20 implementations (7.4 Economic). There are no apparent economic attack vectors or governance vulnerabilities in the provided code, maintaining a simple and predictable economic model.

UpgradesHigh1/10

The `StandardArbERC20` contract is designed as an implementation for a beacon proxy, inheriting from `Cloneable` which correctly distinguishes between master copy and clone instances (7.7 Upgrades). The `bridgeInit` function serves as the initializer, and its single-call execution is assumed to be enforced by the `L2GatewayToken` base contract, ensuring safe initialization for proxy instances (7.7 Upgrades, 7.8 Operations). Storage layout appears straightforward with `ERC20Getters` and `isMasterCopy` occupying distinct slots, minimizing upgrade risks related to storage collisions, assuming `L2GatewayToken` also follows best practices (7.7 Upgrades).

Security Checklist

Contract VerifiedPass
Ownership Renounced?
No Mint FunctionPass
Liquidity LockedFail
Not a ProxyFail

Proxy Upgrade Controls

Proxy TypeBeacon
ImplementationVerified source
Upgrades (30d)0 · stable

Holder Composition

27.5% in wallets14.3% in contracts
Effective Concentration33.3%

Share held by contracts — treasury, vesting, bridge or staking — is discounted against share held by wallets when the score is computed: a contract cannot decide to sell the way an anonymous holder can, though it can still be drained or voted to sell. Effective concentration is the figure the risk score is actually calculated from.

Liquidity Depth

Show 4 more pairsShow less

The 11 remaining pairs hold $7.4K between them and are not listed.

The risk score reads depth across every pair. The volume figure and the volume-to-liquidity ratio elsewhere on this page describe only the pair this audit analysed, so the two are not directly comparable.

LP Distribution

Top-1 Unlocked Holder15.1%
Top-3 Unlocked35.1%

Key Addresses

Deployer
0x3fe3…000f
Unlocked LP Held By
0xbfe6…d71b0xaa56…74620x68d6…126a0x75df…97790xdec1…63760xda7c…da3f0x2832…9f4c0xaf41…a32d0xc044…f44c0x9d3c…b090

No privileged address appears among these holders: the unlocked liquidity sits with independent providers, not with the deployer.

What Raised This Score

  • Ownership status UNKNOWN (owner could not be resolved)
  • Proxy contract (upgradeable — admin can replace logic)
  • Complex proxy pattern (BEACON)
  • Top-10 concentration > 30% (41.8% total → 33.3% effective; 27.5% in EOAs, 14.3% in contracts — moderate)
  • Liquidity not locked, but no owner/deployer address holds LP — market-depth risk, not rug risk
  • 1 Medium finding(s) from audit
  • 2 Low finding(s) from audit

Each factor is an on-chain fact recorded at the time of this analysis. The score is computed from them by a deterministic function, so the same contract returns the same score for anyone who runs the audit. How scores are computed

Related Audits

Arbitrum (ARB)Medium RiskLayerZero (ZRO)Medium RiskChainLink Token (LINK)Medium RiskWrapped liquid staked Ether 2.0 (WSTETH)Medium RiskAave Token (AAVE)Medium RiskRAINMedium Risk

Would You Like a More Detailed Audit of Pendle?

Our AI-powered scanner gives you a deeper, real-time smart contract analysis — free, with every scoring factor shown.

Get Detailed Audit