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

[CHAIN-47] move p into monorepo #7

Merged
merged 9 commits into from
Sep 16, 2024
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
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@
[submodule "nest/lib/openzeppelin-contracts-upgradeable"]
path = nest/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "p/lib/forge-std"]
path = p/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "p/lib/openzeppelin-contracts-upgradeable"]
path = p/lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
[submodule "smart-wallets/lib/forge-std"]
path = smart-wallets/lib/forge-std
url = https://github.com/foundry-rs/forge-std
Expand Down
15 changes: 15 additions & 0 deletions p/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Compiler files
cache/
out/

# Ignores development broadcast logs
!/broadcast
/broadcast/*/31337/
/broadcast/*/18230/
/broadcast/**/dry-run/

# Docs
docs/

# Dotenv file
.env
3 changes: 3 additions & 0 deletions p/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## P Smart Contracts

$P is the governance token of Plume.
28 changes: 28 additions & 0 deletions p/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
[profile.default]
solc = "0.8.25"
evm_version = "paris"
src = "src"
out = "out"
libs = ["lib"]
ffi = true
ast = true
build_info = true
extra_output = ["storageLayout"]
optimizer = true
optimizer_runs = 200 # used default optimization level when deploying $P to mainnet

[fmt]
single_line_statement_blocks = "multi"
multiline_func_header = "params_first"
sort_imports = true
contract_new_lines = true
bracket_spacing = true
int_types = "long"
quote_style = "double"
number_underscore = "thousands"
wrap_comments = true

remappings = [
"@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
]
1 change: 1 addition & 0 deletions p/lib/forge-std
Submodule forge-std added at 1714be
1 change: 1 addition & 0 deletions p/lib/openzeppelin-contracts-upgradeable
37 changes: 37 additions & 0 deletions p/script/DeployToken.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import "forge-std/Script.sol";

import { P } from "../src/P.sol";
import { IDeployer } from "../src/interfaces/IDeployer.sol";
import { PProxy } from "../src/proxy/PProxy.sol";

/**
* @title DeployToken
* @author Eugene Y. Q. Shen
* @notice Deploys P to a deterministic address 0x4C1746A800D224393fE2470C70A35717eD4eA5F1
*/
contract DeployToken is Script {

bytes32 private constant DEPLOY_SALT = keccak256("P");
address private constant DEPLOYER_ADDRESS = 0x6513Aedb4D1593BA12e50644401D976aebDc90d8;

function run(address admin) external {
vm.startBroadcast();

P pImpl = new P();
console.log("pImpl deployed to:", address(pImpl));

address pProxy = IDeployer(DEPLOYER_ADDRESS).deploy(
abi.encodePacked(
type(PProxy).creationCode, abi.encode(pImpl, abi.encodeWithSelector(P.initialize.selector, admin))
),
DEPLOY_SALT
);
console.log("pProxy deployed to:", pProxy);

vm.stopBroadcast();
}

}
131 changes: 131 additions & 0 deletions p/src/P.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import { ERC20Upgradeable } from "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import { ERC20BurnableUpgradeable } from
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20BurnableUpgradeable.sol";
import { ERC20PausableUpgradeable } from
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PausableUpgradeable.sol";
import { ERC20PermitUpgradeable } from
"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol";

/**
* @title P
* @author Eugene Y. Q. Shen
* @notice ERC20 token that is the governance token for Plume Network
*/
contract P is
Initializable,
AccessControlUpgradeable,
ERC20Upgradeable,
ERC20BurnableUpgradeable,
ERC20PausableUpgradeable,
ERC20PermitUpgradeable,
UUPSUpgradeable
{

// Constants

/// @notice Role for the admin of P
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
/// @notice Role for the upgrader of P
bytes32 public constant UPGRADER_ROLE = keccak256("UPGRADER_ROLE");
/// @notice Role for the minter of P
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
/// @notice Role for the burner of P
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
/// @notice Role for the pauser of P
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");

// Initializer

/// @custom:oz-upgrades-unsafe-allow constructor
constructor() {
_disableInitializers();
}

/**
* @notice Initialize P
* @dev Give all roles to the admin address passed into the constructor
* @param admin Address of the admin of P
*/
function initialize(address admin) public initializer {
__ERC20_init("Plume", "P");
__ERC20Burnable_init();
__ERC20Pausable_init();
__AccessControl_init();
__UUPSUpgradeable_init();
__ERC20Permit_init("Plume");

_grantRole(DEFAULT_ADMIN_ROLE, admin);
_grantRole(ADMIN_ROLE, admin);
_grantRole(MINTER_ROLE, admin);
_grantRole(BURNER_ROLE, admin);
_grantRole(PAUSER_ROLE, admin);
_grantRole(UPGRADER_ROLE, admin);
}

// Override Functions

/**
* @notice Revert when `msg.sender` is not authorized to upgrade the contract
* @param newImplementation Address of the new implementation
*/
function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADER_ROLE) { }

