Smart Contract
IncrementReferral
A.2093c0861ff1bd80.IncrementReferral
1/**
2
3# Contract for managing on-chain referral relationships.
4
5# Author: Increment Labs
6
7*/
8
9import LendingInterfaces from 0x2df970b6cdee5735
10
11access(all) contract IncrementReferral {
12 // Struct to hold referee information, including the referee's address and the timestamp when they were bound.
13 access(all) struct RefereeInfo {
14 access(all) let refereeAddr: Address
15 access(all) let bindTimestamp: UFix64
16 init(_ addr: Address, _ timestamp: UFix64) {
17 self.refereeAddr = addr
18 self.bindTimestamp = timestamp
19 }
20 }
21
22 // A dictionary mapping referrers to an array of RefereeInfo, tracking all referees bound to each referrer.
23 // {Referrer : {Referee: BindingTime} }
24 access(self) let _referrerToReferees: {Address: [RefereeInfo]}
25
26 // A dictionary mapping referees to their respective referrers, allowing for lookup of a referee's referrer.
27 // {Referee: Referrer}
28 access(self) let _refereeToReferrer: {Address: Address}
29
30 /// Events
31 access(all) event BindingReferrer(referrer: Address, referee: Address, indexer: Int)
32
33 // Function to bind a referee to a referrer.
34 // Requires the referrer's address and a capability to fetch the referee's address from an identity certificate.
35 access(all) fun bind(referrer: Address, refereeCertificate: &{LendingInterfaces.IdentityCertificate}) {
36 let referee: Address = refereeCertificate.owner!.address
37
38 assert(self._refereeToReferrer.containsKey(referee) == false, message: "Referrer already bound")
39 assert(referee != referrer, message: "Can't bind yourself")
40
41 self._refereeToReferrer[referee] = referrer
42 if self._referrerToReferees.containsKey(referrer) == false {
43 self._referrerToReferees[referrer] = []
44 }
45 self._referrerToReferees[referrer]!.append(RefereeInfo(referee, getCurrentBlock().timestamp))
46
47 // Prevent circular binding
48 //assert(self.checkCirularBinding(referee: referee) == false, message: "Cirular Binding")
49
50 emit BindingReferrer(referrer: referrer, referee: referee, indexer: self._referrerToReferees[referrer]!.length)
51 }
52
53 // Function to check for circular bindings in the referral structure.
54 access(self) fun checkCirularBinding(referee: Address): Bool {
55 let checkedAddrs: {Address: Bool} = {referee: true}
56 var i = 0
57 var addr = referee
58 while i < 32 {
59 if self._refereeToReferrer.containsKey(addr) == false {
60 return false
61 }
62 let nextAddr = self._refereeToReferrer[addr]!
63 if checkedAddrs.containsKey(nextAddr) == true {
64 return true
65 }
66 checkedAddrs[nextAddr] = true
67 addr = nextAddr
68 i = i + 1
69 }
70 return false
71 }
72
73 access(all) view fun getReferrerByReferee(referee: Address): Address? {
74 if self._refereeToReferrer.containsKey(referee) == false {
75 return nil
76 }
77 return self._refereeToReferrer[referee]!
78 }
79
80 access(all) view fun getReferrerCount(): Int {
81 return self._referrerToReferees.length
82 }
83
84 access(all) view fun getSlicedReferrerList(from: Int, to: Int): [Address] {
85 let len = self._referrerToReferees.length
86 let upTo = to > len ? len : to
87 return self._referrerToReferees.keys.slice(from: from, upTo: upTo)
88 }
89
90 access(all) view fun getRefereeCountByReferrer(referrer: Address): Int {
91 return self._referrerToReferees.containsKey(referrer) ? self._referrerToReferees[referrer]!.length : 0
92 }
93
94 access(all) view fun getSlicedRefereesByReferrer(referrer: Address, from: Int, to: Int): [RefereeInfo] {
95 if self._referrerToReferees.containsKey(referrer) == false {
96 return []
97 }
98 let len = self._referrerToReferees[referrer]!.length
99 let endIndex = to > len ? len : to
100 return self._referrerToReferees[referrer]!.slice(from: from, upTo: endIndex)
101 }
102
103 /// Admin
104 ///
105 access(all) resource Admin {
106
107 }
108
109 init() {
110 self._referrerToReferees = {}
111 self._refereeToReferrer = {}
112
113 destroy <-self.account.storage.load<@AnyResource>(from: /storage/referralAdmin)
114 self.account.storage.save(<-create Admin(), to: /storage/referralAdmin)
115 }
116}
117