Omniscia Sova Network Audit
GatedMintEscrow Code Style Findings
GatedMintEscrow Code Style Findings
GME-01C: Inconsistent Off-Chain Related Integration
| Type | Severity | Location |
|---|---|---|
| Standard Conformity | ![]() | GatedMintEscrow.sol:L166, L220 |
Description:
The GatedMintRWA contract implementation will emit the deposit ID for which a share mint has occurred when the GatedMintRWA::batchMintShares function is invoked, however, the GatedMintRWA::mintShares function does not emit it thereby preventing off-chain software from properly correlating all mint operations with their respective deposit IDs.
Example:
140/**141 * @notice Accept a pending deposit142 * @param depositId The deposit ID to accept143 */144function acceptDeposit(bytes32 depositId) external {145 // Only strategy can call this function146 if (msg.sender != strategy) revert Unauthorized();147
148 PendingDeposit storage deposit = pendingDeposits[depositId];149 if (deposit.depositor == address(0)) revert DepositNotFound();150 if (deposit.state != DepositState.PENDING) revert DepositNotPending();151
152 // Mark as accepted153 deposit.state = DepositState.ACCEPTED;154
155 // Update accounting156 totalPendingAssets -= deposit.assetAmount;157 userPendingAssets[deposit.depositor] -= deposit.assetAmount;158
159 // Increment the round number, even for a single deposit160 currentRound++;161
162 // Transfer assets to the strategy163 SafeTransferLib.safeTransfer(asset, strategy, deposit.assetAmount);164
165 // Tell the GatedMintRWA token to mint shares166 GatedMintRWA(token).mintShares(deposit.recipient, deposit.assetAmount);167
168 emit DepositAccepted(depositId, deposit.recipient, deposit.assetAmount);169}170
171/**172 * @notice Accept multiple pending deposits as a batch with equal share accounting173 * @param depositIds Array of deposit IDs to accept174 */175function batchAcceptDeposits(bytes32[] calldata depositIds) external {176 // Only strategy can call this function177 if (msg.sender != strategy) revert Unauthorized();178
179 // Skip empty arrays180 if (depositIds.length == 0) return;181
182 uint256 totalBatchAssets = 0;183
184 address[] memory recipients = new address[](depositIds.length);185 uint256[] memory assetAmounts = new uint256[](depositIds.length);186
187 // First pass: validate all deposits and collect information188 for (uint256 i = 0; i < depositIds.length;) {189 bytes32 depositId = depositIds[i];190 PendingDeposit storage deposit = pendingDeposits[depositId];191
192 // Validate deposit193 if (deposit.depositor == address(0)) revert DepositNotFound();194 if (deposit.state != DepositState.PENDING) revert DepositNotPending();195
196 // Mark as accepted197 deposit.state = DepositState.ACCEPTED;198
199 // Accumulate total assets and store recipient and asset amount200 totalBatchAssets += deposit.assetAmount;201 userPendingAssets[deposit.depositor] -= deposit.assetAmount;202
203 recipients[i] = deposit.recipient;204 assetAmounts[i] = deposit.assetAmount;205
206 unchecked {207 ++i;208 }209 }210
211 totalPendingAssets -= totalBatchAssets;212
213 // Increment the round number214 currentRound++;215
216 // Transfer all assets to the strategy in one transaction217 SafeTransferLib.safeTransfer(asset, strategy, totalBatchAssets);218
219 // Tell the GatedMintRWA token to mint shares for all deposits with equal treatment220 GatedMintRWA(token).batchMintShares(depositIds, recipients, assetAmounts, totalBatchAssets);221
222 emit BatchDepositsAccepted(depositIds, totalBatchAssets);223}Recommendation:
We advise the GatedMintRWA::mintShares function to also accept a deposit ID argument, ensuring consistency in the data emitted by the GatedMintRWA contract.
Alleviation (e4d6885477438291b0d3ca477fab7e088522967b):
The deposit IDs were removed from the batch mint operation instead, ensuring that the two integration points are consistent and thus addressing this exhibit.
GME-02C: Non-Standard Library Usage
| Type | Severity | Location |
|---|---|---|
| Code Style | ![]() | GatedMintEscrow.sol: • I-1: L163 • I-2: L217 • I-3: L245 • I-4: L278 • I-5: L316 |
Description:
In contrast to the rest of the codebase, the GatedMintEscrow contract will invoke the relevant SafeTransferLib functions directly from the library rather than exposing them through the address data type.
Example:
163SafeTransferLib.safeTransfer(asset, strategy, deposit.assetAmount);Recommendation:
We advise the library to be used in a using statement properly and the code to invoke the functions as exposed from the native types, optimizing the code's legibility.
Alleviation (e4d6885477438291b0d3ca477fab7e088522967b):
All instances of SafeTransferLib library usage have been replaced with proper syntax as exposed by the address type directly, addressing this exhibit.