/**
* @notice Update the balance of `from` and `to` before and after token transfer
* @param from Address to transfer tokens from
* @param to Address to transfer tokens to
* @param value Amount of tokens to transfer
*/
function _update(
address from,
address to,
uint256 value
) internal override(ERC20Upgradeable, ERC20PausableUpgradeable) {
super._update(from, to, value);
}

// User Functions

/**
* @notice Mint new P tokens
* @dev Only the minter can mint new tokens
* @param to Address to mint tokens to
* @param amount Amount of tokens to mint
*/
function mint(address to, uint256 amount) external onlyRole(MINTER_ROLE) {
_mint(to, amount);
}

/**
* @notice Burn P tokens
* @dev Only the burner can burn tokens
* @param from Address to burn tokens from
* @param amount Amount of tokens to burn
*/
function burn(address from, uint256 amount) external onlyRole(BURNER_ROLE) {
_burn(from, amount);
}

/**
* @notice Pause the contract
* @dev Only the pauser can pause the contract
*/
function pause() external onlyRole(PAUSER_ROLE) {
_pause();
}

/**
* @notice Unpause the contract
* @dev Only the pauser can unpause the contract
*/
function unpause() external onlyRole(PAUSER_ROLE) {
_unpause();
}

}
16 changes: 16 additions & 0 deletions p/src/interfaces/IDeploy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT
// https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/5f15a1036215f8b9c8eeb6438d352172b430dd38/contracts/interfaces/IDeploy.sol

pragma solidity ^0.8.0;

/**
* @title IDeploy Interface
* @notice This interface defines the errors for a contract that is responsible for deploying new contracts.
*/
interface IDeploy {

error EmptyBytecode();
error AlreadyDeployed();
error DeployFailed();

}
54 changes: 54 additions & 0 deletions p/src/interfaces/IDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// SPDX-License-Identifier: MIT
// https://github.com/axelarnetwork/axelar-gmp-sdk-solidity/blob/5f15a1036215f8b9c8eeb6438d352172b430dd38/contracts/interfaces/IDeployer.sol

pragma solidity ^0.8.0;

import { IDeploy } from "./IDeploy.sol";

/**
* @title IDeployer Interface
* @notice This interface defines the contract responsible for deploying and optionally initializing new contracts
* via a specified deployment method.
*/
interface IDeployer is IDeploy {

error DeployInitFailed();

event Deployed(address indexed deployedAddress, address indexed sender, bytes32 indexed salt, bytes32 bytecodeHash);

/**
* @notice Deploys a contract using a deployment method defined by derived contracts.
* @param bytecode The bytecode of the contract to be deployed
* @param salt A salt to influence the contract address
* @return deployedAddress_ The address of the deployed contract
*/
function deploy(bytes memory bytecode, bytes32 salt) external payable returns (address deployedAddress_);

/**
* @notice Deploys a contract using a deployment method defined by derived contracts and initializes it.
* @param bytecode The bytecode of the contract to be deployed
* @param salt A salt to influence the contract address
* @param init Init data used to initialize the deployed contract
* @return deployedAddress_ The address of the deployed contract
*/
function deployAndInit(
bytes memory bytecode,
bytes32 salt,
bytes calldata init
) external payable returns (address deployedAddress_);

/**
* @notice Returns the address where a contract will be stored if deployed via {deploy} or {deployAndInit} by
* `sender`.
* @param bytecode The bytecode of the contract
* @param sender The address that will deploy the contract
* @param salt The salt that will be used to influence the contract address
* @return deployedAddress_ The address that the contract will be deployed to
*/
function deployedAddress(
bytes calldata bytecode,
address sender,
bytes32 salt
) external view returns (address deployedAddress_);

}
15 changes: 15 additions & 0 deletions p/src/interfaces/IP.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import { IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import { IERC20Permit } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";

interface IP is IERC20, IERC20Metadata, IERC20Permit {

function mint(address to, uint256 amount) external;
function burn(address from, uint256 amount) external;
function pause() external;
function unpause() external;

}
15 changes: 15 additions & 0 deletions p/src/proxy/PProxy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

/**
* @title PProxy
* @author Eugene Y. Q. Shen
* @notice Proxy contract for P
*/
contract PProxy is ERC1967Proxy {

constructor(address logic, bytes memory data) ERC1967Proxy(logic, data) { }

}