[Proposal] Balancer V2: Authorize Gnosis Protocol V2 Contracts as a Vault Relayer

Following the announcement of the Balancer-Gnosis Protocol[0], this proposal aims to authorize the Gnosis Protocol V2 settlement contract with the necessary roles to:

  • Leverage the Vault’s pre-existing user ERC20 allowances and balances.
  • Swap on behalf of users with Balancer V2 pools, thereby providing Balancer with a protocol-level advantage on Gnosis Protocol v2.


Gnosis Protocol enables batched trading using off-chain signed orders. This trading protocol would enable Balancer V2 users to:

  • Trade with MEV protection - leveraging the batch auction mechanism with uniform clearing prices as well as professional transaction submission with tight slippage, guarantees the traders to avoid suffering from MEV.
  • Balancer pools protocol advantage - Gnosis Protocol V2 contracts have Balancer-specific optimizations, making it more efficient to use Balancer pools than other on-chain AMMs, which will therefore lead to more trades being settled on Balancer.
  • Gas-less trading experience - The protocol is set so that the settlement is submitted by a third party which gets refunded its transaction cost from the traded ERC20 sell tokens (instead of ETH). As a nice side effect, if the protocol is not able to execute the trade order, the trader does not pay any fee.

Additionally, given that the vault supports modifying relayer permissions using off-chain signatures, it would be possible to offer users a completely “gas-less” experience, where a first-time user with existing Vault balances and/or allowances could trade on Gnosis Protocol V2 by only signing off-chain messages, with all required gas related being taken in the ERC20 tokens that are being traded.

This proposal would only add the required roles to the Gnosis Protocol V2 vault relayer contract. Users would still be required to opt-in by allowing Gnosis Protocol V2 to function as relayer on their behalf.


The Gnosis Protocol settlement contract requires an order signed by the user in order to execute a transfer of funds or a swap. Additionally, neither the transfer nor the swap will be performed if the amount does not respect the user’s limit price included in the signed order.

Furthermore, while this proposal aims to authorize the Gnosis Protocol V2 contracts to act as a relayer, users must still opt-in to enable trading on Gnosis Protocol V2 by setting a relayer allowance (or signing an off-chain message granting this permission).

The code has been carefully tested, peer-reviewed and fully audited. The full smart contract audit can be found in the Gnosis Protocol V2 contracts public repository on Github[1] and there is an ongoing bug bounty[2].


The Balancer governance multisig would submit a transaction to the the Authorizer contract in order to grant the following roles to the Gnosis Protocol V2 vault relayer contract:

  1. manageUserBalance: this role would be used by GPv2 in order to transfer the “from” tokens for verified user orders to the settlement contract for batch trading.
  2. batchSwap: Perform direct swaps on behalf of users, enabling user orders that were signed off-chain to get matched directly with Balancer pools.

Specifically, the Gnosis Safe at 0x10A19e7eE7d7F8a52822f6817de8ea18204F2e4f[3] would send a transaction to the Vault Authorizer at 0xA331D84eC860Bf466b4CdCcFb4aC09a1B43F3aE6[4] with the following data to authorize the Gnosis Protocol V2 Vault Relayer at 0xC92E8bdf79f0507f65a392b0ab4667716BFE0110[5]:


Which is the ABI-encoded calldata for:

For transparency, a developer could reproduce the encoded data by computing the following:
const ethers = require("ethers")

const authorizer = new ethers.utils.Interface([
  "function grantRoles(bytes32[] memory roles, address account)",
const vault = new ethers.utils.Interface([
  "function manageUserBalance((uint8, address, uint256, address, address)[])",
  "function batchSwap(uint8, (bytes32, uint256, uint256, uint256, bytes)[], address[], (address, bool, address, bool), int256[], uint256)",

function roleId(address, sighash) {
  return ethers.utils.solidityKeccak256(["uint256", "bytes4"], [address, sighash])

const roles = ["manageUserBalance", "batchSwap"]
  .map(name => roleId("0xBA12222222228d8Ba445958a75a0704d566BF2C8", vault.getSighash(name)));
const vaultRelayer = "0xC92E8bdf79f0507f65a392b0ab4667716BFE0110";
const data = authorizer.encodeFunctionData("grantRoles", [roles, vaultRelayer]);

    ${roles.map(role => `${role},`).join("\n    ")}


  1. https://medium.com/balancer-protocol/the-crypto-cinematic-universe-crossover-event-of-the-summer-balancer-gnosis-protocol-bgp-638568aa0385
  2. https://github.com/gnosis/gp-v2-contracts/blob/main/audits/GnosisProtocolV2May2021.pdf
  3. https://medium.com/@gnosisPM/announcing-gnosis-protocol-v2-bug-bounty-f3e44e934566
  4. https://etherscan.io/address/0x10A19e7eE7d7F8a52822f6817de8ea18204F2e4f
  5. https://etherscan.io/address/0xA331D84eC860Bf466b4CdCcFb4aC09a1B43F3aE6
  6. https://etherscan.io/address/0xC92E8bdf79f0507f65a392b0ab4667716BFE0110

Thanks for your proposal @nlordell !

The community had already a week to analyze the proposal and unless someone has any objections someone should put this on snapshot. BTW @marta is working on a simple process that should allow pretty much anyone (there will be some low threshold of BAL to avoid spamming on snapshot) to put a proposal through.

For now I guess @rabmarut could put this on snapshot?

Thank you @nlordell and @Fernando! Let’s revisit this proposal next week.