Contract
LoyaltyPoint
The LoyaltyPoint
contract is the core contract for managing loyalty points. It defines the token logic, including minting and burning points (tokens), as well as role-based access control (RBAC) for managing permissions around minting.
Addresses
Gravity Alpha Testnet Sepolia: 0x8a85eC5AE1ae2c757eEfBb10b1203C984120bf8c
Key Features
- Minting and Burning Allows approved minters to mint and burn loyalty points.
- ERC20 Compatibility This contract follows the ERC20 token standard, making it interoperable with other blockchain systems.
- Role-based Access Control (RBAC) Uses role-based control to assign permissions to mint and burn points.
- Custom Metadata Name and symbol for the loyalty point can be customized during deployment.
Constructor
constructor(
string memory _name,
string memory _symbol,
address _initialAdmin,
address[] memory _minters
)
- _name Name of the loyalty point token (e.g., “Galxe Points”).
- _symbol Token symbol (e.g., “GP”).
- _initialAdmin Admin address responsible for managing permissions.
- _minters An array of addresses with permission to mint points.
Role Management
- The
DEFAULT_ADMIN_ROLE
is given to the_initialAdmin
address. - The
MINTER_ROLE
is assigned to any addresses specified in the_minters
array. - Admin can add or revoke roles using
grantRole
andrevokeRole
.
Minting and Burning
-
mint()
Allows any address with theMINTER_ROLE
to mint new points.function mint(address _to, uint256 _amount) external;
-
burn()
Allows any address with theMINTER_ROLE
to burn points from a specified account.function burn(address _from, uint256 _amount) external;
Usage Example
To mint new loyalty points to a user:
loyaltyPoint.mint(userAddress, 1000); // Mint 1000 points to userAddress
To burn loyalty points from a user:
loyaltyPoint.burn(userAddress, 500); // Burn 500 points from userAddress
Custom Events
- Mint Emitted when new points are minted.
to
: The address receiving the minted points.amount
: The amount of points minted.
- Burn Emitted when points are burned.
from
: The address from which points are burned.amount
: The amount of points burned.
Security
- Pausable The contract can be paused and unpaused by the admin using the inherited
Pausable
functionality. - Access Control Implements role-based control using OpenZeppelin’s
AccessControl
.
ABI
[
{
"type": "constructor",
"inputs": [
{ "name": "spaceName", "type": "string", "internalType": "string" },
{ "name": "initialAdmin", "type": "address", "internalType": "address" },
{ "name": "minters", "type": "address[]", "internalType": "address[]" }
],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "DEFAULT_ADMIN_ROLE",
"inputs": [],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "DOMAIN_SEPARATOR",
"inputs": [],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "MINTER_ROLE",
"inputs": [],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "acceptDefaultAdminTransfer",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "allowance",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" },
{ "name": "spender", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "approve",
"inputs": [
{ "name": "spender", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "balanceOf",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "beginDefaultAdminTransfer",
"inputs": [
{ "name": "newAdmin", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "burn",
"inputs": [
{ "name": "_user", "type": "address", "internalType": "address" },
{ "name": "_amount", "type": "uint256", "internalType": "uint256" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "burnBatch",
"inputs": [
{ "name": "_users", "type": "address[]", "internalType": "address[]" },
{ "name": "_amounts", "type": "uint256[]", "internalType": "uint256[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "cancelDefaultAdminTransfer",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "changeDefaultAdminDelay",
"inputs": [
{ "name": "newDelay", "type": "uint48", "internalType": "uint48" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "decimals",
"inputs": [],
"outputs": [{ "name": "", "type": "uint8", "internalType": "uint8" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "defaultAdmin",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "defaultAdminDelay",
"inputs": [],
"outputs": [{ "name": "", "type": "uint48", "internalType": "uint48" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "defaultAdminDelayIncreaseWait",
"inputs": [],
"outputs": [{ "name": "", "type": "uint48", "internalType": "uint48" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "eip712Domain",
"inputs": [],
"outputs": [
{ "name": "fields", "type": "bytes1", "internalType": "bytes1" },
{ "name": "name", "type": "string", "internalType": "string" },
{ "name": "version", "type": "string", "internalType": "string" },
{ "name": "chainId", "type": "uint256", "internalType": "uint256" },
{
"name": "verifyingContract",
"type": "address",
"internalType": "address"
},
{ "name": "salt", "type": "bytes32", "internalType": "bytes32" },
{ "name": "extensions", "type": "uint256[]", "internalType": "uint256[]" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "getRoleAdmin",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" }
],
"outputs": [{ "name": "", "type": "bytes32", "internalType": "bytes32" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "grantRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "hasRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "mint",
"inputs": [
{ "name": "_user", "type": "address", "internalType": "address" },
{ "name": "_amount", "type": "uint256", "internalType": "uint256" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "mintBatch",
"inputs": [
{ "name": "_users", "type": "address[]", "internalType": "address[]" },
{ "name": "_amounts", "type": "uint256[]", "internalType": "uint256[]" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "name",
"inputs": [],
"outputs": [{ "name": "", "type": "string", "internalType": "string" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "nonces",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" }
],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "owner",
"inputs": [],
"outputs": [{ "name": "", "type": "address", "internalType": "address" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "pause",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "paused",
"inputs": [],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "pendingDefaultAdmin",
"inputs": [],
"outputs": [
{ "name": "newAdmin", "type": "address", "internalType": "address" },
{ "name": "schedule", "type": "uint48", "internalType": "uint48" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "pendingDefaultAdminDelay",
"inputs": [],
"outputs": [
{ "name": "newDelay", "type": "uint48", "internalType": "uint48" },
{ "name": "schedule", "type": "uint48", "internalType": "uint48" }
],
"stateMutability": "view"
},
{
"type": "function",
"name": "permit",
"inputs": [
{ "name": "owner", "type": "address", "internalType": "address" },
{ "name": "spender", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" },
{ "name": "deadline", "type": "uint256", "internalType": "uint256" },
{ "name": "v", "type": "uint8", "internalType": "uint8" },
{ "name": "r", "type": "bytes32", "internalType": "bytes32" },
{ "name": "s", "type": "bytes32", "internalType": "bytes32" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "renounceRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "revokeRole",
"inputs": [
{ "name": "role", "type": "bytes32", "internalType": "bytes32" },
{ "name": "account", "type": "address", "internalType": "address" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "rollbackDefaultAdminDelay",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setName",
"inputs": [
{ "name": "newName", "type": "string", "internalType": "string" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setSymbol",
"inputs": [
{ "name": "newSymbol", "type": "string", "internalType": "string" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "setTransferable",
"inputs": [
{ "name": "newTransferable", "type": "bool", "internalType": "bool" }
],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "supportsInterface",
"inputs": [
{ "name": "interfaceId", "type": "bytes4", "internalType": "bytes4" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "symbol",
"inputs": [],
"outputs": [{ "name": "", "type": "string", "internalType": "string" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "totalSupply",
"inputs": [],
"outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "transfer",
"inputs": [
{ "name": "to", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "transferFrom",
"inputs": [
{ "name": "from", "type": "address", "internalType": "address" },
{ "name": "to", "type": "address", "internalType": "address" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "nonpayable"
},
{
"type": "function",
"name": "transferable",
"inputs": [],
"outputs": [{ "name": "", "type": "bool", "internalType": "bool" }],
"stateMutability": "view"
},
{
"type": "function",
"name": "unpause",
"inputs": [],
"outputs": [],
"stateMutability": "nonpayable"
},
{
"type": "event",
"name": "Approval",
"inputs": [
{
"name": "owner",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "spender",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminDelayChangeCanceled",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminDelayChangeScheduled",
"inputs": [
{
"name": "newDelay",
"type": "uint48",
"indexed": false,
"internalType": "uint48"
},
{
"name": "effectSchedule",
"type": "uint48",
"indexed": false,
"internalType": "uint48"
}
],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminTransferCanceled",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "DefaultAdminTransferScheduled",
"inputs": [
{
"name": "newAdmin",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "acceptSchedule",
"type": "uint48",
"indexed": false,
"internalType": "uint48"
}
],
"anonymous": false
},
{
"type": "event",
"name": "EIP712DomainChanged",
"inputs": [],
"anonymous": false
},
{
"type": "event",
"name": "Paused",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RoleAdminChanged",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "previousAdminRole",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "newAdminRole",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RoleGranted",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "RoleRevoked",
"inputs": [
{
"name": "role",
"type": "bytes32",
"indexed": true,
"internalType": "bytes32"
},
{
"name": "account",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "sender",
"type": "address",
"indexed": true,
"internalType": "address"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Transfer",
"inputs": [
{
"name": "from",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "to",
"type": "address",
"indexed": true,
"internalType": "address"
},
{
"name": "value",
"type": "uint256",
"indexed": false,
"internalType": "uint256"
}
],
"anonymous": false
},
{
"type": "event",
"name": "Unpaused",
"inputs": [
{
"name": "account",
"type": "address",
"indexed": false,
"internalType": "address"
}
],
"anonymous": false
},
{ "type": "error", "name": "AccessControlBadConfirmation", "inputs": [] },
{
"type": "error",
"name": "AccessControlEnforcedDefaultAdminDelay",
"inputs": [
{ "name": "schedule", "type": "uint48", "internalType": "uint48" }
]
},
{
"type": "error",
"name": "AccessControlEnforcedDefaultAdminRules",
"inputs": []
},
{
"type": "error",
"name": "AccessControlInvalidDefaultAdmin",
"inputs": [
{ "name": "defaultAdmin", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "AccessControlUnauthorizedAccount",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" },
{ "name": "neededRole", "type": "bytes32", "internalType": "bytes32" }
]
},
{ "type": "error", "name": "ECDSAInvalidSignature", "inputs": [] },
{
"type": "error",
"name": "ECDSAInvalidSignatureLength",
"inputs": [
{ "name": "length", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ECDSAInvalidSignatureS",
"inputs": [{ "name": "s", "type": "bytes32", "internalType": "bytes32" }]
},
{
"type": "error",
"name": "ERC20InsufficientAllowance",
"inputs": [
{ "name": "spender", "type": "address", "internalType": "address" },
{ "name": "allowance", "type": "uint256", "internalType": "uint256" },
{ "name": "needed", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ERC20InsufficientBalance",
"inputs": [
{ "name": "sender", "type": "address", "internalType": "address" },
{ "name": "balance", "type": "uint256", "internalType": "uint256" },
{ "name": "needed", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ERC20InvalidApprover",
"inputs": [
{ "name": "approver", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC20InvalidReceiver",
"inputs": [
{ "name": "receiver", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC20InvalidSender",
"inputs": [
{ "name": "sender", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC20InvalidSpender",
"inputs": [
{ "name": "spender", "type": "address", "internalType": "address" }
]
},
{
"type": "error",
"name": "ERC2612ExpiredSignature",
"inputs": [
{ "name": "deadline", "type": "uint256", "internalType": "uint256" }
]
},
{
"type": "error",
"name": "ERC2612InvalidSigner",
"inputs": [
{ "name": "signer", "type": "address", "internalType": "address" },
{ "name": "owner", "type": "address", "internalType": "address" }
]
},
{ "type": "error", "name": "EnforcedPause", "inputs": [] },
{ "type": "error", "name": "ExpectedPause", "inputs": [] },
{
"type": "error",
"name": "InvalidAccountNonce",
"inputs": [
{ "name": "account", "type": "address", "internalType": "address" },
{ "name": "currentNonce", "type": "uint256", "internalType": "uint256" }
]
},
{ "type": "error", "name": "InvalidAddress", "inputs": [] },
{ "type": "error", "name": "InvalidShortString", "inputs": [] },
{ "type": "error", "name": "ParamsLengthMismatch", "inputs": [] },
{ "type": "error", "name": "PermissionDenied", "inputs": [] },
{
"type": "error",
"name": "SafeCastOverflowedUintDowncast",
"inputs": [
{ "name": "bits", "type": "uint8", "internalType": "uint8" },
{ "name": "value", "type": "uint256", "internalType": "uint256" }
]
},
{ "type": "error", "name": "SetTransferableNotAllowed", "inputs": [] },
{
"type": "error",
"name": "StringTooLong",
"inputs": [{ "name": "str", "type": "string", "internalType": "string" }]
},
{ "type": "error", "name": "TransferNotAllow", "inputs": [] }
]