A composable, lightweight and fully open source solidity protocol build for real-world customer engagment.
Explore the docs »
View Demo of a dApp interacting with the protocol.
·
Report Bug
·
Request Feature
Table of Contents
The Loyal protocol provides a modular, composable and gas efficient framework for blockchain based customer engagement programs.
Key features:
- It allows anyone to act as a vendor, deploying a loyalty program, minting loyalty points and cards, and distributing points to loyalty cards.
- It allows anyone to deploy gift programs that exchanges loyalty points to gifts or vouchers.
- It disallows the use of loyalty points and vouchers in any other loyalty program than the one in which they were minted.
In other words, loyalty points do not have value of themselves, but give easy-access to a wide range of customer experiences. The project showcases how tokens can be used as a utility, rather than store of value.
The roles in the protocol are
- Vendor: Address that created the LoyaltyProgram contract. More advanced governance options are planned for future versions.
- Customer: Address that owns a loyaltyCard.
The contracts that make up the Loyalty protocol:
LoyaltyProgram.sol
: Mints loyalty points and loyalty cards, distributes points to cards and (de)selects external gift programs.LoyaltyCard6551Account.sol
: a bespoke ERC6551 account implementation optimised for the use with ERC1155 tokens. It acts as loyalty card and collects loyalty points and vouchers.ILoyaltyGift.sol
andLoyaltyGift.sol
: The interface and base implementation of an, ERC-1155 based, gift contract. Loyalty Gifts are external contracts, examples can be found in the dedicated repository for gift contracts. These contracts exchange loyalty points to- either a boolean
true
result. This signals that requirements for the gift have been met and the vendor can give a gift to the customer. - or a loyalty voucher. A semi-fungible token minted at an external gift contract that allows the exchange for a gift at a later stage.
- either a boolean
See the following schema for more detail:
-
Solidity 0.8.19
-
Foundry 0.2.0
-
OpenZeppelin 5.0
-
It builds on the following ERC standards:
- [ERC-1155: Multi-Token Standard]: the Loyalty Program contract mints fungible points and non-fungible loyalty Cards; external contracts can mint semi-fungible vouchers.
- [ERC-6551: Non-fungible Token Bound Accounts]: Loyalty Cards are transformed into Token Based Accounts using ERC-6551 registry.
- [EIP-712: Typed structured data hashing and signing]: customer requests are executed through signed messages (transferred in front-end app as Qr codes) to the vendor. It allows the vendor to cover all gas costs.
- [ERC-165: Standard Interface Detection]: gift contracts are checked if they follow they ILoyaltyGift interface.
To get a local copy up and running do the following.
Foundry
- Install following the directions at getfoundry.sh.
- You'll know you did it right if you can run
forge --version
and you see a response likeforge 0.2.0 (816e00b 2023-03-16T00:05:26.396218Z)
A blockchain with an ERC-6551 registry (v.0.3.1) deployed at address 0x000000006551c19487814612e58FE06813775758.
- To check what chains have an ERC-6551 registry deployed, see tokenbound.org.
- To deploy yourself (or on a local chain) follow the steps at tokenbound.org.
- Clone the repo
git clone https://github.com/7Cedars/loyalty-program-contracts.git
- navigate to the folder
cd loyalty-program-contracts
- create a .env file and add the following:
SELECTED_RPC_URL = <PATH_TO_RPC>
Where <PATH_TO_RPC> is the url to your rpc provider, for example: https://eth-sepolia.g.alchemy.com/v2/... or http://localhost:8545 for a local anvil chain.
Note that tests will not run on a chain that does not have an ERC-6551 registry deployed. Due to compiler conflicts, it is not possible to deterministically deploy the erc6511 registry inside the test suite itself.
- run make
make
$ forge test
forge coverage
and for coverage based testing:
forge coverage --report debug
$ forge build
$ forge script --fork-url <RPC_URL> script/DeployLoyaltyProgram.s.sol --broadcast
Where <RPC_URL> is the url to your rpc provider, for example: https://eth-sepolia.g.alchemy.com/v2/...
A front-end dApp demonstration of this web3 protocol has been deployed on vercel.com. Try it out at https://loyalty-program-psi.vercel.app/.
This contract has not been audited. Do not deploy on anything else than a test chain. More specifically:
- Testing coverage is still low. Fuzz tests especially are still underdeveloped.
- ERC-1155 and ERC-6551 combination ... WIP
- Centralisation. Owner has core priviledges in a consumer program.
- I use a simple self build onlyOwner() modifier, instead of OpenZeppelin's implemntation. Keep gas cost down.
- Owner of a loyalty program is set at construction, cannot be changed later on.
- Further develop testing. Basic unit, integration and invariant tests have been implemented, but fuzz tests not yet. Test coverage is only around 50 percent.
- Implement deployment to multiple testnets.
- ...
See the open issues for a full list of proposed features (and known issues).
Contributions and suggestions are more than welcome. If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Thank you!
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature
) - Commit your Changes (
git commit -m 'Add some AmazingFeature'
) - Push to the Branch (
git push origin feature/AmazingFeature
) - Open a Pull Request
Distributed under the MIT License. See LICENSE.txt
for more information.
Seven Cedars - @7__Cedars - [email protected]
GitHub profile https://github.com/7Cedars
- This project was build while following PatrickCollins amazing Learn Solidity, Blockchain Development, & Smart Contracts Youtube course. Not only does the course come highly recommended (it's really a fantastic course!) many parts of this repo started out as direct rip offs from his examples. I have tried to note all specific cases, but please forgive me when I missed some.
- An introduction to ERC-6551 by Pinata's Kelly Kim was really useful.
- When it comes to EIP-712, the Foundry book was immensly helpful. See https://book.getfoundry.sh/tutorials/testing-eip712. Some other sources I used were:
- As was the documentation from Tokenbound (an organisation advocating the implementation of Tokan Based Accounts).
- I took the template for the readme file from Drew Othneil.
- And a special thanks should go out to SpeedRunEthereum and LearnWeb3 for providing the first introductions to solidity coding.