GuidesAPI Reference
Log In
Guides

Gnosis Safe integration

How does the Blowfish API work with Gnosis Safe based wallets

Blowfish's API has full support for simulating transactions and messages for Gnosis Safe based wallets, including overriding signature thresholds.

Transactions

For simulating transactions of m-of-n without the appropriate signatures in place we have created Gnosis Safe preset simulatorConfig option. When passed in the request payload the EVM simulator will automatically override the signature threshold variable from m-of-n to 1-of-n. If the specified tx.from account is one of the signers for the Safe the transaction will simulate successfully as the tx.from will count as one signature.

If the signer does not have enough funds to submit transactions the nativeBalance override can be used to boost the Signers ETH balance during simulation.

Here is an example using a Gnosis Safe on Optimism where the signer has 0 ETH.

{
  "txObjects": [
    {
      // Signer #1 with 0 ETH balance
      "from": "0x57f4055164D42D1ee320cF7909E997E6828cDb65",
      // Gnosis Safe contract
      "to": "0x2cb5a1589f16655036caf137443ccb50dee3333a",
      // Encoded Gnosis Safe transaction calldata for sending 0.001 ETH
      "data": "0x6a761202000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000003328b944c4000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008200000000000000000000000057f4055164d42d1ee320cf7909e997e6828cdb650000000000000000000000000000000000000000000000000000000000000000011e9850743972b1f25f660f6ec3bf4ee52c3c4f1a753581680b6aee92c574e5205c34b66a53ef53a9a25757f1e85b5cfa32be2e807b6f9eb92b33bffbdb3967c41c000000000000000000000000000000000000000000000000000000000000"
    }
  ],
  // Simulate state changes and scan from the point-of-view of the Safe
  "userAccount": "0x2cb5a1589f16655036caf137443ccb50dee3333a",
  "metadata": {
    "origin": "https://examples.blowfish.tools"
  },
  "simulatorConfig": {
    "stateOverrides": {
      "nativeBalances": [
        {
          // Set Signer #1's balance to 0.1 ETH during simulation
          // so that they would have enough funds to pay for the transaction
          "address": "0x57f4055164D42D1ee320cF7909E997E6828cDb65",
          "value": "100000000000000000"
        }
      ],
      "storage": []
    },
    "presets": [
      {
        // Enable the GNOSIS_SAFE preset
        "kind": "GNOSIS_SAFE",
        // Specify the Safe address so that the signature threshold can be overriden
        "walletAddress": "0x2cb5a1589f16655036caf137443ccb50dee3333a"
      }
    ]
  }
}
curl --request POST \
     --url 'https://api.blowfish.xyz/optimism/v0/mainnet/scan/transactions?language=en' \
     --header 'Content-Type: application/json' \
     --header 'X-Api-Key: YOUR_API_KEY_HERE' \
     --header 'X-Api-Version: 2023-06-05' \
     --header 'accept: application/json' \
     --data '
{
  "txObjects": [
    {
      "from": "0x57f4055164D42D1ee320cF7909E997E6828cDb65",
      "to": "0x2cb5a1589f16655036caf137443ccb50dee3333a",
      "data": "0x6a761202000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000003328b944c4000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008200000000000000000000000057f4055164d42d1ee320cf7909e997e6828cdb650000000000000000000000000000000000000000000000000000000000000000011e9850743972b1f25f660f6ec3bf4ee52c3c4f1a753581680b6aee92c574e5205c34b66a53ef53a9a25757f1e85b5cfa32be2e807b6f9eb92b33bffbdb3967c41c000000000000000000000000000000000000000000000000000000000000"
    }
  ],
  "userAccount": "0x2cb5a1589f16655036caf137443ccb50dee3333a",
  "metadata": {
    "origin": "https://examples.blowfish.tools"
  },
  "simulatorConfig": {
    "stateOverrides": {
      "nativeBalances": [
        {
          "address": "0x57f4055164D42D1ee320cF7909E997E6828cDb65",
          "value": "100000000000000000"
        }
      ],
      "storage": []
    },
    "presets": [
      {
        "kind": "GNOSIS_SAFE",
        "walletAddress": "0x2cb5a1589f16655036caf137443ccb50dee3333a"
      }
    ]
  }
}
'
{
   "action" : "NONE",
   "requestId" : "d70f18e18a0826c7b8fa372196016207",
   "simulationResults" : {
      "aggregated" : {
         "error" : null,
         "expectedStateChanges" : {
            "0x2cb5a1589f16655036caf137443ccb50dee3333a" : [
               {
                  "humanReadableDiff" : "Send 0.0009 ETH",
                  "rawInfo" : {
                     "data" : {
                        "amount" : {
                           "after" : "0",
                           "before" : "900000000000000"
                        },
                        "asset" : {
                           "address" : "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                           "decimals" : 18,
                           "imageUrl" : "https://d1ts37qlq4uz4s.cloudfront.net/evm__evm%3A%3Aethereum__evm%3A%3Aethereum%3A%3Amainnet__0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
                           "name" : "Ether",
                           "price" : {
                              "dollarValuePerToken" : 2644.45,
                              "source" : "Coingecko",
                              "updatedAt" : 1723555200
                           },
                           "symbol" : "ETH",
                           "verified" : true
                        },
                        "counterparty" : {
                           "address" : "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
                           "kind" : "ACCOUNT"
                        }
                     },
                     "kind" : "NATIVE_ASSET_TRANSFER"
                  }
               }
            ],
            "0xd8da6bf26964af9d7eed9e03e53415d37aa96045" : [
               {
                  "humanReadableDiff" : "Receive 0.0009 ETH",
                  "rawInfo" : {
                     "data" : {
                        "amount" : {
                           "after" : "238959654892529998",
                           "before" : "238059654892529998"
                        },
                        "asset" : {
                           "address" : "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                           "decimals" : 18,
                           "imageUrl" : "https://d1ts37qlq4uz4s.cloudfront.net/evm__evm%3A%3Aethereum__evm%3A%3Aethereum%3A%3Amainnet__0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
                           "name" : "Ether",
                           "price" : {
                              "dollarValuePerToken" : 2644.45,
                              "source" : "Coingecko",
                              "updatedAt" : 1723555200
                           },
                           "symbol" : "ETH",
                           "verified" : true
                        },
                        "counterparty" : {
                           "address" : "0x2cb5a1589f16655036caf137443ccb50dee3333a",
                           "kind" : "ACCOUNT"
                        }
                     },
                     "kind" : "NATIVE_ASSET_TRANSFER"
                  }
               }
            ]
         },
         "userAccount" : "0x2cb5a1589f16655036caf137443ccb50dee3333a"
      },
      "perTransaction" : [
         {
            "decodedCalldata" : null,
            "decodedLogs" : [
               null,
               null
            ],
            "error" : null,
            "gas" : {
               "gasLimit" : "64147"
            },
            "logs" : [
               {
                  "address" : "0x2cb5a1589f16655036caf137443ccb50dee3333a",
                  "data" : "0x000000000000000000000000d8da6bf26964af9d7eed9e03e53415d37aa960450000000000000000000000000000000000000000000000000003328b944c40000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008200000000000000000000000057f4055164d42d1ee320cf7909e997e6828cdb650000000000000000000000000000000000000000000000000000000000000000011e9850743972b1f25f660f6ec3bf4ee52c3c4f1a753581680b6aee92c574e5205c34b66a53ef53a9a25757f1e85b5cfa32be2e807b6f9eb92b33bffbdb3967c41c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000400000000000000000000000057f4055164d42d1ee320cf7909e997e6828cdb650000000000000000000000000000000000000000000000000000000000000001",
                  "topics" : [
                     "0x66753cd2356569ee081232e3be8909b950e0a76c1f8460c3a5e3c2be32b11bed"
                  ]
               },
               {
                  "address" : "0x2cb5a1589f16655036caf137443ccb50dee3333a",
                  "data" : "0x1e8de1c5625f533121e5ef0b20d3a2ed00e0df952ac86407fb8cb9008f2a48d80000000000000000000000000000000000000000000000000000000000000000",
                  "topics" : [
                     "0x442e715f626346e8c54381002da614f62bee8d27386535b2521ec8540898556e"
                  ]
               }
            ],
            "protocol" : null
         }
      ]
   },
   "warnings" : []
}


