Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Final version for Kontrol pausability proofs #9530

Merged
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
f51643f
Update tests to native symbolic `bytes` and `bytes[]`
JuanCoRo Feb 7, 2024
f667328
adding lemmas
PetarMax Feb 8, 2024
f937ee5
`run-kontrol.sh`: add more sensible parameters
JuanCoRo Feb 12, 2024
0305162
Change `startPrank` by `prank`
JuanCoRo Feb 12, 2024
5c04ae8
Replace `mockCall` workaround with `vm.mockCall`
JuanCoRo Feb 13, 2024
3710024
Make `bytes` length symbolic
JuanCoRo Feb 13, 2024
951609e
`KontrolUtils`: remove symbolic workarounds
JuanCoRo Feb 13, 2024
3e1b51b
`run-kontrol.sh`: add `prove_proveWithdrawalTransaction_paused`
JuanCoRo Feb 13, 2024
74b875f
`forge fmt`
JuanCoRo Feb 13, 2024
e5c0c5f
`versions.json`: bump Kontrol from `0.1.127` to `0.1.156`
JuanCoRo Feb 13, 2024
f62a205
Remove `ASSUME` comments
JuanCoRo Feb 13, 2024
3bc766a
ci: run kontrol on develop and allow manual dispatch
mds1 Feb 16, 2024
75d7481
ci: rename parameter
mds1 Feb 16, 2024
6498333
`OptimismPortalKontrol`: add remaining ranges for `_withdrawalProof`
JuanCoRo Feb 23, 2024
3f50519
Add forge-like UX to `run-kontrol.sh`
JuanCoRo Feb 23, 2024
2fbd742
`pausability-lemmas.k`: clean file
JuanCoRo Feb 23, 2024
34967a3
general tests, further lemmas, summary claim
PetarMax Feb 25, 2024
27a2d51
Address shellcheck failures
JuanCoRo Feb 27, 2024
9df081a
Change `pausability-lemmas.k` to `pausability-lemmas.md`
JuanCoRo Feb 28, 2024
269fb0b
`versions.json`: bump `kontrol` from `0.1.156` to `0.1.178`
JuanCoRo Mar 4, 2024
40abc60
`OptimismPortalKontrol`: update `kontrol` natspec to version 0.1.178
JuanCoRo Mar 4, 2024
f5ec8a4
`pausability-lemmas.md`: remove unused `Lemmas` header
JuanCoRo Mar 4, 2024
b203b54
Update packages/contracts-bedrock/test/kontrol/pausability-lemmas.md
JuanCoRo Mar 4, 2024
a4ec961
Update packages/contracts-bedrock/test/kontrol/pausability-lemmas.md
JuanCoRo Mar 4, 2024
fc60a41
Update packages/contracts-bedrock/test/kontrol/pausability-lemmas.md
JuanCoRo Mar 4, 2024
692f7c2
Update packages/contracts-bedrock/test/kontrol/pausability-lemmas.md
JuanCoRo Mar 4, 2024
9876b44
`pausability-lemmas.md`: fix spelling typo
JuanCoRo Mar 4, 2024
c45b3cd
`pausability-lemmas.md`: fix typo `bytearrays` to `byte arrays`
JuanCoRo Mar 4, 2024
c8d261a
`run-kontrol.sh`: correctly format temorarily unexecuted lemmas
JuanCoRo Mar 4, 2024
ae554b6
`common.sh`: execute `copy_to_docker` only when in docker mode
JuanCoRo Mar 4, 2024
74d84d1
`make-summary-deployment.sh`: add argument check before parsing
JuanCoRo Mar 4, 2024
1e3b767
Reflect `kontrol summary` change to `kontrol load-state-diff`
JuanCoRo Mar 4, 2024
84e2693
`pausability-lemmas.md`: remove upstreamed lemmas
JuanCoRo Mar 4, 2024
9515caf
fix: writing typos
JuanCoRo Mar 4, 2024
4bbf7b7
lemma text pass
PetarMax Mar 5, 2024
151519b
paragraph about summary maintainability
PetarMax Mar 5, 2024
4b70a43
README.md: include latest changes
JuanCoRo Mar 6, 2024
35f8541
pausability-lemmas.md: markdown link typo
JuanCoRo Mar 6, 2024
98ae98b
KontrolUtils: add documentation comment
JuanCoRo Mar 6, 2024
c721e62
pausability-lemmas.md: fix markdown typo vol2
JuanCoRo Mar 6, 2024
4fcf84a
pausability-lemmas.md: fix markdown typo vol3
JuanCoRo Mar 6, 2024
ca14537
Add specialized usage functions
JuanCoRo Mar 6, 2024
d580048
Merge remote-tracking branch 'origin/develop' into kontrol-symbolic-b…
JuanCoRo Mar 7, 2024
cfa14e0
`README.md`: remove `bash` in `make-summary-deployment.sh` description
JuanCoRo Mar 7, 2024
dcc0699
`README.md`: complete `Add New Proofs` section
JuanCoRo Mar 7, 2024
5d363da
versions.json: bump kontrol from 0.1.178 to 0.1.196
JuanCoRo Mar 12, 2024
4a0cabf
run-kontrol.sh: add `--xml-test-report` flag
JuanCoRo Mar 12, 2024
834e4be
.gitignore: add `kontrol_prove_report.xml`
JuanCoRo Mar 12, 2024
507dea6
foundry.toml: set `ast = true` in `kprove` profile
JuanCoRo Mar 12, 2024
6c01d0f
config.yml: set correct path for kontrol `store_artifacts`
JuanCoRo Mar 12, 2024
6caa62d
config.yml: add `store_test_results` step to `kontrol-tests` job
JuanCoRo Mar 12, 2024
8f8a27c
package.json: execute `run-kontrol.sh` with `script` option
JuanCoRo Mar 12, 2024
d8914e3
run-kontrol.sh: remove proof with 10 elements in favor of 0 and 1
JuanCoRo Mar 12, 2024
0353cef
Merge remote-tracking branch 'origin/develop' into kontrol-symbolic-b…
JuanCoRo Mar 12, 2024
964f640
chore: typos and formatting
mds1 Mar 12, 2024
d702f20
ci: fix kontrol trigger
mds1 Mar 13, 2024
b1d895a
README.md: minor typo
JuanCoRo Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
902 changes: 900 additions & 2 deletions packages/contracts-bedrock/test/kontrol/pausability-lemmas.k

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,18 @@ contract L1CrossDomainMessengerKontrol is DeploymentSummary, KontrolUtils {
superchainConfig = SuperchainConfig(superchainConfigProxyAddress);
}

/// TODO: Replace struct parameters and workarounds with the appropriate
/// types once Kontrol supports symbolic `bytes` and `bytes[]`
/// Tracking issue: https://github.com/runtimeverification/kontrol/issues/272
function prove_relayMessage_paused(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gas
uint256 _gas,
bytes calldata _message
)
external
{
setUpInlined();

// ASSUME: Conservative upper bound on the `_message` length. Most contract calls will have
// a message length less than 600 bytes. This assumption can be removed once Kontrol
// supports symbolic `bytes`: https://github.com/runtimeverification/kontrol/issues/272
bytes memory _message = freshBigBytes(600);

// Pause System
vm.prank(superchainConfig.guardian());
superchainConfig.pause("identifier");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { KontrolUtils } from "./utils/KontrolUtils.sol";
import { Types } from "src/libraries/Types.sol";
import {
IL1ERC721Bridge as L1ERC721Bridge,
IL1CrossDomainMessenger as CrossDomainMessenger,
ISuperchainConfig as SuperchainConfig
} from "./interfaces/KontrolInterfaces.sol";

Expand All @@ -18,43 +19,30 @@ contract L1ERC721BridgeKontrol is DeploymentSummary, KontrolUtils {
superchainConfig = SuperchainConfig(superchainConfigProxyAddress);
}

/// TODO: Replace symbolic workarounds with the appropriate
/// types once Kontrol supports symbolic `bytes` and `bytes[]`
/// Tracking issue: https://github.com/runtimeverification/kontrol/issues/272
function prove_finalizeBridgeERC721_paused(
address _localToken,
address _remoteToken,
address _from,
address _to,
uint256 _amount
uint256 _amount,
bytes calldata _extraData
)
public
{
setUpInlined();

// Current workaround to be replaced with `vm.mockCall`, once the cheatcode is implemented in Kontrol
// This overrides the storage slot read by `CrossDomainMessenger::xDomainMessageSender`
// Tracking issue: https://github.com/runtimeverification/kontrol/issues/285
vm.store(
l1CrossDomainMessengerProxyAddress,
hex"00000000000000000000000000000000000000000000000000000000000000cc",
bytes32(uint256(uint160(address(l1ERC721Bridge.otherBridge()))))
);

// ASSUME: Conservative upper bound on the `_extraData` length, since extra data is optional
// for convenience of off-chain tooling. This assumption can be removed once Kontrol
// supports symbolic `bytes`: https://github.com/runtimeverification/kontrol/issues/272
bytes memory _extraData = freshBigBytes(64);

// Pause Standard Bridge
vm.prank(superchainConfig.guardian());
superchainConfig.pause("identifier");

// Pranking with `vm.prank` instead will result in failure from Kontrol
// Tracking issue: https://github.com/runtimeverification/kontrol/issues/316
vm.startPrank(address(l1ERC721Bridge.messenger()));
vm.mockCall(
address(l1ERC721Bridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(l1ERC721Bridge.otherBridge()))
);

vm.prank(address(l1ERC721Bridge.messenger()));
vm.expectRevert("L1ERC721Bridge: paused");
l1ERC721Bridge.finalizeBridgeERC721(_localToken, _remoteToken, _from, _to, _amount, _extraData);
vm.stopPrank();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { KontrolUtils } from "./utils/KontrolUtils.sol";
import { Types } from "src/libraries/Types.sol";
import {
IL1StandardBridge as L1StandardBridge,
IL1CrossDomainMessenger as CrossDomainMessenger,
ISuperchainConfig as SuperchainConfig
} from "./interfaces/KontrolInterfaces.sol";

Expand All @@ -18,77 +19,55 @@ contract L1StandardBridgeKontrol is DeploymentSummary, KontrolUtils {
superchainConfig = SuperchainConfig(superchainConfigProxyAddress);
}

/// TODO: Replace symbolic workarounds with the appropriate
/// types once Kontrol supports symbolic `bytes` and `bytes[]`
/// Tracking issue: https://github.com/runtimeverification/kontrol/issues/272
function prove_finalizeBridgeERC20_paused(
address _localToken,
address _remoteToken,
address _from,
address _to,
uint256 _amount
uint256 _amount,
bytes calldata _extraData
)
public
{
setUpInlined();

// Current workaround to be replaced with `vm.mockCall`, once the cheatcode is implemented in Kontrol
// This overrides the storage slot read by `CrossDomainMessenger::xDomainMessageSender`
// Tracking issue: https://github.com/runtimeverification/kontrol/issues/285
vm.store(
l1CrossDomainMessengerProxyAddress,
hex"00000000000000000000000000000000000000000000000000000000000000cc",
bytes32(uint256(uint160(address(l1standardBridge.otherBridge()))))
);

// ASSUME: Upper bound on the `_extraData` length, since extra data is optional for
// for convenience of off-chain tooling, and should not affect execution This assumption
// can be removed once Kontrol supports symbolic `bytes`:
// https://github.com/runtimeverification/kontrol/issues/272
bytes memory _extraData = freshBigBytes(32);

// Pause Standard Bridge
vm.prank(superchainConfig.guardian());
superchainConfig.pause("identifier");

// Pranking with `vm.prank` instead will result in failure from Kontrol
// Tracking issue: https://github.com/runtimeverification/kontrol/issues/316
vm.startPrank(address(l1standardBridge.messenger()));
vm.mockCall(
address(l1standardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(l1standardBridge.otherBridge()))
);

vm.prank(address(l1standardBridge.messenger()));
vm.expectRevert("StandardBridge: paused");
l1standardBridge.finalizeBridgeERC20(_localToken, _remoteToken, _from, _to, _amount, _extraData);
vm.stopPrank();
}

/// TODO: Replace symbolic workarounds with the appropriate
/// types once Kontrol supports symbolic `bytes` and `bytes[]`
/// Tracking issue: https://github.com/runtimeverification/kontrol/issues/272
function prove_finalizeBridgeETH_paused(address _from, address _to, uint256 _amount) public {
function prove_finalizeBridgeETH_paused(
address _from,
address _to,
uint256 _amount,
bytes calldata _extraData
)
public
{
setUpInlined();

// Current workaround to be replaced with `vm.mockCall`, once the cheatcode is implemented in Kontrol
// This overrides the storage slot read by `CrossDomainMessenger::xDomainMessageSender`
// Tracking issue: https://github.com/runtimeverification/kontrol/issues/285
vm.store(
l1CrossDomainMessengerProxyAddress,
hex"00000000000000000000000000000000000000000000000000000000000000cc",
bytes32(uint256(uint160(address(l1standardBridge.otherBridge()))))
);

// ASSUME: Upper bound on the `_extraData` length, since extra data is optional for
// for convenience of off-chain tooling, and should not affect execution This assumption
// can be removed once Kontrol supports symbolic `bytes`:
// https://github.com/runtimeverification/kontrol/issues/272
bytes memory _extraData = freshBigBytes(32);

// Pause Standard Bridge
vm.prank(superchainConfig.guardian());
superchainConfig.pause("identifier");

// Pranking with `vm.prank` instead will result in failure from Kontrol
// Tracking issue: https://github.com/runtimeverification/kontrol/issues/316
vm.startPrank(address(l1standardBridge.messenger()));
vm.mockCall(
address(l1standardBridge.messenger()),
abi.encodeWithSelector(CrossDomainMessenger.xDomainMessageSender.selector),
abi.encode(address(l1standardBridge.otherBridge()))
);

vm.prank(address(l1standardBridge.messenger()));
vm.expectRevert("StandardBridge: paused");
l1standardBridge.finalizeBridgeETH(_from, _to, _amount, _extraData);
vm.stopPrank();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,78 +20,35 @@ contract OptimismPortalKontrol is DeploymentSummary, KontrolUtils {
superchainConfig = SuperchainConfig(superchainConfigProxyAddress);
}

/// TODO: Replace struct parameters and workarounds with the appropriate
/// types once Kontrol supports symbolic `bytes` and `bytes[]`
/// Tracking issue: https://github.com/runtimeverification/kontrol/issues/272
/// @custom:kontrol-length-equals _withdrawalProof: 10,
/// @custom:kontrol-length-equals _withdrawalProof[]: 600,
/// @custom:kontrol-length-equals data: 1000,
function prove_proveWithdrawalTransaction_paused(
// WithdrawalTransaction args
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit,
// bytes memory _data,
Types.WithdrawalTransaction memory _tx,
uint256 _l2OutputIndex,
// OutputRootProof args
bytes32 _outputRootProof0,
bytes32 _outputRootProof1,
bytes32 _outputRootProof2,
bytes32 _outputRootProof3
Types.OutputRootProof calldata _outputRootProof,
bytes[] calldata _withdrawalProof
)
external
{
setUpInlined();

// ASSUME: This bound on the `_data` length is too low, and should be at least 1000 bytes.
// Kontrol currently hangs and fails with this value because of the resulting configuration
// size. For now we leave this as a low value to avoid the hang, but it should be increased
// once Kontrol is improved and supports symbolic `bytes`:
// https://github.com/runtimeverification/kontrol/issues/272
bytes memory _data = freshBigBytes(320);
bytes[] memory _withdrawalProof = freshWithdrawalProof();

Types.WithdrawalTransaction memory _tx =
Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data);
Types.OutputRootProof memory _outputRootProof =
Types.OutputRootProof(_outputRootProof0, _outputRootProof1, _outputRootProof2, _outputRootProof3);

// Pause Optimism Portal
vm.prank(optimismPortal.guardian());
superchainConfig.pause("identifier");

// No one can call proveWithdrawalTransaction
vm.expectRevert("OptimismPortal: paused");
optimismPortal.proveWithdrawalTransaction(_tx, _l2OutputIndex, _outputRootProof, _withdrawalProof);
}

/// TODO: Replace struct parameters and workarounds with the appropriate
/// types once Kontrol supports symbolic `bytes` and `bytes[]`
/// Tracking issue: https://github.com/runtimeverification/kontrol/issues/272
function prove_finalizeWithdrawalTransaction_paused(
uint256 _nonce,
address _sender,
address _target,
uint256 _value,
uint256 _gasLimit
)
external
{
function prove_finalizeWithdrawalTransaction_paused(Types.WithdrawalTransaction calldata _tx) external {
setUpInlined();

// ASSUME: This bound on the `_data` length is too low, and should be at least 1000 bytes.
// Kontrol currently hangs and fails with this value because of the resulting configuration
// size. For now we leave this as a low value to avoid the hang, but it should be increased
// once Kontrol is improved and supports symbolic `bytes`:
// https://github.com/runtimeverification/kontrol/issues/272
bytes memory _data = freshBigBytes(320);

// Pause Optimism Portal
vm.prank(optimismPortal.guardian());
superchainConfig.pause("identifier");

vm.expectRevert("OptimismPortal: paused");
optimismPortal.finalizeWithdrawalTransaction(
Types.WithdrawalTransaction(_nonce, _sender, _target, _value, _gasLimit, _data)
);
optimismPortal.finalizeWithdrawalTransaction(_tx);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,78 +4,7 @@ pragma solidity 0.8.15;
import { Vm } from "forge-std/Vm.sol";
import { KontrolCheats } from "kontrol-cheatcodes/KontrolCheats.sol";

// The GhostBytes contracts are a workaround to create a symbolic bytes array. This is slow, but
// required until symbolic bytes are supported in Kontrol: https://github.com/runtimeverification/kontrol/issues/272
contract GhostBytes {
bytes public ghostBytes;
}

contract GhostBytes10 {
bytes public ghostBytes0;
bytes public ghostBytes1;
bytes public ghostBytes2;
bytes public ghostBytes3;
bytes public ghostBytes4;
bytes public ghostBytes5;
bytes public ghostBytes6;
bytes public ghostBytes7;
bytes public ghostBytes8;
bytes public ghostBytes9;

function getGhostBytesArray() public view returns (bytes[] memory _arr) {
_arr = new bytes[](10);
_arr[0] = ghostBytes0;
_arr[1] = ghostBytes1;
_arr[2] = ghostBytes2;
_arr[3] = ghostBytes3;
_arr[4] = ghostBytes4;
_arr[5] = ghostBytes5;
_arr[6] = ghostBytes6;
_arr[7] = ghostBytes7;
_arr[8] = ghostBytes8;
_arr[9] = ghostBytes9;
}
}

/// @notice Tests inheriting this contract cannot be run with forge
abstract contract KontrolUtils is KontrolCheats {
Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));

/// @dev Creates a fresh bytes with length greater than 31
/// @param bytesLength: Length of the fresh bytes. Should be concrete
function freshBigBytes(uint256 bytesLength) internal returns (bytes memory sBytes) {
require(bytesLength >= 32, "Small bytes");

uint256 bytesSlotValue;
unchecked {
bytesSlotValue = bytesLength * 2 + 1;
}

// Deploy ghost contract
GhostBytes ghostBytes = new GhostBytes();

// Make the storage of the ghost contract symbolic
kevm.symbolicStorage(address(ghostBytes));

// Load the size encoding into the first slot of ghostBytes
vm.store(address(ghostBytes), bytes32(uint256(0)), bytes32(bytesSlotValue));

sBytes = ghostBytes.ghostBytes();
}

/// @dev Creates a bounded symbolic bytes[] memory representing a withdrawal proof.
function freshWithdrawalProof() public returns (bytes[] memory withdrawalProof) {
// ASSUME: Withdrawal proofs do not currently exceed 6 elements in length. This can be
// shrank to 2 for faster proof speeds during testing and development.
// TODO: Allow the array length range between 0 and 10 elements. This can be done once
// symbolic bytes are supported in Kontrol: https://github.com/runtimeverification/kontrol/issues/272
uint256 arrayLength = 6;
withdrawalProof = new bytes[](arrayLength);

for (uint256 i = 0; i < withdrawalProof.length; ++i) {
// ASSUME: Each element is 600 bytes. Proof elements are 17 * 32 = 544 bytes long, plus
// ~10% margin for RLP encoding:, giving us the 600 byte assumption.
withdrawalProof[i] = freshBigBytes(600);
}
}
}
10 changes: 5 additions & 5 deletions packages/contracts-bedrock/test/kontrol/scripts/run-kontrol.sh
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ regen=
#################################
# Tests to symbolically execute #
#################################
# Missing: OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused
test_list=( "OptimismPortalKontrol.prove_finalizeWithdrawalTransaction_paused" \
test_list=( "OptimismPortalKontrol.prove_proveWithdrawalTransaction_paused" \
"OptimismPortalKontrol.prove_finalizeWithdrawalTransaction_paused" \
"L1StandardBridgeKontrol.prove_finalizeBridgeERC20_paused" \
"L1StandardBridgeKontrol.prove_finalizeBridgeETH_paused" \
"L1ERC721BridgeKontrol.prove_finalizeBridgeERC721_paused" \
Expand All @@ -120,8 +120,8 @@ done
#########################
# kontrol prove options #
#########################
max_depth=1000000
max_iterations=1000000
max_depth=10000
max_iterations=10000
smt_timeout=100000
max_workers=7 # Set to 7 since the CI machine has 8 CPUs
# workers is the minimum between max_workers and the length of test_list
Expand All @@ -131,7 +131,7 @@ reinit=
break_on_calls=--no-break-on-calls
# break_on_calls=
auto_abstract=--auto-abstract-gas
# auto_abstract=
auto_abstract=
bug_report=--bug-report
bug_report=
use_booster=--use-booster
Expand Down
Loading