Animecoin engaged Guardian to review the security of its review of their cross-chain token claimer. From the 14th of January to the 16th of January, a team of 3 auditors reviewed the source code in scope.
- Published
- Review window
- January 14 to 16, 2025
- Language
- Solidity
- Chains
- Arbitrum
- Sector
- Token launches
- 0 Critical
- 0 High
- 0 Medium
- 12 Low
- 0 Informational
Scope
Overview
Animecoin engaged Guardian to review the security of its review of their cross-chain token claimer. From the 14th of January to the 16th of January, a team of 3 auditors reviewed the source code in scope.
Findings 12
-
L-01 Low Unused Import Best Practices Resolved
Description
The
EVMCallComputeV1struct is imported in theAnimeClaimerhowever it is unused.Recommendation
Consider removing the
EVMCallComputeV1import.Resolution
Animecoin Team: Resolved.
-
L-02 Low Unused Errors Optimization Resolved
Description
The
InvalidClaimerTypeandClaimIsZeroAddresserrors in theAnimeClaimercontract are unused.Recommendation
Remove the
InvalidClaimerTypeandClaimIsZeroAddresserrors.Resolution
Animecoin Team: Resolved.
-
L-03 Low isForNFT Optimization Optimization Acknowledged
Description
In the
_validateRequestClaimfunction theisForNFTvariable is declared outside of the UUID case, however it is only used inside of the UUID case. Therefore an optimization for non-UUID cases is to move theisForNFTdeclaration inside of the UUID case.Recommendation
Move the
isForNFTinside of the UUID case in the_validateRequestClaimfunction.Resolution
Animecoin Team: Acknowledged.
-
L-04 Low Unnecessary Cast Optimization Acknowledged
Description
In the
_claimBatchfunction thes.withdrawnvariable is cast to auint256type when calculating thewithdrawAmount. However thes.withdrawnvariable is already auint256type and therefore does not need to be cast.Recommendation
Remove the unnecessary cast for the
s.withdrawnvariable.Resolution
Animecoin Team: Acknowledged.
-
L-05 Low Compromised Signer Griefing Attack Griefing Acknowledged
Description
In the
_validateRequestClaimfor UUID related claims theuuidToPackedNftIDandnftToUUIDmappings are written to and validate that the corresponding UUID totokenIdpairing is the only one used for either the UUID ortokenIdin future claims.This is to prevent a compromised UUID signer from being able to steal more than the amount of the unrevealed elemental’s vests. However now that the
uuidToPackedNftIDmapping has been introduced a compromised signer gains another potentially harmful attack.Consider the following scenario:
- Normal Azuki with ID 1 has the highest allocation out of all NFTs of 50 Million $ANIME tokens
- Alice does not own the Azuki with ID 1
- Alice gains access to the UUID signer
- Alice forges a signature that shows that Azuki with ID 1 corresponds to a UUID claim with only
10,000 $ANIME tokens
- Alice submits a
requestClaimcall, thenftToUUIDanduuidToPackedNftIDmappings are written with
the errant pairing
- Alice’s claim verification fails the
claimChecker, since she does not own the Azuki with ID 1 - However Alice’s
requestClaimtransaction was successful, so the mapping values remain - The actual owner of Azuki ID 1 cannot make their normal claim and thus loses out on 49,990,000
$ANIME tokens
The compromised signer may repeat this attack for many of the largest token allocations, until low allocation UUID related claims run out.
Recommendation
Consider restricting UUID claims to only Azuki Elemental collection claims to limit this griefing attack vector from affecting large allocations from other NFT collections.
Otherwise be aware of this secondary exploit that can happen with a compromised UUID signer. The contract has the sufficient owner methods to repair this griefing attack if it were to take place.
Resolution
Animecoin Team: Acknowledged.
-
L-06 Low Delayed Claim Warning Warning Partially resolved
Description
The maximum age for a read response to be executed allowed in the
AnimeClaimercontract is 1 hour. This significantly limits the risk of stale read requests being executed far past the time at which ownership/delegation was verified at. However there is still some risk that should be communicated with users.For example, consider the following scenario:
- Alice has Azuki #7 with 10 ANIME tokens vested on day 10 at 11:30pm
- The day 10 withdrawal limit has already been met on Arbitrum
- Alice intentionally submits a claim request that will fail upon
lzReceivedue to the withdrawal limit,
but validates Alice as the owner of Azuki #7 up to block.timestamp of day 10 at 11:30pm, allowing Alice to claim 10 ANIME tokens
- On day 11 at 12:10am Alice lists their Azuki #7 for sale under the pretense of the buyer being able
to claim the 10 vested ANIME tokens
- Azuki #7 is sold to Bob on day 11 at 12:20am
- Alice retries her
lzReceiveon Arbitrum by invoking thelzReceivefunction through the endpoint
herself. The read result is still in the message channel so this action is allowed.
- Alice claims the 10 vested ANIME tokens that had accrued up to day 10 at 11:30pm
- Bob purchased Azuki #7 under the pretense that he would also receive these 10 vested ANIME
tokens, however after his purchase Alice took those 10 ANIME tokens from him
Recommendation
This finding serves merely to document this risk for users.
Resolution
Animecoin Team: Partially Resolved.
-
L-07 Low Lacking Zero Configs Validation Validation Resolved
Description
In the
requestClaimfunction there is no validation that the configs array is a nonzero length.Recommendation
To avoid any unexpected behavior, consider validating that the configs array is a nonzero length.
Resolution
Animecoin Team: Resolved.
-
L-08 Low Anime Coin Trapped Ether Trapped Ether Acknowledged
Description
The
registerTokenOnL2function accepts ether but does not explicitly use all of themsg.valuesent nor refund additionalmsg.valueto the caller. If excess ether is sent it will be trapped in theAnimecoincontract .Recommendation
Consider validating that exactly the
valueForGatewayandvalueForRouteris sent in theregisterTokenOnL2or refund additional ether to the caller. Alternatively consider adding an owner function to withdraw ether from the contract.Resolution
Animecoin Team: Acknowledged.
-
L-09 Low Unused Contract Best Practices Acknowledged
Description
AnimeClaimercontract inherits fromOAppOptionsType3but does not use anything from it.Recommendation
Consider removing the
OAppOptionsType3inherited contract.Resolution
Animecoin Team: Acknowledged.
-
L-10 Low Misleading Comment Best Practices Resolved
Description
The
expectedCalldataSizein the AnimerClaimer contract is set to 128, although the size of the return data fromClaimChecker:checkClaimsis 64 bytes.The comment above the
expectedCalldataSizestorage variable states that "Any extra overallocated is returned to the sender anyways".The calldata parameter is used inside the Executor to determine the amount to pay for the LZ message and if it is larger than the expected size, the extra gas is not returned to the sender.
Recommendation
The additional gas cost is negligible but consider changing the comment to reflect the actual behavior.
Resolution
Animecoin Team: Resolved.
-
L-11 Low Merkle Tree Entries Validation Acknowledged
Description
The
AnimeClaimercontract stores vesting state using a hash key:bytes32 hash = EfficientHashLib.hash(uint160(nft), tokenId, uint160(collector), streamId);When creating multiple allocations in the Merkle tree for:
- Same NFT/
tokenIdpair, or - Same collector address
Each allocation must use a unique
streamIdto prevent storage collisions in the vesting state.Recommendation
When generating the Merkle tree, ensure unique
streamIdvalues for each allocation to the same recipient (NFT or collector).Resolution
Animecoin Team: Acknowledged.
- Same NFT/
-
L-12 Low Incompatible ClockMode Compatibility Acknowledged
Description
The
Animecoincontract on Arbitrum is anERC20Votestoken, however uses the default clock mode of block.number. This means the voting system will rely on checkpoints based on L1 blocks rather than L2 blocks or timestamps.This can lead to integration issues with the governance system that integrates with the
ERC20Votestoken.Recommendation
The recommended clock mode for Arbitrum governance tokens is timestamp.
Resolution
Animecoin Team: Acknowledged.
No findings match.
More from Animecoin
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.