Messages

Gnosis Safe Transaction message

When simulating a Gnosis Transaction in EIP712 message using the Blowfish message scanning endpoint the only caveat is that the userAccount needs to be set to one of the Safe signer accounts. The signer account does not need to have any balance. The message simulator detect that it's a Gnosis transaction simulate the transaction from the point-of-view of the Gnosis Safe. No further configuration is needed.

Here is an example using a Gnosis Safe on Optimism where the signer has 0 ETH.

{
  "message": {
    "kind": "SIGN_TYPED_DATA",
    "data": {
      "types": {
        "SafeTx": [
          {
            "name": "to",
            "type": "address"
          },
          {
            "name": "value",
            "type": "uint256"
          },
          {
            "name": "data",
            "type": "bytes"
          },
          {
            "name": "operation",
            "type": "uint8"
          },
          {
            "name": "safeTxGas",
            "type": "uint256"
          },
          {
            "name": "baseGas",
            "type": "uint256"
          },
          {
            "name": "gasPrice",
            "type": "uint256"
          },
          {
            "name": "gasToken",
            "type": "address"
          },
          {
            "name": "refundReceiver",
            "type": "address"
          },
          {
            "name": "nonce",
            "type": "uint256"
          }
        ],
        "EIP712Domain": [
          {
            "name": "chainId",
            "type": "uint256"
          },
          {
            "name": "verifyingContract",
            "type": "address"
          }
        ]
      },
      "domain": {
        "chainId": "0xa",
        "verifyingContract": "0x2cb5a1589f16655036caf137443ccb50dee3333a"
      },
      "primaryType": "SafeTx",
      "message": {
        "to": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
        "value": "900000000000000",
        "data": "0x",
        "operation": "0",
        "safeTxGas": "0",
        "baseGas": "0",
        "gasPrice": "0",
        "gasToken": "0x0000000000000000000000000000000000000000",
        "refundReceiver": "0x0000000000000000000000000000000000000000",
        "nonce": "4"
      }
    }
  },
  // NOTE: The user account needs to be the address of one of the signers
  // the account does not need to have any ETH balance
  // the simulation results & security scanning will still be performed
  // on the Safe account in the message
  "userAccount": "0x57f4055164D42D1ee320cF7909E997E6828cDb65",
  "metadata": {
    "origin": "https://examples.blowfish.tools"
  }
}

