Apyx – ApxUSD, ApyUSD, Bridged Token

QuantstampFiles named in the report

Quantstamp reviewed ApxUSD (Apyx – ApxUSD, ApyUSD, Bridged Token) on 30 Apr 2026: 4 findings, 0 critical; 2 acknowledged, 2 open.

No open critical findings
Open the reportOpen ApxUSD’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings4

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High000
Medium000
Low220
LowDeposits Accepted Before `unlockToken` Is Configured, Temporarily Blocking WithdrawalsAcknowledged

`ApyUSD.initialize()` does not accept or set an `unlockToken` address. As documented in the NatSpec for `initialize()` (`@dev UnlockToken must be set after deployment using setUnlockToken()`), this is a post-deployment configuration step performed by `ADMIN_ROLE`. Until `setUnlockToken()` is called, every withdraw and redeem call reverts unconditionally: ```solidity // src/ApyUSD.sol:290-293 // Require unlockToken is set if (address($.unlockToken) == address(0)) { revert AddressNotSet("unlockToken"); } ``` The `vesting`, `unlockingFee`, and `feeWallet` parameters share this deferred-configuration pattern, but only the absence of `unlockToken` makes the vault non-functional for holders. The others have safe zero-value defaults (no yield accrual, no fee, fee retained in vault, respectively). This creates a window between deployment and `setUnlockToken` being called during which `deposit()` and `mint()` succeed, but `withdraw()` and `redeem()` are completely blocked.

LowVesting Contract Rotation Potentially Strands Unvested Yield and Causes an Immediate Share Price DropAcknowledged

`ApyUSD.setVesting()` replaces the stored vesting contract by overwriting `$.vesting` directly, with no prior claim of accrued yield from the outgoing contract: ```solidity // src/ApyUSD.sol:387-395 function setVesting(IVesting newVesting) external restricted { ApyUSDStorage storage $ = _getApyUSDStorage(); IVesting oldVesting = $.vesting; // Update Vesting reference $.vesting = newVesting; emit VestingUpdated(address(oldVesting), address(newVesting)); } ``` `LinearVestV0.pullVestedYield()` is gated by `onlyBeneficiary`, which checks `msg.sender == beneficiary`. The beneficiary is the `ApyUSD` vault address, set immutably at construction time. Once `$.vesting` is overwritten, the vault's `_withdraw` and `totalAssets` paths reference only the new contract. There is no protocol-level mechanism that will ever call `pullVestedYield()` on the old contract again, leaving its remaining balance permanently stranded under normal operation. The impact is two-fold: 1. **Immediate share price discontinuity:** `totalAssets()` includes `$.vesting.vestedAmount()` as phantom yield, tokens physically held by the vesting contract but logically attributed to the vault's share price: ```solidity // src/ApyUSD.sol:200-211 function totalAssets() public view override returns (uint256) { ... if (address($.vesting) != address(0)) { vestedYield = $.vesting.vestedAmount(); } return vaultBalance + vestedYield; } ``` At the moment `setVesting` executes, `$.vesting` changes atomically. If the outgoing contract held `V` in `vestedAmount()`, `totalAssets()` drops by `V` in the same transaction. Because `totalSupply()` is unchanged, each outstanding share is immediately redeemable for fewer assets. A loss of value for all current holders proportional to `V / totalSupply`. 2. **Stranded unvested yield:** Beyond the already-vested portion, any yield still in the unvested tranche (`LinearVestV0.unvestedAmount()`) is locked in the old contract indefinitely. There is no admin function on `ApyUSD` to trigger `pullVestedYield` on an arbitrary address, and `LinearVestV0.pullVestedYield` cannot be called by anyone other than the registered beneficiary. The tokens remain in the old contract, inaccessible through any normal protocol flow.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (5)

  • src/ApyUSD.sol
  • src/bridge/IBridgedToken.sol
  • src/ApxUSD.sol
  • src/bridge/BridgedApyxToken.sol
  • src/bridge/BridgeRoles.sol

Part of ApxUSD’s security record

ApxUSD
Audits2 audits by 1 firmLast audit Apr 2026, by Quantstamp.
Critical findingsNo open critical findingsAcross 2 reports.
Open ApxUSD’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us