Skip to content

Commit

Permalink
feat: point token
Browse files Browse the repository at this point in the history
  • Loading branch information
sogipec committed Jan 14, 2025
1 parent 8da1686 commit 742a69b
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 0 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ function run() external broadcast {

The Merkl smart contracts have been audited by Code4rena, find the audit report [here](https://code4rena.com/reports/2023-06-angle).

## Access Control

## Media

Don't hesitate to reach out on [Twitter](https://x.com/merkl_xyz) 🐦
75 changes: 75 additions & 0 deletions contracts/partners/tokenWrappers/PointToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.7;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { IAccessControlManager } from "../../interfaces/IAccessControlManager.sol";
import "../../utils/Errors.sol";

/// @title PointToken
/// @author Angle Labs, Inc.
/// @notice Reference contract for points systems within Merkl
contract PointToken is ERC20 {
mapping(address => bool) public minters;
mapping(address => bool) public whitelistedRecipients;
IAccessControlManager public accessControlManager;
uint8 public allowedTransfers;

constructor(
string memory name_,
string memory symbol_,
address _minter,
address _accessControlManager
) ERC20(name_, symbol_) {
if (_accessControlManager == address(0) || _minter == address(0)) revert Errors.ZeroAddress();
accessControlManager = IAccessControlManager(_accessControlManager);
minters[_minter] = true;
}

modifier onlyGovernorOrGuardian() {
if (!accessControlManager.isGovernorOrGuardian(msg.sender)) revert Errors.NotGovernorOrGuardian();
_;
}

modifier onlyMinter() {
if (!minters[msg.sender]) revert Errors.NotTrusted();
_;
}

function mint(address account, uint256 amount) external onlyMinter {
_mint(account, amount);
}

function burn(address account, uint256 amount) external onlyMinter {
_burn(account, amount);
}

function mintBatch(address[] memory accounts, uint256[] memory amounts) external onlyMinter {
uint256 length = accounts.length;
for (uint256 i = 0; i < length; ++i) {
_mint(accounts[i], amounts[i]);
}
}

function toggleMinter(address minter) external onlyGovernorOrGuardian {
minters[minter] = !minters[minter];
}

function toggleAllowedTransfers() external onlyGovernorOrGuardian {
allowedTransfers = 1 - allowedTransfers;
}

function toggleWhitelistedRecipient(address recipient) external onlyGovernorOrGuardian {
whitelistedRecipients[recipient] = !whitelistedRecipients[recipient];
}

function _beforeTokenTransfer(address from, address to, uint256) internal view override {
if (
allowedTransfers == 0 &&
from != address(0) &&
to != address(0) &&
!whitelistedRecipients[from] &&
!whitelistedRecipients[to]
) revert Errors.NotAllowed();
}
}
11 changes: 11 additions & 0 deletions docs/access_control.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 742a69b

Please sign in to comment.