curl --request POST \
     --url 'https://api.blowfish.xyz/optimism/v0/mainnet/scan/message?language=en' \
     --header 'Content-Type: application/json' \
     --header 'X-Api-Key: YOUR_API_KEY_HERE' \
     --header 'X-Api-Version: 2023-06-05' \
     --header 'accept: application/json' \
     --data '
{
  "message": {
    "kind": "SIGN_TYPED_DATA",
    "data": {
      "types": {
        "SafeTx": [
          {
            "name": "to",
            "type": "address"
          },
          {
            "name": "value",
            "type": "uint256"
          },
          {
            "name": "data",
            "type": "bytes"
          },
          {
            "name": "operation",
            "type": "uint8"
          },
          {
            "name": "safeTxGas",
            "type": "uint256"
          },
          {
            "name": "baseGas",
            "type": "uint256"
          },
          {
            "name": "gasPrice",
            "type": "uint256"
          },
          {
            "name": "gasToken",
            "type": "address"
          },
          {
            "name": "refundReceiver",
            "type": "address"
          },
          {
            "name": "nonce",
            "type": "uint256"
          }
        ],
        "EIP712Domain": [
          {
            "name": "chainId",
            "type": "uint256"
          },
          {
            "name": "verifyingContract",
            "type": "address"
          }
        ]
      },
      "domain": {
        "chainId": "0xa",
        "verifyingContract": "0x2cb5a1589f16655036caf137443ccb50dee3333a"
      },
      "primaryType": "SafeTx",
      "message": {
        "to": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
        "value": "900000000000000",
        "data": "0x",
        "operation": "0",
        "safeTxGas": "0",
        "baseGas": "0",
        "gasPrice": "0",
        "gasToken": "0x0000000000000000000000000000000000000000",
        "refundReceiver": "0x0000000000000000000000000000000000000000",
        "nonce": "4"
      }
    }
  },
  "userAccount": "0x57f4055164D42D1ee320cF7909E997E6828cDb65",
  "metadata": {
    "origin": "https://examples.blowfish.tools"
  }
}
'
{
   "action" : "NONE",
   "requestId" : "9b35e8dbd995d15a7822c88b239e4625",
   "simulationResults" : {
      "error" : null,
      "expectedStateChanges" : [
         {
            "humanReadableDiff" : "Send 0.0009 ETH",
            "rawInfo" : {
               "data" : {
                  "amount" : {
                     "after" : "0",
                     "before" : "900000000000000"
                  },
                  "asset" : {
                     "address" : "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                     "decimals" : 18,
                     "imageUrl" : "https://d1ts37qlq4uz4s.cloudfront.net/evm__evm%3A%3Aethereum__evm%3A%3Aethereum%3A%3Amainnet__0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2.png",
                     "name" : "Ether",
                     "price" : {
                        "dollarValuePerToken" : 2647.2,
                        "source" : "Coingecko",
                        "updatedAt" : 1723554601
                     },
                     "symbol" : "ETH",
                     "verified" : true
                  },
                  "contract" : {
                     "address" : "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
                     "kind" : "ACCOUNT"
                  }
               },
               "kind" : "NATIVE_ASSET_TRANSFER"
            }
         }
      ],
      "protocol" : null
   },
   "warnings" : []
}

