Skip to content

Commit

Permalink
[CHAIN-47] move p into monorepo (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
eyqs authored Sep 16, 2024
1 parent 36a2302 commit 91b45ea
Show file tree
Hide file tree
Showing 12 changed files with 322 additions and 0 deletions.
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) { }

}

0 comments on commit 91b45ea

Please sign in to comment.