[BIP-909] Permissions Update Request #8

PR with payloads

Edit: Following the suggestions in our last ecosystem call, this Permission Update Request was divided into two:

PUR #8 - Permissions for Arbitrum and Gnosis Chain
PUR#9 - Permissions for ETH Mainnet

This action was taken to expedite the release of the already reviewed permissions. No changes were made to the requested permissions.

The following text reflects these changes, and the ETH Mainnet Permission Update Requests will be shared in a new post, where their review will continue.

Abstract

This proposal requests BalancerDAO’s approval for updates and new actions to the permissions policy governing the kpk-managed treasuries on Arbitrum, and Gnosis Chain.

The proposed changes expand the existing permissions to include new strategies, protocols, swaps, and bridging routes, while removing obsolete or deprecated contracts and interactions. They also streamline kpk’s fee-collection process and revoke the delegation’s permissions from the Zodiac Roles Modifier, as outlined in BIP-890.

The additional permissions focus on strategies that aim to increase the treasury’s risk-adjusted yield without introducing material new risk vectors to the current allocation. These include allocations to Aave Umbrella, Ethena, Spark, Resolv, new markets on Compound as well as kpk-curated vaults on Morpho and curated markets on Gearbox, among others.

Motivation

Treasury management must evolve in line with market conditions and protocol developments, including migrations, new pool launches, and improved access to financial instruments. Protocols and pools previously assessed as too immature or risky for BalancerDAO may become viable over time as they demonstrate reliability, liquidity, and operational robustness.

The proposed additions will allow kpk to implement advanced investment strategies such as delta-neutral stablecoin exposure, curated vaults, and the upgraded version of the Aave safety module, while deprecating outdated or higher-risk contracts.

Changes to the Permissions Policy

This proposal outlines the following modifications to the permissions policy:

Gnosis Chain:

  • Bridge:
    • Omnibridge:
      • Update and addition of bridging routes from Gnosis Chain to Mainnet (same as above)
  • Stakewise: removal of SeedNode vault (deprecated)

Arbitrum:

  • Morpho: deposit and withdrawal into - kpk - USDC Yield
  • Balancer v2: withdrawal permissions for Balancer BAL - axBAL
  • Swaps (Cow Swap):
    • COW, ARB <> USDC/ETH/WETH/ sUSDE/USDE
    • USDC, USDT, USDE, sUSDE <> USDC, USDT, USDE, sUSDE
    • WETH, wstETH, ETH <> WETH, wstETH, ETH
    • ARB <> USDC, ETH, WETH

Zodiac Roles Modifier Permissions Policy

Permissions page

Gnosis Chain: link here

Arbitrum: link here

Permissions diff page

Gnosis Chain: link here

Arbitrum: link here

Gnosis

TX 1-7: Remove Deprecated StakeWise SEEDnode Vault

revokeTarget: stakewise seednode vault

revokeFunction: deposit, update, mint, burn, queue, claim

lgtm

TX 9-11, 18-19: Omnibridge Routes

USDC/USDT/WETH/WBTC.transferAndCall(_to: HomeOmnibridge, _data: AVATAR)

lgtm

TX 12: Change Approvals of GNO

GNO.approve(Genesis/Axol/Serenita/NEDO/Stakecat/Stakesaurus, *)

