Last active
August 31, 2022 21:49
-
-
Save santteegt/f0d3b93b383c4c1ba047a6046cd3a2bb to your computer and use it in GitHub Desktop.
Calculate ProxyAddress from a Given CREATE2 call - Example using GnosisSafe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This script assume using the GnosisSafe & GnosisSafeProxyFactory from here | |
// https://github.com/gnosis/safe-contracts/blob/v1.2.0/contracts/proxies/GnosisSafeProxyFactory.sol | |
// safe -> https://github.com/gnosis/safe-contracts/blob/v1.2.0/contracts/GnosisSafe.sol | |
import { ethers } from 'ethers'; | |
import Web3 from 'web3'; | |
import * as ethUtil from 'ethereumjs-util'; | |
import abi from 'ethereumjs-abi'; | |
const rpcUrl = ''; // Fill your RPC URI | |
const web3 = web3 = new Web3(new Web3.providers.HttpProvider(rpcUrl)); | |
const safeProxyFactoryAddress = '0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B'; | |
const safeMasterCopyAddress = '0x6851d6fdfafd08c0295c392436245e5bc78b0185'; | |
// contract for deploying new safes | |
const safeProxyFactory = new web3.eth.Contract( | |
safeProxyFactoryAbi, | |
safeProxyFactoryAddress, | |
); | |
const safe = new web3.eth.Contract( | |
safeMasterCopyAbi, | |
safeMasterCopyAddress, | |
); | |
const saltNonce = (new Date().getTime() / 1000).toFixed(); | |
const setupData = safe.methods | |
.setup( | |
[delegateAddress, minionAddress], // owners | |
threshold, // signing threshol d | |
Address0, // to - Contract address for optional delegate call. | |
"0x", // data - Data payload for optional delegate call. | |
Address0, // fallbackHandler | |
Address0, // paymentToken | |
0, // payment | |
Address0, // paymentReceiver | |
) | |
.encodeABI(); | |
const proxyCreationCode = await safeProxyFactory.methods | |
.proxyCreationCode() | |
.call(); | |
// Alternative 1: Using ethereumjs-abi library | |
// ======================================================== | |
// Check GnosisSafeProxyFactory.deployProxyWithNonce method | |
const encodedNonce = abi | |
.rawEncode(['uint256'], [saltNonce]) | |
.toString('hex'); | |
const salt = ethUtil.keccak256( | |
`0x${ethUtil.keccak256(setupData).toString('hex') + encodedNonce}`, | |
); | |
const constructorData = abi | |
.rawEncode(['address'], [safeMasterCopyAddress]) | |
.toString('hex'); | |
const initCode = proxyCreationCode + constructorData; | |
const contractAddress = `0x${ethUtil | |
.generateAddress2( | |
safeProxyFactory.options.address, | |
salt, | |
initCode, | |
) | |
.toString('hex')}`; | |
console.log('Predicted safe address using ethereumjs-util', contractAddress); | |
// Alternative 2: Using ethers library | |
// ======================================================== | |
const salt2 = ethers.utils.solidityKeccak256( | |
['bytes32', 'uint256'], | |
[ethers.utils.solidityKeccak256(['bytes'], [setupData]), saltNonce], | |
); | |
// does not work with web3.eth.abi.encodeParameters as it packed encode with additional data like length ? | |
const initCode2 = ethers.utils.solidityPack( | |
['bytes', 'uint256'], | |
[proxyCreationCode, safeMasterCopyAddress], | |
); | |
const contractAddress2 = ethers.utils.getCreate2Address( | |
safeProxyFactory.options.address, | |
salt2, | |
ethers.utils.keccak256(initCode2), | |
); | |
console.log('Predicted safe address using ethers', contractAddress2); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment