-
Notifications
You must be signed in to change notification settings - Fork 27
Utilizes rollfork to obsolete deploy-info script #166
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
} | ||
|
||
uint256 low = 5273074; // MCD_VAT Deployed Aug-06-2021 04:26:38 PM +UTC | ||
uint256 high = block.number; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint256 high = block.number; | |
uint256 max = block.number; |
src/DssSpell.t.base.sol
Outdated
return; | ||
} | ||
|
||
uint256 low = 5273074; // MCD_VAT Deployed Aug-06-2021 04:26:38 PM +UTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see why you picked this reference point, but why not pick a recent block. We know that this search really only needs to look at blocks for future spells, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, taking into account this is for future spells we could put a recent block here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created this to address this issue: #168
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Block is where the vat was deployed on goerli. Binary search is O(log n)
so it doesn't matter whether we use this or block 0, the search time will not differ much.
src/DssSpell.t.base.sol
Outdated
return; | ||
} | ||
|
||
uint256 low = 5273074; // MCD_VAT Deployed Aug-06-2021 04:26:38 PM +UTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
uint256 low = 5273074; // MCD_VAT Deployed Aug-06-2021 04:26:38 PM +UTC | |
uint256 min = 5273074; // MCD_VAT Deployed Aug-06-2021 04:26:38 PM +UTC |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I avoided max and min due to higher possibilities of collision with global variables.
// we want to roll our fork to the block where it was deployed | ||
// this means the test suite will continue to accurately pass/fail | ||
// even if mainnet has already scheduled/cast the spell |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// we want to roll our fork to the block where it was deployed | |
// this means the test suite will continue to accurately pass/fail | |
// even if mainnet has already scheduled/cast the spell | |
// we want to roll our fork to a block after it was deployed and | |
// before it was scheduled this means the test suite will continue | |
// to accurately pass/fail even if goerli has already | |
// scheduled/cast the spell |
} | ||
|
||
function _rollToDeployedSpellBlock(address _spell) internal { | ||
if (_spell == address(0)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure I understand this part. The != address(0) check is already happening before calling this function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reusability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A general version of this could probably be moved into dss-test
src/DssSpell.t.base.sol
Outdated
uint256 mid; | ||
|
||
while (low < high) { | ||
mid = (low & high) + (low ^ high) / 2; // rounds down |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why we say that the simple (low + high) / 2;
doesn't round down?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it rounds down to the closest integer, the other way it rounds down towards zero, truncate (I should have specified that).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't understand what you mean. Rounds towards zero?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe with some concrete examples for both ways I can understand what you mean.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mid = (low & high) + (low ^ high) / 2; // rounds down | |
mid = (low & high) + (low ^ high) / 2; // rounds down to zero, truncate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah ok, that's a complete different explanation from what you mentioned above.
It doesn't have anything to do with one "rounding down to the closest integer" vs the other "rounding down towards zero, truncate" (as they both mean the same exact same thing).
They both do the exact same thing, rounds down to the closest integer or rounds down towards zero.
The only difference is one avoids a possible overflow. So let's try to understand the reasons before doing a change and explain it.
In this specific case, the overflow won't happen in practice, so maybe it is just better to keep the simpler form. To be honest I would need to start digging in order to understand why this math does the same thing (just glancing I don't get it). Maybe as it is part of a known library we can just leave it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testing on remix I got both implementation rounding towards zero or truncate and checking solc docs that's seems the case, maybe the issue I was having here was overflow of some sort.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do you have an overflow summing two block numbers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so, testing again against the blocks above, where I noticed the strange pattern (pass, fail, stuck) it seems to pass now with both implementations, so the issue was probably the comparison and the mid bump off by one, but anyway, I think the proposed implementation looks better for general purposes, in case the binary search pattern will be reused, and I agree that a rational would have been helpful there but was driven mostly by reusing a consolidated library pattern, adjusting it to our needs and cover the test scenarios where the previous implementation was having issues and sharing for reviews and discussion.
spellValues.deployed_spell_created = spellValues.deployed_spell != address(0) ? spellValues.deployed_spell_created : block.timestamp; | ||
if (spellValues.deployed_spell != address(0)) { | ||
spell = DssSpell(spellValues.deployed_spell); | ||
if (spell.eta() != 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm isn't there an issue here? We are removing the created timestamp as we assume it will be always block.timestamp
(as we are rolling to the deployment block). However if the spell was deployed but not scheduled, this condition won't be true, then there won't be a roll to the deployment block, meaning that we will be assuming an incorrect timestamp as the deployment of the spell.
The immediate solution is removing this if
rolling always that exists a deployed spell.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was added so that during the time after deployment before scheduling, spell crafters and reviewers do not need a local archive node. Once the spell is scheduled the local tests without an archive would fail (already scheduled), with this they will fail because forge can't rollFork
. But I see your point about the later timestamp tests. Maybe we need to keep that piece in the config?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, if we want to keep this testing without archive, then we will need to do so, put back the timestamp in the config file. But doing that, I almost feel that all the binary search is less worth it and we should just keep the timestamp and block in the config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it would be worth it to see if the deploy script could automatically update with the spell address, timestamp, block number and then keep those values hardcoded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm you mean that the script reads the spell address from the config and looks for the timestamp and block and then saves it in the same config file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An alternative solution is always requesting an archive node, which IMO is a super expensive price to pay just for avoiding to complete two values in the config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just tested that case and I confirm testGeneral
Fails testing on block after the deployment one (via make test block=8451435
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fast nodes do have some archive state, but only the most recent 128 blocks... this won't be suitable for our purposes even if we cache the block number. Will need some further thought, maybe the solution, instead of testing the exact expiration time, would be to modify the test to ensure that the expiration is lteq now + expiration_threshold
instead of eq deployed time + expiration threshold
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Proposed fix here #172
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm aren't we being less specific with that test though? I mean we are putting a weaker check.
On the other hand I was more worried about all the tests that check the specific cast time and so, aren't those failing as well?
* add block start point caching * check low block first * don't write or roll a second time if low is correct' * move file var to function * forgot memory
|
Description
Builds upon the rollFork innovation to use binary search for deployed block.