Smart Contract
CampaignEscrow
A.14aca78d100d2001.CampaignEscrow
1/**
2 * CampaignEscrow Contract
3 *
4 * Manages campaign escrow with USDF tokens and automated payouts
5 * Integrates with Flow Forte scheduled transactions for auto-refund
6 * Handles trustless campaign management between brands and creators
7 */
8
9import FungibleToken from 0xf233dcee88fe0abe
10
11access(all) contract CampaignEscrow {
12
13 // Campaign data structure
14 access(all) struct Campaign {
15 access(all) let id: String
16 access(all) let creator: Address
17 access(all) let brand: Address
18 access(all) let threshold: UFix64
19 access(all) let payout: UFix64
20 access(all) let deadline: UFix64
21 access(all) let createdAt: UFix64
22 access(all) let scheduledTxId: String? // Forte scheduled transaction ID for auto-refund
23
24 init(
25 id: String,
26 creator: Address,
27 brand: Address,
28 threshold: UFix64,
29 payout: UFix64,
30 deadline: UFix64,
31 createdAt: UFix64,
32 scheduledTxId: String?
33 ) {
34 self.id = id
35 self.creator = creator
36 self.brand = brand
37 self.threshold = threshold
38 self.payout = payout
39 self.deadline = deadline
40 self.createdAt = createdAt
41 self.scheduledTxId = scheduledTxId
42 }
43 }
44
45 // Oracle account for triggering payouts
46 access(all) let oracle: Address
47
48 // Storage for campaigns
49 access(all) var campaigns: {String: Campaign}
50
51 // Create a new campaign
52 access(all) fun createCampaign(
53 id: String,
54 creator: Address,
55 threshold: UFix64,
56 payout: UFix64,
57 deadline: UFix64
58 ): Bool {
59 // Validate inputs
60 pre {
61 threshold > 0.0: "Threshold must be positive"
62 payout > 0.0: "Payout must be positive"
63 deadline > getCurrentBlock().timestamp: "Deadline must be in the future"
64 !self.campaigns.containsKey(id): "Campaign ID already exists"
65 }
66
67 // Create campaign
68 let campaign = Campaign(
69 id: id,
70 creator: creator,
71 brand: self.oracle, // Using oracle as brand for simplicity
72 threshold: threshold,
73 payout: payout,
74 deadline: deadline,
75 createdAt: getCurrentBlock().timestamp,
76 scheduledTxId: nil
77 )
78
79 // Store campaign
80 self.campaigns[id] = campaign
81
82 // Emit event
83 emit CampaignCreated(id: id, creator: creator, threshold: threshold, payout: payout)
84
85 return true
86 }
87
88 // Get campaign details
89 access(all) fun getCampaign(id: String): Campaign? {
90 return self.campaigns[id]
91 }
92
93 // Get all campaigns
94 access(all) fun getAllCampaigns(): [Campaign] {
95 let campaigns: [Campaign] = []
96 for campaign in self.campaigns.values {
97 campaigns.append(campaign)
98 }
99 return campaigns
100 }
101
102 // Events
103 access(all) event CampaignCreated(id: String, creator: Address, threshold: UFix64, payout: UFix64)
104 access(all) event PayoutTriggered(id: String, recipient: String, amount: UFix64)
105 access(all) event CampaignRefunded(id: String, brand: String, amount: UFix64)
106
107 init(oracleAddress: Address) {
108 self.oracle = oracleAddress
109 self.campaigns = {}
110 log("CampaignEscrow contract deployed with oracle: ".concat(self.oracle.toString()))
111 }
112}