Skip to content

Conversation

@aspiers
Copy link
Contributor

@aspiers aspiers commented Sep 1, 2025

πŸ•“ Changelog

This PR introduces a new --simulate <rpc_url> CLI option, allowing users to fully simulate a proposed transaction before signing it. The simulation provides a detailed preview of what will happen, including all emitted events, making it especially useful for complex multi-step operations or when interacting with unfamiliar contracts. The implementation works by performing a traced call (cast call --trace) using the calculated transaction parameters (address, to, data) against the specified RPC endpoint, after outputting all relevant hash information. Please note that we override specific Safe contract storage slots for this call:

  • Set owners[signer_address] = address(0x1) to make a random signer_address an owner,
  • Set threshold = 1 to allow single-owner execution,
  • Set nonce equal to the current on-chain value current_nonce of the configured multisig address address,
  • Disable the configured transaction and module guards.

Then execute the cast call --trace command with the transaction payload from signer_address using the overridden state.

Important

The new version of this script is designed to work with the latest stable versions of cast and chisel, starting from version 1.3.5.

Test Examples

./safe_hashes.sh --network ethereum --address 0x5EA1d9A6dDC3A0329378a327746D71A2019eC332 --nonce 6 --simulate https://eth.llamarpc.com

returns:

===================================
= Selected Network Configurations =
===================================

Network: ethereum
Chain ID: 1

========================================
= Transaction Data and Computed Hashes =
========================================

> Transaction Data:
Multisig address: 0x5EA1d9A6dDC3A0329378a327746D71A2019eC332
To: 0x9641d764fc13c8B624c04430C7356C1C7C8102e2
Value: 0
Data: 0x8d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013200cfbfac74c26f8647cbdb8c5caf80bb5b32e4313400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044dd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf08000000000000000000000000000000
Operation: Delegatecall (trusted delegatecall)
Safe Transaction Gas: 0
Base Gas: 0
Gas Price: 0
Gas Token: 0x0000000000000000000000000000000000000000
Refund Receiver: 0x0000000000000000000000000000000000000000
Nonce: 6
Encoded message: 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d80000000000000000000000009641d764fc13c8b624c04430c7356c1c7c8102e200000000000000000000000000000000000000000000000000000000000000003d40cdc9a33bf2a4afd7df145cb5728a5110a40b218c4bd9cd00d4251479d9d50000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006
Method: multiSend
Parameters: [
  {
    "name": "transactions",
    "type": "bytes",
    "value": "0x00cfbfac74c26f8647cbdb8c5caf80bb5b32e4313400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044dd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf0800",
    "valueDecoded": [
      {
        "operation": 0,
        "to": "0xCFbFaC74C26F8647cBDb8c5caf80BB5b32E43134",
        "value": "0",
        "data": "0xdd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b3180000000000000000000000000000000000000000000000000000000000000001",
        "dataDecoded": {
          "method": "removeDelegate",
          "parameters": [
            {
              "name": "delegate",
              "type": "address",
              "value": "0xf46c6d6e62f59D9222F3812874211dF07cF7b318"
            },
            {
              "name": "removeAllowances",
              "type": "bool",
              "value": "True"
            }
          ]
        }
      },
      {
        "operation": 0,
        "to": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "value": "0",
        "data": "0xa9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf0800",
        "dataDecoded": {
          "method": "transfer",
          "parameters": [
            {
              "name": "to",
              "type": "address",
              "value": "0x1FE27A73Cd9f0b3C53b6E936D0b4F9B2f8ca3367"
            },
            {
              "name": "value",
              "type": "uint256",
              "value": "800000000"
            }
          ]
        }
      }
    ]
  }
]

> Hashes:
Domain hash: 0x58122EA8F001782FACC66EE5495A6B8B29730FADF352D8608CA86BD31569FCF5
Message hash: 0xE992E061576268328FAC9175D6AEA3DEFD4C3BEF83A0C6FE08F6AA5A222CBC45
Safe transaction hash: 0x27a0c4abf624b15b776f544a4b31ed4d50dee2b677c6497fbadf4f7a73be705e

==========================
= Transaction Simulation =
==========================

This simulation, run against the latest block, depends on data provided by your RPC provider. Using your own node is always recommended.

Please note that we override specific Safe contract storage slots for this call:
  - Set `owners[signer_address] = address(0x1)` to make a random `signer_address` address `0xD5AEB612f43919FCbfFd0eEa734D0E9130D14b2e` an `owner`,
  - Set `threshold = 1` to allow single-owner execution,
  - Set `nonce` equal to the current on-chain value `6` of the configured multisig address `0x5EA1d9A6dDC3A0329378a327746D71A2019eC332`,
  - Disable the configured transaction and module guards.

Then execute the `cast call --trace` command with the transaction payload from `signer_address` address `0xD5AEB612f43919FCbfFd0eEa734D0E9130D14b2e` using the overridden states:
```bash
cast call --trace --from "0xD5AEB612f43919FCbfFd0eEa734D0E9130D14b2e" \
  "0x5EA1d9A6dDC3A0329378a327746D71A2019eC332" \
  --data "0x6a7612020000000000000000000000009641d764fc13c8b624c04430c7356c1c7c8102e200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000001848d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013200cfbfac74c26f8647cbdb8c5caf80bb5b32e4313400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044dd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf0800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004101427eae1606844b055aabb63778fc9e523e48b25dff5dbd1db76752c68f338a14ef6bb18733969e9db45e96d89fab546609f9404e1f779d15248203d7c7c5a91b00000000000000000000000000000000000000000000000000000000000000" \
  --override-state-diff "0x5EA1d9A6dDC3A0329378a327746D71A2019eC332:0x269bb0dc23923a25a8c39074e6cb0c85f1f29fd13f8dfa05d81baf046ed3b9af:1,0x5EA1d9A6dDC3A0329378a327746D71A2019eC332:4:1,0x5EA1d9A6dDC3A0329378a327746D71A2019eC332:0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8:0,0x5EA1d9A6dDC3A0329378a327746D71A2019eC332:0xb104e0b93118902c651344349b610029d694cfdec91c589c91ebafbcd0289947:0" \
  --rpc-url "https://eth.llamarpc.com"
```

