Merge branch 'develop' into gregtatcam/mpt/audit-attackathon-fixes

This commit is contained in:
Gregory Tsipenyuk
2026-05-26 09:31:16 -04:00
260 changed files with 8708 additions and 3549 deletions

View File

@@ -146,7 +146,7 @@ private:
.pay = 30'000,
.flags = tfMPTCanLock | kMptDexFlags});
usd.set({.flags = tfMPTLock});
AMM const ammAliceFail(env, alice_, XRP(10'000), usd(10'000), Ter(tecFROZEN));
AMM const ammAliceFail(env, alice_, XRP(10'000), usd(10'000), Ter(tecLOCKED));
usd.set({.flags = tfMPTUnlock});
AMM const ammAlice(env, alice_, XRP(10'000), usd(10'000));
}
@@ -350,7 +350,7 @@ private:
.pay = 30'000,
.flags = tfMPTCanLock | kMptDexFlags});
btc.set({.flags = tfMPTLock});
AMM const ammAlice(env, alice_, USD(10'000), btc(10'000), Ter(tecFROZEN));
AMM const ammAlice(env, alice_, USD(10'000), btc(10'000), Ter(tecLOCKED));
BEAST_EXPECT(!ammAlice.ammExists());
}
@@ -367,7 +367,7 @@ private:
btc.set({.holder = alice_, .flags = tfMPTLock});
// alice's token is locked
AMM const ammAlice(env, alice_, USD(10'000), btc(10'000), Ter(tecFROZEN));
AMM const ammAlice(env, alice_, USD(10'000), btc(10'000), Ter(tecLOCKED));
BEAST_EXPECT(!ammAlice.ammExists());
// bob can create
@@ -695,15 +695,15 @@ private:
btc.set({.flags = tfMPTLock});
ammAlice.deposit(
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(
carol_, USD(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, USD(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(
carol_, USD(100), btc(100), std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, USD(100), btc(100), std::nullopt, std::nullopt, Ter(tecLOCKED));
}
// Individually lock MPT or freeze IOU (AMM) with IOU/MPT AMM
@@ -724,20 +724,19 @@ private:
// Carol can not deposit locked mpt
ammAlice.deposit(
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
if (!features[featureAMMClawback])
{
ammAlice.deposit(
carol_, USD(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(carol_, USD(100), std::nullopt, std::nullopt, std::nullopt);
}
else
{
// Carol can not deposit non-forzen token either
// Carol can not deposit non-frozen token either
ammAlice.deposit(
carol_, USD(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, USD(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
}
// Alice can deposit because she's not individually locked
@@ -780,9 +779,9 @@ private:
ammAlice.deposit(carol_, USD(100), std::nullopt, std::nullopt, std::nullopt);
// Can not deposit locked token
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
// Unlock AMM MPT
btc.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
@@ -814,10 +813,10 @@ private:
// Carol's BTC is locked
btc.set({.holder = carol_, .flags = tfMPTLock});
ammAlice.deposit(
carol_, usd(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, usd(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
// Unlock carol's BTC
btc.set({.holder = carol_, .flags = tfMPTUnlock});
@@ -833,9 +832,9 @@ private:
ammAlice.deposit(carol_, usd(100), std::nullopt, std::nullopt, std::nullopt);
// Can not deposit locked token BTC
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, btc(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
// Unlock AMM MPT BTC
btc.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
@@ -850,9 +849,9 @@ private:
ammAlice.deposit(carol_, btc(100), std::nullopt, std::nullopt, std::nullopt);
// Can not deposit locked token USD
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.deposit(carol_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.deposit(
carol_, usd(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecFROZEN));
carol_, usd(100), std::nullopt, std::nullopt, std::nullopt, Ter(tecLOCKED));
// Unlock AMM MPT USD
usd.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
@@ -906,7 +905,7 @@ private:
AMM amm(env, gw, XRP(10'000), btc(10'000));
amm.deposit({.account = alice, .asset1In = btc(10), .err = Ter(tecNO_PERMISSION)});
amm.deposit({.account = alice, .asset1In = btc(10), .err = Ter(tecNO_AUTH)});
}
// Insufficient XRP balance
@@ -2248,23 +2247,22 @@ private:
Env env{*this};
env.fund(XRP(30'000), gw_, alice_);
env.close();
auto btcm = MPTTester(
auto btc = MPTTester(
{.env = env,
.issuer = gw_,
.holders = {alice_},
.pay = 30'000,
.flags = tfMPTCanTrade,
.flags = kMptDexFlags,
.mutableFlags = tmfMPTCanMutateCanTransfer,
.authHolder = true});
MPT const btc = btcm;
AMM amm(env, gw_, XRP(10'000), btc(10'000));
amm.deposit(DepositArg{.account = alice_, .asset1In = XRP(200), .asset2In = btc(200)});
// Allow to withdraw if transfer is disabled
btc.set({.mutableFlags = tmfMPTClearCanTransfer});
amm.withdraw(
WithdrawArg{
.account = alice_,
.asset1Out = btc(100),
.assets = {{XRP, btc}},
.err = Ter(tecNO_PERMISSION)});
WithdrawArg{.account = alice_, .asset1Out = btc(100), .assets = {{XRP, btc}}});
}
// Globally locked MPT
@@ -2285,8 +2283,8 @@ private:
btc.set({.flags = tfMPTLock});
ammAlice.withdraw(
alice_, MPT(ammAlice[1])(100), std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
alice_, MPT(ammAlice[1])(100), std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.withdraw(alice_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
// can single withdraw the other asset
ammAlice.withdraw({.account = alice_, .asset1Out = XRP(100)});
@@ -2314,8 +2312,8 @@ private:
// Alice's BTC is locked
btc.set({.holder = alice_, .flags = tfMPTLock});
ammAlice.withdraw(alice_, 1000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, btc(100), std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, 1000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.withdraw(alice_, btc(100), std::nullopt, std::nullopt, Ter(tecLOCKED));
// can withdraw the other asset
ammAlice.withdraw(alice_, usd(100), std::nullopt, std::nullopt);
@@ -2343,8 +2341,8 @@ private:
// Alice's BTC is locked
btc.set({.holder = alice_, .flags = tfMPTLock});
ammAlice.withdraw(alice_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, btc(100), std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.withdraw(alice_, btc(100), std::nullopt, std::nullopt, Ter(tecLOCKED));
// can still single withdraw the unlocked other asset
ammAlice.withdraw(alice_, USD(100), std::nullopt, std::nullopt);
@@ -2363,8 +2361,8 @@ private:
ammAlice.withdraw(alice_, USD(100), std::nullopt, std::nullopt);
// Can not withdraw locked token BTC
ammAlice.withdraw(alice_, 1'000, std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, btc(100), std::nullopt, std::nullopt, Ter(tecFROZEN));
ammAlice.withdraw(alice_, 1'000, std::nullopt, std::nullopt, Ter(tecLOCKED));
ammAlice.withdraw(alice_, btc(100), std::nullopt, std::nullopt, Ter(tecLOCKED));
// Unlock AMM MPT
btc.set({.holder = ammAlice.ammAccount(), .flags = tfMPTUnlock});
@@ -6424,9 +6422,9 @@ private:
struct MPTList
{
MPTTester const USD;
MPTTester const ETH;
MPTTester const CAN;
MPTTester const usd;
MPTTester const eth;
MPTTester const can;
};
auto prep = [&](Env& env, uint16_t gwTransferFee, uint16_t gw1TransferFee) -> MPTList {
@@ -6455,9 +6453,9 @@ private:
env.close();
return MPTList{
.USD = std::move(usd),
.ETH = std::move(eth),
.CAN = std::move(can),
.usd = std::move(usd),
.eth = std::move(eth),
.can = std::move(can),
};
};
@@ -6482,9 +6480,9 @@ private:
{
Env env(*this, features);
auto mpts = prep(env, rates.first, rates.second);
auto usd = mpts.USD;
auto eth = mpts.ETH;
auto can = mpts.CAN;
auto usd = mpts.usd;
auto eth = mpts.eth;
auto can = mpts.can;
std::optional<AMM> amm;
if (i == 0 || i == 2)
@@ -6527,9 +6525,9 @@ private:
{
Env env(*this, features);
auto mpts = prep(env, rates.first, rates.second);
auto usd = mpts.USD;
auto eth = mpts.ETH;
auto can = mpts.CAN;
auto usd = mpts.usd;
auto eth = mpts.eth;
auto can = mpts.can;
std::optional<AMM> amm;
if (i == 0 || i == 2)
{
@@ -6572,9 +6570,9 @@ private:
{
Env env(*this, features);
auto mpts = prep(env, rates.first, rates.second);
auto usd = mpts.USD;
auto eth = mpts.ETH;
auto can = mpts.CAN;
auto usd = mpts.usd;
auto eth = mpts.eth;
auto can = mpts.can;
std::optional<AMM> amm;
if (i == 0 || i == 2)
{
@@ -6638,9 +6636,9 @@ private:
{
Env env(*this, features);
auto mpts = prep(env, rates.first, rates.second);
auto usd = mpts.USD;
auto eth = mpts.ETH;
auto can = mpts.CAN;
auto usd = mpts.usd;
auto eth = mpts.eth;
auto can = mpts.can;
std::optional<AMM> amm;
if (i == 0 || i == 2)
{
@@ -6716,9 +6714,9 @@ private:
{
Env env(*this, features);
auto mpts = prep(env, rates.first, rates.second);
auto usd = mpts.USD;
auto eth = mpts.ETH;
auto can = mpts.CAN;
auto usd = mpts.usd;
auto eth = mpts.eth;
auto can = mpts.can;
std::optional<AMM> amm;
if (i == 0 || i == 2)
@@ -7011,33 +7009,33 @@ private:
cb(amm, btc);
};
// Deposit two assets, one of which is frozen,
// then we should get tecFROZEN error.
// Deposit two assets, one of which is locked,
// then we should get tecLOCKED error.
{
Env env(*this);
testAMMDeposit(env, [&](AMM& amm, MPTTester& btc) {
amm.deposit(alice_, btc(100), XRP(100), std::nullopt, tfTwoAsset, Ter(tecFROZEN));
amm.deposit(alice_, btc(100), XRP(100), std::nullopt, tfTwoAsset, Ter(tecLOCKED));
});
}
// Deposit one asset, which is the frozen token,
// then we should get tecFROZEN error.
// Deposit one asset, which is the locked token,
// then we should get tecLOCKED error.
{
Env env(*this);
testAMMDeposit(env, [&](AMM& amm, MPTTester& btc) {
amm.deposit(
alice_, btc(100), std::nullopt, std::nullopt, tfSingleAsset, Ter(tecFROZEN));
alice_, btc(100), std::nullopt, std::nullopt, tfSingleAsset, Ter(tecLOCKED));
});
}
// Deposit one asset which is not the frozen token,
// but the other asset is frozen. We should get tecFROZEN error
// but the other asset is frozen. We should get tecLOCKED error
// when feature AMMClawback is enabled.
{
Env env(*this);
testAMMDeposit(env, [&](AMM& amm, MPTTester& btc) {
amm.deposit(
alice_, XRP(100), std::nullopt, std::nullopt, tfSingleAsset, Ter(tecFROZEN));
alice_, XRP(100), std::nullopt, std::nullopt, tfSingleAsset, Ter(tecLOCKED));
});
}
}
@@ -7054,7 +7052,7 @@ private:
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.reference_fee = XRPAmount(1);
cfg->fees.referenceFee = XRPAmount(1);
return cfg;
}),
all);
@@ -7108,7 +7106,7 @@ private:
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.reference_fee = XRPAmount(1);
cfg->fees.referenceFee = XRPAmount(1);
return cfg;
}),
all);
@@ -7143,7 +7141,7 @@ private:
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.reference_fee = XRPAmount(1);
cfg->fees.referenceFee = XRPAmount(1);
return cfg;
}),
all);
@@ -7167,7 +7165,7 @@ private:
Env env(
*this,
envconfig([](std::unique_ptr<Config> cfg) {
cfg->FEES.reference_fee = XRPAmount(1);
cfg->fees.referenceFee = XRPAmount(1);
return cfg;
}),
all);