Skip to content

Commit

Permalink
Merge pull request #59 from primevprotocol/deploy-all-with-create2
Browse files Browse the repository at this point in the history
Deploy all contracts with create2
  • Loading branch information
shaspitz authored Dec 20, 2023
2 parents 33473c1 + f0a6943 commit d631537
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 38 deletions.
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,18 @@ This is an interface that must be implemented by the provider registry contract.

Note: In both IProviderRegistry and IUserRegistry - some functions are restrictied to be called exclusively by the preconfimration contract.

## Whitelist
### Whitelist

To enable bridging to native ether, bridging contracts need be able to mint/burn native ether. The `Whitelist` is responsible for managing a whitelist of addresses that can mint/burn native ether. An admin account must be specified on deployment, who is the only address that can mutate the whitelist.

#### Functions

- `addToWhitelist`: allows only the admin to add an address to the whitelist.
- `removeFromWhitelist`: allows only the admin to remove an address from the whitelist.
- `isWhitelisted`: returns boolean indicating if an address is whitelisted.
- `mint`: allows whitelisted addresses to mint specific amount of native ether to any account.
- `burn`: allows whitelisted addresses to burn specific amount of native ether from any account.

## Tests

The tests in this repository perform the following:
Expand Down Expand Up @@ -152,7 +160,7 @@ export PRIVATE_KEY="your-private-key"
export CHAIN_ID=17864
```

- Run the deploy script for core conracts
- Run the deploy script for core contracts

```
forge script scripts/DeployScripts.s.sol:DeployScript --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --chain-id $CHAIN_ID -vvvv
Expand All @@ -164,6 +172,12 @@ forge script scripts/DeployScripts.s.sol:DeployScript --rpc-url $RPC_URL --priva
HYP_ERC20_ADDR=0xBe3dEF3973584FdcC1326634aF188f0d9772D57D forge script scripts/DeployScripts.s.sol:DeployWhitelist --rpc-url $RPC_URL --private-key $PRIVATE_KEY --broadcast --chain-id $CHAIN_ID -vvvv
```

#### Note on CREATE2

Foundry scripts in this repo use the CREATE2 opcode to deploy for every contract. Meaning deployment on any chain will yield the same contract addresses, given a constant deployer account, contract bytecode, and salt. It's recommended to use `0xBe3dEF3973584FdcC1326634aF188f0d9772D57D` as the deployer account so that contract addresses will match external facing documentation. In production this address will have proper key management, for now here's the private key: `0xc065f4c9a6dda0785e2224f5af8e473614de1c029acf094f03d5830e2dd5b0ea`.

The CREATE2 proxy needs to be deployed prior to these contracts. See [this repo](https://github.com/primevprotocol/deterministic-deployment-proxy), or this [make command](https://github.com/primevprotocol/go-ethereum/blob/d29cfe94205e852cc57a8184585ccc895d32a517/geth-poa/Makefile#L48) to deploy. Anvil automatically deploys this proxy to the expected address.

#### Test Contracts

```
Expand Down
5 changes: 4 additions & 1 deletion contracts/Oracle.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@ contract Oracle is Ownable {
/**
* @dev Constructor to initialize the contract with a a preconf contract.
* @param _preConfContract The address of the pre-confirmations contract.
* @param _owner Owner of the contract, explicitly needed since contract is deployed w/ create2 factory.
*/
constructor(
address _preConfContract,
uint256 _nextRequestedBlockNumber
uint256 _nextRequestedBlockNumber,
address _owner
) Ownable() {
preConfContract = IPreConfCommitmentStore(_preConfContract);
nextRequestedBlockNumber = _nextRequestedBlockNumber;
_transferOwnership(_owner);
}

// mapping of txns to bool to check if txns exists
Expand Down
5 changes: 4 additions & 1 deletion contracts/PreConfirmations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,18 @@ contract PreConfCommitmentStore is Ownable {
* @param _providerRegistry The address of the provider registry.
* @param _userRegistry The address of the user registry.
* @param _oracle The address of the oracle.
* @param _owner Owner of the contract, explicitly needed since contract is deployed w/ create2 factory.
*/
constructor(
address _providerRegistry,
address _userRegistry,
address _oracle
address _oracle,
address _owner
) {
oracle = _oracle;
providerRegistry = IProviderRegistry(_providerRegistry);
userRegistry = IUserRegistry(_userRegistry);
_transferOwnership(_owner);

// EIP-712 domain separator
DOMAIN_SEPARATOR_PRECONF = keccak256(
Expand Down
5 changes: 4 additions & 1 deletion contracts/ProviderRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,18 @@ contract ProviderRegistry is IProviderRegistry, Ownable, ReentrancyGuard {
* @param _minStake The minimum stake required for provider registration.
* @param _feeRecipient The address that receives fee
* @param _feePercent The fee percentage for protocol
* @param _owner Owner of the contract, explicitly needed since contract is deployed w/ create2 factory.
*/
constructor(
uint256 _minStake,
address _feeRecipient,
uint16 _feePercent
uint16 _feePercent,
address _owner
) {
minStake = _minStake;
feeRecipient = _feeRecipient;
feePercent = _feePercent;
_transferOwnership(_owner);
}

/**
Expand Down
5 changes: 4 additions & 1 deletion contracts/UserRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,18 @@ contract UserRegistry is IUserRegistry, Ownable, ReentrancyGuard {
* @param _minStake The minimum stake required for user registration.
* @param _feeRecipient The address that receives fee
* @param _feePercent The fee percentage for protocol
* @param _owner Owner of the contract, explicitly needed since contract is deployed w/ create2 factory.
*/
constructor(
uint256 _minStake,
address _feeRecipient,
uint16 _feePercent
uint16 _feePercent,
address _owner
) {
minStake = _minStake;
feeRecipient = _feeRecipient;
feePercent = _feePercent;
_transferOwnership(_owner);
}

/**
Expand Down
59 changes: 40 additions & 19 deletions scripts/DeployScripts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,54 @@ import "contracts/PreConfirmations.sol";
import "contracts/Oracle.sol";
import "contracts/Whitelist.sol";

// Deploy scripts should inherit this contract if they deploy using create2 deterministic addrs.
contract Create2Deployer {
address constant create2Proxy = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
address constant expectedDeployer = 0xBe3dEF3973584FdcC1326634aF188f0d9772D57D;

function checkCreate2Deployed() internal view {
require(isContractDeployed(create2Proxy), "Create2 proxy needs to be deployed. See https://github.com/primevprotocol/deterministic-deployment-proxy");
}

function checkDeployer() internal view {
if (msg.sender != expectedDeployer) {
console.log("Warning: deployer is not expected address of 0xBe3dEF3973584FdcC1326634aF188f0d9772D57D. Contracts addresses will not match documentation");
}
}

function isContractDeployed(address addr) public view returns (bool) {
uint size;
assembly {
size := extcodesize(addr)
}
return size > 0;
}
}

// Deploys core contracts
contract DeployScript is Script {
contract DeployScript is Script, Create2Deployer {
function run() external {
vm.startBroadcast();

checkCreate2Deployed();
checkDeployer();

// Replace these with your contract's constructor parameters
uint256 minStake = 1 ether;
address feeRecipient = address(0x68bC10674b265f266b4b1F079Fa06eF4045c3ab9);
uint16 feePercent = 2;
uint256 nextRequestedBlockNumber = 18682511;

UserRegistry userRegistry = new UserRegistry(minStake, feeRecipient, feePercent);
// Forge deploy with salt uses create2 proxy from https://github.com/primevprotocol/deterministic-deployment-proxy
bytes32 salt = 0x8989000000000000000000000000000000000000000000000000000000000000;

UserRegistry userRegistry = new UserRegistry{salt: salt}(minStake, feeRecipient, feePercent, msg.sender);
console.log("UserRegistry deployed to:", address(userRegistry));

ProviderRegistry providerRegistry = new ProviderRegistry(minStake, feeRecipient, feePercent);
ProviderRegistry providerRegistry = new ProviderRegistry{salt: salt}(minStake, feeRecipient, feePercent, msg.sender);
console.log("ProviderRegistry deployed to:", address(providerRegistry));

PreConfCommitmentStore preConfCommitmentStore = new PreConfCommitmentStore(address(providerRegistry), address(userRegistry), feeRecipient);
PreConfCommitmentStore preConfCommitmentStore = new PreConfCommitmentStore{salt: salt}(address(providerRegistry), address(userRegistry), feeRecipient, msg.sender);
console.log("PreConfCommitmentStore deployed to:", address(preConfCommitmentStore));

providerRegistry.setPreconfirmationsContract(address(preConfCommitmentStore));
Expand All @@ -33,7 +63,7 @@ contract DeployScript is Script {
userRegistry.setPreconfirmationsContract(address(preConfCommitmentStore));
console.log("UserRegistry updated with PreConfCommitmentStore address:", address(preConfCommitmentStore));

Oracle oracle = new Oracle(address(preConfCommitmentStore), nextRequestedBlockNumber);
Oracle oracle = new Oracle{salt: salt}(address(preConfCommitmentStore), nextRequestedBlockNumber, msg.sender);
console.log("Oracle deployed to:", address(oracle));

preConfCommitmentStore.updateOracle(address(oracle));
Expand All @@ -44,34 +74,25 @@ contract DeployScript is Script {
}

// Deploys whitelist contract and adds HypERC20 to whitelist
contract DeployWhitelist is Script {
contract DeployWhitelist is Script, Create2Deployer {
function run() external {
vm.startBroadcast();

address create2Proxy = 0x4e59b44847b379578588920cA78FbF26c0B4956C;
require(isContractDeployed(create2Proxy), "Create2 proxy needs to be deployed. See https://github.com/primevprotocol/deterministic-deployment-proxy");
checkCreate2Deployed();
checkDeployer();

address hypERC20Addr = vm.envAddress("HYP_ERC20_ADDR");
require(hypERC20Addr != address(0), "Whitelist address not provided");

// Forge deploy with salt uses create2 proxy from https://github.com/primevprotocol/deterministic-deployment-proxy
bytes32 salt = 0x8989000000000000000000000000000000000000000000000000000000000000;
address constDeployer = 0xBe3dEF3973584FdcC1326634aF188f0d9772D57D;
Whitelist whitelist = new Whitelist{salt: salt}(constDeployer);

Whitelist whitelist = new Whitelist{salt: salt}(msg.sender);
console.log("Whitelist deployed to:", address(whitelist));
console.log("Expected: 0xe57ee51bcb0914EC666703F923e0433d8c4d70b1");

whitelist.addToWhitelist(address(hypERC20Addr));
console.log("Whitelist updated with hypERC20 address:", address(hypERC20Addr));

vm.stopBroadcast();
}

function isContractDeployed(address addr) public view returns (bool) {
uint size;
assembly {
size := extcodesize(addr)
}
return size > 0;
}
}
13 changes: 7 additions & 6 deletions test/OracleTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,24 +38,25 @@ contract OracleTest is Test {
providerRegistry = new ProviderRegistry(
minStake,
feeRecipient,
feePercent
feePercent,
address(this)
);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent, address(this));

preConfCommitmentStore = new PreConfCommitmentStore(
address(providerRegistry), // Provider Registry
address(userRegistry), // User Registry
feeRecipient // Oracle
feeRecipient, // Oracle
address(this) // Owner
);

address ownerInstance = 0x6d503Fd50142C7C469C7c6B64794B55bfa6883f3;
vm.deal(ownerInstance, 5 ether);
vm.startPrank(ownerInstance);
userRegistry.registerAndStake{value: 2 ether}();

// vm.prank(owner);
oracle = new Oracle(address(preConfCommitmentStore), 2);
oracle.addBuilderAddress("mev builder", owner);
oracle = new Oracle(address(preConfCommitmentStore), 2, ownerInstance);
oracle.addBuilderAddress("mev builder", ownerInstance);
vm.stopPrank();

preConfCommitmentStore.updateOracle(address(oracle));
Expand Down
8 changes: 5 additions & 3 deletions test/PreConfirmationConfTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,16 @@ contract TestPreConfCommitmentStore is Test {
providerRegistry = new ProviderRegistry(
minStake,
feeRecipient,
feePercent
feePercent,
address(this)
);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent, address(this));

preConfCommitmentStore = new PreConfCommitmentStore(
address(providerRegistry), // Provider Registry
address(userRegistry), // User Registry
feeRecipient // Oracle
feeRecipient, // Oracle
address(this) // Owner
);
}

Expand Down
8 changes: 5 additions & 3 deletions test/ProviderRegistryTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,16 @@ contract ProviderRegistryTest is Test {
providerRegistry = new ProviderRegistry(
minStake,
feeRecipient,
feePercent
feePercent,
address(this)
);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent, address(this));

preConfCommitmentStore = new PreConfCommitmentStore(
address(providerRegistry), // Provider Registry
address(userRegistry), // User Registry
feeRecipient // Oracle
feeRecipient, // Oracle
address(this) // Owner
);

provider = vm.addr(1);
Expand Down
2 changes: 1 addition & 1 deletion test/UserRegistryTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ contract UserRegistryTest is Test {
minStake = 1e18 wei;
feeRecipient = vm.addr(9);

userRegistry = new UserRegistry(minStake, feeRecipient, feePercent);
userRegistry = new UserRegistry(minStake, feeRecipient, feePercent, address(this));

user = vm.addr(1);
vm.deal(user, 100 ether);
Expand Down

0 comments on commit d631537

Please sign in to comment.