> Execution Traces:
Traces:
  [104531] 0x5EA1d9A6dDC3A0329378a327746D71A2019eC332::execTransaction(0x9641d764fc13c8B624c04430C7356C1C7C8102e2, 0, 0x8d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013200cfbfac74c26f8647cbdb8c5caf80bb5b32e4313400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044dd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf08000000000000000000000000000000, 1, 0, 0, 0, 0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000, 0x01427eae1606844b055aabb63778fc9e523e48b25dff5dbd1db76752c68f338a14ef6bb18733969e9db45e96d89fab546609f9404e1f779d15248203d7c7c5a91b)
    β”œβ”€ [99537] 0x41675C099F32341bf84BFc5382aF534df5C7461a::execTransaction(0x9641d764fc13c8B624c04430C7356C1C7C8102e2, 0, 0x8d80ff0a0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000013200cfbfac74c26f8647cbdb8c5caf80bb5b32e4313400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044dd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf08000000000000000000000000000000, 1, 0, 0, 0, 0x0000000000000000000000000000000000000000, 0x0000000000000000000000000000000000000000, 0x01427eae1606844b055aabb63778fc9e523e48b25dff5dbd1db76752c68f338a14ef6bb18733969e9db45e96d89fab546609f9404e1f779d15248203d7c7c5a91b) [delegatecall]
    β”‚   β”œβ”€ [3000] PRECOMPILES::ecrecover(0x27a0c4abf624b15b776f544a4b31ed4d50dee2b677c6497fbadf4f7a73be705e, 27, 569799068248606709654359279365657811530712758201901254503339124358604862346, 9469276693155409892942073865840739087499944749595054468651068267378848023977) [staticcall]
    β”‚   β”‚   └─ ← [Return] 0x000000000000000000000000d5aeb612f43919fcbffd0eea734d0e9130d14b2e
    β”‚   β”œβ”€ [76339] 0x9641d764fc13c8B624c04430C7356C1C7C8102e2::multiSend(0x00cfbfac74c26f8647cbdb8c5caf80bb5b32e4313400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044dd43a79f000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000000000000000000000000000000000000000000100a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044a9059cbb0000000000000000000000001fe27a73cd9f0b3c53b6e936d0b4f9b2f8ca3367000000000000000000000000000000000000000000000000000000002faf0800) [delegatecall]
    β”‚   β”‚   β”œβ”€ [29368] 0xCFbFaC74C26F8647cBDb8c5caf80BB5b32E43134::removeDelegate(0xf46c6d6e62f59D9222F3812874211dF07cF7b318, true)
    β”‚   β”‚   β”‚   β”œβ”€  emit topic 0: 0x9a9bc79dd7e42545ba12d5659704d73a9364d4a18e0a98ca1c992a3bc999d271
    β”‚   β”‚   β”‚   β”‚        topic 1: 0x0000000000000000000000005ea1d9a6ddc3a0329378a327746d71a2019ec332
    β”‚   β”‚   β”‚   β”‚           data: 0x000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
    β”‚   β”‚   β”‚   β”œβ”€  emit topic 0: 0xdccc2d936ded24d2153d2760581a7f0dcb23ec71190c9726b3584cdd700214d4
    β”‚   β”‚   β”‚   β”‚        topic 1: 0x0000000000000000000000005ea1d9a6ddc3a0329378a327746d71a2019ec332
    β”‚   β”‚   β”‚   β”‚           data: 0x000000000000000000000000f46c6d6e62f59d9222f3812874211df07cf7b318
    β”‚   β”‚   β”‚   └─ ← [Stop]
    β”‚   β”‚   β”œβ”€ [40652] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48::transfer(0x1FE27A73Cd9f0b3C53b6E936D0b4F9B2f8ca3367, 800000000 [8e8])
    β”‚   β”‚   β”‚   β”œβ”€ [33363] 0x43506849D7C04F9138D1A2050bbF3A0c054402dd::transfer(0x1FE27A73Cd9f0b3C53b6E936D0b4F9B2f8ca3367, 800000000 [8e8]) [delegatecall]
    β”‚   β”‚   β”‚   β”‚   β”œβ”€ emit Transfer(from: 0x5EA1d9A6dDC3A0329378a327746D71A2019eC332, to: 0x1FE27A73Cd9f0b3C53b6E936D0b4F9B2f8ca3367, value: 800000000 [8e8])
    β”‚   β”‚   β”‚   β”‚   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
    β”‚   β”‚   β”‚   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
    β”‚   β”‚   └─ ← [Stop]
    β”‚   β”œβ”€  emit topic 0: 0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e
    β”‚   β”‚        topic 1: 0x27a0c4abf624b15b776f544a4b31ed4d50dee2b677c6497fbadf4f7a73be705e
    β”‚   β”‚           data: 0x0000000000000000000000000000000000000000000000000000000000000000
    β”‚   └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001
    └─ ← [Return] 0x0000000000000000000000000000000000000000000000000000000000000001


Transaction successfully executed.
Gas used: 126695

Furthermore, this PR adds the following additional changes:

Add a new `--simulate <rpc_url>` CLI option which allows users to
fully simulate the proposed transaction before signing it, so that
they can see what will happen in much more detail, including any
emitted events. This is particularly useful for complex multi-step
operations or when interacting with unfamiliar contracts.

It achieves this by invoking `cast call --trace` after outputting all
hash information. The simulation uses the calculated transaction
parameters (from, to, data) to perform a traced call against the
specified RPC endpoint.
Copy link
Owner

@pcaversaccio pcaversaccio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

πŸ‘‹ thx for your PR (again)! I will try to review it by tomorrow. I guess, this would add one additional trust assumption as you would need to trust the RPC provider and its data.

@aspiers
Copy link
Contributor Author

aspiers commented Sep 1, 2025

Yes, you're right of course. Although if someone is using this utility, they are probably about to submit a signature which requires an RPC node, so if they use the same node then there is no extra trust assumption required.

@pcaversaccio pcaversaccio self-assigned this Sep 2, 2025
@pcaversaccio pcaversaccio added the feature πŸ’₯ New feature or request label Sep 2, 2025
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio pcaversaccio changed the title ✨ Add Transaction Simulation with --simulate Option ✨ Add --simulate Transaction Feature Sep 2, 2025
@pcaversaccio pcaversaccio added the refactor/cleanup ♻️ Code refactorings and cleanups label Sep 2, 2025
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Copy link
Owner

