Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FAIL. Reason: revert: stdStorage find(StdStorage): Failed to write value.] #570

Closed
AAYUSH-GUPTA-coder opened this issue Jun 18, 2024 · 2 comments

Comments

@AAYUSH-GUPTA-coder
Copy link

Description

I am working with the BLAST Blockchain in a Foundry testing environment, specifically using a mainnet fork for testing. My goal is to set the USDB (a stablecoin with 18 decimals) balance for a user account during the testing process.

Error Encountered

When executing the following line in my Foundry test:

deal(usdbAddr, user, 1 * 1e18, false);

I receive the following error:

[FAIL. Reason: revert: stdStorage find(StdStorage): Failed to write value.]

Foundry Test Code

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity 0.8.24;

import "forge-std/Test.sol";
import "forge-std/console.sol";

import {IERC20} from "../src/interfaces/IERC20.sol";

contract TestBlastLoopStrategy is Test {
    IERC20 public usbd;

    address public usdbAddr = 0x4300000000000000000000000000000000000003;

    function setUp() public {
        // setup the value
        usbd = IERC20(usdbAddr);
    }

    function testUsdbZerolend() public {
        address user = address(2);
        console.log("Address of the User", user);

        vm.startPrank(user);
        deal(usdbAddr, user, 1 * 1e18, false);

        console.log("Balance of usdb of user", usbd.balanceOf(user));

        vm.stopPrank();
    }
}

Additional Context

  • I am trying to set the USDB balance of the user account to 1 USDB (1 * 10^18 due to 18 decimals) using the deal function.
  • The usdbAddr is the contract address of the USDB stablecoin on the BLAST Blockchain.
  • The user account is being set to the labeled address address(2) for testing purposes.
  • The test is being executed in a Foundry testing environment with a mainnet fork of the BLAST Blockchain.

Expected Behavior

The deal function should successfully set the USDB balance of the user account to 1 USDB (1 * 10^18) without encountering any errors.

Actual Behavior

The deal function fails with the error [FAIL. Reason: revert: stdStorage find(StdStorage): Failed to write value.], indicating that the test environment is unable to write the USDB balance to the user account.

Please provide guidance on how to resolve this issue and successfully set the USDB balance for the user account during testing in the Foundry mainnet fork environment.

@mds1
Copy link
Collaborator

mds1 commented Jun 18, 2024

The USDB token dynamically calculates balance as you can see here: https://blastscan.io/address/0x4ef0d788470e2feb6559b93075ec5be51dba737d#code%23F4%23L107

Therefore, there is no single slot to directly write to for updating a user's balance, which is why it fails. See #140 (comment) for other examples of tokens with this issue

You will need to understand how the USDB token returns balances and determine what values to write to what slots. Alternatively, you can use vm.mockCall to mock the value returned from balanceOf calls

@mds1 mds1 closed this as not planned Won't fix, can't repro, duplicate, stale Jun 18, 2024
@AAYUSH-GUPTA-coder
Copy link
Author

Thank you @mds1 for your guidance. I've successfully solved this problem using vm.mockCall().

For anyone facing a similar issue, here's a comprehensive solution:

// SPDX-License-Identifier: MIT
pragma solidity 0.8.24;

import "forge-std/Test.sol";
import "forge-std/console.sol";

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
}

contract TestERC20RebasingToken is Test {
    IERC20 public usbd;

    // address of usdb token
    address public usdbAddr = 0x4300000000000000000000000000000000000003;

    function setUp() public {
        usbd = IERC20(usdbAddr);
    }

    function testMockTokenBalance() public {
        address user = address(2);

        // The balance we want to set
        uint256 mockBalance = 1000 * 1e18; // 1000 tokens with 18 decimals

        // 1. Get the function signature for balanceOf
        bytes4 balanceOfSelector = IERC20.balanceOf.selector;

        // 2. Encode the parameters (in this case, just the user address)
        bytes memory balanceOfData = abi.encodeWithSelector(
            balanceOfSelector,
            user
        );

        // 3. Encode the return data (the balance)
        bytes memory returnData = abi.encode(mockBalance);

        // 4. Mock the call
        vm.mockCall(usdbAddr, balanceOfData, returnData);

        // 5. Now when we call balanceOf, it should return our mocked balance
        uint256 balance = IERC20(usdbAddr).balanceOf(user);

        // 6. Assert that the balance is what we set
        assertEq(balance, mockBalance, "Balance should be mocked value");

        console.log("Balance of usdb of user", usbd.balanceOf(user));
    }
}

Foundry Doc link : mockCall()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants