one more TC cleaning

This commit is contained in:
Aleksander Kryukov
2022-03-31 21:08:00 +01:00
parent 53b6ed80bb
commit 50cf82823e
2 changed files with 44 additions and 31 deletions

View File

@ -3,8 +3,9 @@ certoraRun \
--verify TimelockControllerHarness:certora/specs/TimelockController.spec \ --verify TimelockControllerHarness:certora/specs/TimelockController.spec \
--solc solc8.2 \ --solc solc8.2 \
--optimistic_loop \ --optimistic_loop \
--staging alex/unify-hash-functions \ --loop_iter 3 \
--staging alex/new-dt-hashing-alpha \
--rule_sanity \ --rule_sanity \
--rule "$1" \ --rule "$1" \
--msg "$1 false check with hash" --msg "$1"

View File

@ -5,16 +5,13 @@ methods {
_DONE_TIMESTAMP() returns(uint256) envfree _DONE_TIMESTAMP() returns(uint256) envfree
_minDelay() returns(uint256) envfree _minDelay() returns(uint256) envfree
getMinDelay() returns(uint256) envfree getMinDelay() returns(uint256) envfree
hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) returns(bytes32) envfree
cancel(bytes32) cancel(bytes32)
schedule(address, uint256, bytes, bytes32, bytes32, uint256) schedule(address, uint256, bytes32, bytes32, bytes32, uint256)
execute(address, uint256, bytes, bytes32, bytes32) execute(address, uint256, bytes, bytes32, bytes32)
hashOperation(address target, uint256 value, bytes data, bytes32 predecessor, bytes32 salt) returns(bytes32) envfree // => uniqueHashGhost(target, value, data, predecessor, salt)
} }
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Definitions // // Definitions //
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -45,6 +42,19 @@ function hashIdCorrelation(bytes32 id, address target, uint256 value, bytes data
} }
function executionsCall(method f, env e, address target, uint256 value, bytes data,
bytes32 predecessor, bytes32 salt, uint256 delay,
address[] targets, uint256[] values, bytes[] datas) {
if (f.selector == execute(address, uint256, bytes, bytes32, bytes32).selector) {
execute(e, target, value, data, predecessor, salt);
} else if (f.selector == executeBatch(address[], uint256[], bytes[], bytes32, bytes32).selector) {
executeBatch(e, targets, values, datas, predecessor, salt);
} else {
calldataarg args;
f(e, args);
}
}
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Ghosts // // Ghosts //
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
@ -63,22 +73,24 @@ function hashIdCorrelation(bytes32 id, address target, uint256 value, bytes data
rule keccakCheck(method f, env e){ rule keccakCheck(method f, env e){
address target; address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;
uint256 value; address targetRand; uint256 valueRand; bytes dataRand; bytes32 predecessorRand; bytes32 saltRand;
bytes data;
bytes32 predecessor;
bytes32 salt;
require data.length < 3; require data.length < 4;
// uint256 freshIndex;
// require freshIndex <= data.length
// require target != targetRand || value != valueRand || data[freshIndex] != dataRand[freshIndex] || predecessor != predecessorRand || salt != saltRand;
bytes32 a = hashOperation(target, value, data, predecessor, salt); bytes32 a = hashOperation(target, value, data, predecessor, salt);
bytes32 b = hashOperation(target, value, data, predecessor, salt); bytes32 b = hashOperation(target, value, data, predecessor, salt);
// bytes32 c = hashOperation(targetRand, valueRand, dataRand, predecessorRand, saltRand);
assert a == b, "hashes are different"; assert a == b, "hashes are different";
// assert a != c, "hashes are the same";
} }
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
// STATE TRANSITIONS // STATE TRANSITIONS
///////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////
@ -99,7 +111,7 @@ rule unsetPendingTransitionGeneral(method f, env e){
} }
// STATUS - verified // STATUS -
// unset() -> pending() via schedule() and scheduleBatch() only // unset() -> pending() via schedule() and scheduleBatch() only
rule unsetPendingTransitionMethods(method f, env e){ rule unsetPendingTransitionMethods(method f, env e){
bytes32 id; bytes32 id;
@ -109,8 +121,10 @@ rule unsetPendingTransitionMethods(method f, env e){
calldataarg args; calldataarg args;
f(e, args); f(e, args);
assert pending(id) => f.selector == schedule(address, uint256, bytes, bytes32, bytes32, uint256).selector bool tmp = pending(id);
|| f.selector == scheduleBatch(address[], uint256[], bytes[], bytes32, bytes32, uint256).selector , "Why do we need to follow the schedule?";
assert pending(id) => (f.selector == schedule(address, uint256, bytes, bytes32, bytes32, uint256).selector
|| f.selector == scheduleBatch(address[], uint256[], bytes[], bytes32, bytes32, uint256).selector), "Why do we need to follow the schedule?";
} }
@ -181,17 +195,19 @@ rule minDealyOnlyChange(method f, env e){
// execute() is the only way to set timestamp to 1 // execute() is the only way to set timestamp to 1
rule getTimestampOnlyChange(method f, env e){ rule getTimestampOnlyChange(method f, env e){
bytes32 id; bytes32 id;
address target; uint256 value; bytes data ;bytes32 predecessor; bytes32 salt; uint256 delay; address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt; uint256 delay;
address[] targets; uint256[] values; bytes[] datas;
require (targets[0] == target && values[0] == value && datas[0] == data)
|| (targets[1] == target && values[1] == value && datas[1] == data)
|| (targets[2] == target && values[2] == value && datas[2] == data);
require getTimestamp(id) != 1;
hashIdCorrelation(id, target, value, data, predecessor, salt); hashIdCorrelation(id, target, value, data, predecessor, salt);
calldataarg args; executionsCall(f, e, target, value, data, predecessor, salt, delay, targets, values, datas);
// write helper function with values from hashOperation() call;
f(e, args);
assert getTimestamp(id) == 1 => f.selector == execute(address, uint256, bytes, bytes32, bytes32).selector assert getTimestamp(id) == 1 => f.selector == execute(address, uint256, bytes, bytes32, bytes32).selector
|| f.selector == executeBatch(address[], uint256[], bytes[], bytes32, bytes32).selector , "Did you find a way to break the system?"; || f.selector == executeBatch(address[], uint256[], bytes[], bytes32, bytes32).selector, "Did you find a way to break the system?";
} }
@ -233,20 +249,16 @@ rule executeRevertFromUnset(method f, env e, env e2){
address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt; address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;
bytes32 id; bytes32 id;
// hashIdCorrelation(id, target, value, data, predecessor, salt); hashIdCorrelation(id, target, value, data, predecessor, salt);
require data.length < 4;
// require hashOperation(target, value, data, predecessor, salt) == id;
require unset(id); require unset(id);
scheduleCheck1@withrevert(e, id); execute@withrevert(e, target, value, data, predecessor, salt);
// execute@withrevert(e, target, value, data, predecessor, salt);
assert lastReverted, "you go against execution nature"; assert lastReverted, "you go against execution nature";
} }
// STATUS - verified // STATUS -
// Execute reverts => state returns to pending // Execute reverts => state returns to pending
rule executeRevertEffectCheck(method f, env e){ rule executeRevertEffectCheck(method f, env e){
address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt; address target; uint256 value; bytes data; bytes32 predecessor; bytes32 salt;