Skip to content

Commit be87e5c

Browse files
chore: Restore EigenPod.spec
1 parent 2c4f6fb commit be87e5c

File tree

1 file changed

+45
-67
lines changed

1 file changed

+45
-67
lines changed

certora/specs/pods/EigenPod.spec

Lines changed: 45 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -142,18 +142,6 @@ invariant withdrawnValidatorsHaveZeroRestakedGwei(bytes32 pubkeyHash)
142142
(get_restakedBalanceGwei(pubkeyHash) == 0);
143143

144144

145-
ghost mathint sumOfActiveValidatorBalanceGwei {
146-
init_state axiom sumOfActiveValidatorBalanceGwei == 0;
147-
axiom sumOfActiveValidatorBalanceGwei >= 0; // not negative
148-
}
149-
150-
// hook Sstore _validatorPubkeyHashToInfo[KEY bytes32 validatorPubkeyHash].prev uint64 newValue (uint64 oldValue) {
151-
// if (validatorStatus(pubkeyHash) == IEigenPod.VALIDATOR_STATUS.ACTIVE) {
152-
// sumOfActiveValidatorPrevBalanceGwei = sumOfActiveValidatorPrevBalanceGwei + to_mathint(newValue) - to_mathint(oldValue);
153-
// }
154-
// }
155-
156-
157145
// // TODO: see if this draft rule can be salvaged
158146
// // draft rule to capture the following behavior (or at least most of it):
159147
// // The core invariant that ought to be maintained across the EPM and the EPs is that
@@ -180,65 +168,55 @@ hook Sstore _validatorPubkeyHashToInfo[KEY bytes32 validatorPubkeyHash].restaked
180168
to_mathint(newValue) * 1000000000 -
181169
to_mathint(oldValue) * 1000000000
182170
);
183-
184-
// TODO
185-
// if (validatorStatus(validatorPubkeyHash) == IEigenPod.VALIDATOR_STATUS.ACTIVE && _validatorPubkeyHashToInfo[validatorPubkeyHash].lastCheckpointedAt < currentContract.currentCheckpointTimestamp) {
186-
// sumOfActiveValidatorBalanceGwei = sumOfActiveValidatorBalanceGwei + to_mathint(newValue) - to_mathint(oldValue);
187-
// }
188171
}
189172

