Missing public key check in EmptyAccount
leading to deflationary bug
Description
A token account can only be closed if it has a zero balance. This applies to the regular cleartext balance as well as to the balances managed by the confidential transfer extension. Since the latter balances are encrypted, a special instruction called EmptyAccount
has to be executed before closing the account, which enables closing the account after verifying a zero knowledge (ZK) argument that proves the account balance is zero.
Similarly to other confidential token operations, a ZK argument has to be embedded in an instruction in the same transaction that invokes EmptyAccount
. The processor for EmptyAccount
verifies that the ZK argument exists and that it is correctly tied to the current state of the blockchain.
The function processing the EmptyAccount
instruction does not check that the public key associated with the ZK argument corresponds to the public key of the token account to be closed. This might allow an attacker to forge a ZK argument, falsely showing the account balance to be zero.
Impact
By closing an account with a nonzero balance, an attacker would be able to decrease the circulating supply without causing an update to the supply information stored in the mint account.
The attacker would have to give up their balance; therefore, it is difficult to imagine an incentive to perform such an attack. Furthermore, the same effect could be obtained by simply keeping the tokens in the attacker's account. For this reason, this issue is classified as low likelihood and low impact.
Recommendations
Ensure that the public key associated with the proof corresponds to the public key of the account being closed.
Remediation
Pull request #3767↗ fixes the issue following our recommendation. The PR head commit d6a72eb
was merged in the master
branch on October 27, 2022.