Yuga Labs engaged Guardian to review the security of their cross-chain NFT mirroring protocol. From the 30th of December to the 6th of January, a team of 5 auditors reviewed the source code in scope.
- Published
- Review window
- December 30, 2024 to January 6, 2025
- Language
- Solidity
- Chains
- Ethereum
- Sector
- NFTs
- 1 Critical
- 2 High
- 12 Medium
- 16 Low
- 0 Informational
Scope
Overview
Yuga Labs engaged Guardian to review the security of their cross-chain NFT mirroring protocol. From the 30th of December to the 6th of January, a team of 5 auditors reviewed the source code in scope.
Issues Detected Throughout the engagement 3 High/Critical issues were uncovered and promptly remediated by the Yuga Labs team. Several issues impacted the fundamental behavior of the protocol, following their remediation Guardian believes the protocol to uphold the functionality described for the NFT Mirror.
Findings 31
-
C-01 Critical Messaging Channel Blocked By Locked Chain Reads DoS Resolved
Description
The
unlockedExclusiveOwnerByRightsfunction reverts for chains that have the NFT locked. However this will cause the read messaging channel for the OApp on that chain to be blocked, preventing all subsequent reads on the chain.This occurs because the DVNs cannot process the read request, producing an error of
UnresolvableCommandwhich prevents the DVN from verifying their response for the nonce.When DVNs have not verified the response for a nonce, validation in the
EndpointV2contract prevents any subsequent messages for the OApp from being processed inlzReceive:https://github.com/LayerZero-Labs/LayerZero-v2/blob/7da76840e41dc593d3c2007ce35b911b1d8
16b4b/packages/layerzero-v2/evm/protocol/contracts/MessagingChannel.sol#L138
This produces a block of read messages on the chain which the invalid read request was triggered from. The delegate of the OApp can call the skip function on the endpoint in order to skip the affected nonce which cannot be verified and resume
lzReceiveprocessing.However with the commonality of reverts in the target
unlockedExclusiveOwnerByRightsthe delegate will not successfully be able to unstuck the read channels, especially on chains where gas costs are high like Ethereum. As a result the ownership syncing feature is completely DoS'd by either malicious or normal use.Recommendation
Instead of reverting in the
unlockedExclusiveOwnerByRightsfunction when the token is locked on the target chain, consider returning a boolean value in addition to the exclusive owner address which indicates whether the chain is locked or not.Resolution
Yuga Labs Team: The issue was resolved in commit 2f73109.
-
H-01 High Ownership Cannot Be Synced To Base Chain DoS Resolved
Description
In the
_updateOwnershipfunction theexecuteCallbackfunction is always invoked on the_shadowaddress, even when the collection is native to the current chain.In the case that the collection is native to the current chain the
_shadowcontract address is the address of the actual NFT collection, which does not implement theexecuteCallbackfunction.As a result receptions of
lzReadrequests on the base collection chain will always revert, thus preventing the syncing of ownership to the base chain.Recommendation
Only perform the
executeCallbackinvocation on the_shadowaddress ifisNativeisfalse.Resolution
Yuga Labs Team: The issue was resolved in commit cc3f87a.
-
H-02 High Reorgs Invalidate The Locked Invariant Reorg Resolved
Description
function
releaseOnEid()transfers token from origin chain owner to theBeacon.solcontract, then delegates the rights to he owner, completing thelzSend() -> lzReceive()request on the destination chain. For completed request theNFTShadowis minted and is now owned by thebeneficiaryon the destination chain. In the case of a reorg on the base chain, the NFT ownership will revert back to the original owner, become unlocked on the origin chain and the destination chain. Example:- Owner 0xA bridges BAYC ID:11 to polygon
Chain: ETH NFT: BAYC Owner: Beacon Delegate: 0xA Block: 1000
Chain: Polygon NFT: BAYC Shadow Owner: 0xA Block: 100000
- 0xA transfers to 0xB on polygon
Chain: ETH NFT: BAYC Owner: Beacon Block: 1000
Chain: Polygon NFT: BAYC Shadow Owner: 0xB Block: 100001
- 0xB bridges back to eth mainnet. Note this will release the token to beneficiary from mainnet
Beacon contract.
Chain: ETH NFT: BAYC Owner: 0xB Block: 1001
Chain: Polygon NFT: BAYC Shadow Owner: 0xB Block: 100003
- A 3 block Reorg occurs on polygon.
Chain: ETH NFT: BAYC Owner: 0xB Block: 1002
Chain: Polygon NFT: BAYC Shadow Owner: 0xA Block: 100000
A now holds an irredeemable NFT on a side chain, whilst 0xB holds the mainnet native token outside of the constraints of the protocol.
Recommendation
Ensure probabilistic finality on origin chain prior to finalization of the
lzSendforreleaseOnEidandtriggerOwnershipUpdateby configuring an appropriate confirmations threshold depending on the chains involved in each bridging pathway.Resolution
Yuga Labs Team: The issue was resolved in commit e3616ec.
-
M-01 Medium ShadowFactory Cannot Deploy NFTs DoS Resolved
Description
ShadowFactoryis used to create shadow NFTs. It implementsOwnableand hasonlyOwnerondeployAndRegisterto prevent anyone but the owner from using this function.However, the issue is that this owner is never initialized, meaning that after deployment, the owner would be address 0 and no one would be able to call
deployAndRegister.Recommendation
Add
_initializeOwnerinside the constructor, or add another function to call it and initialize it. In the second scenario,_guardInitializeOwneralso needs to be called.Resolution
Yuga Labs Team: The issue was resolved in commit 33ee610.
-
M-02 Medium There Is No Function For triggerMetadataRead DoS Resolved
Description
MetadataReadRendererhas a function to update the metadata for NFTs on different chains. Where the main function -triggerMetadataReadmust be called by theNFTShadowcontract to invoke the change, as it gets thebaseCollectionAddressfromIBeacon(beacon).shadowToBase(msg.sender).Meaning that
msg.sendermust beNFTShadow. However theNFTShadowlacks a method which invokestriggerMetadataRead.Recommendation
Add a function inside
NFTShadowthat can invoketriggerMetadataRead, make sure it hasonlyOwnerResolution
Yuga Labs Team: The issue was resolved in commit ea4a45b.
-
M-03 Medium Release Stuck On Zero Address Beneficiary DoS Resolved
Description
In the
releaseOnEidfunction there is no validation that the beneficiary address is not the zero address. Therefore a layerzero message can be sent with the beneficiary set as the zero address.The execution of this message will perpetually fail as all attempts to execute the
executeMessagefunction will revert as the Solady ERC721 library does not support mints or transfers to the zero address.Therefore the Shadow NFTs and base collection NFT will remain locked on all chains with this message stuck in perpetuity.
Recommendation
In the
releaseOnEidfunction validate that the beneficiary address is not the zero address.Resolution
Yuga Labs Team: The issue was resolved in commit 1b80e4a.
-
M-04 Medium Insufficient Gas DoS Resolved
Description
Inside
releaseOnEid getSendOptionsis used to calculate the amount of gas needed for the_lzReceivecall. However due to rigid nature of the math and vast possible routes that the call could go, it would often result in an revert.Not only that but the math currently lacks the
GAS_RESERVE, which is taken before that call is executed, resulting in the total gas allocated to be30k + (20k * NFT count)Lets look into an example call:Total gas for 5 NFTs gets to be - 80k - 50k + 20k * 5 -> 130k 1. The call goes as usual
executeMessage->_executeMessage, but then we enter the else for_updateLockState2._updateLockStatewould in tern perform a couple of checks and call_clearDelegationsAndReleaseTokensif we are on the native chain 3._clearDelegationsAndReleaseTokenswould executetransferFromfor every NFT 4. This is followed by_clearDelegationswhich would callDELEGATE_REGISTRY.delegateERC721again for every NFTBoth
transferFromanddelegateERC721access storage, be it warm or cold, costing huge amounts of gas.Recommendation
Calculate the gas properly and make sure it covers all routes, even the most expensive one
Resolution
Yuga Labs Team: The issue was resolved in commit 3c4b869.
-
M-05 Medium Enforced Options Not Applied On releaseOnEid Configuration Resolved
Description
In the
releaseOnEidfunction theoptionsprovided to the_lzSendcall are not combined with the apps enforced options using thecombineOptionsfunction. As a result the enforced options for the send message type are not applied.Recommendation
Apply
combineOptionsto the user provided options in thereleaseOnEidfunction.Resolution
Yuga Labs Team: The issue was resolved in commit 41d4919.
-
M-06 Medium Different Gas Limits May Lead To DOS DoS Resolved
Description
Different chains have different gas limits. Due to the fact that a user can send as many tokens as they have using
releaseOnEid, it may be possible that the tx has enough gas limit on the source chain, but not enough gas Limit to execute on destination chain.For example ETH Mainnet gas limit is 30M, however Avalanche C-chain is 15M, half the gas limit. This can lead to permanently stuck NFT's when the execution of the
_lzReceivewill exceed the max block gas limit and any retry attempts will fail.This issue may be more prevalent on chains with an even lower gas limit such as some chains have as low as 8M gas limit. This small of a gas limit can be reached with about 57 tokens being sent.
Recommendation
It is recommended to add a limit of 10-20 on the amount of NFTs that can be bridged in a single tx.
Resolution
Yuga Labs Team: The issue was resolved in commit 152ab98.
-
M-07 Medium Callback Gas Is Never Specified DoS Resolved
Description
The
_updateOwnershipfunction concludes with a callback to the shadow NFT via_shadow.executeCallback(guid);. While this callback is included in the gas cost, it adds only a negligible increase of 20k gas:uint128 baseGasCost = withCallback _BASE_OWNERSHIP_UPDATE_COST_WITH_CALLBACK // 100k _BASE_OWNERSHIP_UPDATE_COST; // 80kThis small gas amount is insufficient to cover any callback, especially a more complex one. Additionally, the callback has no predefined gas limit, which means it could unintentionally consume more gas than expected, causing the function to revert with an OOG error.
Recommendation
Consider passing the gas limit as a parameter and enforcing it during the callback execution.
Resolution
Yuga Labs Team: The issue was resolved in commit a707fbd.
-
M-08 Medium releaseOnEid In NFTShadow May Lead To DOS DoS Resolved
Description
The releaseOnEid function in
NFTShadowassumes that we are only releasing to non native chains. This can be observed by the send calculations belowfunction getSendOptions(uint256[] calldata tokenIds) public pure returns (bytes memory) {uint128 totalGasRequired = _BASE_OWNERSHIP_UPDATE_COST + (_INCREMENTAL_OWNERSHIP_UPDATE_COST * uint128(tokenIds.length)); returnOptionsBuilder.newOptions().addExecutorLzReceiveOption(totalGasRequired, 0);}The function assumes that we are always doing an ownership update but does not account for the fact that if we release to chain that includes the native collection that we will instead use delegations which are more expensive.
This may result in a DOS due to not enough gas being sent to the destination chain to execute the message. However the tx can be retried after failure.
Recommendation
If the Eid that we are releasing on includes that native collection, calculate the send costs to include all the delegations cost.
After talks with dev this was the potential solution: maybe worth removing quotes and options generation from the Shadow and just using the Beacon
Resolution
Yuga Labs Team: The issue was resolved in commit 3c4b869.
-
M-09 Medium Same Address Controlled By Multiple Parties Logical Error Resolved
Description
The
releaseOnEidfunction transfers the delegation rights to the beneficiary address on the origin chain. This means that the owner of the beneficiary address must be the same on both the origin and destination chain.If this is not the case one party is able to steal potential delegated airdrops, or the other party is unable to claim.
In the case of multisig accounts across different chains, it is viable that contract addresses are not the same across different changes despite trading across EVM compatible chains.
Recommendation
Delegated rights should not be granted from the Beacon contract immediately upon calling the
releaseOnEidfunction.Instead the global delegation rights should only be granted on the origin chain after waiting for the
releaseOnEidlifecycle to succeed, and then syncing the ownership state to the origin chain with thetriggerOwnershipUpdatefunction.This way for those users who happen to control the smart contract at the beneficiary address on the destination chain, but not on the origin chain, they can preemptively delegate Shadow token rights on the destination chain to an address that they do control across all chains, preventing the inaccurate delegation on the origin chain.
Resolution
Yuga Labs Team: The issue was resolved in commit 49a83a7.
-
M-10 Medium Read Response Censoring DoS Resolved
Description
Because the
_lzReceivefunction invokes theexecuteMessagefunction in a try/catch and specifically leaves behind 50,000 gas units to complete the outer function execution it is possible for a malicious actor to intentionally censor an lzRead response by executing thelzReceivefunction with a minimal amount of gas.This way the inner
executeMessagefunction is not forwarded enough gas to complete execution and fails. As a result the message is added to thepayloadHashesmapping in theBeaconcontract. Both normal layerzero messages and layerzero read responses can be censored this way.But specifically layerzero read requests are not allowed to be retried in the Beacon contract so they are effectively censored.
To pull off this attack a malicious actor can simply observe that the last required DVN has submitted their verification and then call the
commitVerificationandlzReceivefunctions on the receive library andEndpointV2contracts accordingly.Recommendation
Consider adding validation at the beginning of the
_lzReceivefunction which requires that the transaction has enough gas to complete the receive logic, ideally this validation will also account for any callback which might occur.Resolution
Yuga Labs Team: The issue was resolved in commit dd5130c.
-
M-11 Medium Insufficient Return Data Length Options Gaming Resolved
Description
In the
triggerMetadataReadandtriggerOwnershipUpdatefunctions there is no enforcement of the expectedreturndatalength for the read request.The expected
returndatalength must be specified so that the executor can be adequately compensated for executing thelzReceivefunction once the message has been verified.If users call the
triggerMetadataReadandtriggerOwnershipUpdatefunctions with extra options including the correct return data size then the executor will not execute thelzReceivefunction upon DVN verification and users will have to manually execute the message through the endpoint.Furthermore the return data size cannot be enforced at the enforced options level since it varies based upon the query being made.
Recommendation
For the Beacon contract Implement the use of the
getReadOptionsfunction at the Beacon contract level instead of including this in theNFTShadowcontract so that all read requests are properly configured, not just those coming through theNFTShadowcontract.For the
MetaDataReadRendereronly expose thetriggerMetadataReadfunction through theNFTShadowcollection contract and enforce that sufficient expected return data is specified in the options for each collection's respectivetokenUrilength.Resolution
Yuga Labs Team: The issue was resolved in commit 9169911.
-
M-12 Medium Burned Tokens Minted Arbitrarily Access Control Resolved
Description
The
NFTShadowcontract makes incorrect assumptions about access control on minting. On an unlocked chain, after a token is burned, it remains unlocked. While unlocked it is possible for any user to to remint(),updateOwnership()and steal delegations on other chains.In the comments "Only the Beacon contract can mint tokens, enforced by
_beforeTokenTransfer". However the condition is actually as follows:if (
msg.sender = BEACON_CONTRACT_ADDRESS) if (tokenIsLocked(tokenId)) revertCallerNotBeacon(); // if not beacon and locked} // if you are beacon, or unlockedRecommendation
If the
msg.senderis not theBEACON_CONTRACT_ADDRESSand the token isunlocked, we will be able to mint to any recipient. After minting, we canupdateOwnershipon any other chain to steal delegation rights.Resolution
Yuga Labs Team: The issue was resolved in commit cb807e8.
-
L-01 Low Lacking Read Channel Validation Validation Resolved
Description
In the Beacon contract constructor the
readChannelvalue is assigned without any validation performed on it.Recommendation
Consider validating that the
readChannelvalue is above the_READ_CHANNEL_EID_THRESHOLDas expected.Resolution
Yuga Labs Team: The issue was resolved in commit 188f4ac.
-
L-02 Low Caller Is Always The Refund Receiver Compatibility Resolved
Description
In the
_triggerOwnershipUpdatefunction themsg.senderis always assigned as the refund receiver for the beacontriggerOwnershipUpdateinvocation.It is likely that smart contracts will interact with the
NFTShadowcontract to make use of their callbacks, however if these contracts do not implement a receive function for the native refund then they will not be compatible.Recommendation
Consider either adding a
refundReceiverparameter to theNFTShadowfunctions or documenting this clearly for integrators with theNFTShadowcontract.Resolution
Yuga Labs Team: The issue was resolved in commit 231cd07.
-
L-03 Low Multiple Delegation Rights Risk Gaming Acknowledged
Description
If a peer is assigned for the base chain with the
setPeerfunction then an exploit becomes possible where multiple users obtain global rights for the same token id from the Beacon contract.Consider the following scenario:
- address A holds bayc 12
- address A gives shadow delegation rights to address B on ETH
- address B is now considered the
exclusiveOwnerByRights - address A calls
triggerOwnershipUpdateon ETH, using ETH as the target EID to read from (this is
possible if a peer is assigned for the ETH eid on ETH)
- address B is reported as the owner and is given the global rights from the Beacon contract
- address A calls
releaseOnEidon the Beacon contract on ETH and receives global rights from the
beacon contract as well
Now two addresses have global rights issued from the Beacon contract for token 12, this can be used to steal airdrops or vests that belong to global claiming rights for users which unknowingly receive NFTs which have a second address with allocated global rights from the Beacon.
Recommendation
This exploit is not possible if the peer for the native EID is not assigned on the native chain. This is not a typical configuration that would be expected, however this finding simply serves as an additional warning against such a configuration as it enables the attack described.
Resolution
Yuga Labs Team: Acknowledged.
-
L-04 Low Collection Misconfiguration Leads To DoS Validation Resolved
Description
In the
registerCollectionfunction there is no validation preventing a configuration of thebaseCollectionChainIdto 0.However this mis-configuration will lead to a complete DoS of the OAPP since the
_collectionIsNativefunction validates that thebaseCollectionChainIdis nonzero.Recommendation
Consider validating that the
baseCollectionChainIdis nonzero in theregisterCollectionfunction to avoid any potential mis-configurations which may halt in-flight messages.Resolution
Yuga Labs Team: The issue was resolved in commit 152ab98.
-
L-05 Low safeCall Does Not Validate Contract Existence Warning Acknowledged
Description
The
excessivelySafeCall.excessivelySafeCall()does not validate theto.code.length > 0. As a result EOA recipients and undeployed contract addresses will not execute required function call, but return success on low levelcall()operation.Recommendation
Check
to.code.length > 0before call is complete, or alternatively check that the returnDataSize is non zero.Resolution
Yuga Labs Team: Acknowledged.
-
L-06 Low baseCollectionAddress Clashing Documentation Acknowledged
Description
The
registerCollectionfunction assumes that thebaseCollectionAddressis unique to every NFT collection, however since this is an omnichain application it is possible for multiple NFT collections to correspond to the samebaseCollectionAddresson their respective chains.Recommendation
Be aware that collections which clash like this are not supported by the Beacon system.
Resolution
Yuga Labs Team: Acknowledged.
-
L-07 Low Unnecessary Reason Variable Optimization Resolved
Description
In the
_lzReceivefunction theexecuteMessageis invoked withsafeCallwhich is configured to copy 0 bytes of the return data into memory.However the
bytes memory reasonvalue is still used to emit in the revert reason in theMessageCachedevent. This reason will always be empty because 0 bytes are specified as the_maxCopyvalue.Notice that it is important that the
_maxCopyvalue is small or 0 because without limiting the return data size then a malicious callback could revert with excessively large revert data to produce OOG errors in the_lzReceivefunction and enable the retrying of read requests.Recommendation
Either remove the
reasonstring from theMessageCachedevent as it is currently always empty or allocate a small amount of return data bytes to be able to read the revert reason in thesafeCallinvocation.Resolution
Yuga Labs Team: The issue was resolved in commit cd47b90.
-
L-08 Low Empty Registry Call Revert DoS Resolved
Description
In the
_updateDelegationsfunction themulticallDataarray may be sparsely populated in the case where thestaleOwner = address(0)andIERC721(collectionAddress).ownerOf(tokenId) =address(this)conditions are not satisfied.This will lead to a revert when using the registry multicall since the
DelegateRegistrycontract does not implement a fallback function to receive empty data calls.The only case where these conditions will be met is in a race condition where a
releaseOnEidmessage is executed before the outdated read result is processed. In this case the correct behavior is to revert since this is an unexpected state.Recommendation
Consider explicitly reverting when the
staleOwner = address(0)andIERC721(collectionAddress).ownerOf(tokenId) = address(this)conditions are not satisfied.Resolution
Yuga Labs Team: The issue was resolved in commit fd89120.
-
L-09 Low Missing ERC 5192 Support Composability Resolved
Description
The
NFTShadowcontract aims to support theERC5192interface standard for soulbound tokens, however this is not reflected in thesupportsInterfacefunction.Furthermore, the ERC5192 standard includes a
locked(uint256 tokenId)function. However the NFTShadow contract instead implements atokenIsLocked(uint256 tokenId)which is not congruent with the ERC5192 standard.Recommendation
Update the
supportsInterfacefunction to return true if the queriedinterfaceIdis 0xb45a3c0e as indicated by the ERC standard: https://eips.ethereum.org/EIPS/eip-5192. Update thetokenIsLocked(uint256 tokenId)function to be namedlocked(uint256 tokenId).Resolution
Yuga Labs Team: The issue was resolved in commit 0c87009.
-
L-10 Low Smart Contract Wallets Warning Warning Resolved
Description
Users should be careful to ensure that their highest priority combination of ownership/delegate registry rights as determined by the
ExclusiveDelegateResolveris never granted to an address that they don't control across all chains supported by the Beacon system.In this case the alternative owner of the same address on any chain which the user does not control it can trigger an ownership update to sync ownership to themselves on that chain.
The malicious actor cannot steal the NFT as the NFT is locked on this chain, but they will be able to claim airdrops and allocations which are attributed to this NFT on the respective chain.
Recommendation
Be sure to document this for users and integrators.
Resolution
Yuga Labs Team: The issue was resolved in commit d44e445.
-
L-11 Low Locked ShadowNFT Ownership Warning Warning Resolved
Description
Because the ownership of
ShadowNFTs on locked chains is based upon the result of the resolver'sexclusiveOwnerByRightsfunction, the tokens on these chains can be unexpectedly transferred away from the current owning address.For example:
- Shadow NFT 12 is unlocked on APE and owned by 0xA
- Shadow NFT 12 is locked on Arbitrum and owned by 0xA
- 0xA delegates with shadow rights for NFT 12 on APE to 0xB
- 0xB triggers an ownership update for Arbitrum
- 0xB now controls NFT 12 on Arbitrum
- 0xA revokes the delegation to 0xB
- 0xA triggers an ownership update for Arbitrum
- NFT 12 is transferred away from 0xB back to 0xA
This may be unexpected for 0xB since it had not approved any other address.
Recommendation
Potential integrations and users have to be warned that locked
ShadowNFTownership cannot be trusted.Resolution
Yuga Labs Team: The issue was resolved in commit d44e445.
-
L-12 Low Lacking Read Response Staleness Checks Validation Resolved
Description
It is possible that an executor or DVN verification is delayed longer than expected, in which case the result of a read operation may be recorded on the triggering chain much later than expected.
In these scenarios if the stale read result is allowed then a potential outdated mis-accounting of the owner assigned can occur.
Recommendation
Consider adding validation such that read requests cannot be executed greater than some amount of time after their initiation to avoid stale results.
Resolution
Yuga Labs Team: The issue was resolved in commit bdffafe.
-
L-13 Low Forks Will Enable 2 Shadow NFTs To Be Unlocked Validation Resolved
Description
If a TX fails on the destination chain it gets stored inside
payloadHashes. However there is no protection against hard forks, and in the case of one, the message would be in the storage inside the contract on both chains (main and fork).This will allow the user to
retryFailedMessageon both chains and possibly create 2 shadow NFTs. Given that only 1 shadow or native token must be unlocked at once, this breaks a core invariant which is that only 1 token should be unlocked at one time across all chains.Recommendation
Include
block.chainIdinside the hash making and it's verification.Resolution
Yuga Labs Team: The issue was resolved in commit 95b9d6e.
-
L-14 Low CryptoPunks Not Supported Logical Error Resolved
Description
In order to
triggerOwnershipUpdateand mint a shadow theownerOffunction must successfully resolve withinunlockedExclusiveOwnerByRights.However,
CryptoPunksdo not comply to ERC-721 standard and do not contain many crucial functions for the Shadows to operate properly such as theownerOffunction. Consequently,CryptoPunksare not currently compatible with Shadows.Recommendation
If support for this collection is not necessary, do not register the
CryptoPunkscollection and clearly document this. Otherwise, addCryptoPunksownership checks and transfer functions within the Beacon.Resolution
Yuga Labs Team: The issue was resolved in commit b0b8a5e.
-
L-15 Low Incorrect Initialize Comment Logical Error Resolved
Description
The constructor of the
MetadataReadRendererincorrectly states that it “Initializes the Beacon contract” which is just a copy of the Beacon’s documentation.Recommendation
Correct the NatSpec for the constructor of the
MetadataReadRenderer.Resolution
Yuga Labs Team: The issue was resolved in commit 3d8c6bc.
-
L-16 Low Missing Validation On Triggers Validation Resolved
Description
Functions
triggerOwnershipUpdateandtriggerMetadataReaddo not validate that the arrays passed are non-empty. If empty parameters are passed, then the function could early return to prevent building a command for a message that will ultimately fail.Recommendation
Validate that the array parameters passed are non-empty.
Resolution
Yuga Labs Team: The issue was resolved in commit 0aae7e9.
No findings match.
More from Yuga Labs
Put your code through the same review.
This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.
