Bug(forge): Panic When Transfer To A Vm.cooled Contract
Introduction
In this article, we will explore a bug that occurs when transferring funds to a contract that has been cooled using the vm.cool()
function in Forge. This bug is particularly interesting because it highlights the importance of understanding the behavior of contracts in different states, especially when it comes to interactions with the virtual machine (VM).
The Bug
The bug is triggered when we attempt to transfer funds to a contract that has been cooled using the vm.cool()
function. The error message indicates that the application panicked (crashed) due to a None
value being unwrapped. This suggests that there is an issue with the way the contract is being interacted with, specifically when it comes to the transfer of funds.
The Code
To better understand the bug, let's take a look at the code that is causing the issue. We have two contracts: Counter
and CounterB
. The Counter
contract has a function transferSomething()
that allows us to transfer funds to another contract. The CounterB
contract has a function transferSomething()
that takes an address and a value as input and transfers the funds to that address.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
contract Counter {
uint256 public number;
function setNumber(uint256 newNumber) public {
number = newNumber;
}
function increment() public {
number++;
}
}
contract CounterB {
function transferSomething(address a, uint256 funds) external {
payable(a).transfer(funds);
}
}
The test contract, CounterTest
, creates instances of both Counter
and CounterB
and attempts to transfer funds to the Counter
contract using the transferSomething()
function.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import "../src/Counter.sol";
contract CounterTest is Test {
Counter counter = new Counter();
CounterB counterB = new CounterB();
function testCoolBug() public {
vm.deal(address(counterB), 10000 ether);
counter.setNumber(1);
vm.cool(address(counter));
counterB.transferSomething(address(counter), 1 ether);
}
}
The Issue
The issue arises when we attempt to transfer funds to the Counter
contract using the transferSomething()
function. The vm.cool()
function is used to cool the contract, which means that it is put into a state where it is not executing any code. However, when we attempt to transfer funds to the contract, the VM is still in the cooled state, and this causes the panic.
Conclusion
In conclusion, the bug that occurs when transferring funds to a VM.cooled contract is a result of the contract being in a state where it is not executing any code. This highlights the importance of understanding the behavior of contracts in different states, especially when it comes to interactions with the virtual machine (VM). By using the vm.cool()
function, we can put the contract into a state where it is not executing any code, and this can cause issues when attempting to interact with the contract.
Recommendations
To avoid this bug, it is recommended to ensure that the contract is not cooled when attempting to transfer funds to it. This can be achieved by removing the vm.cool()
function call or by using a different approach to interact with the contract.
Additional Information
- Component: Forge
- Foundry: Not up to date
- Foundryup: Not up to date
- Operating System: None
- Describe the bug: The application panicked (crashed) due to a
None
value being unwrapped.
Backtrace
The application panicked (crashed).
Message: called `Option::unwrap()` on a `None` value
Location: /home/george/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/revm-19.7.0/src/journaled_state.rs:402
This is a bug. Consider reporting it at https://github.com/foundry-rs/foundry
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ BACKTRACE ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⋮ 8 frames hidden ⋮
9: core::panicking::panic::h857be6a7877f0791
at /rustc/00095b3da4f23d9b3e7a809ac6a4e2b2530df84c/library/core/src/panicking.rs:145
10: core::option::unwrap_failed::hb8d0c37e2ce3e599
at /rustc/00095b3da4f23d9b3e7a809ac6a4e2b2530df84c/library/core/src/option.rs:2015
11: unwrap<&mut revm_primitives::state::EvmStorageSlot><unknown>
at /home/george/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:978
12: journal_revert<unknown>
at /home/george/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/revm-19.7.0/src/journaled_state.rs:402
13: {closure#0}<unknown>
at /home/george/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/revm-19.7.0/src/journaled_state.rs:460
```<br/>
**Bug(Forge): Panic When Transfer to a VM.Cooled Contract - Q&A**
===========================================================
**Q: What is the bug that occurs when transferring funds to a VM.cooled contract?**
--------------------------------------------------------------------------------
A: The bug that occurs when transferring funds to a VM.cooled contract is a result of the contract being in a state where it is not executing any code. This highlights the importance of understanding the behavior of contracts in different states, especially when it comes to interactions with the virtual machine (VM).
**Q: What is the cause of the bug?**
-----------------------------------
A: The cause of the bug is the use of the `vm.cool()` function to cool the contract. This function puts the contract into a state where it is not executing any code, and this can cause issues when attempting to interact with the contract.
**Q: How can I avoid this bug?**
-------------------------------
A: To avoid this bug, it is recommended to ensure that the contract is not cooled when attempting to transfer funds to it. This can be achieved by removing the `vm.cool()` function call or by using a different approach to interact with the contract.
**Q: What is the impact of this bug?**
--------------------------------------
A: The impact of this bug is that the application will panic (crash) when attempting to transfer funds to a VM.cooled contract. This can cause issues with the functionality of the contract and may result in lost funds.
**Q: How can I report this bug?**
-------------------------------
A: You can report this bug on the Forge GitHub page at https://github.com/foundry-rs/foundry. This will help to ensure that the bug is addressed and that future versions of Forge are free from this issue.
**Q: What is the recommended solution?**
-----------------------------------------
A: The recommended solution is to remove the `vm.cool()` function call or to use a different approach to interact with the contract. This will ensure that the contract is not in a state where it is not executing any code, and this will prevent the bug from occurring.
**Q: What are the implications of this bug?**
--------------------------------------------
A: The implications of this bug are that it highlights the importance of understanding the behavior of contracts in different states, especially when it comes to interactions with the virtual machine (VM). This bug demonstrates the need for careful consideration when using the `vm.cool()` function and when interacting with contracts in different states.
**Q: Can this bug be fixed?**
---------------------------
A: Yes, this bug can be fixed by removing the `vm.cool()` function call or by using a different approach to interact with the contract. This will ensure that the contract is not in a state where it is not executing any code, and this will prevent the bug from occurring.
**Q: What is the next step?**
---------------------------
A: The next step is to ensure that the contract is not cooled when attempting to transfer funds to it. This can be achieved by removing the `vm.cool()` function call or by using a different approach to interact with the contract.
**Q: What are the benefits of fixing this bug?**
------------------------------------------------
A: The benefits of fixing this bug are that it will ensure that the contract is functioning correctly and that funds are not lost due to the bug. This will also help to improve the overall security and reliability of the contract.
**Q: What are the potential consequences of not fixing this bug?**
----------------------------------------------------------------
A: The potential consequences of not fixing this bug are that the contract may continue to malfunction and that funds may be lost due to the bug. This can result in a loss of trust in the contract and may lead to a decline in its usage.
**Q: What is the recommended course of action?**
------------------------------------------------
A: The recommended course of action is to remove the `vm.cool()` function call or to use a different approach to interact with the contract. This will ensure that the contract is not in a state where it is not executing any code, and this will prevent the bug from occurring.