Foundry test Underflow/Overflow error if using dscE.getCollateralBalanceOfUser(msg.sender, address(collateral));
#3038
-
Advanced Foundry Section 3, Lesson 23 Create the collateral redeem handler, around 1m47s Does anyone know why when calling If my getter function is like this, should't it be thanks in advance function getCollateralBalanceOfUser(address user, address token) external view returns (uint256) {
return s_collateralDeposited[user][token];
} This causes error: function redeemCollateral(uint256 collateralSeed, uint256 amountCollateral) public {
ERC20Mock collateral = _getCollateralFromSeed(collateralSeed);
uint256 maxAmountCollateralToRedeem = dscE.getCollateralBalanceOfUser(msg.sender, address(collateral));
amountCollateral = bound(amountCollateral, 0, maxAmountCollateralToRedeem);
if (amountCollateral == 0) {
// vm.assume // try it out
return; // and dont call function redeemCollateral
}
dscE.redeemCollateral(address(collateral), amountCollateral);
vm.stopPrank();
} This error DSCEngine::redeemCollateral(ERC20Mock: [0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3], 167)
│ └─ ← [Revert] panic: arithmetic underflow or overflow (0x11)
└─ ← [Revert] panic: arithmetic underflow or overflow (0x11) Encountered 1 failing test in test/fuzz/Invariants.t.sol:Invariants
[FAIL: panic: arithmetic underflow or overflow (0x11)]
[Sequence]
sender=0x0000000000000000000014F0BEAB475Eb7DebFc4 addr=[test/fuzz/Handler.t.sol:Handler]0x2e234DAe75C793f67A35089C9d99245E1C58470b calldata=depositCollateral(uint256,uint256) args=[5380788795577376420283429479373100551244819186416366991098466917595694285 [5.38e72], 240]
sender=0x0000000000000000000014F0BEAB475Eb7DebFc4 addr=[test/fuzz/Handler.t.sol:Handler]0x2e234DAe75C793f67A35089C9d99245E1C58470b calldata=redeemCollateral(uint256,uint256) args=[4183, 2376452956 [2.376e9]]
invariant_protocolMustHaveMoreValueThanTotalSupply() (runs: 0, calls: 0, reverts: 1) This works fine function redeemCollateral(uint256 collateralSeed, uint256 amountCollateral) public {
ERC20Mock collateral = _getCollateralFromSeed(collateralSeed);
uint256 maxAmountCollateralToRedeem = dscE.getCollateralBalanceOfUser(address(collateral), msg.sender) ;
amountCollateral = bound(amountCollateral, 0, maxAmountCollateralToRedeem);
if (amountCollateral == 0) {
// vm.assume // try it out
return; // and dont call function redeemCollateral
}
dscE.redeemCollateral(address(collateral), amountCollateral);
vm.stopPrank();
} |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
Hello @yawarasuuna, one tip is put use console.log inside the function that is reverting and see what are the values that are dividing each other and like that you will gain more insight into what is running in the process and what might be causing the revert. |
Beta Was this translation helpful? Give feedback.
-
@yawarasuuna You're absolutely right in saying that the call should be dscE.getCollateralBalanceOfUser(msg.sender, address(collateral)); as the function signature clearly expect the user as first argument. function _redeemCollateral(address tokenCollateralAddress, uint256 collateralAmount, address from, address to)
private
{
console2.log("Redeeming collateral");
console2.log("From: ", from);
console2.log("Token: ", tokenCollateralAddress);
console2.log("Current Collateral: ", s_collateralDeposited[from][tokenCollateralAddress]);
console2.log("Redeem Amount: ", collateralAmount);
// Redeem collateral
s_collateralDeposited[from][tokenCollateralAddress] -= collateralAmount;
emit CollateralRedeemed(from, to, tokenCollateralAddress, collateralAmount);
bool success = IERC20(tokenCollateralAddress).transfer(to, collateralAmount);
if (!success) {
revert DSCEngine__TransferFailed();
}
}
function reddemCollateral(uint256 collateralSeed, uint256 collateralAmount) public {
console2.log("redeemCollateral");
ERC20Mock collateral = _getCollateralFromSeed(collateralSeed);
console2.log("User: ", msg.sender);
console2.log("Collateral: ", address(collateral));
uint256 maxCollateralToRedeem = engine.getCollateralBalanceOfUser(msg.sender, address(collateral));
console2.log("maxCollateralToRedeem: ", maxCollateralToRedeem);
collateralAmount = bound(collateralAmount, 0, maxCollateralToRedeem);
console2.log("collateralAmount: ", collateralAmount);
if (collateralAmount == 0) {
return;
}
engine.redeemCollateral(address(collateral), collateralAmount);
} I got Logs:
Bound result 137472159
redeemCollateral
User: 0x00000000000000000000000000000000000002a5
Collateral: 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3
maxCollateralToRedeem: 137472159
Bound result 89197275
collateralAmount: 89197275
Redeeming collateral
From: 0x2e234DAe75C793f67A35089C9d99245E1C58470b
Token: 0xBb2180ebd78ce97360503434eD37fcf4a1Df61c3
Current Collateral: 0
Redeem Amount: 89197275
totalSupply: 0 From the logs, we see that the From address in _redeemCollateral is the Handler contract (0x2e234DAe75C793f67A35089C9d99245E1C58470b) rather than the user (0x00000000000000000000000000000000000002a5). This mismatch is causing the s_collateralDeposited[from][tokenCollateralAddress] to return 0, leading to an arithmetic underflow when trying to subtract collateralAmount. Cause Solution function reddemCollateral(uint256 collateralSeed, uint256 collateralAmount) public {
console2.log("redeemCollateral");
ERC20Mock collateral = _getCollateralFromSeed(collateralSeed);
console2.log("User: ", msg.sender);
console2.log("Collateral: ", address(collateral));
uint256 maxCollateralToRedeem = engine.getCollateralBalanceOfUser(msg.sender, address(collateral));
console2.log("maxCollateralToRedeem: ", maxCollateralToRedeem);
collateralAmount = bound(collateralAmount, 0, maxCollateralToRedeem);
console2.log("collateralAmount: ", collateralAmount);
if (collateralAmount == 0) {
return;
}
vm.startPrank(msg.sender); // Ensure msg.sender is set to the user
engine.redeemCollateral(address(collateral), collateralAmount);
vm.stopPrank();
} I think this is an error in the video. |
Beta Was this translation helpful? Give feedback.
Hello @yawarasuuna, one tip is put use console.log inside the function that is reverting and see what are the values that are dividing each other and like that you will gain more insight into what is running in the process and what might be causing the revert.