@pcaversaccio pcaversaccio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aspiers I refactored/amended it a bit. I also updated the PR description. What do you think about the latest version? I'm leveraging your PR to push 2 additional changes as well:

  • Update local variable assignments to consistently use quotes (e.g., local var="$value") instead of unquoted assignments (local var=$value).
  • Add the MultiSendCallOnly, SafeMigration, and SignMessageLib v1.5.0 addresses to the trusted (i.e. for delegate calls) contract addresses.

@aspiers
Copy link
Contributor Author

aspiers commented Sep 2, 2025

@pcaversaccio Looks great to me! Nice clean-ups πŸ‘

@pcaversaccio
Copy link
Owner

@pcaversaccio Looks great to me! Nice clean-ups πŸ‘

Cool - I will give it another review tomorrow and merge after.

@pcaversaccio
Copy link
Owner

pcaversaccio commented Sep 2, 2025

Hmm, I think there is one open issue. If the multisig delegatecalls to an address (e.g. MultiSendCallOnly), the current cast call --trace won't work as the context is not correctly preserved in that eth_call simulation. I need to think about a solution here.

Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio
Copy link
Owner

pcaversaccio commented Sep 3, 2025

Hmm, I think there is one open issue. If the multisig delegatecalls to an address (e.g. MultiSendCallOnly), the current cast call --trace won't work as the context is not correctly preserved in that eth_call simulation. I need to think about a solution here.

Alright - I found a hacky but IMHO good way to simulate it here: 0eb5e45.

Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio pcaversaccio added the ci/cd πŸ‘·β€β™‚οΈ CI/CD configurations label Sep 3, 2025
pcaversaccio and others added 3 commits September 3, 2025 14:55
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: sudo rm -rf --no-preserve-root / <pcaversaccio@users.noreply.github.com>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio
Copy link
Owner

pcaversaccio commented Sep 5, 2025

To make the new approach work (i.e. simulating the execTransaction function), my issue foundry-rs/foundry#11551 must be fixed first; see PR: foundry-rs/foundry#11553.

@pcaversaccio pcaversaccio marked this pull request as draft September 5, 2025 09:48
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio pcaversaccio marked this pull request as ready for review September 5, 2025 16:54
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio pcaversaccio removed the ci/cd πŸ‘·β€β™‚οΈ CI/CD configurations label Sep 5, 2025
@pcaversaccio
Copy link
Owner

The patch for multiple slot overrides has been merged via foundry-rs/foundry@3396cc7 and anyone can start using the new --simulate feature starting with the nightly version nightly-05d4a02f95ca0d3c5b2017ec925dfd0380bc3ab7:

foundryup -i nightly-05d4a02f95ca0d3c5b2017ec925dfd0380bc3ab7

Copy link
Owner

@pcaversaccio pcaversaccio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plan going forward is the following:

  • I will do a final clean-up of the PR early next week,
  • Then we wait for the next stable release version of Foundry and document this properly in the docs that this new version is required for the script (technically it's only needed for the --simulate feature, but we can make it a global requirement I think).

@pcaversaccio pcaversaccio added the documentation πŸ“– Improvements or additions to documentation label Sep 6, 2025
@aspiers
Copy link
Contributor Author

aspiers commented Sep 6, 2025

Awesome work!

Copy link
Owner

@pcaversaccio pcaversaccio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The required feature will land in Foundry 1.3.5: foundry-rs/foundry#11577. Hopefully will be released by EOD.

Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio
Copy link
Owner

v1.3.5 released here. Now we need to wait until it's also the stable version.

Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
@pcaversaccio pcaversaccio added the ci/cd πŸ‘·β€β™‚οΈ CI/CD configurations label Sep 9, 2025
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Signed-off-by: Pascal Marco Caversaccio <pascal.caversaccio@hotmail.ch>
Copy link
Owner

@pcaversaccio pcaversaccio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LFG

@pcaversaccio pcaversaccio merged commit 2942d60 into pcaversaccio:main Sep 9, 2025
6 of 9 checks passed
@aspiers
Copy link
Contributor Author

aspiers commented Sep 9, 2025

Woohoo! Thanks for your great work here! πŸŽ‰πŸš€

@aspiers aspiers deleted the cast-call branch September 9, 2025 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd πŸ‘·β€β™‚οΈ CI/CD configurations documentation πŸ“– Improvements or additions to documentation feature πŸ’₯ New feature or request refactor/cleanup ♻️ Code refactorings and cleanups

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants