creation_sourcecode: // SPDX-License-Identifier: LGPL-3.0-only
  pragma solidity >=0.7.0 <0.9.0;
  
  /// @title IProxy - Helper interface to access masterCopy of the Proxy on-chain
  /// @author Richard Meissner - <richard@gnosis.io>
  interface IProxy {
      function masterCopy() external view returns (address);
  }
  
  /// @title GnosisSafeProxy - Generic proxy contract allows to execute all transactions applying the code of a master contract.
  /// @author Stefan George - <stefan@gnosis.io>
  /// @author Richard Meissner - <richard@gnosis.io>
  contract GnosisSafeProxy {
      // singleton always needs to be first declared variable, to ensure that it is at the same location in the contracts to which calls are delegated.
      // To reduce deployment costs this variable is internal and needs to be retrieved via `getStorageAt`
      address internal singleton;
  
      /// @dev Constructor function sets address of singleton contract.
      /// @param _singleton Singleton address.
      constructor(address _singleton) {
          require(_singleton != address(0), "Invalid singleton address provided");
          singleton = _singleton;
      }
  
      /// @dev Fallback function forwards all transactions and returns all received return data.
      fallback() external payable {
          // solhint-disable-next-line no-inline-assembly
          assembly {
              let _singleton := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
              // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
              if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
                  mstore(0, _singleton)
                  return(0, 0x20)
              }
              calldatacopy(0, 0, calldatasize())
              let success := delegatecall(gas(), _singleton, 0, calldatasize(), 0, 0)
              returndatacopy(0, 0, returndatasize())
              if eq(success, 0) {
                  revert(0, returndatasize())
              }
              return(0, returndatasize())
          }
      }
  }
  
  /// @title Proxy Factory - Allows to create new proxy contact and execute a message call to the new proxy within one transaction.
  /// @author Stefan George - <stefan@gnosis.pm>
  contract GnosisSafeProxyFactory {
      event ProxyCreation(GnosisSafeProxy proxy, address singleton);
  
      /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.
      /// @param singleton Address of singleton contract.
      /// @param data Payload for message call sent to new proxy contract.
      function createProxy(address singleton, bytes memory data) public returns (GnosisSafeProxy proxy) {
          proxy = new GnosisSafeProxy(singleton);
          if (data.length > 0)
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  if eq(call(gas(), proxy, 0, add(data, 0x20), mload(data), 0, 0), 0) {
                      revert(0, 0)
                  }
              }
          emit ProxyCreation(proxy, singleton);
      }
  
      /// @dev Allows to retrieve the runtime code of a deployed Proxy. This can be used to check that the expected Proxy was deployed.
      function proxyRuntimeCode() public pure returns (bytes memory) {
          return type(GnosisSafeProxy).runtimeCode;
      }
  
      /// @dev Allows to retrieve the creation code used for the Proxy deployment. With this it is easily possible to calculate predicted address.
      function proxyCreationCode() public pure returns (bytes memory) {
          return type(GnosisSafeProxy).creationCode;
      }
  
      /// @dev Allows to create new proxy contact using CREATE2 but it doesn't run the initializer.
      ///      This method is only meant as an utility to be called from other methods
      /// @param _singleton Address of singleton contract.
      /// @param initializer Payload for message call sent to new proxy contract.
      /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
      function deployProxyWithNonce(
          address _singleton,
          bytes memory initializer,
          uint256 saltNonce
      ) internal returns (GnosisSafeProxy proxy) {
          // If the initializer changes the proxy address should change too. Hashing the initializer data is cheaper than just concatinating it
          bytes32 salt = keccak256(abi.encodePacked(keccak256(initializer), saltNonce));
          bytes memory deploymentData = abi.encodePacked(type(GnosisSafeProxy).creationCode, uint256(uint160(_singleton)));
          // solhint-disable-next-line no-inline-assembly
          assembly {
              proxy := create2(0x0, add(0x20, deploymentData), mload(deploymentData), salt)
          }
          require(address(proxy) != address(0), "Create2 call failed");
      }
  
      /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.
      /// @param _singleton Address of singleton contract.
      /// @param initializer Payload for message call sent to new proxy contract.
      /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
      function createProxyWithNonce(
          address _singleton,
          bytes memory initializer,
          uint256 saltNonce
      ) public returns (GnosisSafeProxy proxy) {
          proxy = deployProxyWithNonce(_singleton, initializer, saltNonce);
          if (initializer.length > 0)
              // solhint-disable-next-line no-inline-assembly
              assembly {
                  if eq(call(gas(), proxy, 0, add(initializer, 0x20), mload(initializer), 0, 0), 0) {
                      revert(0, 0)
                  }
              }
          emit ProxyCreation(proxy, _singleton);
      }
  
      /// @dev Allows to create new proxy contact, execute a message call to the new proxy and call a specified callback within one transaction
      /// @param _singleton Address of singleton contract.
      /// @param initializer Payload for message call sent to new proxy contract.
      /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
      /// @param callback Callback that will be invoced after the new proxy contract has been successfully deployed and initialized.
      function createProxyWithCallback(
          address _singleton,
          bytes memory initializer,
          uint256 saltNonce,
          IProxyCreationCallback callback
      ) public returns (GnosisSafeProxy proxy) {
          uint256 saltNonceWithCallback = uint256(keccak256(abi.encodePacked(saltNonce, callback)));
          proxy = createProxyWithNonce(_singleton, initializer, saltNonceWithCallback);
          if (address(callback) != address(0)) callback.proxyCreated(proxy, _singleton, initializer, saltNonce);
      }
  
      /// @dev Allows to get the address for a new proxy contact created via `createProxyWithNonce`
      ///      This method is only meant for address calculation purpose when you use an initializer that would revert,
      ///      therefore the response is returned with a revert. When calling this method set `from` to the address of the proxy factory.
      /// @param _singleton Address of singleton contract.
      /// @param initializer Payload for message call sent to new proxy contract.
      /// @param saltNonce Nonce that will be used to generate the salt to calculate the address of the new proxy contract.
      function calculateCreateProxyWithNonceAddress(
          address _singleton,
          bytes calldata initializer,
          uint256 saltNonce
      ) external returns (GnosisSafeProxy proxy) {
          proxy = deployProxyWithNonce(_singleton, initializer, saltNonce);
          revert(string(abi.encodePacked(proxy)));
      }
  }
  
  interface IProxyCreationCallback {
      function proxyCreated(
          GnosisSafeProxy proxy,
          address _singleton,
          bytes calldata initializer,
          uint256 saltNonce
      ) external;
  }