Skip to main content
aPrioriaPriori ~ LockedAprMON - November 24, 2025

aPriori ~ LockedAprMON

Smart Contract Security Assessment

November 21, 2025

aPriori

SUMMARY


ABSTRACT

Dedaub was commissioned to perform a security audit of LockedAprMON, a contract belonging to the aPriori protocol.


BACKGROUND

LockedAprMON is an ERC4626-compliant tokenized vault in which deposited assets are locked for a period 45 days, preventing withdrawals/redeemals until the lock period has elapsed.

The contract restricts several of the usual features of ERC4626 vaults:

  • Direct transfer/transferFrom operations on shares between users are not allowed. However, it’s possible for a user to approve another one as a spender of their shares. This enables withdraw/redeem operations on behalf of a different user if the appropriate approval has been granted and funds become unlocked.
  • Deposits and mints can only be made by and to the caller of the contract; this is done to prevent griefing by other users, since deposit and mint operations reset the lock period.

SETTING & CAVEATS

This audit report mainly covers the contracts of the at-the-time private https://github.com/apriori-network repository of the aPriori Protocol at commit 3fe03138e248d01be38f9cd64fdd6bde31f49bdb.

Audit Start Date: November 21, 2025

Report Submission Date: November 24, 2025

2 auditors worked on the following contracts:

src/

└── LockedAprMON.py

The audit’s main target is security threats, i.e., what the community understanding would likely call "hacking", rather than the regular use of the protocol. Functional correctness (i.e. issues in "regular use") is a secondary consideration. Typically it can only be covered if we are provided with unambiguous (i.e. full-detail) specifications of what is the expected, correct behavior. In terms of functional correctness, we often trusted the code’s calculations and interactions, in the absence of any other specification. Functional correctness relative to low-level calculations (including units, scaling and quantities returned from external protocols) is generally most effectively done through thorough testing rather than human auditing.


PROTOCOL-LEVEL CONSIDERATIONS

P1

Anti-share-inflation mechanism can be bypassed

PROTOCOL-LEVEL-CONSIDERATION
info

Serving as an additional defense mechanism against the known ERC4626 share inflation attack, the contract uses a designated number of token units of the underlying asset provided by the owner in order to mint an initial number of shares:

LockedAprMON::initialize:84-85
    ...
uint256 shares = previewDeposit(_initialDeposit);
_deposit(_initialOwner, _initialOwner, _initialDeposit, shares);
}

However, it should be noted that it’s possible for someone to front-run the deployment and initialization of the contract, donate an appropriately large amount and initiate the share-inflation attack with the owner as the first victim. The donation can occur as a direct transfer operation to the predicted deployed address, making totalAssets()’s value sufficiently large to force the calculations of owner-minted shares to be 0:

LockedAprMON::initialize:84-85
function _convertToShares(uint256 assets, Math.Rounding rounding) ... {
return assets.mulDiv(totalSupply() + 10 ** _decimalsOffset(), totalAssets() + 1, rounding);
}


This alone does not yield any profits to the attacker, the donation goes to the vault directly. The default virtual decimal offset of the OpenZeppepelin implementation ensures that typically attacker donations are not profitable and can only be used to grief other users.

This means that even if this attack scenario takes place, the attacker will be able to grief users without walking away with a profit. We therefore not consider this a likely thing to occur in practice but note it for the sake of completeness.



VULNERABILITIES & FUNCTIONAL ISSUES

This section details issues affecting the functionality of the contract. Dedaub generally categorizes issues according to the following severities, but may also take other considerations into account such as impact or difficulty in exploitation:

CATEGORY
DESCRIPTION
CRITICAL
Can be profitably exploited by any knowledgeable third-party attacker to drain a portion of the system’s or users’ funds OR the contract does not function as intended and severe loss of funds may result.
HIGH
Third-party attackers or faulty functionality may block the system or cause the system or users to lose funds. Important system invariants can be violated.
MEDIUM
Examples:
  • User or system funds can be lost when third-party systems misbehave
  • DoS, under specific conditions
  • Part of the functionality becomes unusable due to a programming error
LOW
Examples:
  • Breaking important system invariants but without apparent consequences
  • Buggy functionality for trusted users where a workaround exists
  • Security issues which may manifest when the system evolves

Issue resolution includes “dismissed” or “acknowledged” but no action taken, by the client, or “resolved”, per the auditors.


CRITICAL SEVERITY

[No critical severity issues]


HIGH SEVERITY

[No critical severity issues]


MEDIUM SEVERITY

[No medium severity issues]


