Add timestamp based governor with EIP-6372 and EIP-5805 (#3934)

Co-authored-by: Francisco Giordano <fg@frang.io>
Co-authored-by: Ernesto García <ernestognw@gmail.com>
Co-authored-by: Francisco <frangio.1@gmail.com>
This commit is contained in:
Hadrien Croubois
2023-02-09 22:33:55 +01:00
committed by GitHub
parent 94cd8ef12e
commit 790cc5b65a
42 changed files with 4081 additions and 3209 deletions

View File

@ -10,7 +10,6 @@ for (const name in oldLayout) {
if (name in newLayout) {
const report = getStorageUpgradeReport(oldLayout[name], newLayout[name], {});
if (!report.ok) {
console.log(`ERROR: Storage incompatibility in ${name}`);
console.log(report.explain());
process.exitCode = 1;
}

View File

@ -10,6 +10,14 @@ const { argv } = require('yargs')
choices: ['shell', 'markdown'],
default: 'shell',
},
hideEqual: {
type: 'boolean',
default: true,
},
strictTesting: {
type: 'boolean',
default: false,
},
});
// Deduce base tx cost from the percentage denominator
@ -40,7 +48,7 @@ class Report {
}
// Compare two reports
static compare(update, ref, opts = { hideEqual: true }) {
static compare(update, ref, opts = { hideEqual: true, strictTesting: false }) {
if (JSON.stringify(update.config.metadata) !== JSON.stringify(ref.config.metadata)) {
throw new Error('Reports produced with non matching metadata');
}
@ -70,7 +78,9 @@ class Report {
const methods = Object.keys(update.info.methods)
.filter(key => ref.info.methods[key])
.filter(key => update.info.methods[key].numberOfCalls > 0)
.filter(key => update.info.methods[key].numberOfCalls === ref.info.methods[key].numberOfCalls)
.filter(
key => !opts.strictTesting || update.info.methods[key].numberOfCalls === ref.info.methods[key].numberOfCalls,
)
.map(key => ({
contract: ref.info.methods[key].contract,
method: ref.info.methods[key].fnSig,
@ -220,7 +230,7 @@ function formatCmpMarkdown(rows) {
}
// MAIN
const report = Report.compare(Report.load(argv._[0]), Report.load(argv._[1]));
const report = Report.compare(Report.load(argv._[0]), Report.load(argv._[1]), argv);
switch (argv.style) {
case 'markdown':

View File

@ -1,7 +1,28 @@
const format = require('../format-lines');
// OPTIONS
const defaultOpts = size => ({
historyTypeName: `Trace${size}`,
checkpointTypeName: `Checkpoint${size}`,
checkpointFieldName: '_checkpoints',
keyTypeName: `uint${256 - size}`,
keyFieldName: '_key',
valueTypeName: `uint${size}`,
valueFieldName: '_value',
});
const VALUE_SIZES = [224, 160];
const OPTS = VALUE_SIZES.map(size => defaultOpts(size));
const LEGACY_OPTS = {
...defaultOpts(224),
historyTypeName: 'History',
checkpointTypeName: 'Checkpoint',
keyFieldName: '_blockNumber',
};
// TEMPLATE
const header = `\
pragma solidity ^0.8.0;
@ -62,6 +83,31 @@ function upperLookup(${opts.historyTypeName} storage self, ${opts.keyTypeName} k
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, 0, len);
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
}
/**
* @dev Returns the value in the most recent checkpoint with key lower or equal than the search key.
*
* NOTE: This is a variant of {upperLookup} that is optimised to find "recent" checkpoint (checkpoints with high keys).
*/
function upperLookupRecent(${opts.historyTypeName} storage self, ${opts.keyTypeName} key) internal view returns (${opts.valueTypeName}) {
uint256 len = self.${opts.checkpointFieldName}.length;
uint256 low = 0;
uint256 high = len;
if (len > 5) {
uint256 mid = len - Math.sqrt(len);
if (key < _unsafeAccess(self.${opts.checkpointFieldName}, mid)._key) {
high = mid;
} else {
low = mid + 1;
}
}
uint256 pos = _upperBinaryLookup(self.${opts.checkpointFieldName}, key, low, high);
return pos == 0 ? 0 : _unsafeAccess(self.${opts.checkpointFieldName}, pos - 1).${opts.valueFieldName};
}
`;
const legacyOperations = opts => `\
@ -263,26 +309,6 @@ function _unsafeAccess(${opts.checkpointTypeName}[] storage self, uint256 pos)
`;
/* eslint-enable max-len */
// OPTIONS
const defaultOpts = size => ({
historyTypeName: `Trace${size}`,
checkpointTypeName: `Checkpoint${size}`,
checkpointFieldName: '_checkpoints',
keyTypeName: `uint${256 - size}`,
keyFieldName: '_key',
valueTypeName: `uint${size}`,
valueFieldName: '_value',
});
const OPTS = VALUE_SIZES.map(size => defaultOpts(size));
const LEGACY_OPTS = {
...defaultOpts(224),
historyTypeName: 'History',
checkpointTypeName: 'Checkpoint',
keyFieldName: '_blockNumber',
};
// GENERATE
module.exports = format(
header.trimEnd(),