fix: assorted safety checks (#7030)

This commit is contained in:
Shawn Xie
2026-04-27 14:36:54 -04:00
committed by GitHub
parent 8457b91b10
commit 5a643b1a7f
4 changed files with 27 additions and 4 deletions

View File

@@ -95,7 +95,8 @@ ConfidentialMPTClawback::preclaim(PreclaimContext const& ctx)
// Sanity check: claw amount can not exceed confidential outstanding amount
auto const amount = ctx.tx[sfMPTAmount];
if (amount > (*sleIssuance)[~sfConfidentialOutstandingAmount].value_or(0))
if (amount > (*sleIssuance)[~sfConfidentialOutstandingAmount].value_or(0) ||
amount > (*sleIssuance)[sfOutstandingAmount])
return tecINSUFFICIENT_FUNDS;
auto const contextHash =
@@ -162,10 +163,14 @@ ConfidentialMPTClawback::doApply()
// Decrease Global Confidential Outstanding Amount
auto const oldCOA = (*sleIssuance)[sfConfidentialOutstandingAmount];
if (clawAmount > oldCOA)
return tecINTERNAL; // LCOV_EXCL_LINE
(*sleIssuance)[sfConfidentialOutstandingAmount] = oldCOA - clawAmount;
// Decrease Global Total Outstanding Amount
auto const oldOA = (*sleIssuance)[sfOutstandingAmount];
if (clawAmount > oldOA)
return tecINTERNAL; // LCOV_EXCL_LINE
(*sleIssuance)[sfOutstandingAmount] = oldOA - clawAmount;
view().update(sleHolderMPToken);

View File

@@ -139,7 +139,8 @@ ConfidentialMPTConvertBack::preclaim(PreclaimContext const& ctx)
if (!sleIssuance)
return tecOBJECT_NOT_FOUND;
if (!sleIssuance->isFlag(lsfMPTCanConfidentialAmount))
if (!sleIssuance->isFlag(lsfMPTCanConfidentialAmount) ||
!sleIssuance->isFieldPresent(sfIssuerEncryptionKey))
return tecNO_PERMISSION;
bool const hasAuditor = ctx.tx.isFieldPresent(sfAuditorEncryptedAmount);
@@ -209,9 +210,14 @@ ConfidentialMPTConvertBack::doApply()
// Converting back increases regular balance and decreases confidential
// outstanding. This is the inverse of Convert.
if (amt > maxMPTokenAmount - amtToConvertBack)
return tecINTERNAL; // LCOV_EXCL_LINE
(*sleMptoken)[sfMPTAmount] = amt + amtToConvertBack;
(*sleIssuance)[sfConfidentialOutstandingAmount] =
(*sleIssuance)[sfConfidentialOutstandingAmount] - amtToConvertBack;
auto const coa = (*sleIssuance)[~sfConfidentialOutstandingAmount].value_or(0);
if (coa < amtToConvertBack)
return tecINTERNAL; // LCOV_EXCL_LINE
(*sleIssuance)[sfConfidentialOutstandingAmount] = coa - amtToConvertBack;
std::optional<Slice> const auditorEc = ctx_.tx[~sfAuditorEncryptedAmount];

View File

@@ -37,6 +37,10 @@ ConfidentialMPTSend::preflight(PreflightContext const& ctx)
if (account == ctx.tx[sfDestination])
return temMALFORMED;
// Issuer cannot be the destination
if (ctx.tx[sfDestination] == issuer)
return temMALFORMED;
// Check the length of the encrypted amounts
if (ctx.tx[sfSenderEncryptedAmount].length() != ecGamalEncryptedTotalLength ||
ctx.tx[sfDestinationEncryptedAmount].length() != ecGamalEncryptedTotalLength ||

View File

@@ -2111,6 +2111,14 @@ class ConfidentialTransfer_test : public beast::unit_test::suite
.err = temMALFORMED,
});
// can not send to issuer
mptAlice.send({
.account = bob,
.dest = alice,
.amt = 10,
.err = temMALFORMED,
});
// sender encrypted amount wrong length
mptAlice.send({
.account = bob,