LOW SEVERITY

[No low severity issues]


CENTRALIZATION ISSUES

It is often desirable for DeFi protocols to assume no trust in a central authority, including the protocol’s owner. Even if the owner is reputable, users are more likely to engage with a protocol that guarantees no catastrophic failure even in the case the owner gets hacked/compromised. We list issues of this kind below. (These issues should be considered in the context of usage/deployment, as they are not uncommon. Several high-profile, high-value protocols have significant centralization threats.)

N1

Some parties are considered trusted

CENTRALIZATION
acknowledged

The owner of the contract is permissioned to initiate any upgrades of the implementation of the contract, giving them full control of the contract’s logic:

ILockedAprMON::_authorizeUpgrade:170
...
/**
* @dev UUPS authorize upgrade restricted to owner
*/
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
...


Additionally, as noted in P1, a number of vault shares is minted to the owner of the vault in order to enhance protection against the known ERC4626 share inflation attack.

It should be noted that with the inclusion of this protection mechanism there exists an implicit assumption that the associated shares are not redeemed by the owner when the vault is empty. Otherwise, the extra protection is disabled.



OTHER / ADVISORY ISSUES

This section details issues that are not thought to directly affect the functionality of the project, but we recommend considering them.

A1

Misleading event parameter use

ADVISORY
resolved

Resolution:

Fixed in PR #14.


The ILockedAprMON interface defines the LockPeriodUpdated even as follows:

ILockedAprMON:27
...
/**
* @dev Emitted when the lock period is updated.
*/
event LockPeriodUpdated(address user, uint32 unlockTime);
...

The parameter unlockTime suggests that the value represents the updated unlock time. However, in the code locations the event is emitted, the parameter corresponds to the timestamp of the user’s last deposit operation:

LockedAprMON:116
...
function deposit(uint256 assets, address receiver)
...
_lastDeposit[receiver] = SafeCast.toUint32(block.timestamp);
emit ILockedAprMON.LockPeriodUpdated(receiver, _lastDeposit[receiver]);
...
function mint(uint256 shares, address receiver)
...
_lastDeposit[receiver] = SafeCast.toUint32(block.timestamp);
emit ILockedAprMON.LockPeriodUpdated(receiver, _lastDeposit[receiver]);
...

A2

Misleading comment

ADVISORY
resolved

Resolved

Fixed in PR #15.

The following snippet suggests that ERC20 transfers are possible for shares (while funds are not locked):

\LockedAprMON:25
...
* - While funds are locked, users cannot transfer their shares to another address. This prevents circumvention of the lock mechanism via transfers.
...

However, transferring shares is permanently disallowed (not just when funds are locked):

LockedAprMON::_update:187-193
function _update(address from, address to, uint256 amount) internal virtual override {
// only allow minting and burning for deposit and withdraw purposes
if (from != address(0) && to != address(0))
revert ILockedAprMON.TransferNotAllowed();
}
super._update(from, to, amount);
}

A3

Owner shares do not carry over when ownership changes

ADVISORY
info

The initial owner mints shares through the deposit of some non-zero amount of assets upon deployment, intended not to be redeemed.

While the shares remain owned by the initial owner throughout the lifetime of the contract, the owner of the contract can change. The protocol team should be aware that in the event of ownership change, there exist implicit trust assumptions for the previous owner - as noted in N1.

A4

Compiler bugs

ADVISORY
info

The code is compilable with a floating pragma, supporting all Solidity versions ranging from 0.8.24 up to (but not including) version 0.9.0. We recommend a fixed compiler version for deployment, i.e., no floating pragmas, to remove all ambiguity.

Version 0.8.24, in particular, has no known bugs.



DISCLAIMER

The audited contracts have been analyzed using automated techniques and extensive human inspection in accordance with state-of-the-art practices as of the date of this report. The audit makes no statements or warranties on the security of the code. On its own, it cannot be considered a sufficient assessment of the correctness of the contract. While we have conducted an analysis to the best of our ability, it is our recommendation for high-value contracts to commission several independent audits, a public bug bounty program, as well as continuous security auditing and monitoring through Dedaub Security Suite.


ABOUT DEDAUB

Dedaub offers significant security expertise combined with cutting-edge program analysis technology to secure some of the most prominent protocols in DeFi. The founders, as well as many of Dedaub's auditors, have a strong academic research background together with a real-world hacker mentality to secure code. Protocol blockchain developers hire us for our foundational analysis tools and deep expertise in program analysis, reverse engineering, DeFi exploits, cryptography and financial mathematics.