General EIP-712 messages with Gnosis Safe

When scanning general EIP-712 messages with a Gnosis Safe the underlying message that the dapp is prompting signature for should be sent to the message scanner endpoint. The userAccount property should be set to the Safe wallet account.

Here is an example using a Gnosis Safe on Optimism using Permit2 with the Uniswap Universal Router

{
    "message": {
        "kind": "SIGN_TYPED_DATA",
        "data": {
            "types": {
                "PermitSingle": [
                    {
                        "name": "details",
                        "type": "PermitDetails"
                    },
                    {
                        "name": "spender",
                        "type": "address"
                    },
                    {
                        "name": "sigDeadline",
                        "type": "uint256"
                    }
                ],
                "PermitDetails": [
                    {
                        "name": "token",
                        "type": "address"
                    },
                    {
                        "name": "amount",
                        "type": "uint160"
                    },
                    {
                        "name": "expiration",
                        "type": "uint48"
                    },
                    {
                        "name": "nonce",
                        "type": "uint48"
                    }
                ],
                "EIP712Domain": [
                    {
                        "name": "name",
                        "type": "string"
                    },
                    {
                        "name": "chainId",
                        "type": "uint256"
                    },
                    {
                        "name": "verifyingContract",
                        "type": "address"
                    }
                ]
            },
            "domain": {
                "name": "Permit2",
                "chainId": "10",
                "verifyingContract": "0x000000000022d473030f116ddee9f6b43ac78ba3"
            },
            "primaryType": "PermitSingle",
            "message": {
                "details": {
                    "token": "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
                    "amount": "1461501637330902918203684832716283019655932542975",
                    "expiration": "2726145248",
                    "nonce": "0"
                },
                "spender": "0xcb1355ff08ab38bbce60111f1bb2b784be25d7e8",
                "sigDeadline": "2723555048"
            }
        }
    },
    // NOTE: The userAccount should be the address of the Gnosis Safe
    "userAccount": "0x2cb5a1589f16655036caf137443CcB50dEe3333a",
    "metadata": {
        "origin": "https://examples.blowfish.xyz"
    }
}
curl --request POST \
     --url 'https://api.blowfish.xyz/optimism/v0/mainnet/scan/message?language=en' \
     --header 'Content-Type: application/json' \
     --header 'X-Api-Key: YOUR_API_KEY_HERE' \
     --header 'X-Api-Version: 2023-06-05' \
     --header 'accept: application/json' \
     --data '
{
    "message": {
        "kind": "SIGN_TYPED_DATA",
        "data": {
            "types": {
                "PermitSingle": [
                    {
                        "name": "details",
                        "type": "PermitDetails"
                    },
                    {
                        "name": "spender",
                        "type": "address"
                    },
                    {
                        "name": "sigDeadline",
                        "type": "uint256"
                    }
                ],
                "PermitDetails": [
                    {
                        "name": "token",
                        "type": "address"
                    },
                    {
                        "name": "amount",
                        "type": "uint160"
                    },
                    {
                        "name": "expiration",
                        "type": "uint48"
                    },
                    {
                        "name": "nonce",
                        "type": "uint48"
                    }
                ],
                "EIP712Domain": [
                    {
                        "name": "name",
                        "type": "string"
                    },
                    {
                        "name": "chainId",
                        "type": "uint256"
                    },
                    {
                        "name": "verifyingContract",
                        "type": "address"
                    }
                ]
            },
            "domain": {
                "name": "Permit2",
                "chainId": "10",
                "verifyingContract": "0x000000000022d473030f116ddee9f6b43ac78ba3"
            },
            "primaryType": "PermitSingle",
            "message": {
                "details": {
                    "token": "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
                    "amount": "1461501637330902918203684832716283019655932542975",
                    "expiration": "2726145248",
                    "nonce": "0"
                },
                "spender": "0xcb1355ff08ab38bbce60111f1bb2b784be25d7e8",
                "sigDeadline": "2723555048"
            }
        }
    },
    "userAccount": "0x2cb5a1589f16655036caf137443CcB50dEe3333a",
    "metadata": {
        "origin": "https://examples.blowfish.xyz"
    }
}
'
{
   "action" : "WARN",
   "requestId" : "93d65d5c81d3bc53d354d706af22b0d2",
   "simulationResults" : {
      "error" : null,
      "expectedStateChanges" : [
         {
            "humanReadableDiff" : "Permit to transfer any amount of your USDC within 31 years",
            "rawInfo" : {
               "data" : {
                  "amount" : "1461501637330902918203684832716283019655932542975",
                  "asset" : {
                     "address" : "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
                     "decimals" : 6,
                     "imageUrl" : "https://d1ts37qlq4uz4s.cloudfront.net/evm__evm%3A%3Aoptimism__evm%3A%3Aoptimism%3A%3Amainnet__0x0b2c639c533813f4aa9d7837caf62653d097ff85.png",
                     "lists" : [
                        "COINGECKO",
                        "UNISWAP",
                        "KLEROS_TOKENS"
                     ],
                     "name" : "USDCoin",
                     "price" : {
                        "dollarValuePerToken" : 1.001,
                        "source" : "Defillama",
                        "updatedAt" : 1723554082
                     },
                     "symbol" : "USDC",
                     "verified" : true
                  },
                  "contract" : {
                     "address" : "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
                     "kind" : "ACCOUNT"
                  },
                  "deadline" : 2726145248,
                  "nonce" : "0",
                  "owner" : {
                     "address" : "0x2cb5a1589f16655036caf137443ccb50dee3333a",
                     "kind" : "ACCOUNT"
                  },
                  "spender" : {
                     "address" : "0xcb1355ff08ab38bbce60111f1bb2b784be25d7e8",
                     "kind" : "ACCOUNT"
                  }
               },
               "kind" : "ERC20_PERMIT"
            }
         }
      ],
      "protocol" : null
   },
   "warnings" : [
      {
         "data" : null,
         "kind" : "PERMIT_UNLIMITED_ALLOWANCE",
         "message" : "You are allowing this dApp to withdraw funds from your account in the future.",
         "severity" : "WARNING"
      }
   ]
}