Gorgeous Maroon Stallion
Medium
stablecoinSwap
allows for users to swap the same token (ie ss.origin
== ss.target
) between 2 different addresses. Hence, since it is allowed and is a valid function for people to send tokens to a different address through a official channel: the StablecoinHandler.sol
.
However, checks in _verifyStablecoinSwap
are incorrect and will cause the swap to fail in certain senarios/
In _verifyStablecoinSwap
:
function _verifyStablecoinSwap(
address wallet,
StablecoinSwap memory ss
) internal view nonZero(ss) {
// Ensure the wallet address is not zero.
if (wallet == address(0)) revert ZeroValueInput("WALLET");
// For the origin currency:
if (isXYZ(ss.origin)) {
// Ensure the total supply does not drop below the minimum limit after burning the specified amount.
if (
--> Stablecoin(ss.origin).totalSupply() - ss.oAmount <
--> getMinLimit(ss.origin)
--> ) revert InvalidMintBurnBoundry(ss.origin, ss.oAmount);
} else if (ss.liquiditySafe == address(0)) {
// Ensure the liquidity safe is provided for ERC20 origin tokens.
revert ZeroValueInput("LIQUIDITY SAFE");
}
// For the target currency:
if (isXYZ(ss.target)) {
// Ensure the total supply does not exceed the maximum limit after minting the specified amount.
if (
--> Stablecoin(ss.target).totalSupply() + ss.tAmount >
--> getMaxLimit(ss.target)
--> ) revert InvalidMintBurnBoundry(ss.target, ss.tAmount);
} else if (ss.liquiditySafe == address(0)) {
// Ensure the liquidity safe is provided for ERC20 target tokens.
revert ZeroValueInput("LIQUIDITY SAFE");
}
}
We can see from the lines marked with an arrow that it ensures totalSupply - oAmount >= getMinLimit
and totalSupply + tAmount <= getMaxLimit
.
However, during a swap where origin token == target token
(same token, but swapping from one address to a different address) then that is the not the inequality that should be compared.
Namely, if origin token == target token
then:
Stablecoin(ss.origin).totalSupply() - ss.oAmount + ss.tAmount
is the equation that should be compared withgetMinLimit
andgetMaxLimit
Swaps done for the same token from one address to an another different address and have totalSupply
near either getMinDeposits
or getMaxDeposits
will be affected.
No response
No response
No response
No response
Account for the senario where ss.origin == ss.target
and compare the right amount with getMinLimit
and getMaxLimit
function _verifyStablecoinSwap(
address wallet,
StablecoinSwap memory ss
) internal view nonZero(ss) {
// Ensure the wallet address is not zero.
if (wallet == address(0)) revert ZeroValueInput("WALLET");
// For the origin currency:
if (isXYZ(ss.origin)) {
// Ensure the total supply does not drop below the minimum limit after burning the specified amount.
if (
- Stablecoin(ss.origin).totalSupply() - ss.oAmount <
+ Stablecoin(ss.origin).totalSupply() - ss.oAmount + (ss.origin == ss.target ? ss.tAmount : 0) <
getMinLimit(ss.origin)
) revert InvalidMintBurnBoundry(ss.origin, ss.oAmount);
} else if (ss.liquiditySafe == address(0)) {
// Ensure the liquidity safe is provided for ERC20 origin tokens.
revert ZeroValueInput("LIQUIDITY SAFE");
}
// For the target currency:
if (isXYZ(ss.target)) {
// Ensure the total supply does not exceed the maximum limit after minting the specified amount.
if (
- Stablecoin(ss.target).totalSupply() + ss.tAmount >
+ Stablecoin(ss.origin).totalSupply() + ss.tAmount - (ss.origin == ss.target ? ss.oAmount : 0) >
getMaxLimit(ss.target)
) revert InvalidMintBurnBoundry(ss.target, ss.tAmount);
} else if (ss.liquiditySafe == address(0)) {
// Ensure the liquidity safe is provided for ERC20 target tokens.
revert ZeroValueInput("LIQUIDITY SAFE");
}
}