fromAddress static method

Future<SafeContractController> fromAddress({
  1. required ONREQUESTETHPROVIDER onRequestProvider,
  2. required SafeContractAssets assets,
  3. required ETHAddress address,
  4. BigInt? chainId,
})

Implementation

static Future<SafeContractController> fromAddress({
  required ONREQUESTETHPROVIDER onRequestProvider,
  required SafeContractAssets assets,
  required ETHAddress address,
  BigInt? chainId,
}) async {
  final provider = await onRequestProvider();
  chainId ??= await provider.request(EthereumRequestGetChainId());
  Future<SafeContractController> getController() async {
    final firstSlot = await provider.request(
      EthereumRequestGetStorageAt(
        address: address.address,
        storageSlot: "0x00",
      ),
    );
    final singletonProxy =
        ABIUtils.decodeSingle<SolidityAddress>(
          type: "address",
          bytes: BytesUtils.fromHexString(firstSlot),
        ).toEthereumAddress();
    if (singletonProxy != ETHAddress.zero) {
      final manifest = assets.fromSingletonAddress(singletonProxy);
      return SafeContractController(
        contract: SafeSingletonContract(
          contract:
              manifest
                  .getSafeSingletonManifestFromAddress(singletonProxy)
                  .abi,
          contractAddress: address,
          version: manifest.version,
        ),
        onRequestProvider: onRequestProvider,
        chainId: chainId!,
      );
    }
    final chainIds = assets.getSupportedChainIds();
    if (!chainIds.contains(chainId)) {
      throw ETHPluginException(
        "The provided chainId is not supported by Safe assets.",
        details: {"chainId": chainId.toString()},
      );
    }
    final manifest = assets.getLatestDeployment();
    final contract = SafeSingletonContract(
      contract: manifest.getSingletonContractAbi(),
      contractAddress: address,
      version: manifest.version,
    );
    try {
      final storage = await contract.getStorageAt(
        provider: provider,
        offset: 0,
        length: 1,
      );
      final singletonProxy =
          ABIUtils.decodeSingle<SolidityAddress>(
            type: "address",
            bytes: storage,
          ).toEthereumAddress();
      if (singletonProxy != ETHAddress.zero) {
        final manifest = assets.fromSingletonAddress(singletonProxy);
        return SafeContractController(
          contract: SafeSingletonContract(
            contract:
                manifest
                    .getSafeSingletonManifestFromAddress(singletonProxy)
                    .abi,
            contractAddress: address,
            version: manifest.version,
          ),
          onRequestProvider: onRequestProvider,
          chainId: chainId!,
        );
      }
    } on RPCError catch (_) {}
    throw ETHPluginException(
      "Unable to locate the ABI for the specified Safe Singleton address.",
      details: {"address": address.address},
    );
  }

  final controller = await getController();
  final version = SafeContractVersion.fromVersion(
    await controller.contract.getVersion(provider),
  );
  if (version == controller.contract.version) {
    return controller;
  }
  throw ETHPluginException(
    "Failed to verify the singleton contract address.",
  );
}