I’ve made a tool to deploy Safe contracts on a blockchain based on the presigned trasaction from this repo.
Multi-sig wallets are a great way to secure your funds, they are also a safe way to interact with your smart contract to call some sensitive functions. This post will show you how to deploy Safe contracts to enable multi-sig for a blockchain.
To deploy a Safe multi-sig contract on a blockchain, several Safe contracts are necessary to be deployed first. They are:
GnosisSafeProxyFactory
GnosisSafe
andGnosisSafeL2
DefaultCallbackHandler
andCompatibilityFallbackHandler
MultiSend
andMultiSendCallOnly
CreateCall
SignMessageLib
SimulateTxAccessor
Three Repositories
Safe (privious Gnosis Safe) provides three different repositories to deploy Safe contracts on a blockchains:
- A deterministic deployment factory with presigned transaction: https://github.com/safe-global/safe-singleton-factory. This repo is called
Safe Singleton Factory
, which is a contract can deploy Safe contracts with deterministic addresses by usingcreate2
opcode. - A serie of Safe contracts to be deployed through the
Safe Singleton Factory
: https://github.com/safe-global/safe-contracts. They will act as the components to deploy a Safe multi-sig and provide the functionalities for the Safe multi-sig. - A repository to publish the addresses of deployed Safe contracts on different blockchains: https://github.com/safe-global/safe-deployments.
Deploy Safe Single Factory
Through a contract which can call create2
opcode to deploy contracts, we can deploy a contract with a deterministic address, due to
new_contract_address = hash(0xFF, single_factory_address, salt, bytecode)
That means no matter when the transaction is issued, as long as the singleton factory address and the salt are fixed, the address is only determined by the bytecode of the deployed contract. Therefore, we can deploy the same contract on different blockchains with the same address.
To ensure that the Safe contracts on different blockchains have the same address, the Safe Singleton Factory
is deployed on each blockchain firstly with the same nonce through a normal contract deployment transaction. Then the Safe contracts are deployed through the Safe Singleton Factory
by calling create2
opcode on each blockchain .
There are two ways to deploy the Safe Singleton Factory
on a blockchain:
- Deploy the
Safe Singleton Factory
with the help from Safe team, they can issue a transction on each blockchain to deploy theSafe Singleton Factory
with the same address (the same nonce and bytecode); - Deploy the
Safe Singleton Factory
by yourself. You can deploy theSafe Singleton Factory
on a blockchain by using a presigned transaction without chain ID included, which is provided in this repo https://github.com/Arachnid/deterministic-deployment-proxy.
Entrance A: Safe Preisgned Transaction
To get a presigned transaction from Safe team to deploy the Safe Singleton Factory
on a blockchain, an issue should be opened on the Safe Singleton Factory
repo and provide necessary information
to publish a presigned transaction for a given blockchain.
Safe team requires the following information to publish a presigned transaction:
- The blockchain name
- The blockchain ID
- The link to chainlist.org for the blockchain
- RPC url for the blockchain
- Explorer url for the blockchain
- Necessary native token transfer to the signer address
0xE1CB04A0fA36DdD16a06ea828007E35e1a3cBC37
The presigned transaction issued by Safe team is obeying EIP-155, which requires the chain ID to be signed within transaction to protect replay attck. The chain ID is the ID of the target blockchain, which can be found on chainlist.org.
Safe team will periodically publish a presigned transaction on the artifacts
folder in the Safe Singleton Factory
repo for the given blockchain. For example, the presigned transaction for the base
blockchain is published as
{
"gasPrice": 200000000,
"gasLimit": 100000,
"signerAddress": "0xE1CB04A0fA36DdD16a06ea828007E35e1a3cBC37",
"transaction": "0xf8a680840bebc200830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf382422ea08dd745c4f66575e8d66550978dd6fd6d7f15236dc7bcc0360cfa2abd090c6a82a06b53e59bc854a90820624342e9aaa6b9fac224f1efe90a8466ce6e03d65c9bb1",
"address": "0x914d7Fec6aaC8cd542e72Bca78B30650d45643d7"
}
The presigned transaction can be submitted to deploy the Safe Singleton Factory
contract on the target blockchain. The signer of this transaction is 0xE1CB04A0fA36DdD16a06ea828007E35e1a3cBC37
, and this presigned transaction is always the very first transaction of this account on the target blockchain, that means nonce=0
.
Before you can submit the transaction successfully, amount of native gas token on the target blockchain must be transfered to the signer address. Usually, 0.001
is enough to execute this presigned transaction.
After token transfered, please set a proper RPC url for the target blockchain in the .env
file
RPC="an available RPC url for the target blockchain"
And run yarn submit
to relay the presigned transaction to the RPC node of the target blockchain. The Safe Singleton Factory
contract will be deployed on the target blockchain with the same address as other blockchains.
Bingo, you got the entry point to deploy Safe contracts deterministically on your chain.
Entrance B: Universal Preisgned Transaction
For some reason, the Safe team cannot always respose quickly to the request for deploying the Safe Singleton Factory
on a blockchain. In this case, you can deploy the Safe Singleton Factory
by yourself, which is called here as Universal Presigned Transaction
.
Before EIP-155, the chain ID is not included in the transaction signature, which means the same transaction can be replayed on different blockchains. This is a security issue, because the transaction on one blockchain can be replayed on another blockchain, which may cause unexpected result, such as stealing token. And the Safe team also decide to sign transaction with chain ID included, but there is an open Singleton Facotry
contract can be deployed on different blockchains with the same address
To do so, we need a presigned transaction without chainID included, which is published on this repository. You can create a deployment.json
file under the /artifacts/<chainID>/
folder and paste the presigned transaction into it. For example, the deployment.json
file for the Orderly mainnet is under /artifacts/291/
{
"gasPrice": 100,
"gasLimit": 100000,
"signerAddress": "0x3fab184622dc19b6109349b94811493bf2a45362",
"transaction": "0xf8a58085174876e800830186a08080b853604580600e600039806000f350fe7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf31ba02222222222222222222222222222222222222222222222222222222222222222a02222222222222222222222222222222222222222222222222222222222222222",
"address": "0x4e59b44847b379578588920ca78fbf26c0b4956c"
}
Through this presigned transaction, we can deploy the Safe Singleton Factory
on the target blockchain with the address = 0x4e59b...4956c
. And of course, you should transfer some native token to the signer address 0x3fab1...45362
and set proper RPC url in .env
file before you can submit this transaction.
Some RPC provider doesn’t support transaction without chain ID included, you need choose a proper one, or you can set a local node to submit the transaction.
Deploy Safe Contracts
After the Singleton Factory
is deployed on the target blockchain, we can deploy Safe contracts through it. All Safe contracts are included in this repo, and the version 1.3.0
is most popular one. You should first checkout to the v1.3.0-libs.0
branch, and then run yarn install
to install the dependencies.
If you request a presigned transaction from Safe team, the deployment.json
file is downloaded automatically into node_modules/@gnosis.pm/safe-singleton-factory/artifacts/<chainID>/
folder after yarn install
. If you deployed the singleton factory
by yourself, you should copy the deployment.json
file into the node_modules/@gnosis.pm/safe-singleton-factory/artifacts/<Target chainID>/
.
And set the private key in .evn
file and proper network configuration into network
filed of hardhat.config.ts
, such as
network: {
orderly:{
...sharedNetworkConfig,
url: "https://rpc.orderly.network"
}
}
Then, execute the following command to deploy Safe contracts on the target blockchain
yarn deploy-all <network>
If you are lucky, you will get the following output
Verification status for SimulateTxAccessor: FAILURE
Verification status for GnosisSafeProxyFactory: SUCCESS
Verification status for DefaultCallbackHandler: SUCCESS
Verification status for CompatibilityFallbackHandler: SUCCESS
Verification status for CreateCall: SUCCESS
Verification status for MultiSend: FAILURE
Verification status for MultiSendCallOnly: SUCCESS
Verification status for SignMessageLib: SUCCESS
Verification status for GnosisSafeL2: SUCCESS
Verification status for GnosisSafe: SUCCESS
Now, you can find the deployed Safe contracts on the target blockchain and the addresses are the same as other blockchains, if both Singleton Factory
contracts are deployed with the same way (Entrance A or Entrance B). For Entrance B, the addresses are listed here below:
Contract Name | Contract Address |
---|---|
GnosisSafeProxyFactory |
0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2 |
GnosisSafe |
0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552 |
GnosisSafeL2 |
0x3E5c63644E683549055b9Be8653de26E0B4CD36E |
DefaultCallbackHandler |
0x1AC114C2099aFAf5261731655Dc6c306bFcd4Dbd |
CompatibilityFallbackHandler |
0xf48f2B2d2a534e402487b3ee7C18c33Aec0Fe5e4 |
MultiSend |
0xA238CBeb142c10Ef7Ad8442C6D1f9E89e07e7761 |
MultiSendCallOnly |
0x40A2aCCbd92BCA938b02010E17A5b8929b49130D |
CreateCall |
0x7cbB62EaA69F79e6873cD1ecB2392971036cFAa4 |
SignMessageLib |
0xA65387F16B013cf2Af4605Ad8aA5ec25a2cbA3a2 |
SimulateTxAccessor |
0x59AD6735bCd8152B84860Cb256dD9e96b85F69Da |
Publish Safe Contracts
Once the ten contracts are deployed on the target blockchain, you should publish the addresses of them on the Safe Deployments repo through a PR request.
Becuase there are two ways to deploy the Singleton Factory
contract, so you can find there are two different addresses for each Safe contract, such as this ProxyFactory
address file due to the deterministica deployment.
safe_contract_address = hash(0xFF, singleton_factory_address, salt, bytecode)
Once your PR has been merged into this repo, other projects now can deploy Safe multi-sig contracts through these Safe contracts on the your blockchain.
Good luck and happy building!
Summary
In this article, we explained how to deploy Safe contracts on a blockchain. The entry point Signleton Factory
contract is most critical part to deploy Safe contracts deterministically on a blockchain. There are two ways to deploy the Singleton Factory
contract on a blockchain, one is to request a presigned transaction from Safe team, and the other is to deploy the Singleton Factory
contract by yourself. After the Singleton Factory
contract is deployed, you can deploy Safe contracts through it. Finally, you should publish the addresses of deployed Safe contracts on the Safe Deployments repo.
Next article, we will show you how to deploy Safe multi-sig contracts on a blockchain through the deployed Safe contracts, and introduce how to interact with Safe multi-sig contract to execute onchain actions.