Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/evm/.env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ SOLVER=0xE0D76433Edd9f5df370561bd0AF231E72c83Cd3a
VALIDATOR=0xc76B16fA2Fa75D93e08099DC16413D9a083404A1

SETTLER_PROXY=
SAFE=
SAFE_API_KEY=

ETHERSCAN_KEY=
DEPLOYER_PRIVATE_KEY=
2 changes: 2 additions & 0 deletions packages/evm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
"@nomicfoundation/hardhat-toolbox-mocha-ethers": "^3.0.0-next.23",
"@nomicfoundation/hardhat-typechain": "^3.0.0-next.23",
"@nomicfoundation/hardhat-verify": "^3.0.0-next.23",
"@safe-global/api-kit": "^4.0.0",
"@safe-global/protocol-kit": "^6.0.0",
"@types/chai": "^4.3.20",
"@types/chai-as-promised": "^8.0.2",
"@types/mocha": "^10.0.10",
Expand Down
11 changes: 8 additions & 3 deletions packages/evm/scripts/deploy-contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ async function main(): Promise<void> {
if (!process.env.ADMIN) throw Error('ADMIN env variable not provided')
if (!process.env.SOLVER) throw Error('SOLVER env variable not provided')
if (!process.env.VALIDATOR) throw Error('VALIDATOR env variable not provided')
const { ADMIN, SOLVER, AXIA, VALIDATOR } = process.env
if (!process.env.SAFE) throw Error('SAFE env variable not provided')
const { ADMIN, SOLVER, AXIA, VALIDATOR, SAFE } = process.env

const controllerArgs = [ADMIN, [SOLVER], [], [AXIA], [VALIDATOR], MIN_VALIDATORS]
const controller = await deployCreate3(ControllerArtifact, controllerArgs, '0x17')
Expand All @@ -25,12 +26,16 @@ async function main(): Promise<void> {

const initializeData = new Interface(SettlerArtifact.abi).encodeFunctionData('initialize', [
controller.target,
ADMIN,
ADMIN, // settler owner
dynamicCallEncoder.target,
])
const settlerProxy = await deployCreate3(
ProxyArtifact,
[settlerImplementation.target, ADMIN, initializeData],
[
settlerImplementation.target,
SAFE, // proxy owner
initializeData,
],
'0x04302603'
)

Expand Down
58 changes: 51 additions & 7 deletions packages/evm/scripts/upgrade-settler.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { HardhatEthers, HardhatEthersSigner } from '@nomicfoundation/hardhat-ethers/types'
import { Contract, getAddress } from 'ethers'
import SafeApiKit from '@safe-global/api-kit'
import Safe from '@safe-global/protocol-kit'
import { MetaTransactionData as Transaction } from '@safe-global/types-kit'
import { Contract, Eip1193Provider, getAddress } from 'ethers'
import { network } from 'hardhat'

import ProxyAdminArtifact from '../artifacts/@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol/ProxyAdmin.json'
Expand All @@ -9,22 +12,63 @@ import { deployCreate3 } from './deploy-create3'
const ERC1967_ADMIN_SLOT = '0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103'

async function main(): Promise<void> {
const { ethers } = await network.connect()
const { ethers, networkConfig, provider } = await network.connect()
const [signer] = await ethers.getSigners()

if (!process.env.SETTLER_PROXY) throw Error('SETTLER_PROXY env variable not provided')
const proxy = getAddress(process.env.SETTLER_PROXY)

const proxyAdmin = await getProxyAdmin(ethers, proxy, signer)
const proxyAdminOwner = await proxyAdmin.owner()
if (proxyAdminOwner !== signer.address) {
throw Error(`Signer ${signer.address} is not the ProxyAdmin owner ${proxyAdminOwner}`)

const safeAddress = process.env.SAFE ? getAddress(process.env.SAFE) : undefined
const expectedOwner = safeAddress ?? signer.address

if (proxyAdminOwner !== expectedOwner) {
throw Error(`Expected owner ${expectedOwner} does not match ProxyAdmin owner ${proxyAdminOwner}`)
}

const implementation = await deployCreate3(SettlerArtifact, [], '0x04302605', 'V1')
const tx = await proxyAdmin.upgradeAndCall(proxy, implementation.target, '0x')
await tx.wait()
console.log(`✅ Settler ${proxy} upgraded in tx ${tx.hash}`)

if (safeAddress) {
const { chainId } = await ethers.provider.getNetwork()
if (networkConfig.type !== 'http') throw Error('Safe proposal requires an HTTP network')
const to = await proxyAdmin.getAddress()
const data = proxyAdmin.interface.encodeFunctionData('upgradeAndCall', [proxy, implementation.target, '0x'])
const transactions = [{ to, value: '0', data }]
await proposeSafeTransaction(safeAddress, transactions, chainId, signer, provider)
} else {
const tx = await proxyAdmin.upgradeAndCall(proxy, implementation.target, '0x')
await tx.wait()
console.log(`✅ Settler ${proxy} upgraded in tx ${tx.hash}`)
}
}

async function proposeSafeTransaction(
safeAddress: string,
transactions: Transaction[],
chainId: bigint,
signer: HardhatEthersSigner,
provider: Eip1193Provider
): Promise<void> {
if (!process.env.SAFE_API_KEY) throw Error('SAFE_API_KEY env variable required for Safe proposal')
const apiKit = new SafeApiKit({ chainId, apiKey: process.env.SAFE_API_KEY })

const safe = await Safe.init({ safeAddress, signer: signer.address, provider })
const safeTx = await safe.createTransaction({ transactions })
const safeTxHash = await safe.getTransactionHash(safeTx)
const senderSignature = await safe.signHash(safeTxHash)

await apiKit.proposeTransaction({
safeAddress,
safeTransactionData: safeTx.data,
safeTxHash,
senderAddress: signer.address,
senderSignature: senderSignature.data,
})

console.log(`✅ Upgrade proposed to Safe ${safeAddress}`)
console.log(` Safe TX Hash: ${safeTxHash}`)
}

async function getProxyAdmin(ethers: HardhatEthers, proxy: string, signer: HardhatEthersSigner): Promise<Contract> {
Expand Down
Loading
Loading