-
Notifications
You must be signed in to change notification settings - Fork 39
✨ exa: add crosschain mint and burn support #797
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
base: main
Are you sure you want to change the base?
Changes from all commits
d322d46
6491108
5c5fc4b
eca7029
a9bdd54
26d6ecd
13d87a3
e849de1
6006846
07bdc21
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@exactly/protocol": patch | ||
| --- | ||
|
|
||
| ✨ exa: add crosschain mint and burn support | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "@exactly/protocol": patch | ||
| --- | ||
|
|
||
| 🔒 exa: restrict initialize to proxy admin or construction |
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
| /lcov.info | ||
| /types/ | ||
|
|
||
| .claude/settings.local.json | ||
| .openzeppelin/unknown-* | ||
| .vscode/ | ||
| cache/ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,61 @@ | ||
| // SPDX-License-Identifier: BUSL-1.1 | ||
| pragma solidity ^0.8.17; | ||
|
|
||
| import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable-v4/access/AccessControlUpgradeable.sol"; | ||
| import { | ||
| ERC20VotesUpgradeable | ||
| } from "@openzeppelin/contracts-upgradeable-v4/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; | ||
| import { StorageSlotUpgradeable } from "@openzeppelin/contracts-upgradeable-v4/utils/StorageSlotUpgradeable.sol"; | ||
| import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; | ||
| import { IERC7802 } from "@openzeppelin/contracts/interfaces/draft-IERC7802.sol"; | ||
|
|
||
| contract EXA is ERC20VotesUpgradeable, AccessControlUpgradeable, IERC7802 { | ||
| bytes32 public constant BRIDGE_ROLE = keccak256("BRIDGE_ROLE"); | ||
| bytes32 internal constant ADMIN_SLOT = bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1); | ||
|
|
||
| /// @custom:oz-upgrades-unsafe-allow constructor | ||
| constructor() { | ||
| _disableInitializers(); | ||
| } | ||
|
|
||
| contract EXA is ERC20VotesUpgradeable { | ||
| function initialize() external initializer { | ||
| if (address(this).code.length > 0 && msg.sender != StorageSlotUpgradeable.getAddressSlot(ADMIN_SLOT).value) { | ||
| revert NotProxyAdmin(); | ||
| } | ||
|
|
||
| __ERC20_init("exactly", "EXA"); | ||
| __ERC20Permit_init("exactly"); | ||
| __ERC20Votes_init(); | ||
| _mint(msg.sender, 10_000_000e18); | ||
| if (block.chainid == 10) _mint(msg.sender, 10_000_000e18); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
On chain 10, Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| function initialize2(address admin_) external reinitializer(2) { | ||
| if (msg.sender != StorageSlotUpgradeable.getAddressSlot(ADMIN_SLOT).value) revert NotProxyAdmin(); | ||
| if (admin_ == address(0)) revert ZeroAddress(); | ||
| if (bytes(symbol()).length == 0) revert NotInitialized(); | ||
|
|
||
| __AccessControl_init(); | ||
| _grantRole(DEFAULT_ADMIN_ROLE, admin_); | ||
|
Comment on lines
+32
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Useful? React with 👍 / 👎. |
||
| } | ||
|
|
||
| /// @inheritdoc IERC7802 | ||
| function crosschainMint(address to, uint256 amount) public onlyRole(BRIDGE_ROLE) { | ||
| _mint(to, amount); | ||
| emit CrosschainMint(to, amount, msg.sender); | ||
| } | ||
|
|
||
| /// @inheritdoc IERC7802 | ||
| function crosschainBurn(address from, uint256 amount) public onlyRole(BRIDGE_ROLE) { | ||
| _burn(from, amount); | ||
| emit CrosschainBurn(from, amount, msg.sender); | ||
| } | ||
|
|
||
| function mint(address to, uint256 amount) external { | ||
| crosschainMint(to, amount); | ||
| } | ||
|
|
||
| function burn(address from, uint256 amount) external { | ||
| crosschainBurn(from, amount); | ||
| } | ||
|
|
||
| function clock() public view override returns (uint48) { | ||
|
|
@@ -21,4 +66,14 @@ contract EXA is ERC20VotesUpgradeable { | |
| function CLOCK_MODE() public pure override returns (string memory) { | ||
| return "mode=timestamp"; | ||
| } | ||
|
|
||
| function supportsInterface( | ||
| bytes4 interfaceId | ||
| ) public view override(AccessControlUpgradeable, IERC165) returns (bool) { | ||
| return interfaceId == type(IERC7802).interfaceId || super.supportsInterface(interfaceId); | ||
| } | ||
| } | ||
|
|
||
| error NotInitialized(); | ||
| error NotProxyAdmin(); | ||
| error ZeroAddress(); | ||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Uh oh!
There was an error while loading. Please reload this page.