hats-finance / Intuition-0x538dbadc50cc87b281cd655f1edbc6ebda02a66a

The smart contracts of the Intuition protocol v1.
https://intuition.systems
Other
0 stars 1 forks source link

Changing `atomWarden` will result in losing `atomWalletInitialDepositAmount` for Created and not Deployed Atoms #50

Open hats-bug-reporter[bot] opened 1 week ago

hats-bug-reporter[bot] commented 1 week ago

Github username: @Al-Qa-qa Twitter username: al_qa_qa Submission hash (on-chain): 0xc518fa0e591487973f4d31750e421dc652b1ae07f42aee2489353a9ea1ea9f70 Severity: medium

Description: Description\ When creating new Atom wallets, there are two processes. First, is the creation of the atom vault. Second, is deploying the wallet.

When creating atom, atomWalletInitialDepositAmount goes to the atom wallet address that will be deployed using the current ID.

EthMultiVault.sol#L481-L488

        address atomWallet = computeAtomWalletAddr(id);

        // deposit atomWalletInitialDepositAmount amount of assets and mint the shares for the atom wallet
        _depositOnVaultCreation(
            id,
            atomWallet, // receiver
            atomConfig.atomWalletInitialDepositAmount
        );

When creating atomWallet address that will receive the initialDeposit, it is calculating using the current args, and atomWarden is one of the args.

EthMultiVault.sol#L1421-L1423

        bytes memory initData = abi.encodeWithSelector(
@>          AtomWallet.init.selector, IEntryPoint(walletConfig.entryPoint), walletConfig.atomWarden, address(this)
        );

But in case of deploying, we recompute this address again.

EthMultiVault.sol#L366

    function deployAtomWallet(uint256 atomId) external whenNotPaused returns (address) {
        if (atomId == 0 || atomId > count) {
            revert Errors.MultiVault_VaultDoesNotExist();
        }

        // compute salt for create2
        bytes32 salt = bytes32(atomId);

        // get contract deployment data
@>      bytes memory data = _getDeploymentData();
        ...
        assembly {
            atomWallet := create2(0, add(data, 0x20), mload(data), salt)
        }
        ...
    }

So all AtomVaults that did not deployed there Wallets, will not be able to claim their initialAmount, if the atomWarden changed.

Senario\

Recommendations\

In case of changing AtomWarden, you need to check that all created atoms gets deployed. this can either be done on-chain, or off-chain.

Al-Qa-qa commented 5 days ago

Mitigation may be a little complex, I will provide more info about Mitigation in the Judging Process.

mihailo-maksa commented 4 days ago

The reported issue concerning the potential loss of atomWalletInitialDepositAmount when the atomWarden is changed has been reviewed. Here is our detailed perspective:

Enhancement Suggestion: The suggestion to keep track of the mapping of vault IDs to atom wallet addresses is a valid enhancement to ensure that the initial deposit amount is not lost if the atomWarden is changed. This enhancement would improve the robustness and reliability of the protocol.

Current Design: The current design ensures that if the atomWarden is changed, it automatically gets updated for all atom wallets whose ownership has not been claimed by their rightful owners. The atomWalletInitialDepositAmount remains with the first deployed AtomWallet, which is considered the valid one due to its association with the initial deposit and the AtomCreated event.

Considerations: While adding a mapping to track vault IDs to atom wallet addresses could enhance clarity, it also introduces additional gas costs. The same information can be retrieved from emitted events off-chain, which might be a more efficient approach.

Severity Assessment: Since this issue does not introduce any vulnerabilities or risks to users and the current design handles ownership updates adequately, it is classified as an enhancement.

Conclusion: While the enhancement to track vault IDs to atom wallet addresses on-chain could improve the system, it is not necessary from a security standpoint. The current design ensures that the first deployed AtomWallet is the valid one, and this can be verified off-chain using events.

Status: This issue is a potential enhancement.

Suggested Fix: A potential fix, if on-chain tracking ends up being preferred, can be adding a mapping to track vault IDs to atom wallet addresses, but note that this increases the deployment gas costs considerably:

mapping(uint256 => address) public vaultToAtomWallet;

function deployAtomWallet(uint256 atomId) external whenNotPaused returns (address) {
    if (atomId == 0 || atomId > count || isTripleId(atomId)) {
        revert Errors.MultiVault_VaultDoesNotExist();
    }

    // compute salt for create2
    bytes32 salt = bytes32(atomId);

    // get contract deployment data
    bytes memory data = _getDeploymentData();

    address atomWallet;

    // deploy atom wallet with create2:
    // value sent in wei,
    // memory offset of `code` (after first 32 bytes where the length is),
    // length of `code` (first 32 bytes of code),
    // salt for create2
    assembly {
        atomWallet := create2(0, add(data, 0x20), mload(data), salt)
    }

    if (atomWallet == address(0)) {
        revert Errors.MultiVault_DeployAccountFailed();
    }

    // Update mapping
    vaultToAtomWallet[atomId] = atomWallet;

    return atomWallet;
}

If off-chain verification is sufficient, no changes are needed.

Comment for the Reporter: Thank you for highlighting this potential issue. While the current design ensures that the first deployed AtomWallet is valid, adding a mapping could provide additional clarity. This is considered an enhancement rather than a vulnerability, and we can still consider a lower payout for this valid suggestion. Adding this mapping could lead to higher gas costs, and we are interested in your feedback on the necessity of on-chain tracking versus using off-chain event retrieval.

Extra Considerations:

Al-Qa-qa commented 3 days ago

Hi @mihailo-maksa, I think there is a misunderstanding between this issue and issue #51

I will explain the flow of the problem for both issues.

This is the issue described in the sponser reply, if atomWaden was 0xee01 and then changed to 0xee02 all AA wallets that are not claimed yet (deployed and not claimed yet) will have old atomWarden ownership, and the protocol said that in case of changing atomWarden, all AA wallets that are not claimed will get there ownership changed to the new atomWarden in EthMultiVault.

This is what issue 51 was targeting, and it was targeting the ability to redeploy the wallet again. I will not explain more in issue 51, and wait for any additional input from @mihailo-maksa in issue 51 page, and goes to our main issue 50


As it is seen when creating AA wallet and do not deploy it, which is known as counterfactional wallet in that case. it received atomWalletInitialDepositAmount.

        address atomWallet = computeAtomWalletAddr(id);

        // deposit atomWalletInitialDepositAmount amount of assets and mint the shares for the atom wallet
        _depositOnVaultCreation(
            id,
@>          atomWallet, // receiver
            atomConfig.atomWalletInitialDepositAmount
        );

The problem lies is that if this wallets gets deployed it will not get deployed with address 0xAA02, instead it will get deployed with address 0xAA12 if atomWarden changed before deploying.

        bytes memory data = _getDeploymentData();

        address atomWallet;
        assembly {
            atomWallet := create2(0, add(data, 0x20), mload(data), salt)
        }

As we can see the atomWallet address depends on data which uses atomWarden address, and changing it will change the AA address.

The issue explains the loss of atomWalletInitialDepositAmount for all created and not deployed atomWallets, not for deployed and not claimed atom wallets.

So in brief, when creating the wallet, shares are minted to the AA atomWallet that is supposed to be created with atomWarden. but changing atomWarden will result in deploying that wallet (with the specific ID), in a different address, which will cause the loss of funds (atomWalletInitialDepositAmount) for all counterfactional (created and not deployed) wallets.

Please let me know if things are clear, or there is something I should explain more clearly in the issue @mihailo-maksa