Skip to content

Commit

Permalink
Merge branch 'Abitype-1_3_0-safe-contract' into Abitype-CreateCall-co…
Browse files Browse the repository at this point in the history
…ntract
  • Loading branch information
dasanra committed Mar 27, 2024
2 parents bfeb244 + cca8d86 commit 8ae3224
Show file tree
Hide file tree
Showing 24 changed files with 1,005 additions and 133 deletions.
6 changes: 2 additions & 4 deletions packages/protocol-kit/scripts/generateTypechainFiles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@ const outDirTests = 'typechain/tests/'
const safeContractsPath = '../../node_modules/@safe-global/safe-deployments/dist/assets'

const safeContracts_V1_4_1 = [
`${safeContractsPath}/v1.4.1/compatibility_fallback_handler.json`,
`${safeContractsPath}/v1.4.1/simulate_tx_accessor.json`
`${safeContractsPath}/v1.4.1/compatibility_fallback_handler.json`
].join(' ')
const safeContracts_V1_3_0 = [
`${safeContractsPath}/v1.3.0/compatibility_fallback_handler.json`,
`${safeContractsPath}/v1.3.0/simulate_tx_accessor.json`
`${safeContractsPath}/v1.3.0/compatibility_fallback_handler.json`
].join(' ')

// Won't be included in dist/ folder
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { contractName, getContractDeployment } from '@safe-global/protocol-kit/contracts/config'
import { SafeVersion } from '@safe-global/safe-core-sdk-types'

/**
* Abstract class SimulateTxAccessorBaseContract serves as a base for creating a SimulateTxAccessorBaseContract 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 SimulateTxAccessorBaseContractEthers, SimulateTxAccessorBaseContractWeb3, and SimulateTxAccessorBaseContractViem.
* It includes the core logic for selecting the appropriate ABI and the address from SimulateTxAccessor deployments.
*
* @template SimulateTxAccessorContractAbiType - The ABI associated with the SimulateTxAccessor contract.
*
* Example subclasses extending this base class:
* - SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_3_0_Abi> extends SimulateTxAccessorBaseContract<SimulateTxAccessorContract_v1_3_0_Abi>
* - SimulateTxAccessorBaseContractWeb3<SimulateTxAccessorContract_v1_3_0_Abi> extends SimulateTxAccessorBaseContract<SimulateTxAccessorContract_v1_3_0_Abi>
* - SimulateTxAccessorBaseContractViem<SimulateTxAccessorContract_v1_3_0_Abi> extends SimulateTxAccessorBaseContract<SimulateTxAccessorContract_v1_3_0_Abi>
*/
abstract class SimulateTxAccessorBaseContract<SimulateTxAccessorContractAbiType> {
contractAbi: SimulateTxAccessorContractAbiType
contractAddress: string

contractName: contractName
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 SimulateTxAccessorBaseContract instance.
*
* @param chainId - The chain ID of the contract.
* @param defaultAbi - The hardcoded ABI of the SimulateTxAccessor contract.
* @param safeVersion - The version of the SimulateTxAccessor 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: SimulateTxAccessorContractAbiType,
safeVersion: SafeVersion,
customContractAddress?: string,
customContractAbi?: SimulateTxAccessorContractAbiType
) {
this.contractName = 'simulateTxAccessorVersion'

const deployment = getContractDeployment(safeVersion, chainId, this.contractName)

const contractAddress = customContractAddress || deployment?.defaultAddress

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

this.contractAddress = contractAddress
this.contractAbi =
customContractAbi ||
(deployment?.abi as SimulateTxAccessorContractAbiType) || // 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 SimulateTxAccessorBaseContract
17 changes: 11 additions & 6 deletions packages/protocol-kit/src/adapters/ethers/EthersAdapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import {
EthAdapterTransaction,
GetContractProps,
SafeEIP712Args,
SignMessageLibContract
SignMessageLibContract,
SimulateTxAccessorContract
} from '@safe-global/safe-core-sdk-types'
import { ethers, TransactionResponse, AbstractSigner, Provider } from 'ethers'
import CompatibilityFallbackHandlerContractEthers from './contracts/CompatibilityFallbackHandler/CompatibilityFallbackHandlerEthersContract'
import SafeContractEthers from './contracts/Safe/SafeContractEthers'
import SimulateTxAccessorEthersContract from './contracts/SimulateTxAccessor/SimulateTxAccessorEthersContract'
import {
getCompatibilityFallbackHandlerContractInstance,
getCreateCallContractInstance,
Expand Down Expand Up @@ -235,16 +235,21 @@ class EthersAdapter implements EthAdapter {
async getSimulateTxAccessorContract({
safeVersion,
singletonDeployment,
customContractAddress
}: GetContractProps): Promise<SimulateTxAccessorEthersContract> {
customContractAddress,
customContractAbi
}: GetContractProps): Promise<SimulateTxAccessorContract> {
const chainId = await this.getChainId()
const contractAddress =
customContractAddress ?? singletonDeployment?.networkAddresses[chainId.toString()]
if (!contractAddress) {
throw new Error('Invalid SimulateTxAccessor contract address')
}
const signerOrProvider = this.#signer || this.#provider
return getSimulateTxAccessorContractInstance(safeVersion, contractAddress, signerOrProvider)
return getSimulateTxAccessorContractInstance(
safeVersion,
contractAddress,
this,
customContractAbi
)
}

async getContractCode(address: string, blockTag?: string | number): Promise<string> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Contract, ContractRunner, InterfaceAbi } from 'ethers'

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

/**
* Abstract class SimulateTxAccessorBaseContractEthers extends SimulateTxAccessorBaseContract 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 SimulateTxAccessor contract version.
*
* Subclasses of SimulateTxAccessorBaseContractEthers are expected to represent specific versions of the contract.
*
* @template SimulateTxAccessorContractAbiType - The ABI type specific to the version of the SimulateTxAccessor contract, extending InterfaceAbi from Ethers.
* @extends SimulateTxAccessorBaseContract<SimulateTxAccessorContractAbiType> - Extends the generic SimulateTxAccessorBaseContract with Ethers-specific implementation.
*
* Example subclasses:
* - SimulateTxAccessorContract_v1_4_1_Ethers extends SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_4_1_Abi>
* - SimulateTxAccessorContract_v1_3_0_Ethers extends SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_3_0_Abi>
*/
abstract class SimulateTxAccessorBaseContractEthers<
SimulateTxAccessorContractAbiType extends InterfaceAbi
> extends SimulateTxAccessorBaseContract<SimulateTxAccessorContractAbiType> {
contract: Contract
adapter: EthersAdapter

/**
* @constructor
* Constructs an instance of SimulateTxAccessorBaseContractEthers.
*
* @param chainId - The chain ID of the contract.
* @param ethersAdapter - An instance of EthersAdapter.
* @param defaultAbi - The default ABI for the SimulateTxAccessor 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: SimulateTxAccessorContractAbiType,
safeVersion: SafeVersion,
customContractAddress?: string,
customContractAbi?: SimulateTxAccessorContractAbiType,
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 SimulateTxAccessorBaseContractEthers

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import SimulateTxAccessorBaseContractEthers from '@safe-global/protocol-kit/adapters/ethers/contracts/SimulateTxAccessor/SimulateTxAccessorBaseContractEthers'
import EthersAdapter from '@safe-global/protocol-kit/adapters/ethers/EthersAdapter'
import SimulateTxAccessorContract_v1_3_0_Contract, {
SimulateTxAccessorContract_v1_3_0_Abi
} from '@safe-global/protocol-kit/contracts/AbiType/SimulateTxAccessor/v1.3.0/SimulateTxAccessorContract_v1_3_0'
import SimulateTxAccessor_1_3_0_ContractArtifacts from '@safe-global/protocol-kit/contracts/AbiType/assets/SimulateTxAccessor/v1.3.0/simulate_tx_accessor'
import { SafeVersion } from '@safe-global/safe-core-sdk-types'
import {
EncodeSimulateTxAccessorFunction,
GetAddressSimulateTxAccessorFunction
} from '@safe-global/protocol-kit/contracts/AbiType/SimulateTxAccessor/SimulateTxAccessorBaseContract'

/**
* SimulateTxAccessorContract_v1_3_0_Ethers is the implementation specific to the SimulateTxAccessor contract version 1.3.0.
*
* This class specializes in handling interactions with the SimulateTxAccessor contract version 1.3.0 using Ethers.js v6.
*
* @extends SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_3_0_Abi> - Inherits from SimulateTxAccessorBaseContractEthers with ABI specific to SimulateTxAccessor contract version 1.3.0.
* @implements SimulateTxAccessorContract_v1_3_0_Contract - Implements the interface specific to SimulateTxAccessor contract version 1.3.0.
*/
class SimulateTxAccessorContract_v1_3_0_Ethers
extends SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_3_0_Abi>
implements SimulateTxAccessorContract_v1_3_0_Contract
{
safeVersion: SafeVersion

/**
* Constructs an instance of SimulateTxAccessorContract_v1_3_0_Ethers
*
* @param chainId - The chain ID where the contract resides.
* @param ethersAdapter - An instance of EthersAdapter.
* @param customContractAddress - Optional custom address for the contract. If not provided, the address is derived from the SimulateTxAccessor deployments based on the chainId and safeVersion.
* @param customContractAbi - Optional custom ABI for the contract. If not provided, the default ABI for version 1.3.0 is used.
*/
constructor(
chainId: bigint,
ethersAdapter: EthersAdapter,
customContractAddress?: string,
customContractAbi?: SimulateTxAccessorContract_v1_3_0_Abi
) {
const safeVersion = '1.3.0'
const defaultAbi = SimulateTxAccessor_1_3_0_ContractArtifacts.abi

super(chainId, ethersAdapter, defaultAbi, safeVersion, customContractAddress, customContractAbi)

this.safeVersion = safeVersion
}

getAddress: GetAddressSimulateTxAccessorFunction = () => {
return this.contract.getAddress()
}

encode: EncodeSimulateTxAccessorFunction<SimulateTxAccessorContract_v1_3_0_Abi> = (
functionToEncode,
args
) => {
return this.contract.interface.encodeFunctionData(functionToEncode, args)
}

simulate: SimulateTxAccessorContract_v1_3_0_Contract['simulate'] = (
args: readonly [to: string, value: bigint, data: string, operation: number]
) => {
return this.contract.simulate(...args)
}
}

export default SimulateTxAccessorContract_v1_3_0_Ethers

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import SimulateTxAccessorBaseContractEthers from '@safe-global/protocol-kit/adapters/ethers/contracts/SimulateTxAccessor/SimulateTxAccessorBaseContractEthers'
import EthersAdapter from '@safe-global/protocol-kit/adapters/ethers/EthersAdapter'
import SimulateTxAccessorContract_v1_4_1_Contract, {
SimulateTxAccessorContract_v1_4_1_Abi
} from '@safe-global/protocol-kit/contracts/AbiType/SimulateTxAccessor/v1.4.1/SimulateTxAccessorContract_v1_4_1'
import SimulateTxAccessor_1_4_1_ContractArtifacts from '@safe-global/protocol-kit/contracts/AbiType/assets/SimulateTxAccessor/v1.4.1/simulate_tx_accessor'
import { SafeVersion } from '@safe-global/safe-core-sdk-types'
import {
EncodeSimulateTxAccessorFunction,
GetAddressSimulateTxAccessorFunction
} from '@safe-global/protocol-kit/contracts/AbiType/SimulateTxAccessor/SimulateTxAccessorBaseContract'

/**
* SimulateTxAccessorContract_v1_4_1_Ethers is the implementation specific to the SimulateTxAccessor contract version 1.4.1.
*
* This class specializes in handling interactions with the SimulateTxAccessor contract version 1.4.1 using Ethers.js v6.
*
* @extends SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_4_1_Abi> - Inherits from SimulateTxAccessorBaseContractEthers with ABI specific to SimulateTxAccessor contract version 1.4.1.
* @implements SimulateTxAccessorContract_v1_4_1_Contract - Implements the interface specific to SimulateTxAccessor contract version 1.4.1.
*/
class SimulateTxAccessorContract_v1_4_1_Ethers
extends SimulateTxAccessorBaseContractEthers<SimulateTxAccessorContract_v1_4_1_Abi>
implements SimulateTxAccessorContract_v1_4_1_Contract
{
safeVersion: SafeVersion

/**
* Constructs an instance of SimulateTxAccessorContract_v1_4_1_Ethers
*
* @param chainId - The chain ID where the contract resides.
* @param ethersAdapter - An instance of EthersAdapter.
* @param customContractAddress - Optional custom address for the contract. If not provided, the address is derived from the SimulateTxAccessor deployments based on the chainId and safeVersion.
* @param customContractAbi - Optional custom ABI for the contract. If not provided, the default ABI for version 1.4.1 is used.
*/
constructor(
chainId: bigint,
ethersAdapter: EthersAdapter,
customContractAddress?: string,
customContractAbi?: SimulateTxAccessorContract_v1_4_1_Abi
) {
const safeVersion = '1.4.1'
const defaultAbi = SimulateTxAccessor_1_4_1_ContractArtifacts.abi

super(chainId, ethersAdapter, defaultAbi, safeVersion, customContractAddress, customContractAbi)

this.safeVersion = safeVersion
}

getAddress: GetAddressSimulateTxAccessorFunction = () => {
return this.contract.getAddress()
}

encode: EncodeSimulateTxAccessorFunction<SimulateTxAccessorContract_v1_4_1_Abi> = (
functionToEncode,
args
) => {
return this.contract.interface.encodeFunctionData(functionToEncode, args)
}

simulate: SimulateTxAccessorContract_v1_4_1_Contract['simulate'] = (
args: readonly [to: string, value: bigint, data: string, operation: number]
) => {
return this.contract.simulate(...args)
}
}

export default SimulateTxAccessorContract_v1_4_1_Ethers
Loading

0 comments on commit 8ae3224

Please sign in to comment.