🤖 Automated Auction Completion Options
❌ Why Contracts Can't Self-Execute
The Fundamental Problem:
Smart contracts are passive - they can only run when:
- Someone sends a transaction to them
- Another contract calls them
- An external system triggers them
Contracts cannot:
- ❌ Wake themselves up
- ❌ Execute on a schedule
- ❌ Trigger based on time alone
This is by design for security and cost reasons.
✅ Solution 1: Chainlink Automation (BEST FOR PRODUCTION)
What It Is:
- Decentralized network of keeper nodes
- Monitors your contract
- Automatically calls functions when conditions are met
- Officially supported by Chainlink
How It Works:
// Add to CCALaunchStrategy.sol
import "@chainlink/contracts/src/v0.8/automation/AutomationCompatible.sol";
contract CCALaunchStrategy is AutomationCompatibleInterface {
/**
* @notice Check if auction needs completion
* @dev Called by Chainlink Automation off-chain
*/
function checkUpkeep(bytes calldata /* checkData */)
external
view
override
returns (bool upkeepNeeded, bytes memory /* performData */)
{
if (currentAuction == address(0)) {
return (false, "");
}
IContinuousClearingAuction auction = IContinuousClearingAuction(currentAuction);
// Check if auction ended and not yet graduated
bool isGraduated = auction.isGraduated();
bool hasEnded = block.number > auction.endBlock();
upkeepNeeded = hasEnded && !isGraduated;
}
/**
* @notice Complete auction automatically
* @dev Called by Chainlink Automation when checkUpkeep returns true
*/
function performUpkeep(bytes calldata /* performData */) external override {
// Verify conditions again (for security)
if (currentAuction == address(0)) revert NoActiveAuction();
IContinuousClearingAuction auction = IContinuousClearingAuction(currentAuction);
if (!auction.isGraduated()) revert AuctionNotGraduated();
// Complete auction
this.sweepCurrency();
// Note: Hook configuration still needs to be done separately by token owner
}
}
Setup Steps:
-
Register with Chainlink Automation:
- Go to https://automation.chain.link
- Connect wallet
- Click "Register new Upkeep"
- Select "Custom logic"
- Enter your CCALaunchStrategy address
- Fund with LINK tokens
-
Configuration:
- Check interval: Every hour
- Gas limit: 500,000
- Funding: ~5 LINK (lasts months)
Pros:
- ✅ Fully decentralized
- ✅ Highly reliable (Chainlink network)
- ✅ No server maintenance
- ✅ Industry standard
- ✅ Works on Base
Cons:
- 💰 Costs LINK tokens (~$20-50 to set up)
- 📝 Requires contract modification and redeployment
✅ Solution 2: Gelato Network (ALTERNATIVE)
What It Is:
- Similar to Chainlink but different provider
- Also decentralized automation
- Slightly cheaper
How It Works:
// Add to CCALaunchStrategy.sol
interface IAutomate {
function createTask(
address execAddress,
bytes calldata execDataOrSelector,
ModuleData calldata moduleData,
address feeToken
) external returns (bytes32 taskId);
}
contract CCALaunchStrategy {
IAutomate public gelato;
bytes32 public taskId;
function createAutomationTask() external onlyOwner {
// Create Gelato task to call sweepCurrency after auction ends
// ... Gelato-specific setup
}
}
Pros:
- ✅ Decentralized
- ✅ Cheaper than Chainlink
- ✅ Easy to use
Cons:
- ⚠️ Less proven than Chainlink
- 📝 Still requires contract modification
✅ Solution 3: Incentivized Permissionless (SIMPLEST)
Make Completion Profitable for Anyone:
// Modify CCALaunchStrategy.sol
function sweepCurrency() external nonReentrant {
if (currentAuction == address(0)) revert NoActiveAuction();
IContinuousClearingAuction auction = IContinuousClearingAuction(currentAuction);
// Check if auction has ended
(, uint256 endBlock,,) = auction.auctionParameters();
if (block.number < endBlock) revert AuctionStillActive();
uint256 raised = auction.currencyRaised();
auction.sweepCurrency();
// 🎁 INCENTIVE: Give 0.1% of raised ETH to caller
uint256 incentive = raised / 1000; // 0.1%
if (incentive > 0 && msg.sender != owner()) {
payable(msg.sender).transfer(incentive);
}
graduatedAuction = currentAuction;
isGraduated = true;
emit AuctionGraduated(currentAuction, raised, 0);
emit FundsSwept(currentAuction, raised);
}
Why This Works:
Example: $10,000 raised
- Incentive: $10 (0.1%)
- Anyone can call after day 7
- Gets $10 for ~$1 gas
- Profitable = guaranteed execution
Pros:
- ✅ Simple modification
- ✅ No ongoing costs
- ✅ Decentralized (anyone can call)
- ✅ Market-driven reliability
- ✅ Works immediately after redeploy
Cons:
- 💰 Costs 0.1% of raised ETH
- 📝 Requires redeployment
- ⚠️ Still needs someone to notice
✅ Solution 4: Simple Keeper Bot (QUICK FIX)
Run Your Own Bot:
// keeper.ts
import { ethers } from 'ethers'
import { AKITA } from './config/contracts'
const provider = new ethers.JsonRpcProvider(process.env.BASE_RPC)
const wallet = new ethers.Wallet(process.env.KEEPER_KEY, provider)
const ccaStrategy = new ethers.Contract(
AKITA.ccaStrategy,
['function getAuctionStatus() view returns (address, bool, bool, uint256, uint256)',
'function sweepCurrency() external'],
wallet
)
async function checkAndComplete() {
console.log(`[${new Date().toISOString()}] Checking auction...`)
try {
const [auction, isActive, isGraduated] = await ccaStrategy.getAuctionStatus()
if (!isActive && !isGraduated && auction !== ethers.ZeroAddress) {
console.log('🎯 Auction ended but not graduated! Completing...')
const tx = await ccaStrategy.sweepCurrency()
console.log(`TX sent: ${tx.hash}`)
await tx.wait()
console.log('✅ Auction completed!')
// Send notification (optional)
await fetch(process.env.DISCORD_WEBHOOK, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
content: '🎉 AKITA auction completed automatically!'
})
})
} else {
console.log('⏳ Auction still active or already graduated')
}
} catch (error) {
console.error('❌ Error:', error)
}
}
// Check every hour
setInterval(checkAndComplete, 60 * 60 * 1000)
// Also check on start
checkAndComplete()
Deploy to Render.com (FREE):
- Create
render.yaml:
services:
- type: worker
name: akita-keeper
env: node
buildCommand: npm install
startCommand: node keeper.ts
envVars:
- key: BASE_RPC
value: https://mainnet.base.org
- key: KEEPER_KEY
sync: false # Add via Render dashboard
- key: DISCORD_WEBHOOK
sync: false
- Push to GitHub
- Connect to Render.com
- Add environment variables
- Deploy (takes 2 minutes)
Pros:
- ✅ No contract changes needed
- ✅ Works with current deployment
- ✅ Free hosting (Render/Railway)
- ✅ Full control
- ✅ Can add custom logic
Cons:
- ⚠️ Centralized (depends on your server)
- 🔑 Requires private key management
- 💰 Needs gas funds (~0.01 ETH)
📊 Comparison Table
| Solution | Cost | Decentralized | Requires Redeploy | Setup Time | Reliability |
|---|---|---|---|---|---|
| Chainlink Automation | ~$50 LINK | ✅ Yes | ✅ Yes | 4 hours | ⭐⭐⭐⭐⭐ |
| Gelato Network | ~$30 | ✅ Yes | ✅ Yes | 3 hours | ⭐⭐⭐⭐ |
| Incentivized | 0.1% raised | ✅ Yes | ✅ Yes | 2 hours | ⭐⭐⭐⭐ |
| Keeper Bot | $0 hosting | ❌ No | ❌ No | 1 hour | ⭐⭐⭐ |
🎯 RECOMMENDED APPROACH FOR YOU:
Option A: Launch Now + Keeper Bot (Fastest)
For immediate launch without redeployment:
- ✅ Launch with current contracts
- ✅ Deploy keeper bot to Render.com (1 hour)
- ✅ Set multiple calendar reminders (backup)
- ✅ Works with current deployment
After launch, consider upgrading to Chainlink Automation for future vaults.
Option B: Add Incentive + Redeploy (Best Long-Term)
For production-ready solution:
- 📝 Modify
CCALaunchStrategy.solto add 0.1% incentive - 🔄 Redeploy CCALaunchStrategy
- 🎯 Launch vault
- ✅ Completion is guaranteed (someone will claim the incentive)
This makes it truly permissionless and self-sustaining.
🛠️ QUICK IMPLEMENTATION:
I can help you with either:
-
Deploy the keeper bot RIGHT NOW (works with current contracts)
- Takes 1 hour
- No contract changes
- Ready for launch today
-
Add incentive to contract (better long-term)
- Takes 2 hours
- Requires redeployment
- Truly decentralized
Which would you prefer?
💡 MY RECOMMENDATION:
Do BOTH:
- Now: Deploy keeper bot (backup)
- Future: Add Chainlink Automation for next vault
This gives you:
- ✅ Immediate launch capability
- ✅ Reliable automation
- ✅ Backup plan
- ✅ Professional infrastructure
Would you like me to:
- Create the keeper bot code for you? (1 hour)
- Modify the contract to add incentive? (2 hours)
- Both? (best option)