Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Deterministic contract addresses #39

Merged
merged 7 commits into from
Nov 6, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions contracts/.env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,22 @@
ETHERSCAN_API_KEY=

ROPSTEN_URL=
RINKEBY_URL=
ARBITRUM_TESTNET_URL=https://rinkeby.arbitrum.io/rpc
ARBITRUM_URL=https://arb1.arbitrum.io/rpc
OPTIMISM_LOCAL_URL=http://localhost:8545
OPTIMISM_TESETNET_URL=https://kovan.optimism.io
OPTIMISM_URL=

# Only used for deploying the deployer contract at the same address on each evm network
DEPLOYER_MNEMONIC=
DEPLOYER_SET_INDEX=1
DEPLOYER_ACCOUNT=0xFD55C6Eb365C832a7a292aeE61754eB1BFb8c666,
DEPLOYER_CONTRACT_ADDRESS=0x58BAc5845a2c94c5754583283A50811eE3dc7b22

# Used for deploying contracts via the deployment contract, and testing
MAIN_MNEMONIC="test test test test test test test test test test test junk"

PRIVATE_KEY_AGG=0000000000000000000000000000000000000000000000000000000000000a99
PRIVATE_KEY_AGG_OKOV=
PRIVATE_KEY_AGG_RINKARBY=
Expand All @@ -7,15 +26,8 @@ PRIVATE_KEY_003=0000000000000000000000000000000000000000000000000000000000000003
PRIVATE_KEY_004=0000000000000000000000000000000000000000000000000000000000000004
PRIVATE_KEY_005=0000000000000000000000000000000000000000000000000000000000000005


BLS_SECRET_NUM_1=
BLS_SECRET_NUM_2=
BLS_SECRET_NUM_3=

LOCAL_BLS_LIBRARY=0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
LOCAL_VERIFICATION_GATEWAY_ADDRESS=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
LOCAL_BLS_EXPANDER_ADDRESS=0x5FC8d32690cc91D4c39d9d3abcBD16989F875707
LOCAL_ERC20_CONTRACT_ADDRESS=
# Addresses as deployed with create2 from deployer contract (same address per network)
PRECOMPILE_COST_ESTIMATOR_ADDRESS=0x28D80eadB668952bC7a39a56c807b189c1F30b74

ARB1_PRECOMPILE_COST_ESTIMATOR_ADDRESS=
ARB1_BLS_LIBRARY=
Expand Down
4 changes: 4 additions & 0 deletions contracts/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
artifacts
cache
coverage
24 changes: 24 additions & 0 deletions contracts/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
module.exports = {
env: {
browser: false,
es2021: true,
mocha: true,
node: true,
},
plugins: ["@typescript-eslint"],
extends: [
"standard",
"plugin:prettier/recommended",
"plugin:node/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
ecmaVersion: 12,
},
rules: {
"node/no-unsupported-features/es-syntax": [
"error",
{ ignores: ["modules"] },
],
},
};
5 changes: 4 additions & 1 deletion contracts/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
.env*
!.env.example
node_modules
coverage
coverage.json
typechain

#Hardhat files
artifacts
Expand All @@ -12,4 +15,4 @@ artifacts-ovm
cache-ovm

#editor files
.vscode
.vscode
3 changes: 3 additions & 0 deletions contracts/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
hardhat.config.ts
scripts
test
5 changes: 5 additions & 0 deletions contracts/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules
artifacts
cache
coverage*
gasReporterOutput.json
7 changes: 7 additions & 0 deletions contracts/.solhint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", "^0.8.0"],
"func-visibility": ["warn", { "ignoreConstructors": true }]
}
}
1 change: 1 addition & 0 deletions contracts/.solhintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
15 changes: 11 additions & 4 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ Note: each of these savings is proportional to the number of transactions submit
- receive contract wallet address
3. Create contract wallet with existing ECDSA keypair

