creation_sourcecode: // SPDX-License-Identifier: LGPL-3.0-or-later
  // Taken from: https://github.com/gnosis/safe-contracts/blob/development/contracts/proxies/GnosisSafeProxy.sol
  pragma solidity ^0.7.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 WalletProxy - 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 WalletProxy {
  
      // masterCopy 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 masterCopy;
  
      /// @dev Constructor function sets address of master copy contract.
      /// @param _masterCopy Master copy address.
      constructor(address _masterCopy)
      {
          require(_masterCopy != address(0), "Invalid master copy address provided");
          masterCopy = _masterCopy;
      }
  
      /// @dev Fallback function forwards all transactions and returns all received return data.
      fallback()
      payable
      external
      {
          // solium-disable-next-line security/no-inline-assembly
          assembly {
              let _masterCopy := and(sload(0), 0xffffffffffffffffffffffffffffffffffffffff)
          // 0xa619486e == keccak("masterCopy()"). The value is right padded to 32-bytes with 0s
              if eq(calldataload(0), 0xa619486e00000000000000000000000000000000000000000000000000000000) {
                  mstore(0, _masterCopy)
                  return(0, 0x20)
              }
              calldatacopy(0, 0, calldatasize())
              let success := delegatecall(gas(), _masterCopy, 0, calldatasize(), 0, 0)
              returndatacopy(0, 0, returndatasize())
              if eq(success, 0) { revert(0, returndatasize()) }
              return(0, returndatasize())
          }
      }
  }