Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#22 contract factory #33

Merged
163 changes: 163 additions & 0 deletions contracts/Deployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
//SPDX-License-Identifier: MIT

pragma solidity 0.8.13;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import "hardhat/console.sol";

contract Deployer is AccessControl{
struct DeployedContractInfo {
address deploymentAddress;
string contractType;
}
struct ContractDeployParameters {
bytes32 byteCodeHash;
uint price;
}
mapping(string => ContractDeployParameters) contractParamsByKey;
mapping(address => DeployedContractInfo[]) contractsDeloyedByEOA;

event ByteCodeUploaded(string key, uint price, bytes32 byteCodeHash);
event PriceUpdated(string key, uint newPrice);
event ContractDiscontinued(string key);
event ContractDeployed(address contractAddress, string contractType, uint paid);

/*
* @dev Deploys a contract and returns the address of the deployed contract
* @param _admin The address that can call the admin functions
* @return The address of the deployed contract
*/
constructor(address admin) {
_setupRole(DEFAULT_ADMIN_ROLE, admin);
}

/*
* @dev Deploys a contract and returns the address of the deployed contract
* @param contractType The key to get the bytecode of the contract
* @param bytecode The bytecode of the contract to deploy
* @param params Bytecode of the constructor parameters (if any) of the contract to deploy
* @param salt Salt to be used to generate the hash of the contract bytecode
* (used to generate a deterministic address)
*/
function deployContract(
string calldata contractType,
bytes calldata bytecode,
bytes calldata params,
bytes32 salt
) public payable {
(bool success, ContractDeployParameters memory c) = getContractByteCodeHash(contractType);
if (!success || c.byteCodeHash != keccak256(bytecode)) {
revert("Contract is unregistered or discontinued");
}
require(
msg.value >= c.price,
"Insufficient payment to deploy"
);
if(salt == 0x0) {
salt = keccak256(abi.encode(getDeployed(msg.sender).length));
}
bytes memory code = abi.encodePacked(
bytecode,
params
);
address contractAddress;
assembly {
contractAddress := create2(0, add(code, 0x20), mload(code), salt)
if iszero(extcodesize(contractAddress)) {
revert(0, "Error deploying contract")
}
}
DeployedContractInfo memory ci = DeployedContractInfo(contractAddress, contractType);
contractsDeloyedByEOA[msg.sender].push(ci);
emit ContractDeployed(contractAddress, contractType, msg.value);
}

/*
* @dev Returns contract info deployed by the given address
* @param deployer address to lookup
* @return array of contracts deployed by deployer
*/
function getDeployed(address deployer)
public
view
returns (DeployedContractInfo[] memory contractsDeployed)
{
contractsDeployed = contractsDeloyedByEOA[deployer];
}

/*
* @dev Gets the bytecode of a contract by name
* @param contractKey The key used to reference the contract
* @returns boolean flag and the contract info
*/
function getContractByteCodeHash(string calldata contractKey)
public
view
returns (bool success, ContractDeployParameters memory contractParams)
{
contractParams = contractParamsByKey[contractKey];
if(contractParams.byteCodeHash.length == 0) {
return (false, contractParams);
}
return (true, contractParams);
}

/*
* @dev Sets the bytecode of a contract by name
* @param contractKey The key which must be used to access the bytecode
* @param bytecode The bytecode to store
* @param contractDeployPrice The price (in wei) that users must pay to deploy a contract
*/
function setContractByteCode(
string calldata contractKey,
bytes calldata byteCode,
uint contractDeployPrice
) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (contractParamsByKey[contractKey].byteCodeHash == 0x0) {
contractParamsByKey[contractKey] = ContractDeployParameters(keccak256(byteCode), contractDeployPrice);
emit ByteCodeUploaded(contractKey, contractDeployPrice, keccak256(byteCode));
} else {
revert("Contract already deployed");
}
}

/*
* @dev Updates the price of a contract
* @param contractKey The key used to reference the contract
* @param newPrice The new price (in wei) that users must pay to deploy the contract
*/
function updateContractPrice(
string calldata contractKey,
uint newPrice
) external onlyRole(DEFAULT_ADMIN_ROLE) {
ContractDeployParameters memory contractParams = contractParamsByKey[contractKey];
if (contractParams.byteCodeHash != 0x0) {
contractParamsByKey[contractKey] = ContractDeployParameters(contractParams.byteCodeHash, newPrice);
emit PriceUpdated(contractKey, newPrice);
} else {
revert("Contract not registered");
}
}

/*
* @dev Makes a contract undeployable
* @param contractKey The key used to reference the contract
*/
function discontinueContract(
string calldata contractKey
) external onlyRole(DEFAULT_ADMIN_ROLE) {
ContractDeployParameters memory contractParams = contractParamsByKey[contractKey];
if (contractParams.byteCodeHash != 0x0) {
contractParamsByKey[contractKey] = ContractDeployParameters(0x0, 0x0);
emit ContractDiscontinued(contractKey);
} else {
revert("Contract not registered");
}
}


function withdraw() external onlyRole(DEFAULT_ADMIN_ROLE) {
payable(address(msg.sender)).transfer(address(this).balance);
}
}
2 changes: 1 addition & 1 deletion contracts/curves/BondingCurve.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.6;
pragma solidity 0.8.13;
import "./Power.sol";

// import "hardhat/console.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/curves/Power.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.6;
pragma solidity 0.8.13;

/**
* @title Power function by Bancor
Expand Down
2 changes: 1 addition & 1 deletion contracts/testHelpers/ExposedTimedMint.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//SPDX-License-Identifier: Unlicense

pragma solidity ^0.8.6;
pragma solidity ^0.8.13;

import "../tokens/standards/ERC20TimedMint.sol";

Expand Down
2 changes: 1 addition & 1 deletion contracts/tokens/CreatorToken.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.6;
pragma solidity 0.8.13;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/tokens/SimpleToken.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.6;
pragma solidity 0.8.13;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/tokens/TimedMintToken.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.6;
pragma solidity 0.8.13;

import "@openzeppelin/contracts/access/AccessControl.sol";
import "./standards/ERC20TimedMint.sol";
Expand Down
2 changes: 1 addition & 1 deletion contracts/tokens/standards/ERC20TimedMint.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//SPDX-License-Identifier: Unlicensed

pragma solidity ^0.8.6;
pragma solidity ^0.8.13;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

Expand Down
2 changes: 1 addition & 1 deletion contracts/utils/Airdroppable.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//SPDX-License-Identifier: Unlicense
pragma solidity 0.8.6;
pragma solidity 0.8.13;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
Expand Down
2 changes: 1 addition & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {
* @type import('hardhat/config').HardhatUserConfig
*/
export default {
solidity: "0.8.6",
solidity: "0.8.13",
};

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{
"scripts": {
"compile": "npx hardhat compile",
"test": "npx hardhat test"
},
"devDependencies": {
"@nomiclabs/hardhat-ethers": "^2.0.4",
"@nomiclabs/hardhat-waffle": "^2.0.1",
Expand Down
Loading