TL;DR
not mentioned in the proposal but found in the payload:
- pendle
- silo
- sablier
- cctp
- sky psm
- makerdao psm
- polygon staking revokes
- lido withdrawal revokes
- old xdai bridge revokes
- dai and gno bridging
discrepancies:
- you mention unwinding balancer 80bal20weth positions but also add permissions to join those pools
- gyd is not revoked, only sgyd
- not only stkaave delegation is revoked, also aave
- swapping pairs are more complex than how you describe it
- also bridge dai and gno, plus cctp arb1 bridge
furthermore some minor comments, mostly unnecessary transactions, but no security concerns (except for maybe usr swapping, which has been depegged)
TX 0: USDC Allowance
now correctly sets a usdc allowance of 100_000usdc to kpk every 90 days. used in tx 18
setAllowance(USDC_KPK-FEES, bal=100000000000, period=90d)
TX 1-13, 182-188: Revokes
as stated previously, i dont think there is a need to revoke permissions unless there is a security concern. however, i understand it was easier to keep these in the payload for now:
- revoke delegate permissions for aave and stkaave
- revoke withdrawal permissions for unsteth
- revoke sgyd permissions to deposit and redeem
- revoke susds permissions to deposit
- revoke xdai foreign bridge permissions (replaced by newer one; see tx 177-181)
AAVE.delegate
AAVE.delegateByType
stkAAVE.delegate
stkAAVE.delegateByType
unstETH.requestWithdrawalsWithPermit
unstETH.requestWithdrawalsWstETHWithPermit
sGYD.[TARGET]
sGYD.deposit
sGYD.redeem
sUSDS.deposit
XDaiForeignBridge.[TARGET]
XDaiForeignBridge.relayTokens
XDaiForeignBridge.executeSignatures
revoke permissions to manage pol delegation
POL.[TARGET]
POL.approve
DelegateRegistry.[TARGET]
DelegateRegistry.setDelegation
DelegateRegistry.clearDelegation
dPOLa2.[TARGET]
dPOLa2.buyVoucherPOL
TX 14, 189: Metadata
n/a; metadata
_post_(removeAnnotations)
_post_(addAnnotations)
TX 15: WETH
approve weth for bridging, gearbox, morpho, compound, aave umbrella, balancer vault and cow relayer
WETH.approve(OR(SwapRouter02, ForeignOmnibridge, kpkWETH, cWETHv3, stkwaEthWETH.v1, Vault, kpk_ETH_PrimeV2, UNI-V3-POS, GPv2VaultRelayer, UmbrellaBatchHelper), *)
TX 16, 44-53, 158-159: Compound
scope the rewards claim to only the relevant reward markets, and not all of them (why i dont know, unscoped should be fine):
CometRewards.claim(OR(cUSDTv3, cUSDSv3, cWETHv3, cUSDCv3), AVATAR, *)
supply and withdraw from usds/usdt/weth compound markets:
cUSDSv3.[TARGET]
cUSDSv3.supply(USDS, *)
cUSDSv3.withdraw(USDS, *)
cUSDTv3.[TARGET]
cUSDTv3.supply(USDT, *)
cUSDTv3.withdraw(USDT, *)
cWETHv3.[TARGET]
cWETHv3.supply(WETH, *)
cWETHv3.withdraw(WETH, *)
cWETHv3.allow(MainnetBulker, *)
eth<>weth helper for cwethv3
MainnetBulker.[TARGET]
MainnetBulker.invoke(EVERY(...), EVERY(...)) [Send]
TX 17-21: Stablecoin Approvals
- approve usdc and usdt for spark, spark savings, kpk vault, (batch) aave umbrella, gnosis bridge
- approve usds for compound and gnosis bridge
- allow transfer of usdc to kpk within allowance defined in tx 0
- stake usds into susds
USDC.approve(OR(spUSDC, kpk_USDC_PrimeV2, PSMVariant1Actions, SwapRouter02, stkwaEthUSDC.v1, PoolInstance, ForeignOmnibridge, UsdsPsmWrapper, Vault, Pool, cUSDCv3, GPv2VaultRelayer, UmbrellaBatchHelper, PSMVariant1Actions), *)
USDC.transfer(kpk-fees-safe, <=USDC_KPK-FEES)
USDT.approve(OR(cUSDTv3, SwapRouter02, ForeignOmnibridge, stkwaEthUSDT.v1, Vault, Pool, GPv2VaultRelayer, UmbrellaBatchHelper, spUSDT), *)
USDS.approve(OR(cUSDSv3, PoolInstance, BridgeRouter, UsdsPsmWrapper, sUSDS, GPv2VaultRelayer, MigrationActions), *)
sUSDS.deposit(*, AVATAR, *)
TX 22: OETH
opt in to oeth rebasing; doesnt pose a problem for safe contracts
OETH.rebaseOptIn()
TX 23: Merkl
allow claiming of rewards via merkl. not sure why this needs to be scoped; what is the security concern here?
Distributor.claim(OR(..., ..., ..., ..., ...), *, *, *)
TX 24-26: Bridging
allow bridging of wbtc, gno, weth, usdt and usdc
ForeignOmnibridge.relayTokens(OR(WBTC, GNO, WETH, USDT), AVATAR, *)
ForeignOmnibridge.relayTokensAndCall(USDC, 0x0392a2f5, *, ...)
ForeignAMB.safeExecuteSignaturesWithAutoGasLimit(OR(AND(0x), AND(0x), AND(0x), AND(0x), AND(0x)), *)
TX 27-31
new approvals here are:
- gho: (batch) aave umbrella
- dai: redundant!
- sdai: redundant!
- wbtc: bridge
- wsteth: kpk gearbox vault
GHO.approve(OR(stkGHO, stkGHO.v1, PoolInstance, Vault, GPv2VaultRelayer, UmbrellaBatchHelper), *)
DAI.approve(OR(DsrManager, SwapRouter02, sDAI, PoolInstance, BridgeRouter, GPv2VaultRelayer, MigrationActions), *)
sDAI.approve(OR(PSMVariant1Actions, PoolInstance, Vault, GPv2VaultRelayer), *)
WBTC.approve(OR(SwapRouter02, PoolInstance, ForeignOmnibridge, UNI-V3-POS, GPv2VaultRelayer), *)
wstETH.approve(OR(SwapRouter02, PoolInstance, unstETH, kpkwstETH, Vault, GPv2VaultRelayer), *)
TX 32-33, 54-71, 75-92: CoW Swap
allow signing of the following swapping pairs:
- gho staking/unstaking via swap: stkgho<>gho
- dust liquidations: fjo, mta, gtc > usdc, weth
- oeth exit: oeth > wsteth, reth, steth, weth, eth
- bal token rebalance: aethbal, abal, weth, anybal > aethbal, abal, weth, anybal, eth
- main rebalance: wbtc, swise, stkaave, syrup, dai, wsteth, aave, usdc, reth, steth, comp, weth, usdt, cow > wbtc, dai, wsteth, usdc, reth, steth, weth, usdt
- stablecoin rebalance: usda, stusd, steur, wstusr, eura, eurc, gho, usde, usr, dai, sdai, susde, usdc, susds, aetheurc, usdt, usds, gyd <> usda, stusd, steur, wstusr, eura, eurc, gho, usde, usr, dai, sdai, susde, usdc, susds, aetheurc, usdt, gyd
looks like you missed usds as a buy token, or was this by design? i guess there is always the psm as a fallback
CowswapOrderSigner.signOrder([...], *, [...])
approve cow relayer:
GYD.approve(OR(Vault, GPv2VaultRelayer), *)
COW.[TARGET]
COW.approve(GPv2VaultRelayer, *)
SYRUP.[TARGET]
SYRUP.approve(GPv2VaultRelayer, *)
aEthEURC.[TARGET]
aEthEURC.approve(GPv2VaultRelayer, *)
EURA.[TARGET]
EURA.approve(GPv2VaultRelayer, *)
EURC.[TARGET]
EURC.approve(OR(kpk_EURC_YieldV2, GPv2VaultRelayer), *)
stEUR.[TARGET]
stEUR.approve(GPv2VaultRelayer, *)
stUSD.[TARGET]
stUSD.approve(GPv2VaultRelayer, *)
USR.[TARGET]
USR.approve(GPv2VaultRelayer, *)
sUSDe.[TARGET]
sUSDe.approve(GPv2VaultRelayer, *)
USDA.[TARGET]
USDA.approve(GPv2VaultRelayer, *)
USDe.[TARGET]
USDe.approve(OR(PendleRouterV4, sUSDe, GPv2VaultRelayer), *)
wstUSR.[TARGET]
wstUSR.approve(GPv2VaultRelayer, *)
FJO.[TARGET]
FJO.approve(GPv2VaultRelayer, *)
GTC.[TARGET]
GTC.approve(GPv2VaultRelayer, *)
MTA.[TARGET]
MTA.approve(GPv2VaultRelayer, *)
aBAL.[TARGET]
aBAL.approve(GPv2VaultRelayer, *)
aEthBAL.[TARGET]
aEthBAL.approve(GPv2VaultRelayer, *)
anyBAL.[TARGET]
anyBAL.approve(GPv2VaultRelayer, *)
TX 34-35, 38-41: Balancer
join (why?) and exit 80bal20weth pools:
Vault.joinPool(OR(0x5c6ee304399d..., 0xc5c91aea7551...), AVATAR, AVATAR, *) [Send]
Vault.exitPool(OR(0x5c6ee304399d..., 0xc5c91aea7551...), AVATAR, AVATAR, *)
B-80BAL-20WETH.[TARGET]
B-80BAL-20WETH.approve(Vault, *)
BAL.[TARGET]
BAL.approve(Vault, *)
TX 36-37: AAVE V3
aave v3 reward claiming:
RewardsController.[TARGET]
RewardsController.claimRewards(*, *, AVATAR, *)
TX 42-43: CCTP
receive cctp messages from arb1 to eth; usdc burning from treasury on arb1 that result in minting of usdc on eth treasury
MessageTransmitterV2.[TARGET]
MessageTransmitterV2.receiveMessage(AND(...), *)
TX 72-74: Ethena
stake and unstake (s)usde
sUSDe.deposit(*, AVATAR)
sUSDe.cooldownShares(*)
sUSDe.unstake(AVATAR)
TX 93-104: Morpho
deposit, withdraw and redeem from eth, eurc and usdc kpk vaults:
kpk_ETH_PrimeV2.[TARGET]
kpk_ETH_PrimeV2.deposit(*, AVATAR)
kpk_ETH_PrimeV2.withdraw(*, AVATAR, AVATAR)
kpk_ETH_PrimeV2.redeem(*, AVATAR, AVATAR)
kpk_EURC_YieldV2.[TARGET]
kpk_EURC_YieldV2.deposit(*, AVATAR)
kpk_EURC_YieldV2.withdraw(*, AVATAR, AVATAR)
kpk_EURC_YieldV2.redeem(*, AVATAR, AVATAR)
kpk_USDC_PrimeV2.[TARGET]
kpk_USDC_PrimeV2.deposit(*, AVATAR)
kpk_USDC_PrimeV2.withdraw(*, AVATAR, AVATAR)
kpk_USDC_PrimeV2.redeem(*, AVATAR, AVATAR)
TX 160-167: Gearbox
kpkWETH.[TARGET]
kpkWETH.deposit(*, AVATAR)
kpkWETH.depositWithReferral(*, AVATAR, *)
kpkWETH.redeem(*, AVATAR, AVATAR)
kpkwstETH.[TARGET]
kpkwstETH.deposit(*, AVATAR)
kpkwstETH.depositWithReferral(*, AVATAR, *)
kpkwstETH.redeem(*, AVATAR, AVATAR)
TX 105-111, 116-119, 127-132: Spark
supply and withdraw from usdc and usdt markets:
Pool.[TARGET]
Pool.supply(OR(USDC, USDT), *, AVATAR, *)
Pool.withdraw(OR(USDC, USDT), *, AVATAR)
Pool.setUserUseReserveAsCollateral(OR(USDC, USDT), *)
spark reward claiming (fork of aave v3, so same pattern as tx 36-37)
RewardsController.[TARGET]
RewardsController.claimRewards(*, *, AVATAR, *)
RewardsController.claimAllRewards(*, AVATAR)
deposit/withdraw/redeem spark savings usdc:
spUSDC.[TARGET]
spUSDC.deposit(*, AVATAR, *)
spUSDC.withdraw(*, AVATAR, AVATAR)
spUSDC.redeem(*, AVATAR, AVATAR)
not clear why susdc needs approval? i think you confuse it for susds or usdc here
sUSDC.[TARGET]
sUSDC.approve(PSMVariant1Actions, *)
deposit/withdraw/redeem spark savings usdt:
spUSDT.[TARGET]
spUSDT.deposit(*, AVATAR, *)
spUSDT.withdraw(*, AVATAR, AVATAR)
spUSDT.redeem(*, AVATAR, AVATAR)
TX 112-115: MakerDAO PSM
makerdao psm routing (usdc <> dai <> sdai)
PSMVariant1Actions.[TARGET]
PSMVariant1Actions.swapAndDeposit(AVATAR, *, *)
PSMVariant1Actions.withdrawAndSwap(AVATAR, *, *)
PSMVariant1Actions.redeemAndSwap(AVATAR, *, *)
TX 120-126: Sky PSM
sky psm wrapper (usdc<>usds):
UsdsPsmWrapper.[TARGET]
UsdsPsmWrapper.sellGem(AVATAR, *)
UsdsPsmWrapper.buyGem(AVATAR, *)
sky psm routing (usdc <> usds <> susds)
PSMVariant1Actions.[TARGET]
PSMVariant1Actions.swapAndDeposit(AVATAR, *, *)
PSMVariant1Actions.withdrawAndSwap(AVATAR, *, *)
PSMVariant1Actions.redeemAndSwap(AVATAR, *, *)
TX 133-153: AAVE Umbrella
stake and unstake usdc, usdt, weth and gho into aave umbrella
UmbrellaBatchHelper.[TARGET]
UmbrellaBatchHelper.deposit(OR(MATCH(0x), MATCH(0x), MATCH(0x), MATCH(0x)))
UmbrellaBatchHelper.redeem(OR(MATCH(0x), MATCH(0x), MATCH(0x), MATCH(0x)))
stkGHO.v1.[TARGET]
stkGHO.v1.deposit(*, AVATAR)
stkGHO.v1.cooldown()
stkGHO.v1.redeem(*, AVATAR, AVATAR)
stkwaEthUSDC.v1.[TARGET]
stkwaEthUSDC.v1.deposit(*, AVATAR)
stkwaEthUSDC.v1.cooldown()
stkwaEthUSDC.v1.redeem(*, AVATAR, AVATAR)
stkwaEthUSDT.v1.[TARGET]
stkwaEthUSDT.v1.deposit(*, AVATAR)
stkwaEthUSDT.v1.cooldown()
stkwaEthUSDT.v1.redeem(*, AVATAR, AVATAR)
stkwaEthWETH.v1.[TARGET]
stkwaEthWETH.v1.deposit(*, AVATAR)
stkwaEthWETH.v1.cooldown()
stkwaEthWETH.v1.redeem(*, AVATAR, AVATAR)
RewardsController.[TARGET]
RewardsController.claimSelectedRewards(*, *, AVATAR)
TX 154-157: CoW AMM
unwind weth/usdc and bal/eth positions on cow amm
BCoW-50WETH-50USDC.[TARGET]
BCoW-50WETH-50USDC.exitPool(*, *)
BCoW-50BAL-50ETH.[TARGET]
BCoW-50BAL-50ETH.exitPool(*, *)
TX 168-169: Sablier
withdraw sablier streams:
SAB-V2-LOCKUP-DYN.[TARGET]
SAB-V2-LOCKUP-DYN.withdraw(*, AVATAR, *)
TX 170-171: Silo
withdraw from bal silo
SiloRouterV2.[TARGET]
SiloRouterV2.execute((MATCH))
TX 172-176: Pendle
this particular PENDLE-LPT appears expired already (1770249600; 2026-02-05)
PendleRouterV4.[TARGET]
PendleRouterV4.swapExactTokenForPt(AVATAR, PENDLE-LPT, *, *, (USDe, *, USDe, 0x0, MATCH), (0x0, *, ..., ...))
PendleRouterV4.swapExactPtForToken(AVATAR, PENDLE-LPT, *, (USDe, *, USDe, 0x0, MATCH), (0x0, *, ..., ...))
PENDLE-LPT.[TARGET]
PENDLE-LPT.approve(PendleRouterV4, *)
TX 177-181: Gnosis Chain Bridge
bridge weth, dai or usds to gnosis and receive inbound bridge messages from gnosis
BridgeRouter.[TARGET]
BridgeRouter.relayTokens(OR(DAI, USDS), AVATAR, *)
BridgeRouter.executeSignatures([recipient=AVATAR, bridge=XDaiForeignBridge], *)
WETHOmnibridgeRouter.[TARGET]
WETHOmnibridgeRouter.wrapAndRelayTokens(AVATAR) [Send]