Reputation: 103
What I'm trying to achieve is to have two mappings of struct value type pointing to the same struct reference, so I can lookup and edit a specific struct instance in two ways. However, updating the struct in one mapping does not seem to update the struct in the other one. Here is my simplified contract to illustrate the idea:
contract Example {
mapping(uint => Pool) public poolsByDay;
mapping(uint => Pool) public poolsById;
constructor(uint day) public {
for (uint i = 1; i <= day; i++) {
Pool memory pool = Pool({
id: i,
amount: 0
});
poolsByDay[i] = pool;
poolsById[i] = pool;
}
}
function deposit(uint day, uint amount) external {
Pool storage pool = poolsByDay[day];
pool.amount += amount;
}
}
Notice that the keys for poolsByDay
may change every day. And I want to be able to lookup a pool either by day or by ID.
Here is my test:
const example = await Example.new(7)
const day = 1
const amount = 100e18
await example.deposit(day, amount.toString())
const pool = await example.poolsByDay(term)
const anotherPool = await example.poolsById(pool.id)
assert.equal(pool.amount, amount) // succeeded
assert.equal(anotherPool.amount, amount) // failed
From what I understand, Solidity struct is a reference type. So I'm expecting the modification of one pool will be reflected in both mappings poolsByDay
and poolsById
, but it's not. Is it that I failed to initialize two mappings correctly?
Upvotes: 2
Views: 1978
Reputation: 60143
No, the two mappings will point to distinct structs, so you'll need to handle the indirection yourself, e.g. by using a mapping from day to ID:
contract Example {
mapping(uint => uint) public poolsByDay;
mapping(uint => Pool) public poolsById;
constructor(uint day) public {
for (uint i = 1; i <= day; i++) {
poolsById[i] = Pool({ id: i, amount: 0 });
poolsByDay[i] = i;
}
}
function deposit(uint day, uint amount) external {
Pool storage pool = poolsById[poolsByDay[day]];
pool.amount += amount;
}
}
(In this contrived example, they seem to both use the same keys, but I assume in your real code there's a reason for having two mappings.)
Upvotes: 2