Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(protocol-kit): Migrate Safe Proxy Factory contract to Abitype #664

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
562ef98
Add SafeProxyFactoryContract as base contract type
tmjssz Jan 12, 2024
3203ba7
Add SafeProxyFactoryBaseContract class for creating Safe Proxy Factor…
tmjssz Jan 12, 2024
7ea151f
Add SafeProxyFactoryBaseContractEthers class for Ethers.js v6 integra…
tmjssz Jan 12, 2024
391d2b5
Define types specific to SafeProxyFactory contract v1.3.0
tmjssz Jan 12, 2024
7ae7004
Add SafeProxyFactory_v1_3_0_Ethers implementation for handling intera…
tmjssz Jan 12, 2024
7a8ff5d
Update `contractInstancesEthers` to use the new class
tmjssz Jan 12, 2024
677ed74
Remove the old SafeProxyFactory v1.3.0 implementation for ethers.js
tmjssz Jan 12, 2024
c2465a1
Update the `generateTypechainFiles.ts` script to remove the generatio…
tmjssz Jan 12, 2024
a6d5d93
fix: add param for contract runner to be used in `SafeProxyFactoryBas…
tmjssz Jan 12, 2024
f5b314f
Migrate Safe Proxy Factory contract v1.4.1 to Abitype for ethers.js
tmjssz Jan 12, 2024
18d930c
Migrate Safe Proxy Factory contract v1.1.1 to Abitype for ethers.js
tmjssz Jan 12, 2024
3a30b0a
Migrate Safe Proxy Factory contract v1.0.0 to Abitype for ethers.js
tmjssz Jan 12, 2024
9f37f72
Remove old `SafeProxyFactoryEthersContract`
tmjssz Jan 15, 2024
a3ea936
Add `SafeProxyFactoryBaseContractWeb3` class for Web3.js integration …
tmjssz Jan 16, 2024
897b711
Migrate Safe Proxy Factory contract v1.3.0 to Abitype for web3.js
tmjssz Jan 25, 2024
7a22aa8
Migrate Safe Proxy Factory contract v1.4.1 to Abitype for web3.js
tmjssz Jan 25, 2024
1b1aa61
Migrate Safe Proxy Factory contract v1.1.1 to Abitype for web3.js
tmjssz Jan 25, 2024
c67e4ef
Migrate Safe Proxy Factory contract v1.0.0 to Abitype for web3.js
tmjssz Jan 25, 2024
d217749
Remove old `SafeProxyFactoryWeb3Contract`
tmjssz Jan 25, 2024
915bd42
Remove unused contract parameter in `getSafeProxyFactoryContractInsta…
tmjssz Jan 25, 2024
a2e13aa
Remove contracts v1.1.1 from typechain generation script
tmjssz Jan 25, 2024
e06a457
Remove commented lines
tmjssz Feb 1, 2024
3227f3d
fix: Uppercase filename's first letter
tmjssz Feb 1, 2024
5c94050
fix: Consistent use of "SafeProxyFactory" name (instead of only "Prox…
tmjssz Feb 1, 2024
66b1eb5
fix: Rename `SafeBaseProxyFactoryContract` to `SafeProxyFactoryBaseCo…
tmjssz Feb 1, 2024
a7796d6
fix: Uppercase filenames' first letter
tmjssz Feb 1, 2024
477c0c6
fix: Uppercase filenames' first letter
tmjssz Feb 1, 2024
1501d55
fix: Add "Contract" suffix for consistency
tmjssz Feb 2, 2024
703b637
fix: Start file name with capital letter
tmjssz Feb 2, 2024
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
24 changes: 2 additions & 22 deletions packages/protocol-kit/scripts/generateTypechainFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,27 +16,16 @@ const outDirTests = 'typechain/tests/'
const safeContractsPath = '../../node_modules/@safe-global/safe-deployments/dist/assets'

const safeContracts_V1_4_1 = [
// `${safeContractsPath}/v1.4.1/safe.json`, // Remove contract 1.4.1 from typechain as it's migrated to Abitype
`${safeContractsPath}/v1.4.1/safe_proxy_factory.json`,
`${safeContractsPath}/v1.4.1/compatibility_fallback_handler.json`,
`${safeContractsPath}/v1.4.1/create_call.json`,
`${safeContractsPath}/v1.4.1/simulate_tx_accessor.json`
].join(' ')
const safeContracts_V1_3_0 = [
// `${safeContractsPath}/v1.3.0/gnosis_safe.json`, // Remove contract 1.3.0 from typechain as it's migrated to Abitype
`${safeContractsPath}/v1.3.0/proxy_factory.json`,
`${safeContractsPath}/v1.3.0/compatibility_fallback_handler.json`,
`${safeContractsPath}/v1.3.0/create_call.json`,
`${safeContractsPath}/v1.3.0/simulate_tx_accessor.json`
].join(' ')
const safeContracts_V1_1_1 = [
// `${safeContractsPath}/v1.1.1/gnosis_safe.json`, // Remove contract 1.1.1 from typechain as it's migrated to Abitype,
`${safeContractsPath}/v1.1.1/proxy_factory.json`
].join(' ')
const safeContracts_V1_0_0 = [
`${safeContractsPath}/v1.0.0/gnosis_safe.json`,
`${safeContractsPath}/v1.0.0/proxy_factory.json`
].join(' ')
const safeContracts_V1_0_0 = [`${safeContractsPath}/v1.0.0/gnosis_safe.json`].join(' ')

// Won't be included in dist/ folder
const safeContractsTestV1_4_1Path =
Expand Down Expand Up @@ -90,7 +79,7 @@ function moveTypechainFiles(inDir: string, outDir: string): void {
})
}

// Contract 1.2.0 is migrated to Abitype already, so it's not included in here
// Contracts v1.1.1 + v1.2.0 are migrated to Abitype already, so they're not included in here
function generateTypes(typechainTarget: string) {
// Src
generateTypechainFiles(
Expand All @@ -103,11 +92,6 @@ function generateTypes(typechainTarget: string) {
`${outDirSrc}${typechainTarget}/v1.3.0`,
safeContracts_V1_3_0
)
generateTypechainFiles(
typechainTarget,
`${outDirSrc}${typechainTarget}/v1.1.1`,
safeContracts_V1_1_1
)
generateTypechainFiles(
typechainTarget,
`${outDirSrc}${typechainTarget}/v1.0.0`,
Expand All @@ -121,10 +105,6 @@ function generateTypes(typechainTarget: string) {
`${typeChainDirectorySrcPath}${typechainTarget}/v1.3.0`,
`${typeChainDirectoryBuildPath}${typechainTarget}/v1.3.0`
)
moveTypechainFiles(
`${typeChainDirectorySrcPath}${typechainTarget}/v1.1.1`,
`${typeChainDirectoryBuildPath}${typechainTarget}/v1.1.1`
)
moveTypechainFiles(
`${typeChainDirectorySrcPath}${typechainTarget}/v1.0.0`,
`${typeChainDirectoryBuildPath}${typechainTarget}/v1.0.0`
Expand Down
58 changes: 58 additions & 0 deletions packages/protocol-kit/src/adapters/SafeProxyFactoryBaseContract.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { contractName, getContractDeployment } from '@safe-global/protocol-kit/contracts/config'
import { SafeVersion } from '@safe-global/safe-core-sdk-types'

/**
* Abstract class SafeProxyFactoryBaseContract serves as a base for creating a Safe Proxy Factory contract for a specific adapter (Ethers.js, Web3.js, or viem.js)
* This class is designed to be extended by adapter-specific abstract classes, such as SafeProxyFactoryBaseContractEthers, SafeProxyFactoryBaseContractWeb3, and SafeProxyFactoryBaseContractViem.
*
* @template SafeProxyFactoryContractAbiType - The ABI associated with the Safe Proxy Factory contract.
*
* Example subclasses extending this base class:
* - SafeProxyFactoryBaseContractEthers<SafeProxyFactoryContract_v1_3_0_Abi> extends SafeProxyFactoryBaseContract<SafeProxyFactoryContract_v1_3_0_Abi>
* - SafeProxyFactoryBaseContractWeb3<SafeProxyFactoryContract_v1_3_0_Abi> extends SafeProxyFactoryBaseContract<SafeProxyFactoryContract_v1_3_0_Abi>
* - SafeProxyFactoryBaseContractViem<SafeProxyFactoryContract_v1_3_0_Abi> extends SafeProxyFactoryBaseContract<SafeProxyFactoryContract_v1_3_0_Abi>
*/
abstract class SafeProxyFactoryBaseContract<SafeProxyFactoryContractAbiType> {
contractAbi: SafeProxyFactoryContractAbiType
contractAddress: string

readonly contractName: contractName = 'safeProxyFactoryVersion'
abstract safeVersion: SafeVersion

abstract contract: unknown // This needs to be implemented for each adapter.
abstract adapter: unknown // This needs to be implemented for each adapter.

/**
* Constructs a new SafeProxyFactoryBaseContract instance.
*
* @param chainId - The chain ID of the contract.
* @param defaultAbi - The hardcoded ABI of the Safe Proxy Factory contract.
* @param safeVersion - The version of the Safe contract.
* @param customContractAddress - Optional custom address for the contract.
* @param customContractAbi - Optional custom ABI for the contract.
* @throws Will throw an error if the contract address is invalid.
*/
constructor(
chainId: bigint,
defaultAbi: SafeProxyFactoryContractAbiType,
safeVersion: SafeVersion,
customContractAddress?: string,
customContractAbi?: SafeProxyFactoryContractAbiType
) {
const contractDeployment = getContractDeployment(safeVersion, chainId, this.contractName)

const contractAddress = customContractAddress || contractDeployment?.defaultAddress

if (!contractAddress) {
throw new Error('Invalid SafeProxyFactory contract address')
}

this.contractAddress = contractAddress
this.contractAbi =
customContractAbi ||
(contractDeployment?.abi as SafeProxyFactoryContractAbiType) || // this cast is required because abi is set as any[] in safe-deployments
defaultAbi // if no customAbi and no abi is present in the safe-deployments we use our hardcoded abi
}
}

export default SafeProxyFactoryBaseContract
14 changes: 10 additions & 4 deletions packages/protocol-kit/src/adapters/ethers/EthersAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { ethers, TransactionResponse, AbstractSigner, Provider } from 'ethers'
import CompatibilityFallbackHandlerContractEthers from './contracts/CompatibilityFallbackHandler/CompatibilityFallbackHandlerEthersContract'
import CreateCallEthersContract from './contracts/CreateCall/CreateCallEthersContract'
import SafeContractEthers from './contracts/Safe/SafeContractEthers'
import SafeProxyFactoryEthersContract from './contracts/SafeProxyFactory/SafeProxyFactoryEthersContract'
import SimulateTxAccessorEthersContract from './contracts/SimulateTxAccessor/SimulateTxAccessorEthersContract'
import {
getCompatibilityFallbackHandlerContractInstance,
Expand Down Expand Up @@ -122,16 +121,23 @@ class EthersAdapter implements EthAdapter {
async getSafeProxyFactoryContract({
safeVersion,
singletonDeployment,
customContractAddress
}: GetContractProps): Promise<SafeProxyFactoryEthersContract> {
customContractAddress,
customContractAbi
}: GetContractProps) {
const chainId = await this.getChainId()
const contractAddress =
customContractAddress ?? singletonDeployment?.networkAddresses[chainId.toString()]
if (!contractAddress) {
throw new Error('Invalid SafeProxyFactory contract address')
}
const signerOrProvider = this.#signer || this.#provider
return getSafeProxyFactoryContractInstance(safeVersion, contractAddress, signerOrProvider)
return getSafeProxyFactoryContractInstance(
safeVersion,
contractAddress,
signerOrProvider,
this,
customContractAbi
)
}

async getMultiSendContract({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Contract, ContractRunner, InterfaceAbi } from 'ethers'

import EthersAdapter from '@safe-global/protocol-kit/adapters/ethers/EthersAdapter'
import SafeProxyFactoryBaseContract from '@safe-global/protocol-kit/adapters/SafeProxyFactoryBaseContract'
import { SafeVersion } from '@safe-global/safe-core-sdk-types'

/**
* Abstract class SafeProxyFactoryBaseContractEthers extends SafeProxyFactoryBaseContract to specifically integrate with the Ethers.js v6 library.
* It is designed to be instantiated for different versions of the Safe contract.
*
* This abstract class sets up the Ethers v6 Contract object that interacts with a Safe Proxy Factory contract version.
*
* Subclasses of SafeProxyFactoryBaseContractEthers are expected to represent specific versions of the contract.
*
* @template SafeProxyFactoryContractAbiType - The ABI type specific to the version of the Safe Proxy Factory contract, extending InterfaceAbi from Ethers.
* @extends SafeProxyFactoryBaseContract<SafeProxyFactoryContractAbiType> - Extends the generic SafeProxyFactoryBaseContract with Ethers-specific implementation.
*
* Example subclasses:
* - SafeProxyFactoryContract_v1_4_1_Ethers extends SafeProxyFactoryBaseContractEthers<SafeProxyFactoryContract_v1_4_1_Abi>
* - SafeProxyFactoryContract_v1_3_0_Ethers extends SafeProxyFactoryBaseContractEthers<SafeProxyFactoryContract_v1_3_0_Abi>
* - SafeProxyFactoryContract_v1_2_0_Ethers extends SafeProxyFactoryBaseContractEthers<SafeProxyFactoryContract_v1_2_0_Abi>
* - SafeProxyFactoryContract_v1_1_1_Ethers extends SafeProxyFactoryBaseContractEthers<SafeProxyFactoryContract_v1_1_1_Abi>
* - SafeProxyFactoryContract_v1_0_0_Ethers extends SafeProxyFactoryBaseContractEthers<SafeProxyFactoryContract_v1_0_0_Abi>
*/
abstract class SafeProxyFactoryBaseContractEthers<
SafeProxyFactoryContractAbiType extends InterfaceAbi
> extends SafeProxyFactoryBaseContract<SafeProxyFactoryContractAbiType> {
contract: Contract
adapter: EthersAdapter

/**
* @constructor
* Constructs an instance of SafeProxyFactoryBaseContractEthers.
*
* @param chainId - The chain ID of the contract.
* @param ethersAdapter - An instance of EthersAdapter.
* @param defaultAbi - The default ABI for the Safe contract. It should be compatible with the specific version of the contract.
* @param safeVersion - The version of the Safe contract.
* @param customContractAddress - Optional custom address for the contract. If not provided, the address is derived from the Safe deployments based on the chainId and safeVersion.
* @param customContractAbi - Optional custom ABI for the contract. If not provided, the ABI is derived from the Safe deployments or the defaultAbi is used.
*/
constructor(
chainId: bigint,
ethersAdapter: EthersAdapter,
defaultAbi: SafeProxyFactoryContractAbiType,
safeVersion: SafeVersion,
customContractAddress?: string,
customContractAbi?: SafeProxyFactoryContractAbiType,
runner?: ContractRunner | null
) {
super(chainId, defaultAbi, safeVersion, customContractAddress, customContractAbi)

this.adapter = ethersAdapter
this.contract = new Contract(
this.contractAddress,
this.contractAbi,
runner || this.adapter.getSigner()
)
}
}

export default SafeProxyFactoryBaseContractEthers

This file was deleted.

This file was deleted.

Loading
Loading