Smart Contract

CampaignEscrow

A.14aca78d100d2001.CampaignEscrow

Valid From

130,449,220

Deployed

1w ago
Feb 21, 2026, 02:38:27 PM UTC

Dependents

3 imports
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}