190-
// TODO
191-
// invariant sumOfActiveValidatorsIsPrevBeaconGwei()
192-
// sumOfActiveValidatorBalanceGwei == currentContract._currentCheckpoint.prevBeaconBalanceGwei;
193-
194-
// TODO
195-
// rule consistentAccounting() {
196-
// // fetch info before call
197-
// int256 podOwnerSharesBefore = get_podOwnerShares();
198-
// uint256 withdrawableRestakedExecutionLayerGweiBefore = get_withdrawableRestakedExecutionLayerGwei();
199-
// uint256 eigenPodBalanceBefore = get_ETH_Balance();
200-
// // filter down to valid pre-states
201-
// require(sumOfValidatorRestakedbalancesWei ==
202-
// to_mathint(podOwnerSharesBefore) - to_mathint(withdrawableRestakedExecutionLayerGweiBefore));
173+
rule consistentAccounting() {
174+
// fetch info before call
175+
int256 podOwnerSharesBefore = get_podOwnerShares();
176+
uint256 withdrawableRestakedExecutionLayerGweiBefore = get_withdrawableRestakedExecutionLayerGwei();
177+
uint256 eigenPodBalanceBefore = get_ETH_Balance();
178+
// filter down to valid pre-states
179+
require(sumOfValidatorRestakedbalancesWei ==
180+
to_mathint(podOwnerSharesBefore) - to_mathint(withdrawableRestakedExecutionLayerGweiBefore));
203181

204-
// // perform arbitrary function call
205-
// method f;
206-
// env e;
207-
// calldataarg args;
208-
// f(e,args);
182+
// perform arbitrary function call
183+
method f;
184+
env e;
185+
calldataarg args;
186+
f(e,args);
209187

210-
// // fetch info after call
211-
// int256 podOwnerSharesAfter = get_podOwnerShares();
212-
// uint256 withdrawableRestakedExecutionLayerGweiAfter = get_withdrawableRestakedExecutionLayerGwei();
213-
// uint256 eigenPodBalanceAfter = get_ETH_Balance();
214-
// /**
215-
// * handling for weird, unrealistic edge case where calling `initialize` causes the pod owner to change, so the
216-
// * call to `get_podOwnerShares` queries the shares for a different address.
217-
// * calling `initialize` should *not* change user shares, so it is unrealistic to simulate it doing so.
218-
// */
219-
// if (f.selector == sig:initialize(address).selector) {
220-
// podOwnerSharesAfter = podOwnerSharesBefore;
221-
// }
222-
// // check post-state
223-
// // TODO: this check is still broken for `withdrawRestakedBeaconChainETH` since it does a low-level call to transfer the ETH, which triggers optimistic fallback dispatching
224-
// // special handling for one function
225-
// if (f.selector == sig:withdrawRestakedBeaconChainETH(address,uint256).selector) {
226-
// /* TODO: un-comment this once the dispatching is handled correctly
227-
// assert(sumOfValidatorRestakedbalancesWei ==
228-
// to_mathint(podOwnerSharesAfter) - to_mathint(withdrawableRestakedExecutionLayerGweiAfter)
229-
// // adjustment term for the ETH balance of the contract changing
230-
// + to_mathint(eigenPodBalanceBefore) - to_mathint(eigenPodBalanceAfter),
231-
// "invalid post-state");
232-
// */
233-
// // TODO: delete this once the above is salvaged (was added since CVL forbids empty blocks)
234-
// assert(true);
235-
// // outside of special case, we don't need the adjustment term
236-
// } else {
237-
// assert(sumOfValidatorRestakedbalancesWei ==
238-
// to_mathint(podOwnerSharesAfter) - to_mathint(withdrawableRestakedExecutionLayerGweiAfter),
239-
// "invalid post-state");
240-
// }
241-
// }
188+
// fetch info after call
189+
int256 podOwnerSharesAfter = get_podOwnerShares();
190+
uint256 withdrawableRestakedExecutionLayerGweiAfter = get_withdrawableRestakedExecutionLayerGwei();
191+
uint256 eigenPodBalanceAfter = get_ETH_Balance();
192+
/**
193+
* handling for weird, unrealistic edge case where calling `initialize` causes the pod owner to change, so the
194+
* call to `get_podOwnerShares` queries the shares for a different address.
195+
* calling `initialize` should *not* change user shares, so it is unrealistic to simulate it doing so.
196+
*/
197+
if (f.selector == sig:initialize(address).selector) {
198+
podOwnerSharesAfter = podOwnerSharesBefore;
199+
}
200+
// check post-state
201+
// TODO: this check is still broken for `withdrawRestakedBeaconChainETH` since it does a low-level call to transfer the ETH, which triggers optimistic fallback dispatching
202+
// special handling for one function
203+
if (f.selector == sig:withdrawRestakedBeaconChainETH(address,uint256).selector) {
204+
/* TODO: un-comment this once the dispatching is handled correctly
205+
assert(sumOfValidatorRestakedbalancesWei ==
206+
to_mathint(podOwnerSharesAfter) - to_mathint(withdrawableRestakedExecutionLayerGweiAfter)
207+
// adjustment term for the ETH balance of the contract changing
208+
+ to_mathint(eigenPodBalanceBefore) - to_mathint(eigenPodBalanceAfter),
209+
"invalid post-state");
210+
*/
211+
// TODO: delete this once the above is salvaged (was added since CVL forbids empty blocks)
212+
assert(true);
213+
// outside of special case, we don't need the adjustment term
214+
} else {
215+
assert(sumOfValidatorRestakedbalancesWei ==
216+
to_mathint(podOwnerSharesAfter) - to_mathint(withdrawableRestakedExecutionLayerGweiAfter),
217+
"invalid post-state");
218+
}
219+
}
242220

243221
/*
244222
rule baseInvariant() {

0 commit comments

Comments
 (0)