Note: roles ui is showing all of these vaults are being revoked a lot of calls (eg burnOsToken, updateState, etc). I dont see those revokes being present in the proposed payload (https://github.com/taravellokpk/multisig-ops/blob/03457c49fb6bdb28f29934acf6cf19c48705b03c/BIPs/2025-W51/balancer-pur8-gno.json)

eg left column here in this screenshot:

what am i missing, how are those permissions being revoked if there is no mention of them in the payload?

same goes for these approvals disappearing which is not in line with what i am seeing in the payload (tx 12 explicitly keeps them?)

bug in ui? iiuc, the intention is simply to remove the GNO.approve(seednode, *) permission

TX 8, 13-17: Enable Use of USDC Transmuter

USDC/USDCe.approve(USDCTransmuter, *)

USDCTransmuter.deposit(*)/withdraw(*)

Note1: not mentioned in your forum post

Note2: i interpret the roles ui here to show a replacement of the GPv2VaultRelayer address with the USDCTransmuter address. but as far as i understand, the transmuter here is being added (ie besides the permission to approve * to the vault relayer). Bug in the roles ui?

imo the ui should show a blue table on the right side with _to 0x0392... OR _to 0xc92e...

scopeFunction args from the payload:

{
    "roleKey": "0x4d414e4147455200000000000000000000000000000000000000000000000000",
    "targetAddress": "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83",
    "selector": "0x095ea7b3",
    "conditions": "[
        [\"0\",\"5\",\"5\",\"0x\"],
        [\"0\",\"0\",\"2\",\"0x\"],
        [\"1\",\"1\",\"16\",\"0x0000000000000000000000000392a2f5ac47388945d8c84212469f545fae52b2\"],
        [\"1\",\"1\",\"16\",\"0x000000000000000000000000c92e8bdf79f0507f65a392b0ab4667716bfe0110\"]
    ]",
    "options": "0"
}

TX 20-21: Enable Use of USDS

USDSDepositContract.relayTokens(*)

Solidity source code:

function relayTokens(address recipient) external payable {
    IHomeBridgeErcToNative(xDAIBridge).relayTokens{value: msg.value}(recipient);
}

Note: is there a reason this is unconstrained? Looks like this gives the module a blank check to bridge xdai to any address? Why not limit recipient to AVATAR only?

TX 22: KPK Kit Metadata

Log some stuff via erc3722 poster contract (ERC-3722: Poster).

FYI this contract is not verified on gnosisscan (i did get a partial verification via blockscout)

Hello! Thanks for the feedback.

Here are answers to your points:

  • UI bug / screenshots: In your screenshots you’re using the annotated version of the diff page. Could you switch to the non-annotated view? It’s much clearer for reviewing the permission changes. That should address your questions there.

  • Enable use of USDC Transmuter: When bridging USDC from Mainnet to GC, USDC.e is the default destination token. That’s expected behaviour, not a UI bug. We added the Transmuter so you can swap USDC.e<> USDC on GC directly from the bridge UI. If you’d rather, we can also execute it via CoW Swap.

  • Enable use of USDS: Yep, we intentionally limited the recipient to the Avatar only. You can see it clearly on the diff page (see image below).

Gnosis

ah great, sorry i missed the annotation toggle. i wasnt expecting it to actually display erroneous info in this other mode. anyway all good for this chain then!

Arbitrum One

matches your description on forum (except for “ARB <> USDC, ETH, WETH” which is a typo i believe; already covered by “COW, ARB <> USDC/ETH/WETH/ sUSDE/USDE”)

Tx 0, 2-5, 9-23: Approvals

  • USDC.approve({CCTP|Morpho_kpk_USDC|CoW_Swap_Vault}, *)

  • BAL.approve(Balancer_V2_Vault, *)

  • axBAL.approve(Balancer_V2_Vault, *)

  • sUSDe.approve(CoW_Swap_Vault, *)

  • USDe.approve(CoW_Swap_Vault, *)

  • USDT.approve(CoW_Swap_Vault, *)

  • ARB.approve(CoW_Swap_Vault, *)

  • COW.approve(CoW_Swap_Vault, *)

  • WETH.approve(CoW_Swap_Vault, *)

  • wstETH.approve(CoW_Swap_Vault, *)

Tx 1

  • sell: (wsteth or WETH) to buy: (wsteth or WETH or ETH)

  • sell: (ARB or COW) to buy: (sUSDe or USDe or WETH or USDC or ETH)

  • sell: (sUSDe or USDe or USDC or USDT) to buy (sUSDe or USDe or USDC or USDT)

Tx 6-8: Join and Exit Balancer V2 Pools

  • VaultV2.joinPool(bpt_BAL_axlBAL, AVATAR, AVATAR, *)

  • VaultV2.exitPool(bpt_BAL_axlBAL, AVATAR, AVATAR, *)

Tx 24-28: Wire Up Safe CoW Swap Order

signing via custom callback and twap orders:

  • Safe.setFallbackHandler(ExtensibleFallbackHandler)

  • Safe.setDomainVerifier(*, ComposableCoW)

  • ComposableCow.createWithContext(*, CurrentBlockTimestampFactory, *, TWAP)

Tx 29-32: Morpho Deposit and Withdrawals

  • Morpho_kpk_USDC.deposit(*, AVATAR)

  • Morpho_kpk_USDC.withdraw(*, AVATAR, AVATAR)

  • Morpho_kpk_USDC.redeem(*, AVATAR, AVATAR)

1 Like

Ethereum

first batch of reviews; tx0-26. 27-189 are work in progress

Tx 0: Set Allowance for sending USDC

creates an allowance of 100 USDC per 90 days with label USDC_KPK-FEES

NOTE: i believe this is missing some decimals? intention is 100k usdc == 100000000000

Tx 1-4: Revoke AAVE/stAAVE Delegation Calls

  • revoke AAVE.delegate

  • revoke stAAVE.delegate

  • revoke AAVE.delegateByType

  • revoke stAAVE.delegateByType

Tx 5-6: Revoke Unstake via Lido’s stETH Queue

  • revoke unstETH.requestWithdrawalsWithPermit

  • revoke unstETH.requestWithdrawalsWstETHWithPermit

NOTE: unclear why revoked? also not mentioned in your forum post

Tx 8-9: Revoke sGYD

  • revoke sGYD.deposit

  • revoke sGYD.redeem

NOTE: unclear why revoked? also not mentioned in your forum post

Tx 10: Revoke sUSDS

  • revoke sUSDS.deposit

NOTE: unclear why revoked? is this simply because you want to pass a referral code on balancer’s behalf (tx#21)? also not mentioned in your forum post

Tx 11-13: Revoke Old XDai Bridge

  • revoke bridge.relayTokens

  • revoke bridge.executeSignatures

NOTE: unclear why revoked? also not mentioned in your forum post

Tx 14: Annotation Metadata

N/A

Tx 15, 17, 19-20: USDC, USDT, USDS Approvals

  • grant WETH9.approve({ForeignOmnibridge|kpkWETH|cWETHv3|UmbrellaStakeToken|kpk_ETH_PrimeV2|UmbrellaBatchHelper})

  • grant USDC.approve({})

  • grant USDT.approve({cUSDTv3|ForeignOmnibridge|stkwaEthUSDT.v1|AavePool|UmbrellaBatchHelper|spUSDT})

  • grant USDS.approve({BridgeRouter|cUSDSv3})

Tx 16: Narrow Comet Claiming Scope

  • grant CometRewards.claim({cUSDTv3|cUSDSv3|cWETHv3|cUSDCv3})

NOTE: why? previous claim was unscoped (which is fine imo), now only these 4 specific comets can be claimed?

Tx 18: Grant Sending USDC to KPK (Using Allowance)

this uses the allowance created in Tx 0 to send USDC to the KPK fees address:

  • grant USDC.transfer(KPK, ≤USDC_KPK-FEES)

Tx 21: Grant sUSDS Depositing

previously revoked in Tx 10, but now re-granting depositing but also allow for passing of a referral code:

  • grant sUSDS.deposit(*, AVATAR, *)

NOTE: why?

Tx 22: OETH?

  • grant OETH.rebaseOptIn()

NOTE: OETH is not mentioned in your forum post at all?

Tx 23

grant more scope to the AngleDistributor.claim address[] users arg. instead of only allowing array [AVATAR], now also allow for:

  • [AVATAR,AVATAR]

  • [AVATAR,AVATAR,AVATAR]

  • [AVATAR,AVATAR,AVATAR,AVATAR]

  • [AVATAR,AVATAR,AVATAR,AVATAR,AVATAR]

NOTE: why not make users unscoped?

Tx 24-25: Grant Omnibridge

  • grant ForeignOmnibridge.relayTokens({WBTC|WETH|USDT}, AVATAR, *)

  • grant ForeignOmnibridge.relayTokensAndCall(USDC, EOA, *, AVATAR)

NOTE: why is _receiver here hardcoded to EOA 0x0392A2F5Ac47388945D8c84212469F545fAE52B2??

Tx 26: Receive Gnosis Bridges

  • grant ForeignAMB.safeExecuteSignaturesWithAutoGasLimit to claim tokens {WBTC|GNO|USDC|WETH|USDT} coming from gnosis chain

Tx 27-189

wip

1 Like

Edit by MAXYZ:

  • Assign BIP-ID
  • remove Ethereum permissions as requested by @kpk

https://snapshot.org/#/s:balancer.eth/proposal/0x8f1f69fba5d2d2ac82bf9d35e3c014bc572f7587d671eb6983f11995b259d1b2