setup method

  1. @override
Future<SafeContractEncodedCall> setup({
  1. required List<ETHAddress> owners,
  2. required BigInt threshold,
  3. ETHAddress? to,
  4. List<int>? data,
  5. ETHAddress? fallbackHandler,
  6. ETHAddress? paymentToken,
  7. BigInt? payment,
  8. ETHAddress? paymentReceiver,
})
override

"stateMutability": "nonpayable", Initializes the Safe account with its initial storage configuration.

Notes:

  • This method can only be called once.
  • ⚠️ SECURITY WARNING: If a proxy is deployed without running setup, anyone can call setup and take control of the Safe.
  • ⚠️ EIP-7702 Warning: A Safe can set itself as an owner, which is valid for EIP-7702 delegation setups. However, if the Safe address is not an EOA (Externally Owned Account) and cannot sign for itself, this may lock access to the account permanently. For example, in an n/n Safe (where threshold == ownerCount), if the Safe includes itself as an owner without EIP-7702 delegation, no valid signature can ever be produced, effectively bricking the Safe.
  • This method emits a SafeSetup event containing the setup parameters instead of reading them from storage, meaning the emitted event data may not reflect the actual state if the delegate call (to) modifies owners, threshold, or fallback handler.

Parameters:

  • owners: List of initial Safe owner addresses.
  • threshold: Number of required confirmations for a Safe transaction.
  • to: Optional initializer contract address; it will be called via DELEGATECALL with data. Use the zero address (0x0) to skip additional initialization.
  • data: Data payload for the initializer contract.
  • fallbackHandler: Address of the fallback handler contract.
  • paymentToken: Token used for payment (0x0 for native token, e.g., ETH).
  • payment: Amount to pay for initialization.
  • paymentReceiver: Address to receive the payment (0x0 for tx.origin).

Implementation

@override
Future<SafeContractEncodedCall> setup({
  required List<ETHAddress> owners,
  required BigInt threshold,
  ETHAddress? to,
  List<int>? data,
  ETHAddress? fallbackHandler,
  ETHAddress? paymentToken,
  BigInt? payment,
  ETHAddress? paymentReceiver,
}) async {
  final params = [
    owners,
    threshold,
    to ?? ETHAddress.zero,
    data ?? <int>[],
    if (fallbackHandler != null) fallbackHandler,
    paymentToken ?? ETHAddress.zero,
    payment ?? BigInt.zero,
    paymentReceiver ?? ETHAddress.zero,
  ];
  return encodeTransactionCall(
    functionName: SafeContractFunction.setup,
    params: params,
  );
}