Beginner FriendlyFoundry
100 EXP
View results
Submission Details
Severity: medium
Valid

When a user creates a new Mondrian wallet smart account, no Mondrian art painting NFT is minted.

Summary

When a user creates a new Mondrian wallet smart account, no Mondrian art painting NFT is minted.

Vulnerability Details

MondrianWallet.sol doesn't call a function _safeMint for minting an NFT. The fact that MondrianWallet.sol inherits functions from an ERC721 is not enough to be able to mint an nft every time user create a cool account abstraction wallet.

Impact

No Mondrian art painting NFT will be minted and distributed to the account abstraction wallet.

Tools Used

Manual review

Recommendations

To be compliant with your protocol announcement you must refactor your smartcontract to include a way to mint a Mondrian Art Painting NFT during the account abstraction wallet creation, first add an AccountFactory contract to create and deploy your AA wallet and then modify the constructor to allows your smartWallet to mint a Mondrian art painting NFT.

AccountFactory.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol";
import "./MondrianWallet.sol";
contract AccountFactory is VRFConsumerBase {
bytes32 internal keyHash;
uint256 internal fee;
address public entryPoint;
// VRF-related variables
mapping(bytes32 => address) public requestIdToSender;
constructor(
address _vrfCoordinator,
address _linkToken,
bytes32 _keyHash,
uint256 _fee,
address _entryPoint
) VRFConsumerBase(_vrfCoordinator, _linkToken) {
keyHash = _keyHash;
fee = _fee;
entryPoint = _entryPoint;
}
function createAccount(address owner) external returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
requestId = requestRandomness(keyHash, fee);
requestIdToSender[requestId] = owner;
}
function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override {
address owner = requestIdToSender[requestId];
uint256 tokenId = randomness % 10; // Reduce the randomness range for token ID
deploy(owner, tokenId);
}
function deploy(address owner, uint256 tokenId) internal {
bytes32 salt = keccak256(abi.encodePacked(owner, tokenId));
bytes memory creationCode = type(MondrianWallet).creationCode;
bytes memory bytecode = abi.encodePacked(creationCode, abi.encode(entryPoint, tokenId));
address walletAddress;
assembly {
walletAddress := create2(0, add(bytecode, 0x20), mload(bytecode), salt)
}
require(walletAddress != address(0), "Create2: Failed on deploy");
// Optionally: emit an event here with walletAddress and owner
}
}

MondrianWallet.sol

constructor(address entryPoint, uint256 _tokenId)
Ownable(msg.sender)
ERC721("MondrianWallet", "MW")
{
i_entryPoint = IEntryPoint(entryPoint);
tokenId = _tokenId;
_safeMint(owner(), tokenId);
_setTokenURI(tokenId, tokenURI(tokenId));
}
// Existing functions...
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

The Wallet doesn't end up owning any nft

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.