Try   HackMD

Governance Example - Whitelisting new bridge adapter

We can write proposals in Solidity and simulate them. Part of the simulation is also verification process, so we can be sure the state after proposal is correct.

Example: We initially deployed only 2 networks (Sepolia and Base Sepolia), therefore we needed to propose a change to whitelist another 2 chains we've added later.

The proposal is defined as Solidity script:

```/// @notice Sets up actions for the proposal
    function _build() internal override {
        /// STATICCALL -- not recorded for the run stage
        address wormholeBridge = addresses.getAddress(
            "WORMHOLE_BRIDGE_ADAPTER_PROXY"
        );

        WormholeTrustedSender.TrustedSender[]
            memory trustedSenders = new WormholeTrustedSender.TrustedSender[](
                2
            );
        trustedSenders[0] = WormholeTrustedSender.TrustedSender({
            chainId: arbitrumSepoliaWormholeChainId,
            addr: wormholeBridge
        });
        trustedSenders[1] = WormholeTrustedSender.TrustedSender({
            chainId: optimismSepoliaWormholeChainId,
            addr: wormholeBridge
        });

        WormholeBridgeAdapter(wormholeBridge).setTargetAddresses(
            trustedSenders
        );
        WormholeBridgeAdapter(wormholeBridge).addTrustedSenders(trustedSenders);
    }

    /// @notice Executes the proposal actions.
    function _run() internal override {
        /// Call parent _run function to check if there are actions to execute
        super._run();

        address multisig = addresses.getAddress("GOV_MULTISIG");

        /// CALLS -- mutative and recorded
        _simulateActions(multisig);
    }

    /// @notice Validates the post-execution state.
    function _validate() internal view override {
        /// STATICCALL -- not recorded for the run stage
        address wormholeBridge = addresses.getAddress(
            "WORMHOLE_BRIDGE_ADAPTER_PROXY"
        );

        WormholeTrustedSender.TrustedSender[]
            memory trustedSenders = new WormholeTrustedSender.TrustedSender[](
                2
            );
        trustedSenders[0] = WormholeTrustedSender.TrustedSender({
            chainId: arbitrumSepoliaWormholeChainId,
            addr: wormholeBridge
        });
        trustedSenders[1] = WormholeTrustedSender.TrustedSender({
            chainId: optimismSepoliaWormholeChainId,
            addr: wormholeBridge
        });

        for (uint256 i = 0; i < trustedSenders.length; i++) {
            require(
                WormholeBridgeAdapter(wormholeBridge).isTrustedSender(
                    trustedSenders[i].chainId,
                    trustedSenders[i].addr
                ),
                "Trusted sender not added"
            );
        }
    }

Output of the proposal looks like this:




---------------- Proposal Description ----------------
  Update trusted senders for the Wormhole Bridge Adapter
  
------------------ Proposal Actions ------------------
  1). calling 0x48b02a246861abb10166d383787689793b1a51a6 with 0 eth and 8db0eb2400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000271300000000000000000000000048b02a246861abb10166d383787689793b1a51a6000000000000000000000000000000000000000000000000000000000000271500000000000000000000000048b02a246861abb10166d383787689793b1a51a6 data.
  target: 0x48B02a246861Abb10166D383787689793b1A51a6
payload
  0x8db0eb2400000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000271300000000000000000000000048b02a246861abb10166d383787689793b1a51a6000000000000000000000000000000000000000000000000000000000000271500000000000000000000000048b02a246861abb10166d383787689793b1a51a6
  

  2). calling 0x48b02a246861abb10166d383787689793b1a51a6 with 0 eth and d68d945b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000271300000000000000000000000048b02a246861abb10166d383787689793b1a51a6000000000000000000000000000000000000000000000000000000000000271500000000000000000000000048b02a246861abb10166d383787689793b1a51a6 data.
  target: 0x48B02a246861Abb10166D383787689793b1A51a6
payload
  0xd68d945b00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000271300000000000000000000000048b02a246861abb10166d383787689793b1a51a6000000000000000000000000000000000000000000000000000000000000271500000000000000000000000048b02a246861abb10166d383787689793b1a51a6

Now, we can take that into our Safe, where we can simulate the batch of these 2 transactions:

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

And that was the first proposal that added 2 chains into our multichain stack.

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →