foundry-rs / foundry-rs/forge-std
bug(StdStorage): find() fails for packed struct slots
- Dominant language
- Solidity
- Stars
- 1.1k
- Forks
- 520
- Avg merge
- 2d 21h
- Merged PRs (30d)
- 11
Description
Hello I opened a discussion here: https://github.com/foundry-rs/foundry/discussions/2188 but was recommended to open an issue as there may be a bug.
I created a mock contract to simulate Property Management. Please see below:
``` solidity
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
contract PropertyManagement {
address payable private propertyManager;
address payable private tenant;
using Counters for Counters.Counter;
Counters.Counter private _propertyId;
Counters.Counter private _agreementId;
struct Property {
uint256 propertyId;
uint256 rent;
uint8 bedrooms;
uint8 bathrooms;
address _tenant;
bool vacant;
}
struct Agreement {
Property property;
uint256 agreementId;
uint256 duration;
address _tenant;
address _propertyManager;
}
mapping(uint => Property) public propertyById;
mapping(uint => Agreement) public agreementById;
constructor(address _propertymanager) {
propertyManager = payable(_propertymanager);
}
receive() external payable {}
modifier onlyPropertyManager {
require(msg.sender == propertyManager, "You're not the property manager.");
_;
}
function createProperty(uint256 _rent, uint8 _bedrooms, uint8 _bathrooms) public onlyPropertyManager {
_propertyId.increment();
uint256 setPropertyId = _propertyId.current();
Property storage property = propertyById[setPropertyId];
property.propertyId = setPropertyId;
property.rent = _rent;
property.bedrooms = _bedrooms;
property.bathrooms = _bathrooms;
property.vacant = true;
}
function createAgreement(uint256 _pId, uint256 _duration, address _tenant, uint256 _amount) public payable onlyPropertyManager {
Property memory property = propertyById[_pId];
require(property.rent == _amount, "Please provide correct amount.");
require(_amount <= msg.sender.balance, "You dont have enough money.");
_agreementId.increment();
uint256 setAgreementId = _agreementId.current();
Agreement storage agreement = agreementById[setAgreementId];
agreement.property = property;
agreement.agreementId = setAgreementId;
agreement.duration = _duration;
agreement._tenant = _tenant;
agreement._propertyManager = msg.sender;
payable(address(this)).transfer(_amount);
Property storage rental = propertyById[_pId];
rental.vacant = false;
rental._tenant = _tenant;
}
}
```
Two of my tests are below:
``` solidity
function testCheckTenant() public {
vm.prank(address(1));
propertyManagement.createProperty(1000, 3, 3);
vm.prank(address(1));
propertyManagement.createAgreement{value: 1000}(1, 1, tenant, 1000);
address slot = stdstore
.target(address(propertyManagement))
.sig(propertyManagement.agreementById.selector)
.with_key(1)
.depth(2)
.read_address();
emit log_address(slot);
//assertEq(address(uint160(uint(vm.load(address(propertyManagement), slot)))), tenant);
}
function testCreateProperty() public {
vm.prank(address(1));
propertyManagement.createProperty(1000, 4, 3);
uint256 slot = stdstore
.target(address(propertyManagement))
.sig(propertyManagement.propertyById.selector)
.with_key(1)
.depth(2)
.find();
assertEq(uint(vm.load(address(propertyManagement), bytes32(slot))),4);
}
```
I am unable to access slots past slot 0 and 1 for `testCreateProperty()` and have trouble accessing any of my needed slots on `testCheckTenant()`. I was told that Forge may have difficulties with packed structs like my `Property` struct, but also having issues with the `Agreement` struct - maybe in part due to the fact that I store the `Property` struct in my `Agreement` struct.
I did notice when I was doing my test yesterday that when i switched the `bedrooms` field in `Property` from uint8 to uint256 that it did work so that does seem to be part of the problem. However, it is not only the Property struct it's also the Agreement struct that I cannot access.
Appreciate the guidance on this and interested to know if this is a bug with forge-std. Thanks!
Contributor guide
Assessment
This issue has not been assessed yet.