Note: Depending on the network being used, the address of the deployed PrecompileCostEstimator will need to be set [here](https://github.com/jzaki/bls-wallet/blob/main/contracts/contracts/lib/hubble-contracts/contracts/libs/BLS.sol#L42). #15 will resolve this.

## See it in action
See `extension`

Expand Down Expand Up @@ -83,15 +81,24 @@ Proposed solution to make use of [BLS](https://github.com/thehubbleproject/hubbl
- Run the aggregation server (see `./server`).
- build and test contracts - `npx hardhat test`

## Optimism's L2
Note: Depending on the network being used, the address of the deployed PrecompileCostEstimator will need to be set [here](https://github.com/jzaki/bls-wallet/blob/main/contracts/contracts/lib/hubble-contracts/contracts/libs/BLS.sol#L42). #15 will resolve this.

For each network, the deployer contract can be deployed with the following script (only needed once)
`DEPLOY_DEPLOYER=true yarn hardhat run scripts/deploy-deployer.ts --network <network-name>`


## Arbitrum


## Optimism's L2 (paused)
- clone https://github.com/ethereum-optimism/optimism
- follow instructions (using latest version of docker)
- in `opt/`, run script - `docker-compose up`
- L1 - http://localhost:9545 (chainId 31337)
- L2 - http://localhost:8545 (chainId 420)

## Deploy scripts
Specify network - `npx hardhat run scripts/<#_script.ts> --network optimism`
Specify network - `npx hardhat run scripts/<#_script.ts> --network arbitrum-testnet`

# License
MIT
13 changes: 9 additions & 4 deletions contracts/contracts/BLSWallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,27 @@ interface IVerificationGateway {
function walletCrossCheck(bytes32 publicKeyHash) external;
}

contract BLSWallet
contract BLSWallet is Initializable
{
address public gateway;
uint256[4] public publicKey;
uint256 public nonce;

constructor(uint256[4] memory blsKey) {
constructor() {
gateway = msg.sender;
publicKey = blsKey;
nonce = 0;
}

function initialize(
uint256[4] memory blsKey
) external initializer onlyGateway {
publicKey = blsKey;
}

receive() external payable {}
fallback() external payable {}

function getPublicKey() external returns (uint256[4] memory) {
function getPublicKey() external view returns (uint256[4] memory) {
return publicKey;
}

Expand Down
36 changes: 36 additions & 0 deletions contracts/contracts/Create2Deployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

contract Create2Deployer {
event Deployed(address sender, uint256 salt, address addr);

function addressFrom(
address sender,
uint256 salt,
bytes calldata code
) public pure returns (
address predictedAddress
) {
predictedAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
sender,
salt,
keccak256(code)
)))));
}

function deploy(
uint256 salt,
bytes memory code
) public {
address addr;
assembly {
addr := create2(0, add(code, 0x20), mload(code), salt)
if iszero(extcodesize(addr)) {
revert(0, 0)
}
}
emit Deployed(msg.sender, salt, addr);
}

}
42 changes: 33 additions & 9 deletions contracts/contracts/VerificationGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ contract VerificationGateway is Initializable
uint8 constant BLS_LEN = 4;
// uint256[BLS_LEN] ZERO_BLS_SIG = [uint256(0), uint256(0), uint256(0), uint256(0)];

mapping (bytes32 => BLSWallet) public walletFromHash;

IBLS public blsLib;

/**
Expand Down Expand Up @@ -74,11 +72,35 @@ contract VerificationGateway is Initializable
require(verified, "VerificationGateway: All sigs not verified");
}

function hasCode(address a) private view returns (bool) {
uint256 size;
// solhint-disable-next-line no-inline-assembly
assembly { size := extcodesize(a) }
return size > 0;
}

/**
@param hash BLS public key hash used as salt for create2
@return BLSWallet at calculated address (if code exists), otherwise zero address
*/
function walletFromHash(bytes32 hash) public view returns (BLSWallet) {
address walletAddress = address(uint160(uint(keccak256(abi.encodePacked(
bytes1(0xff),
address(this),
hash,
keccak256(type(BLSWallet).creationCode)
)))));
if (!hasCode(walletAddress)) {
walletAddress = address(0);
}
return BLSWallet(payable(walletAddress));
}

/**
Useful no-op function to call when calling a wallet for the first time.
*/
function walletCrossCheck(bytes32 hash) public payable {
require(msg.sender == address(walletFromHash[hash]));
require(msg.sender == address(walletFromHash(hash)));
}

/**
Expand Down Expand Up @@ -107,7 +129,7 @@ contract VerificationGateway is Initializable

// construct params for signature verification
publicKeyHash = keccak256(abi.encodePacked(publicKeys[i]));
wallet = walletFromHash[publicKeyHash];
wallet = walletFromHash(publicKeyHash);

if (txs[i].nonce == wallet.nonce()) {
// action transaction (increments nonce)
Expand All @@ -132,12 +154,14 @@ contract VerificationGateway is Initializable
private // consider making external and VG stateless
{
bytes32 publicKeyHash = keccak256(abi.encodePacked(publicKey));
// wallet at publicKeyHash doesn't exist
if (address(walletFromHash[publicKeyHash]) == address(0)) {
// blsKeysFromHash[publicKeyHash] = publicKey;
walletFromHash[publicKeyHash] = new BLSWallet(publicKey);
BLSWallet blsWallet = walletFromHash(publicKeyHash);

// wallet with publicKeyHash doesn't exist at expected create2 address
if (address(blsWallet) == address(0)) {
blsWallet = new BLSWallet{salt: publicKeyHash}();
blsWallet.initialize(publicKey);
emit WalletCreated(
address(walletFromHash[publicKeyHash]),
address(blsWallet),
publicKey
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,7 @@ library BLS {
uint256 private constant MASK24 = 0xffffffffffffffffffffffffffffffffffffffffffffffff;

// estimator address
address private constant COST_ESTIMATOR_ADDRESS =
// 0x85C17E7180879a71EDAE76B43E4a85159a7eA601; // rinkarby
0x5FbDB2315678afecb367f032d93F642f64180aa3; // local hardhat test
//0x079d8077C465BD0BF0FC502aD2B846757e415661; initial
address private constant COST_ESTIMATOR_ADDRESS = 0x28D80eadB668952bC7a39a56c807b189c1F30b74;

function verifySingle(
uint256[2] memory signature,
Expand Down
Loading