foundry-rs / foundry-rs/forge-std

bug(StdStorage): find() fails for packed struct slots

Open
#101 1 comment 1 reaction 0 assignees View on GitHub
bug
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.