➡️Rewards
After a successful referral, Spindl will automatically credit wallets with rewards in an on-chain smart contract. The smart contract provides methods to directly to check the status of rewards for a particular wallet and facilitate a withdrawal transaction on-chain.
Check Available Rewards
RPC Call
getRecipient(_campaignId, _recpientAddress) public view returns (RecipientDetails memory)
Parameters
Campaign ID: This is the campaign id associated with the campaign you are running. If you are running multiple campaigns, you can check for rewards for each one individually.
Recipient Address: Logged in wallet.
Response
struct RecipientDetails {
RecipientStatus status;
uint256 earned;
uint256 withdrawn;
}
enum RecipientStatus {
NONE,
ACTIVE,
PAUSED
}
(Note: The status will almost always be NONE or ACTIVE. The PAUSED status is a special flag that only you can trigger, for suspicious referrers)
Examples
Withdraw Rewards
Transaction Call
withdrawRecipientEarnings(uint32 _campaignId, uint256 _amount, address _to) public virtual
Parameters
Campaign ID: This is the campaign id associated with the campaign you are running.
Amount: The amount to withdraw. This is usually the total withdrawal amount, but can be a smaller amount as well. This will be in the currency for the campaign.
To: The recipient of the funds. This is usually the address of the wallet calling this function, but you can set it to another address specific by the user
Returns
This is a transaction, so there will be no return type. The transaction should be successful if the caller is owed at least that amount in the campaign.
Campaign Details
RPC Call
campaigns(_campaignId) public view returns (totalBudget uint256, status uint8, paymentType address, totalEarned uint256)
Parameters
Campaign ID: This is the campaign id associated with the campaign you are running.
Returns
Total Budget: The total budget set by the owner of the campaign
Status
Payment Type: The ERC20 token, or 0x0... for the native currency
Total Earned: The total amount of token allocated referrers and referees.
Test Contract
Here is an example contract on the Arbitrum Tesnet:
Address: 0xEC16738B5c89837e90f117dEAb1e9743Be562d69 (URL)
Campaign ID: 1
We populated the campaign with earnings for these referrer addresses to make testing easier:
0xD4ed4369ae2c27924ee59bd49459C642C20395B2
0x0000000000000000000000000000000000000021
0x0000000000000000000000000000000000000022
0x0000000000000000000000000000000000000023
0x0000000000000000000000000000000000000024
0x0000000000000000000000000000000000000025
0x0000000000000000000000000000000000000026
0x0000000000000000000000000000000000000027
0x0000000000000000000000000000000000000028
0x0000000000000000000000000000000000000029
0x0000000000000000000000000000000000000030
Contract ABI
You can use this to interact with the contract with any Web3 client libraries, like Ethers.js
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadAddress","type":"error"},{"inputs":[],"name":"BadPayment","type":"error"},{"inputs":[],"name":"BadRequest","type":"error"},{"inputs":[],"name":"ImproperCampaignState","type":"error"},{"inputs":[],"name":"IncorrectAmount","type":"error"},{"inputs":[],"name":"OverAttributed","type":"error"},{"inputs":[],"name":"PaymentTypeDoesNotExist","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"withdrawAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTotalBalance","type":"uint256"}],"name":"BalanceWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":false,"internalType":"address","name":"paymentType","type":"address"}],"name":"CampaignCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"updatedBudget","type":"uint256"}],"name":"CampaignFunded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":false,"internalType":"enum PayoutVault.CampaignStatus","name":"oldState","type":"uint8"},{"indexed":false,"internalType":"enum PayoutVault.CampaignStatus","name":"newState","type":"uint8"}],"name":"CampaignStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"ManagerAddressUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"paymentAddress","type":"address"}],"name":"PaymentAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":false,"internalType":"address","name":"recipientAddress","type":"address"}],"name":"RecipientAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"enum PayoutVault.RecipientStatus","name":"status","type":"uint8"}],"name":"RecipientStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":true,"internalType":"address","name":"recipientAddress","type":"address"},{"indexed":false,"internalType":"address","name":"paymentType","type":"address"},{"indexed":false,"internalType":"uint256","name":"newEarnings","type":"uint256"}],"name":"UpdateCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"campaignId","type":"uint32"},{"indexed":true,"internalType":"address","name":"recipientAddress","type":"address"},{"indexed":false,"internalType":"address","name":"paymentType","type":"address"},{"indexed":false,"internalType":"uint256","name":"totalWithdrawn","type":"uint256"},{"indexed":false,"internalType":"enum PayoutVault.RecipientWithdrawType","name":"withdrawType","type":"uint8"}],"name":"WithdrawSuccess","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"WorkerAddressUpdated","type":"event"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"addERC20Payment","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"address[]","name":"_recipientAddresses","type":"address[]"}],"name":"addRecipients","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"campaignCounter","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"}],"name":"campaigns","outputs":[{"internalType":"uint256","name":"totalBudget","type":"uint256"},{"internalType":"enum PayoutVault.CampaignStatus","name":"status","type":"uint8"},{"internalType":"address","name":"paymentType","type":"address"},{"internalType":"uint256","name":"totalEarned","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_paymentType","type":"address"},{"internalType":"address[]","name":"_recipientAddresses","type":"address[]"}],"name":"createCampaign","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"fundCampaign","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"address","name":"_recipientAddress","type":"address"}],"name":"getRecipient","outputs":[{"components":[{"internalType":"enum PayoutVault.RecipientStatus","name":"status","type":"uint8"},{"internalType":"uint256","name":"earned","type":"uint256"},{"internalType":"uint256","name":"withdrawn","type":"uint256"}],"internalType":"struct PayoutVault.RecipientDetails","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_managerAddress","type":"address"},{"internalType":"address","name":"_workerAddress","type":"address"},{"internalType":"address[]","name":"_paymentTypes","type":"address[]"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"managerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"paymentTypes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"address[]","name":"_recipientAddresses","type":"address[]"}],"name":"pushRecipientEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"enum PayoutVault.CampaignStatus","name":"_status","type":"uint8"}],"name":"setCampaignStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"setManagerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"address","name":"_recipientAddress","type":"address"},{"internalType":"enum PayoutVault.RecipientStatus","name":"_status","type":"uint8"}],"name":"setRecipientStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newAddress","type":"address"}],"name":"setWorkerAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"performData","type":"bytes"}],"name":"updateBalances","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint32","name":"campaignId","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct PayoutVault.RecipientEarnings[]","name":"_campaigns","type":"tuple[]"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawManyRecipientEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawRecipientEarnings","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_campaignId","type":"uint32"},{"internalType":"address","name":"_to","type":"address"}],"name":"withdrawRemainingCampaignBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"workerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Last updated