Repository: safe-global/safe-config-service

Issue:
Include `L1` or `L2` information for chains
## Feature

The web app needs to know to which layer any given chain corresponds to.

## Proposal


### Proposal 1
Add the field `layer` to the current `ChainInfo` payload.

```json
{
  "chainId":"4",
  "chainName":"Rinkeby",
  // ...
  "layer":"1" // <stringified-int> 
}
```

Currently `layer` could only take values of either `"1"` or `"2"`

### Proposal 2

(I am not sure I understood the comment correctly)
Return a map of the address to contract for the safe related contracts as part of the chain info. (see https://github.com/gnosis/safe-deployments)


Discussion:
Could we add information why this information is required (e.g. what decision are based on this) ?
In this case in web we opted by this solution because we were already using safe-deployments so a flag to detect whether we should use L1 or L2 function to fetch the safe instance was enough.

If we don't expect to use other different smart contract instances depending on the chain layer (multisend, fallbackhandler...) we could just return the correct gnosisSafe instance address. But if some other smart contracts could also be different depending on network we will need addresses for all the others in future


This information is more or less available via the `/api/v1/about/master-copies/` endpoint of the core services. We can think about piping it though the client gateway instead 🤔 The core services endpoint returns something like:

```javascript
[
  {
    "address": "0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552",
    "version": "1.3.0",
    "deployer": "Gnosis",
  },
  {
    "address": "0x3E5c63644E683549055b9Be8653de26E0B4CD36E",
    "version": "1.3.0+L2", // L2 chain because version contains +L2
    "deployer": "Gnosis",
  }
]
```

How would you fetch this information @dasanra ? On per chain basis or do you need it to be present on a collection view of the chains (array with all the chains and corresponding data)?
We should change the purpose of the issue to return the information missing to completely remove network specific configurations from the safe-react project. A big part of this would be the contract addresses (e.g. default mastercopy, proxy factory, etc).
@gnosis/safe-web can you share what information is required for this?
We currently use the safe-deployments repo for contract addresses. The problem is, [safe-deployments exports two functions](https://github.com/gnosis/safe-deployments/blob/main/src/safes.ts#L14-L23):

* getSafeSingletonDeployment
* getSafeL2SingletonDeployment

And we don't know which one to call for which network. I mean, we know that Polygon is L2, but the app doesn't.
> We currently use the safe-deployments repo for contract addresses. The problem is, [safe-deployments exports two functions](https://github.com/gnosis/safe-deployments/blob/main/src/safes.ts#L14-L23):
> 
> * getSafeSingletonDeployment
> * getSafeL2SingletonDeployment
> 
> And we don't know which one to call for which network. I mean, we know that Polygon is L2, but the app doesn't.

So you require something like this interface to be returned right? https://github.com/gnosis/safe-deployments/blob/c3a8ef4ee5c980b1d1e74eaa1ad01e82dc301a5f/src/types.ts#L1-L8

I see that you use `networkAddresses`, `defaultAddress` and `abi` from this interface. Are these the fields that you require to be added to the `safe-config-service`?


These are just the two functions that differ depending on L1/L2. We also use:
* getProxyFactoryDeployment
* getFallbackHandlerDeployment
* getMultiSendCallOnlyDeployment

So if we go the route of adding the deployment artifacts to the config service, those 3 should also be there.
Got it. But how do you use those functions? Which fields do you require to be returned by the config-service so that the migration on your side is done without issues?

I think it'd be better to start with a json payload proposal from the client side.
There's only one L1 network - the mainnet. So cannot it be hardcoded for the network with chain id 1?
I think rinkeby is also L1.
@fmrsabino the proposal in this issue description will definitely satisfy our need in the mid/short term. We can continue using the safe-deployments repo in combination with that.
As mentioned in our meeting, if we pull the information from the service about what networks are supported then we should switch away from the `safe-deployments`. There are currently a couple of addresses that I see depend on the network (and in the near future L1 or L2 is not enough to differentiate this):
- proxy factory
- mastercopy/ singleton address
- fallback handler
- multisend/ multisendcallonly
- allowance module

There fore I would propose that the backend returns an object `contracts` where the keys are the contracts mentioned above. For example:
```json
{
  "chainId": "1",
  "chainName": "Mainnet",
  "contracts": {
    "factory": "<factory_address>",
    "singleton": "<singleton_address>",
    "fallback": "<fallback_handler_address>",
    "multisend": "<multisend_address>",
    "allowances": "<allowance_module_address>"
  }
}
```


Edit: 
What needs to be discussed is if we should add additional checks for the validity of the returned values (e.g. let the clients or client gateway check this against the supported mastercopies/ factories).

Edit2:

- `factory`, `singleton` and `fallback` are used when creating/ upgrading Safes. 
- `allowances` are used for everything that uses the "Spending Limit" feature
- `multisend` is used for everything where transaction are batched (e.g. Safe apps or Safe contract version upgrade)
I like the suggestion above, that would allow us to remove the safe-deployments dependency.
I guess the maintenance effort on the admin side would be the same as updating the safe-deployments repo.

Since 1.3.0 contracts support earlier safes (1.1.1), we probably wouldn't need to maintain any legacy contract addresses on config service?
> I like the suggestion above, that would allow us to remove the safe-deployments dependency.
> I guess the maintenance effort on the admin side would be the same as updating the safe-deployments repo.
> 
> Since 1.3.0 contracts support earlier safes (1.1.1), we probably wouldn't need to maintain any legacy contract addresses on config service?

Would the payload that @rmeissner suggested work for what you need on the client side?
Yes, unless we want to keep supporting 1.1.1.
As of now, we have this in the code:
<img width="934" alt="Screenshot 2021-09-07 at 11 49 02" src="https://user-images.githubusercontent.com/381895/132324412-3ebce4a5-680d-46d4-9100-c859171ce8d3.png">
Conclusions of the meeting about this issue with  @dasanra @fmrsabino @katspaugh  @rmeissner

**Decision**
We decided that we will go with the original proposal of having a flag returned by the `safe-config-service`:

```javascript
GET api/v1/chains
{
  "l2": <boolean>
}
```

**Why not have the contract addresses returned as suggested in one iteration?**
The proposal for having the contracts returned by the `config-service` raised some security concerns where we have a centralised point where this data is returned – the safe creation payload would be just used as is with any connected wallet on the `safe-react` side.

An additional check on the CGW was proposed but would still rely on trusting our infrastructure.

Given the security concerns raised above, the preferred option is still to rely on the current configuration of the `safe-deployments` repo because it involves more parties/coordination and the information is publicly available – `safe-deployment` releases, `safe-config-service` data (l2 flag) and open cross checking (since the repositories are public. This is more in line with our vision with trust-less deployments.

**What about the allowances module address?**

The allowances module is currently not available in the `safe-deployments` and it was suggested to be added as part of this ticket in a previous iteration.

A followup meeting/ticket will tackle if this address is going to be added to the `safe-deployments` repo and in which way. 

Resolving patch:
diff --git a/src/chains/migrations/0026_chain_l2.py b/src/chains/migrations/0026_chain_l2.py
new file mode 100644
--- /dev/null
+++ b/src/chains/migrations/0026_chain_l2.py
@@ -0,0 +1,19 @@
+# Generated by Django 3.2.7 on 2021-09-15 08:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("chains", "0025_alter_chain_currency_logo_uri"),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name="chain",
+            name="l2",
+            field=models.BooleanField(default=False),
+            preserve_default=False,
+        ),
+    ]
diff --git a/src/chains/models.py b/src/chains/models.py
--- a/src/chains/models.py
+++ b/src/chains/models.py
@@ -33,6 +33,7 @@ class RpcAuthentication(models.TextChoices):
         default=100
     )  # A lower number will indicate more relevance
     name = models.CharField(verbose_name="Chain name", max_length=255)
+    l2 = models.BooleanField()
     rpc_authentication = models.CharField(
         max_length=255, choices=RpcAuthentication.choices
     )
diff --git a/src/chains/serializers.py b/src/chains/serializers.py
--- a/src/chains/serializers.py
+++ b/src/chains/serializers.py
@@ -97,6 +97,7 @@ class Meta:
         fields = [
             "chain_id",
             "chain_name",
+            "l2",
             "rpc_uri",
             "safe_apps_rpc_uri",
             "block_explorer_uri_template",


Test patch:
diff --git a/src/chains/tests/factories.py b/src/chains/tests/factories.py
--- a/src/chains/tests/factories.py
+++ b/src/chains/tests/factories.py
@@ -14,6 +14,7 @@ class Meta:
     id = factory.Sequence(lambda id: id)
     relevance = factory.Faker("pyint")
     name = factory.Faker("company")
+    l2 = factory.Faker("pybool")
     rpc_authentication = factory.lazy_attribute(
         lambda o: random.choice(list(Chain.RpcAuthentication))
     )
diff --git a/src/chains/tests/test_views.py b/src/chains/tests/test_views.py
--- a/src/chains/tests/test_views.py
+++ b/src/chains/tests/test_views.py
@@ -28,6 +28,7 @@ def test_json_payload_format(self):
                 {
                     "chainId": str(gas_price.chain.id),
                     "chainName": chain.name,
+                    "l2": chain.l2,
                     "rpcUri": {
                         "authentication": chain.rpc_authentication,
                         "value": chain.rpc_uri,
@@ -132,6 +133,7 @@ def test_json_payload_format(self):
         json_response = {
             "chainId": str(chain.id),
             "chainName": chain.name,
+            "l2": chain.l2,
             "rpcUri": {
                 "authentication": chain.rpc_authentication,
                 "value": chain.rpc_uri,
@@ -185,6 +187,7 @@ def test_match(self):
         json_response = {
             "chain_id": str(chain.id),
             "chain_name": chain.name,
+            "l2": chain.l2,
             "rpc_uri": {
                 "authentication": chain.rpc_authentication,
                 "value": chain.rpc_uri,