Referral Design Pattern

A design pattern build for rewarding user attribution


One way to use XP Protocol is as an on-chain Referral System. This design encourages your users to refer new users to your platform/protocol.
A referral is said to be "attributed" to the person who brought the new user in.
The key to setting this up correctly while ensuring it does not get gamed is to tap into the unique identifier of a updateScore() transaction.
updateId: Is a unique identifier that must be sent with each updateScore() transaction. This transaction is Deduped on-chain to prevent attacks.
let myHeaders = new Headers();
let message =;
let signatureObject = await web3.eth.accounts.sign(message, <PRIVATE_KEY>); //Private key of a wallet that is either an Updater or an Owner of the current project.
let signature = signatureObject.signature;
myHeaders.append("Content-Type", "application/json");
let attributedAddress = "0xa6869c3001de171c26418e9e2eedca1c0d763ee2";
let newUserAddress = "0x0baBda04f62C549A09EF3313Fe187f29c099FF3C";
let updateId = "referral:"+attributedAddress+":"+newUserAddress;
updateId = '0x' + sha256(updateId).toString(); // 0x to signify its a bytes32
//Send to API
const body = JSON.stringify({
"updateId": updateId,
"projectId": "0xadb591795f9e9047f9117163b83c2ebcd5edc4503644d59a98cf911aef0367f8",
"actionName": "referral",
"scoreType": "social",
"targetWallet": attributedAddress,
"signature": signature,
"message": message
const requestOptions = {
method: 'POST',
headers: myHeaders,
body: body,
redirect: 'follow'
let response = await fetch(', requestOptions).then(async (response) => ({ status: response.status, value: await response.text() }));
Notice this particular line below:
let updateId = "referral:"+attributedAddress+":"+newUserAddress
This line sets the updateId to a concatenation of the two user addresses involved in this score update.
The simplicity in this line is that as a developer you do not need to worry about checking to see if a user has already gotten a reward for referring that particular user. This means there is no state management or querying that needs to happen before you fire off a score update.
The deduping will happen on-chain, each score update is Idempotent.
Idempotence is a key differentiator with XP Protocol which allows developers to bypass complexity in storying and tracking referrals.
That's it!