11import { HardhatEthers , HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/types'
2- import { Contract , getAddress } from 'ethers'
2+ import SafeApiKit from '@safe-global/api-kit'
3+ import Safe from '@safe-global/protocol-kit'
4+ import { MetaTransactionData as Transaction } from '@safe-global/types-kit'
5+ import { Contract , Eip1193Provider , getAddress } from 'ethers'
36import { network } from 'hardhat'
47
58import ProxyAdminArtifact from '../artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json'
@@ -9,22 +12,63 @@ import { deployCreate3 } from './deploy-create3'
912const ERC1967_ADMIN_SLOT = '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103'
1013
1114async function main ( ) : Promise < void > {
12- const { ethers } = await network . connect ( )
15+ const { ethers, networkConfig , provider } = await network . connect ( )
1316 const [ signer ] = await ethers . getSigners ( )
1417
1518 if ( ! process . env . SETTLER_PROXY ) throw Error ( 'SETTLER_PROXY env variable not provided' )
1619 const proxy = getAddress ( process . env . SETTLER_PROXY )
1720
1821 const proxyAdmin = await getProxyAdmin ( ethers , proxy , signer )
1922 const proxyAdminOwner = await proxyAdmin . owner ( )
20- if ( proxyAdminOwner !== signer . address ) {
21- throw Error ( `Signer ${ signer . address } is not the ProxyAdmin owner ${ proxyAdminOwner } ` )
23+
24+ const safeAddress = process . env . SAFE ? getAddress ( process . env . SAFE ) : undefined
25+ const expectedOwner = safeAddress ?? signer . address
26+
27+ if ( proxyAdminOwner !== expectedOwner ) {
28+ throw Error ( `Expected owner ${ expectedOwner } does not match ProxyAdmin owner ${ proxyAdminOwner } ` )
2229 }
2330
2431 const implementation = await deployCreate3 ( SettlerArtifact , [ ] , '0x04302605' , 'V1' )
25- const tx = await proxyAdmin . upgradeAndCall ( proxy , implementation . target , '0x' )
26- await tx . wait ( )
27- console . log ( `✅ Settler ${ proxy } upgraded in tx ${ tx . hash } ` )
32+
33+ if ( safeAddress ) {
34+ const { chainId } = await ethers . provider . getNetwork ( )
35+ if ( networkConfig . type !== 'http' ) throw Error ( 'Safe proposal requires an HTTP network' )
36+ const to = await proxyAdmin . getAddress ( )
37+ const data = proxyAdmin . interface . encodeFunctionData ( 'upgradeAndCall' , [ proxy , implementation . target , '0x' ] )
38+ const transactions = [ { to, value : '0' , data } ]
39+ await proposeSafeTransaction ( safeAddress , transactions , chainId , signer , provider )
40+ } else {
41+ const tx = await proxyAdmin . upgradeAndCall ( proxy , implementation . target , '0x' )
42+ await tx . wait ( )
43+ console . log ( `✅ Settler ${ proxy } upgraded in tx ${ tx . hash } ` )
44+ }
45+ }
46+
47+ async function proposeSafeTransaction (
48+ safeAddress : string ,
49+ transactions : Transaction [ ] ,
50+ chainId : bigint ,
51+ signer : HardhatEthersSigner ,
52+ provider : Eip1193Provider
53+ ) : Promise < void > {
54+ if ( ! process . env . SAFE_API_KEY ) throw Error ( 'SAFE_API_KEY env variable required for Safe proposal' )
55+ const apiKit = new SafeApiKit ( { chainId, apiKey : process . env . SAFE_API_KEY } )
56+
57+ const safe = await Safe . init ( { safeAddress, signer : signer . address , provider } )
58+ const safeTx = await safe . createTransaction ( { transactions } )
59+ const safeTxHash = await safe . getTransactionHash ( safeTx )
60+ const senderSignature = await safe . signHash ( safeTxHash )
61+
62+ await apiKit . proposeTransaction ( {
63+ safeAddress,
64+ safeTransactionData : safeTx . data ,
65+ safeTxHash,
66+ senderAddress : signer . address ,
67+ senderSignature : senderSignature . data ,
68+ } )
69+
70+ console . log ( `✅ Upgrade proposed to Safe ${ safeAddress } ` )
71+ console . log ( ` Safe TX Hash: ${ safeTxHash } ` )
2872}
2973
3074async function getProxyAdmin ( ethers : HardhatEthers , proxy : string , signer : HardhatEthersSigner ) : Promise < Contract > {
0 commit comments