Hackathon: X Layer X Cup Hackathon (May 19 - May 28, 2026) Goal: Extend the existing
shield-suiteproject into Pitchside AI—a World Cup-themed autonomous scouting and trading network that leverages your existing DEX aggregator (ShieldSwap), TEE bot infrastructure, and ScanGuard MCP security APIs.
Pitchside AI is an autonomous trading and performance speculation platform for the World Cup. It merges DeFi yield vaults, autonomous AI scouts, and dynamic player index tokens into a unified, secure ecosystem on X Layer.
- DeFi Deposit (No-Loss): Users deposit USDC/USDT into a No-Loss Yield Vault on X Layer. Their principal is 100% safe and withdrawable at any time.
- Generate Scout Credits: The yield generated by the vault is automatically converted into Scout Credits (simulated or real-time micro-yield).
- Deploy AI Scouts: Users allocate their Scout Credits to fund an autonomous AI Scout Agent (running inside a TEE enclave using
okx-agentic-wallet). - Autonomous Speculation: The AI Scout reads live World Cup news and stats. It automatically scans synthetic Player Share Tokens via the ScanGuard API for safety, then swaps them on the ShieldSwap DEX to maximize returns.
- Dynamic Asset Upgrades: As real-world player ratings shift during matches, the Player Share tokens update their metadata (artwork and power ratings) on-chain via oracle checkpoints.
User Wallet (Depositor)
│
▼
[NoLossVault.sol] ← Staking stablecoins
│
(yield → Scout Credits)
│
▼
[ScoutAgent (TEE)] ← Uses okx-agentic-wallet
│ │
(1. Scan token) │ │ (2. Execute swap)
▼ ▼
[ScanGuard MCP] [ShieldSwap DEX]
│ │
▼ ▼
`okx-security` `okx-dex-swap`
│ │
▼ ▼
Malicious check Trade PlayerShares
You will extend the existing shield-suite monorepo. Here is how the folders map:
shield-suite/
├── packages/
│ ├── scanguard/ # REST API & MCP Server
│ │ └── src/
│ │ └── routes/
│ │ └── worldcup.ts # [NEW] World Cup sports data / player index API
│ │
│ ├── shieldswap/ # React/Vite DEX Frontend
│ │ └── src/
│ │ ├── components/
│ │ │ ├── VaultPanel.tsx # [NEW] No-loss vault staking interface
│ │ │ ├── ScoutConsole.tsx# [NEW] AI Scout dashboard & sentiment logs
│ │ │ └── PlayerMarket.tsx# [NEW] Buy/Sell Player Shares & see NFT metrics
│ │
│ └── agent/ # [NEW / MODIFIED] The TEE Autonomous Bot
│ ├── src/
│ │ ├── scout.ts # Core agent logic: fetch stats, trade tokens
│ │ └── wallets.ts # Integrates okx-agentic-wallet and enclave signing
│ └── package.json
│
└── contracts/ # [NEW / MODIFIED] Hardhat project for contracts
├── contracts/
│ ├── NoLossVault.sol # ⭐ Yield vault converting interest to credits
│ ├── PlayerShares.sol # ⭐ Dynamic ERC-1155 representing players
│ └── PlayerDex.sol # Simple AMM for exchanging PlayerShares
└── scripts/
└── deploy.ts
A custom vault where users deposit stablecoins. Instead of returning raw yield, it tracks accumulated "Scout Credits" which users delegate to their AI agents.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title NoLossVault
* @notice Deposits stablecoins and earns virtual "Scout Credits" based on block yield.
* Principal is 100% safe and withdrawable at any time.
*/
contract NoLossVault is Ownable {
IERC20 public stablecoin;
// Virtual yield rate (e.g., 5% APY simulated for hackathon demo)
uint256 public constant CREDITS_PER_TOKEN_PER_SECOND = 15844; // scaled by 1e12 (approx 5% APY)
struct UserInfo {
uint256 balance;
uint256 lastUpdated;
uint256 accumulatedCredits;
address delegatedAgent;
}
mapping(address => UserInfo) public users;
event Deposited(address indexed user, uint256 amount);
event Withdrawn(address indexed user, uint256 amount);
event AgentDelegated(address indexed user, address indexed agent);
constructor(address _stablecoin) Ownable(msg.sender) {
stablecoin = IERC20(_stablecoin);
}
function deposit(uint256 amount) external {
require(amount > 0, "Amount must be greater than 0");
updateCredits(msg.sender);
stablecoin.transferFrom(msg.sender, address(this), amount);
users[msg.sender].balance += amount;
emit Deposited(msg.sender, amount);
}
function withdraw(uint256 amount) external {
UserInfo storage user = users[msg.sender];
require(user.balance >= amount, "Insufficient balance");
updateCredits(msg.sender);
user.balance -= amount;
stablecoin.transfer(msg.sender, amount);
emit Withdrawn(msg.sender, amount);
}
function delegateAgent(address agent) external {
updateCredits(msg.sender);
users[msg.sender].delegatedAgent = agent;
emit AgentDelegated(msg.sender, agent);
}
function updateCredits(address userAddress) public {
UserInfo storage user = users[userAddress];
if (user.balance > 0) {
uint256 elapsed = block.timestamp - user.lastUpdated;
uint256 earned = (user.balance * elapsed * CREDITS_PER_TOKEN_PER_SECOND) / 1e12;
user.accumulatedCredits += earned;
}
user.lastUpdated = block.timestamp;
}
function getCredits(address userAddress) external view returns (uint256) {
UserInfo memory user = users[userAddress];
if (user.balance == 0) return user.accumulatedCredits;
uint256 elapsed = block.timestamp - user.lastUpdated;
uint256 earned = (user.balance * elapsed * CREDITS_PER_TOKEN_PER_SECOND) / 1e12;
return user.accumulatedCredits + earned;
}
function spendCredits(address userAddress, uint256 amount) external {
// Only allow the delegated agent or the contract owner to spend credits to execute trades
UserInfo storage user = users[userAddress];
require(msg.sender == user.delegatedAgent || msg.sender == owner(), "Unauthorized spender");
updateCredits(userAddress);
require(user.accumulatedCredits >= amount, "Insufficient credits");
user.accumulatedCredits -= amount;
}
}Dynamic ERC-1155 token representing synthetic player index shares. Attributes and metadata update dynamically based on real-world World Cup performances.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
contract PlayerShares is ERC1155, Ownable {
using Strings for uint256;
string public name = "X-Cup Player Shares";
string public symbol = "XCPS";
// Player metadata
struct PlayerStats {
string nameString;
string country;
uint256 rating; // Current dynamic rating (e.g. 88)
uint256 goals;
uint256 assists;
}
mapping(uint256 => PlayerStats) public players;
mapping(uint256 => string) private _tokenURIs;
event PlayerUpdated(uint256 indexed tokenId, uint256 rating, uint256 goals, uint256 assists, string metadataUri);
constructor() ERC1155("") Ownable(msg.sender) {
// Initialize top 5 players for the demo
_registerPlayer(1, "Lionel Messi", "Argentina", 90);
_registerPlayer(2, "Kylian Mbappe", "France", 91);
_registerPlayer(3, "Bukayo Saka", "England", 87);
_registerPlayer(4, "Erling Haaland", "Norway", 90);
_registerPlayer(5, "Vinicius Junior", "Brazil", 89);
}
function _registerPlayer(uint256 id, string memory _name, string memory _country, uint256 _rating) internal {
players[id] = PlayerStats(_name, _country, _rating, 0, 0);
_tokenURIs[id] = string(abi.encodePacked("https://api.pitchside.ai/metadata/", id.toString()));
}
function updatePlayer(
uint256 id,
uint256 rating,
uint256 goals,
uint256 assists,
string calldata newUri
) external onlyOwner {
require(bytes(players[id].nameString).length > 0, "Player does not exist");
players[id].rating = rating;
players[id].goals = goals;
players[id].assists = assists;
if (bytes(newUri).length > 0) {
_tokenURIs[id] = newUri;
}
emit PlayerUpdated(id, rating, goals, assists, _tokenURIs[id]);
}
function uri(uint256 id) public view override returns (string memory) {
return _tokenURIs[id];
}
function mint(address to, uint256 id, uint256 amount, bytes memory data) external onlyOwner {
_mint(to, id, amount, data);
}
function burn(address from, uint256 id, uint256 amount) external {
require(from == msg.sender || isApprovedForAll(from, msg.sender), "Not authorized to burn");
_burn(from, id, amount);
}
}Deploy a dedicated agent sub-package in packages/agent running a loop that behaves as follows:
- Read World Cup News Feed / API: Scrape mock or real-world matches feeds.
- Evaluate Player Sentiment: Use an LLM completion API (e.g. Gemini) to analyze whether a player's valuation should increase or decrease.
- Input:
"Bukayo Saka scored a brace in England's 3-0 win against Senegal." - Decision: Upward momentum → Target
BUYtoken ID3.
- Input:
- Security Pre-Flight (ScanGuard integration): Check token safety via your existing ScanGuard local endpoint.
const checkSafety = await fetch('http://localhost:3402/api/scan', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ tokenAddress: playerTokenAddress }) });
- Execute Swap on ShieldSwap:
- Utilize
okx-agentic-walletto sign and execute the trade onPlayerDex.solusing the user's delegated virtual Scout Credits. - Write logs directly to the dashboard so users can see their Scout Agent's thoughts in real time.
- Utilize
You will add three responsive panels to the glassmorphic trading application:
- Shows user deposit statistics (Total Deposits, APY, and live-ticking accumulated Scout Credits).
- Actions: Deposit USDT, Withdraw USDT, and Delegate AI Agent.
- Displays a list of available AI Agent profiles users can delegate to (e.g., "Aggressive Attacker Hunter", "Defensive Value Finder").
- Displays a real-time console showing what your TEE Scout Bot is currently doing.
- Shows a terminal feed of live logs:
[10:15:32] AI Scout checking news feed...[10:15:35] Match Update: Mbappe scored a penalty.[10:15:36] Calling ScanGuard: Token ID 2 (Mbappe) is safe.[10:15:40] Executed Buy of 1.5 Shares of Mbappe using 150 Scout Credits.
- Features a hardware-heartbeat widget showing the TEE Enclave's public address and on-chain verification links.
- Displays the World Cup Player Share cards with their live attributes (Goals, Assists, FIFA Ratings).
- Includes a simple buy/sell widget utilizing the custom AMM.
- Cards should dynamically change styling (e.g., green indicators for positive performance, dynamic glow for hot performers).
- Draft & Deploy Contracts: Deploy
NoLossVault.solandPlayerShares.solto X Layer Testnet (or local Hardhat network for immediate validation). - Add World Cup Sports Feeds: Create an Express route
/api/worldcup/matchesinscanguardthat serves simulated live matches feeds (so you have deterministic triggers for your agent demo). - Build the Agent Loop: Create the node script
packages/agent/src/scout.tsthat triggers trades on-chain when the match feeds show goals/assists. - Integrate Frontend Panels: Implement the panels in
packages/shieldswapusing TailwindCSS to match the sleek, glassmorphic design of ShieldSwap. - Write Tests: Write Hardhat tests for
NoLossVaultandPlayerSharesto satisfy the AI judges' code quality criteria.